/* * Copyright (C) 2011 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. */ #ifdef _WIN32 #include "utils.h" #define _CRT_SECURE_NO_WARNINGS 1 // Set to true to get some extra debug information bool gIsDebug = false; // Set to true to output errors to stderr (for a Console app) // or to false to output using msg box (for a Windows UI app) bool gIsConsole = false; // Displays a message in an ok+info dialog box. void msgBox(const char* text, ...) { CString formatted; va_list ap; va_start(ap, text); formatted.setv(text, ap); va_end(ap); MessageBoxA(NULL, formatted.cstr(), "Android SDK Manager", MB_OK | MB_ICONINFORMATION); } // Displays GetLastError prefixed with a description in an error dialog box void displayLastError(const char *description, ...) { CString formatted; va_list ap; va_start(ap, description); formatted.setv(description, ap); va_end(ap); CString error; error.setLastWin32Error(NULL); formatted.add("\r\n"); formatted.add(error.cstr()); if (gIsConsole) { fprintf(stderr, "%s\n", formatted.cstr()); } else { MessageBox(NULL, formatted.cstr(), "Android SDK Manager - Error", MB_OK | MB_ICONERROR); } } // Executes the command line. Does not wait for the program to finish. // The return code is from CreateProcess (0 means failure), not the running app. int execNoWait(const char *app, const char *params, const char *workDir) { STARTUPINFO startup; PROCESS_INFORMATION pinfo; ZeroMemory(&pinfo, sizeof(pinfo)); ZeroMemory(&startup, sizeof(startup)); startup.cb = sizeof(startup); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = SW_SHOWDEFAULT; int ret = CreateProcessA( (LPSTR) app, /* program path */ (LPSTR) params, /* command-line */ NULL, /* process handle is not inheritable */ NULL, /* thread handle is not inheritable */ TRUE, /* yes, inherit some handles */ 0, /* create flags */ NULL, /* use parent's environment block */ workDir, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo); if (ret) { CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); } return ret; } // Executes command, waits for completion and returns exit code. // As indicated in MSDN for CreateProcess, callers should double-quote the program name // e.g. cmd="\"c:\program files\myapp.exe\" arg1 arg2"; int execWait(const char *cmd) { STARTUPINFO startup; PROCESS_INFORMATION pinfo; ZeroMemory(&pinfo, sizeof(pinfo)); ZeroMemory(&startup, sizeof(startup)); startup.cb = sizeof(startup); startup.dwFlags = STARTF_USESHOWWINDOW; startup.wShowWindow = SW_HIDE|SW_MINIMIZE; int ret = CreateProcessA( NULL, /* program path */ (LPSTR) cmd, /* 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 */ NULL, /* use parent's starting directory */ &startup, /* startup info, i.e. std handles */ &pinfo); int result = -1; if (ret) { WaitForSingleObject(pinfo.hProcess, INFINITE); DWORD exitCode; if (GetExitCodeProcess(pinfo.hProcess, &exitCode)) { // this should not return STILL_ACTIVE (259) result = exitCode; } CloseHandle(pinfo.hProcess); CloseHandle(pinfo.hThread); } return result; } bool getModuleDir(CPath *outDir) { CHAR programDir[MAX_PATH]; int ret = GetModuleFileName(NULL, programDir, sizeof(programDir)); if (ret != 0) { // Remove the last segment to keep only the directory. int pos = ret - 1; while (pos > 0 && programDir[pos] != '\\') { --pos; } outDir->set(programDir, pos); return true; } return false; } // Disables the FS redirection done by WOW64. // Because this runs as a 32-bit app, Windows automagically remaps some // folder under the hood (e.g. "Programs Files(x86)" is mapped as "Program Files"). // This prevents the app from correctly searching for java.exe in these folders. // The registry is also remapped. This method disables this redirection. // Caller should restore the redirection later by using revertWow64FsRedirection(). PVOID disableWow64FsRedirection() { // The call we want to make is the following: // PVOID oldWow64Value; // Wow64DisableWow64FsRedirection(&oldWow64Value); // However that method may not exist (e.g. on XP non-64 systems) so // we must not call it directly. PVOID oldWow64Value = 0; HMODULE hmod = LoadLibrary("kernel32.dll"); if (hmod != NULL) { FARPROC proc = GetProcAddress(hmod, "Wow64DisableWow64FsRedirection"); if (proc != NULL) { typedef BOOL (WINAPI *disableWow64FuncType)(PVOID *); disableWow64FuncType funcPtr = (disableWow64FuncType)proc; funcPtr(&oldWow64Value); } FreeLibrary(hmod); } return oldWow64Value; } // Reverts the redirection disabled in disableWow64FsRedirection. void revertWow64FsRedirection(PVOID oldWow64Value) { // The call we want to make is the following: // Wow64RevertWow64FsRedirection(oldWow64Value); // However that method may not exist (e.g. on XP non-64 systems) so // we must not call it directly. HMODULE hmod = LoadLibrary("kernel32.dll"); if (hmod != NULL) { FARPROC proc = GetProcAddress(hmod, "Wow64RevertWow64FsRedirection"); if (proc != NULL) { typedef BOOL (WINAPI *revertWow64FuncType)(PVOID); revertWow64FuncType funcPtr = (revertWow64FuncType)proc; funcPtr(oldWow64Value); } FreeLibrary(hmod); } } #endif /* _WIN32 */