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