aboutsummaryrefslogtreecommitdiffstats
path: root/avdlauncher/avdlauncher.c
diff options
context:
space:
mode:
Diffstat (limited to 'avdlauncher/avdlauncher.c')
-rw-r--r--avdlauncher/avdlauncher.c271
1 files changed, 271 insertions, 0 deletions
diff --git a/avdlauncher/avdlauncher.c b/avdlauncher/avdlauncher.c
new file mode 100644
index 0000000..ab2c88d
--- /dev/null
+++ b/avdlauncher/avdlauncher.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The "AVD Manager" is for Windows only.
+ * This simple .exe will sit at the root of the Windows SDK
+ * and currently simply executes tools\android.bat.
+ * Eventually it should simply replace the batch file.
+ *
+ * TODO: replace by a jar-exe wrapper.
+ */
+
+#ifdef _WIN32
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <windows.h>
+
+
+int _enable_dprintf = 0;
+
+void dprintf(char *msg, ...) {
+ va_list ap;
+ va_start(ap, msg);
+
+ if (_enable_dprintf) {
+ vfprintf(stderr, msg, ap);
+ }
+
+ va_end(ap);
+}
+
+void display_error(LPSTR description) {
+ DWORD err = GetLastError();
+ LPSTR s, s2;
+
+ fprintf(stderr, "%s, error %ld\n", description, err);
+
+ if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | /* dwFlags */
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, /* lpSource */
+ err, /* dwMessageId */
+ 0, /* dwLanguageId */
+ (LPSTR)&s, /* lpBuffer */
+ 0, /* nSize */
+ NULL) != 0) { /* va_list args */
+ fprintf(stderr, "%s", s);
+
+ s2 = (LPSTR) malloc(strlen(description) + strlen(s) + 5);
+ sprintf(s2, "%s\r\n%s", description, s);
+ MessageBox(NULL, s2, "Android AVD Manager - Error", MB_OK);
+ free(s2);
+ LocalFree(s);
+ }
+}
+
+
+HANDLE create_temp_file(LPSTR temp_filename) {
+
+ HANDLE file_handle = INVALID_HANDLE_VALUE;
+ LPSTR temp_path = (LPSTR) malloc(MAX_PATH);
+
+ /* Get the temp directory path using GetTempPath.
+ GetTempFilename indicates that the temp path dir should not be larger than MAX_PATH-14.
+ */
+ int ret = GetTempPath(MAX_PATH - 14, temp_path);
+ if (ret > MAX_PATH || ret == 0) {
+ display_error("GetTempPath failed");
+ free(temp_path);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ /* Now get a temp filename in the temp directory. */
+ if (!GetTempFileName(temp_path, "txt", 0, temp_filename)) {
+ display_error("GetTempFileName failed");
+
+ } else {
+ SECURITY_ATTRIBUTES sattr;
+ ZeroMemory(&sattr, sizeof(sattr));
+ sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sattr.bInheritHandle = TRUE;
+
+ file_handle = CreateFile(temp_filename, // filename
+ GENERIC_WRITE, // access: write
+ FILE_SHARE_READ, // share mode: read OK
+ &sattr, // security attributes
+ CREATE_ALWAYS, // create even if exists
+ FILE_ATTRIBUTE_NORMAL, // flags and attributes
+ NULL); // template
+ if (file_handle == INVALID_HANDLE_VALUE) {
+ display_error("Create temp file failed");
+ }
+ }
+
+ free(temp_path);
+ return file_handle;
+}
+
+
+void read_temp_file(LPSTR temp_filename) {
+ HANDLE handle;
+
+ handle = CreateFile(temp_filename, // filename
+ GENERIC_READ, // access: read
+ FILE_SHARE_READ, // share mode: read OK
+ NULL, // security attributes
+ OPEN_EXISTING, // only open existing file
+ FILE_ATTRIBUTE_NORMAL, // flags and attributes
+ NULL); // template
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ display_error("Open temp file failed");
+ return;
+ }
+
+ /* Cap the size we're reading.
+ 4K is good enough to display in a message box.
+ */
+ DWORD size = 4096;
+
+ LPSTR buffer = (LPSTR) malloc(size + 1);
+
+ LPSTR p = buffer;
+ DWORD num_left = size;
+ DWORD num_read;
+ do {
+ if (!ReadFile(handle, p, num_left, &num_read, NULL)) {
+ display_error("Read Output failed");
+ break;
+ }
+
+ num_left -= num_read;
+ p += num_read;
+ } while (num_read > 0);
+
+ if (p != buffer) {
+ *p = 0;
+
+ /* Only output the buffer if it contains special keywords WARNING or ERROR. */
+ char* s1 = strstr(buffer, "WARNING");
+ char* s2 = strstr(buffer, "ERROR");
+
+ if (s2 != NULL && s2 < s1) {
+ s1 = s2;
+ }
+
+ if (s1 != NULL) {
+ /* We end the message at the first occurence of [INFO]. */
+ s2 = strstr(s1, "[INFO]");
+ if (s2 != NULL) {
+ *s2 = 0;
+ }
+
+ MessageBox(NULL, s1, "Android AVD Manager - Output", MB_OK);
+ }
+
+ }
+
+ free(buffer);
+
+ if (!CloseHandle(handle)) {
+ display_error("CloseHandle read temp file failed");
+ }
+}
+
+
+int avd_launcher() {
+ int result = 0;
+ STARTUPINFO startup;
+ PROCESS_INFORMATION pinfo;
+ CHAR program_dir[MAX_PATH];
+ int ret, pos;
+ CHAR temp_filename[MAX_PATH];
+ HANDLE temp_handle;
+
+ ZeroMemory(&pinfo, sizeof(pinfo));
+
+ temp_handle = create_temp_file(temp_filename);
+ if (temp_handle == INVALID_HANDLE_VALUE) {
+ return 1;
+ }
+
+ ZeroMemory(&startup, sizeof(startup));
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESTDHANDLES;
+ startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
+ startup.hStdOutput = temp_handle;
+ startup.hStdError = temp_handle;
+
+ /* get path of current program, to switch dirs here when executing the command. */
+ ret = GetModuleFileName(NULL, program_dir, sizeof(program_dir));
+ if (ret == 0) {
+ display_error("Failed to get program's filename:");
+ result = 1;
+ } else {
+ /* Remove the last segment to keep only the directory. */
+ pos = ret - 1;
+ while (pos > 0 && program_dir[pos] != '\\') {
+ --pos;
+ }
+ program_dir[pos] = 0;
+ }
+
+ if (!result) {
+ dprintf("Program dir: %s\n", program_dir);
+
+ ret = CreateProcess(
+ NULL, /* program path */
+ "tools\\android.bat avd", /* command-line */
+ NULL, /* process handle is not inheritable */
+ NULL, /* thread handle is not inheritable */
+ TRUE, /* yes, inherit some handles */
+ CREATE_NO_WINDOW, /* we don't want a console */
+ NULL, /* use parent's environment block */
+ program_dir, /* use parent's starting directory */
+ &startup, /* startup info, i.e. std handles */
+ &pinfo);
+
+ dprintf("CreateProcess returned %d\n", ret);
+
+ if (!ret) {
+ display_error("Failed to execute tools\\android.bat:");
+ result = 1;
+ } else {
+ dprintf("Wait for process to finish.\n");
+
+ WaitForSingleObject(pinfo.hProcess, INFINITE);
+ CloseHandle(pinfo.hProcess);
+ CloseHandle(pinfo.hThread);
+ }
+ }
+
+ dprintf("Cleanup.\n");
+
+ if (!CloseHandle(temp_handle)) {
+ display_error("CloseHandle temp file failed");
+ }
+
+ if (!result) {
+ read_temp_file(temp_filename);
+ }
+
+ if (!DeleteFile(temp_filename)) {
+ display_error("Delete temp file failed");
+ }
+
+ return result;
+}
+
+int main(int argc, char **argv) {
+ _enable_dprintf = argc > 1 && strcmp(argv[1], "-v") == 0;
+ dprintf("Verbose debug mode.\n");
+
+ return avd_launcher();
+}
+
+#endif /* _WIN32 */