1628920b73c59cbbb976c0c352baffb533b33c142Raphael/* 2628920b73c59cbbb976c0c352baffb533b33c142Raphael * Copyright (C) 2011 The Android Open Source Project 3628920b73c59cbbb976c0c352baffb533b33c142Raphael * 4628920b73c59cbbb976c0c352baffb533b33c142Raphael * Licensed under the Apache License, Version 2.0 (the "License"); 5628920b73c59cbbb976c0c352baffb533b33c142Raphael * you may not use this file except in compliance with the License. 6628920b73c59cbbb976c0c352baffb533b33c142Raphael * You may obtain a copy of the License at 7628920b73c59cbbb976c0c352baffb533b33c142Raphael * 8628920b73c59cbbb976c0c352baffb533b33c142Raphael * http://www.apache.org/licenses/LICENSE-2.0 9628920b73c59cbbb976c0c352baffb533b33c142Raphael * 10628920b73c59cbbb976c0c352baffb533b33c142Raphael * Unless required by applicable law or agreed to in writing, software 11628920b73c59cbbb976c0c352baffb533b33c142Raphael * distributed under the License is distributed on an "AS IS" BASIS, 12628920b73c59cbbb976c0c352baffb533b33c142Raphael * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13628920b73c59cbbb976c0c352baffb533b33c142Raphael * See the License for the specific language governing permissions and 14628920b73c59cbbb976c0c352baffb533b33c142Raphael * limitations under the License. 15628920b73c59cbbb976c0c352baffb533b33c142Raphael */ 16628920b73c59cbbb976c0c352baffb533b33c142Raphael 17628920b73c59cbbb976c0c352baffb533b33c142Raphael#ifdef _WIN32 18628920b73c59cbbb976c0c352baffb533b33c142Raphael 19628920b73c59cbbb976c0c352baffb533b33c142Raphael#include "utils.h" 20628920b73c59cbbb976c0c352baffb533b33c142Raphael 21628920b73c59cbbb976c0c352baffb533b33c142Raphael#define _CRT_SECURE_NO_WARNINGS 1 22628920b73c59cbbb976c0c352baffb533b33c142Raphael 23d2d6999d779fffe976c55db04bf523907a8743edRaphael// Set to true to get some extra debug information 24d2d6999d779fffe976c55db04bf523907a8743edRaphaelbool gIsDebug = false; 25d2d6999d779fffe976c55db04bf523907a8743edRaphael// Set to true to output errors to stderr (for a Console app) 26d2d6999d779fffe976c55db04bf523907a8743edRaphael// or to false to output using msg box (for a Windows UI app) 27d2d6999d779fffe976c55db04bf523907a8743edRaphaelbool gIsConsole = false; 28628920b73c59cbbb976c0c352baffb533b33c142Raphael 29628920b73c59cbbb976c0c352baffb533b33c142Raphael// Displays a message in an ok+info dialog box. 30628920b73c59cbbb976c0c352baffb533b33c142Raphaelvoid msgBox(const char* text, ...) { 31628920b73c59cbbb976c0c352baffb533b33c142Raphael CString formatted; 32628920b73c59cbbb976c0c352baffb533b33c142Raphael va_list ap; 33628920b73c59cbbb976c0c352baffb533b33c142Raphael va_start(ap, text); 34628920b73c59cbbb976c0c352baffb533b33c142Raphael formatted.setv(text, ap); 35628920b73c59cbbb976c0c352baffb533b33c142Raphael va_end(ap); 36628920b73c59cbbb976c0c352baffb533b33c142Raphael 37628920b73c59cbbb976c0c352baffb533b33c142Raphael MessageBoxA(NULL, formatted.cstr(), "Android SDK Manager", MB_OK | MB_ICONINFORMATION); 38628920b73c59cbbb976c0c352baffb533b33c142Raphael} 39628920b73c59cbbb976c0c352baffb533b33c142Raphael 40628920b73c59cbbb976c0c352baffb533b33c142Raphael// Displays GetLastError prefixed with a description in an error dialog box 41628920b73c59cbbb976c0c352baffb533b33c142Raphaelvoid displayLastError(const char *description, ...) { 42628920b73c59cbbb976c0c352baffb533b33c142Raphael CString formatted; 43628920b73c59cbbb976c0c352baffb533b33c142Raphael va_list ap; 44628920b73c59cbbb976c0c352baffb533b33c142Raphael va_start(ap, description); 45628920b73c59cbbb976c0c352baffb533b33c142Raphael formatted.setv(description, ap); 46628920b73c59cbbb976c0c352baffb533b33c142Raphael va_end(ap); 47628920b73c59cbbb976c0c352baffb533b33c142Raphael 48628920b73c59cbbb976c0c352baffb533b33c142Raphael CString error; 4942a9cedd9d2aa55a9ed71e50cb4a7199a926a4e9Raphael error.setLastWin32Error(NULL); 50628920b73c59cbbb976c0c352baffb533b33c142Raphael formatted.add("\r\n"); 51628920b73c59cbbb976c0c352baffb533b33c142Raphael formatted.add(error.cstr()); 52d2d6999d779fffe976c55db04bf523907a8743edRaphael 53d2d6999d779fffe976c55db04bf523907a8743edRaphael if (gIsConsole) { 54d2d6999d779fffe976c55db04bf523907a8743edRaphael fprintf(stderr, "%s\n", formatted.cstr()); 55d2d6999d779fffe976c55db04bf523907a8743edRaphael } else { 56d2d6999d779fffe976c55db04bf523907a8743edRaphael MessageBox(NULL, formatted.cstr(), "Android SDK Manager - Error", MB_OK | MB_ICONERROR); 57d2d6999d779fffe976c55db04bf523907a8743edRaphael } 58628920b73c59cbbb976c0c352baffb533b33c142Raphael} 59628920b73c59cbbb976c0c352baffb533b33c142Raphael 60628920b73c59cbbb976c0c352baffb533b33c142Raphael// Executes the command line. Does not wait for the program to finish. 61628920b73c59cbbb976c0c352baffb533b33c142Raphael// The return code is from CreateProcess (0 means failure), not the running app. 62628920b73c59cbbb976c0c352baffb533b33c142Raphaelint execNoWait(const char *app, const char *params, const char *workDir) { 63628920b73c59cbbb976c0c352baffb533b33c142Raphael STARTUPINFO startup; 64628920b73c59cbbb976c0c352baffb533b33c142Raphael PROCESS_INFORMATION pinfo; 65628920b73c59cbbb976c0c352baffb533b33c142Raphael 66628920b73c59cbbb976c0c352baffb533b33c142Raphael ZeroMemory(&pinfo, sizeof(pinfo)); 67628920b73c59cbbb976c0c352baffb533b33c142Raphael 68628920b73c59cbbb976c0c352baffb533b33c142Raphael ZeroMemory(&startup, sizeof(startup)); 69628920b73c59cbbb976c0c352baffb533b33c142Raphael startup.cb = sizeof(startup); 70628920b73c59cbbb976c0c352baffb533b33c142Raphael startup.dwFlags = STARTF_USESHOWWINDOW; 711bb7440c9f2e3548a420a1033973fa59337ebd25Raphael startup.wShowWindow = SW_SHOWDEFAULT; 72628920b73c59cbbb976c0c352baffb533b33c142Raphael 73628920b73c59cbbb976c0c352baffb533b33c142Raphael int ret = CreateProcessA( 74628920b73c59cbbb976c0c352baffb533b33c142Raphael (LPSTR) app, /* program path */ 75628920b73c59cbbb976c0c352baffb533b33c142Raphael (LPSTR) params, /* command-line */ 76628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* process handle is not inheritable */ 77628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* thread handle is not inheritable */ 78628920b73c59cbbb976c0c352baffb533b33c142Raphael TRUE, /* yes, inherit some handles */ 791bb7440c9f2e3548a420a1033973fa59337ebd25Raphael 0, /* create flags */ 80628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* use parent's environment block */ 81628920b73c59cbbb976c0c352baffb533b33c142Raphael workDir, /* use parent's starting directory */ 82628920b73c59cbbb976c0c352baffb533b33c142Raphael &startup, /* startup info, i.e. std handles */ 83628920b73c59cbbb976c0c352baffb533b33c142Raphael &pinfo); 84628920b73c59cbbb976c0c352baffb533b33c142Raphael 85628920b73c59cbbb976c0c352baffb533b33c142Raphael if (ret) { 86628920b73c59cbbb976c0c352baffb533b33c142Raphael CloseHandle(pinfo.hProcess); 87628920b73c59cbbb976c0c352baffb533b33c142Raphael CloseHandle(pinfo.hThread); 88628920b73c59cbbb976c0c352baffb533b33c142Raphael } 89628920b73c59cbbb976c0c352baffb533b33c142Raphael 90628920b73c59cbbb976c0c352baffb533b33c142Raphael return ret; 91628920b73c59cbbb976c0c352baffb533b33c142Raphael} 92628920b73c59cbbb976c0c352baffb533b33c142Raphael 93628920b73c59cbbb976c0c352baffb533b33c142Raphael// Executes command, waits for completion and returns exit code. 94628920b73c59cbbb976c0c352baffb533b33c142Raphael// As indicated in MSDN for CreateProcess, callers should double-quote the program name 95628920b73c59cbbb976c0c352baffb533b33c142Raphael// e.g. cmd="\"c:\program files\myapp.exe\" arg1 arg2"; 96628920b73c59cbbb976c0c352baffb533b33c142Raphaelint execWait(const char *cmd) { 97628920b73c59cbbb976c0c352baffb533b33c142Raphael STARTUPINFO startup; 98628920b73c59cbbb976c0c352baffb533b33c142Raphael PROCESS_INFORMATION pinfo; 99628920b73c59cbbb976c0c352baffb533b33c142Raphael 100628920b73c59cbbb976c0c352baffb533b33c142Raphael ZeroMemory(&pinfo, sizeof(pinfo)); 101628920b73c59cbbb976c0c352baffb533b33c142Raphael 102628920b73c59cbbb976c0c352baffb533b33c142Raphael ZeroMemory(&startup, sizeof(startup)); 103628920b73c59cbbb976c0c352baffb533b33c142Raphael startup.cb = sizeof(startup); 104628920b73c59cbbb976c0c352baffb533b33c142Raphael startup.dwFlags = STARTF_USESHOWWINDOW; 105628920b73c59cbbb976c0c352baffb533b33c142Raphael startup.wShowWindow = SW_HIDE|SW_MINIMIZE; 106628920b73c59cbbb976c0c352baffb533b33c142Raphael 107628920b73c59cbbb976c0c352baffb533b33c142Raphael int ret = CreateProcessA( 108628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* program path */ 109628920b73c59cbbb976c0c352baffb533b33c142Raphael (LPSTR) cmd, /* command-line */ 110628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* process handle is not inheritable */ 111628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* thread handle is not inheritable */ 112628920b73c59cbbb976c0c352baffb533b33c142Raphael TRUE, /* yes, inherit some handles */ 113628920b73c59cbbb976c0c352baffb533b33c142Raphael CREATE_NO_WINDOW, /* we don't want a console */ 114628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* use parent's environment block */ 115628920b73c59cbbb976c0c352baffb533b33c142Raphael NULL, /* use parent's starting directory */ 116628920b73c59cbbb976c0c352baffb533b33c142Raphael &startup, /* startup info, i.e. std handles */ 117628920b73c59cbbb976c0c352baffb533b33c142Raphael &pinfo); 118628920b73c59cbbb976c0c352baffb533b33c142Raphael 119628920b73c59cbbb976c0c352baffb533b33c142Raphael int result = -1; 120628920b73c59cbbb976c0c352baffb533b33c142Raphael if (ret) { 121628920b73c59cbbb976c0c352baffb533b33c142Raphael WaitForSingleObject(pinfo.hProcess, INFINITE); 122628920b73c59cbbb976c0c352baffb533b33c142Raphael 123628920b73c59cbbb976c0c352baffb533b33c142Raphael DWORD exitCode; 124628920b73c59cbbb976c0c352baffb533b33c142Raphael if (GetExitCodeProcess(pinfo.hProcess, &exitCode)) { 125628920b73c59cbbb976c0c352baffb533b33c142Raphael // this should not return STILL_ACTIVE (259) 126628920b73c59cbbb976c0c352baffb533b33c142Raphael result = exitCode; 127628920b73c59cbbb976c0c352baffb533b33c142Raphael } 128628920b73c59cbbb976c0c352baffb533b33c142Raphael CloseHandle(pinfo.hProcess); 129628920b73c59cbbb976c0c352baffb533b33c142Raphael CloseHandle(pinfo.hThread); 130628920b73c59cbbb976c0c352baffb533b33c142Raphael } 131628920b73c59cbbb976c0c352baffb533b33c142Raphael 132628920b73c59cbbb976c0c352baffb533b33c142Raphael return result; 133628920b73c59cbbb976c0c352baffb533b33c142Raphael} 134628920b73c59cbbb976c0c352baffb533b33c142Raphael 135628920b73c59cbbb976c0c352baffb533b33c142Raphaelbool getModuleDir(CPath *outDir) { 136628920b73c59cbbb976c0c352baffb533b33c142Raphael CHAR programDir[MAX_PATH]; 137628920b73c59cbbb976c0c352baffb533b33c142Raphael int ret = GetModuleFileName(NULL, programDir, sizeof(programDir)); 138628920b73c59cbbb976c0c352baffb533b33c142Raphael if (ret != 0) { 139628920b73c59cbbb976c0c352baffb533b33c142Raphael // Remove the last segment to keep only the directory. 140628920b73c59cbbb976c0c352baffb533b33c142Raphael int pos = ret - 1; 141628920b73c59cbbb976c0c352baffb533b33c142Raphael while (pos > 0 && programDir[pos] != '\\') { 142628920b73c59cbbb976c0c352baffb533b33c142Raphael --pos; 143628920b73c59cbbb976c0c352baffb533b33c142Raphael } 144628920b73c59cbbb976c0c352baffb533b33c142Raphael outDir->set(programDir, pos); 145628920b73c59cbbb976c0c352baffb533b33c142Raphael return true; 146628920b73c59cbbb976c0c352baffb533b33c142Raphael } 147628920b73c59cbbb976c0c352baffb533b33c142Raphael return false; 148628920b73c59cbbb976c0c352baffb533b33c142Raphael} 149628920b73c59cbbb976c0c352baffb533b33c142Raphael 150628920b73c59cbbb976c0c352baffb533b33c142Raphael// Disables the FS redirection done by WOW64. 151628920b73c59cbbb976c0c352baffb533b33c142Raphael// Because this runs as a 32-bit app, Windows automagically remaps some 152628920b73c59cbbb976c0c352baffb533b33c142Raphael// folder under the hood (e.g. "Programs Files(x86)" is mapped as "Program Files"). 153628920b73c59cbbb976c0c352baffb533b33c142Raphael// This prevents the app from correctly searching for java.exe in these folders. 1541bb7440c9f2e3548a420a1033973fa59337ebd25Raphael// The registry is also remapped. This method disables this redirection. 1551bb7440c9f2e3548a420a1033973fa59337ebd25Raphael// Caller should restore the redirection later by using revertWow64FsRedirection(). 156628920b73c59cbbb976c0c352baffb533b33c142RaphaelPVOID disableWow64FsRedirection() { 157628920b73c59cbbb976c0c352baffb533b33c142Raphael 158628920b73c59cbbb976c0c352baffb533b33c142Raphael // The call we want to make is the following: 159628920b73c59cbbb976c0c352baffb533b33c142Raphael // PVOID oldWow64Value; 160628920b73c59cbbb976c0c352baffb533b33c142Raphael // Wow64DisableWow64FsRedirection(&oldWow64Value); 1611bb7440c9f2e3548a420a1033973fa59337ebd25Raphael // However that method may not exist (e.g. on XP non-64 systems) so 162628920b73c59cbbb976c0c352baffb533b33c142Raphael // we must not call it directly. 163628920b73c59cbbb976c0c352baffb533b33c142Raphael 164628920b73c59cbbb976c0c352baffb533b33c142Raphael PVOID oldWow64Value = 0; 165628920b73c59cbbb976c0c352baffb533b33c142Raphael 166628920b73c59cbbb976c0c352baffb533b33c142Raphael HMODULE hmod = LoadLibrary("kernel32.dll"); 167628920b73c59cbbb976c0c352baffb533b33c142Raphael if (hmod != NULL) { 168628920b73c59cbbb976c0c352baffb533b33c142Raphael FARPROC proc = GetProcAddress(hmod, "Wow64DisableWow64FsRedirection"); 169628920b73c59cbbb976c0c352baffb533b33c142Raphael if (proc != NULL) { 170628920b73c59cbbb976c0c352baffb533b33c142Raphael typedef BOOL (WINAPI *disableWow64FuncType)(PVOID *); 171628920b73c59cbbb976c0c352baffb533b33c142Raphael disableWow64FuncType funcPtr = (disableWow64FuncType)proc; 172628920b73c59cbbb976c0c352baffb533b33c142Raphael funcPtr(&oldWow64Value); 173628920b73c59cbbb976c0c352baffb533b33c142Raphael } 174628920b73c59cbbb976c0c352baffb533b33c142Raphael 175628920b73c59cbbb976c0c352baffb533b33c142Raphael FreeLibrary(hmod); 176628920b73c59cbbb976c0c352baffb533b33c142Raphael } 177628920b73c59cbbb976c0c352baffb533b33c142Raphael 178628920b73c59cbbb976c0c352baffb533b33c142Raphael return oldWow64Value; 179628920b73c59cbbb976c0c352baffb533b33c142Raphael} 180628920b73c59cbbb976c0c352baffb533b33c142Raphael 181628920b73c59cbbb976c0c352baffb533b33c142Raphael// Reverts the redirection disabled in disableWow64FsRedirection. 182628920b73c59cbbb976c0c352baffb533b33c142Raphaelvoid revertWow64FsRedirection(PVOID oldWow64Value) { 183628920b73c59cbbb976c0c352baffb533b33c142Raphael 184628920b73c59cbbb976c0c352baffb533b33c142Raphael // The call we want to make is the following: 185628920b73c59cbbb976c0c352baffb533b33c142Raphael // Wow64RevertWow64FsRedirection(oldWow64Value); 1861bb7440c9f2e3548a420a1033973fa59337ebd25Raphael // However that method may not exist (e.g. on XP non-64 systems) so 187628920b73c59cbbb976c0c352baffb533b33c142Raphael // we must not call it directly. 188628920b73c59cbbb976c0c352baffb533b33c142Raphael 189628920b73c59cbbb976c0c352baffb533b33c142Raphael HMODULE hmod = LoadLibrary("kernel32.dll"); 190628920b73c59cbbb976c0c352baffb533b33c142Raphael if (hmod != NULL) { 191628920b73c59cbbb976c0c352baffb533b33c142Raphael FARPROC proc = GetProcAddress(hmod, "Wow64RevertWow64FsRedirection"); 192628920b73c59cbbb976c0c352baffb533b33c142Raphael if (proc != NULL) { 193628920b73c59cbbb976c0c352baffb533b33c142Raphael typedef BOOL (WINAPI *revertWow64FuncType)(PVOID); 194628920b73c59cbbb976c0c352baffb533b33c142Raphael revertWow64FuncType funcPtr = (revertWow64FuncType)proc; 195628920b73c59cbbb976c0c352baffb533b33c142Raphael funcPtr(oldWow64Value); 196628920b73c59cbbb976c0c352baffb533b33c142Raphael } 197628920b73c59cbbb976c0c352baffb533b33c142Raphael 198628920b73c59cbbb976c0c352baffb533b33c142Raphael FreeLibrary(hmod); 199628920b73c59cbbb976c0c352baffb533b33c142Raphael } 200628920b73c59cbbb976c0c352baffb533b33c142Raphael} 201628920b73c59cbbb976c0c352baffb533b33c142Raphael 202628920b73c59cbbb976c0c352baffb533b33c142Raphael#endif /* _WIN32 */ 203