Changeset 39742 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Jan 10, 2012 5:47:55 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Installer/Loader/VBoxWindowsAdditions.cpp
r31661 r39742 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxWindowsAdditions - The Windows Guest Additions Loader 3 * VBoxWindowsAdditions - The Windows Guest Additions Loader. 4 * 5 * This is STUB which select whether to install 32-bit or 64-bit additions. 4 6 */ 5 7 6 8 /* 7 * Copyright (C) 2006-20 07Oracle Corporation9 * Copyright (C) 2006-2012 Oracle Corporation 8 10 * 9 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 18 */ 17 19 18 #ifndef UNICODE 19 #define UNICODE 20 /******************************************************************************* 21 * Header Files * 22 *******************************************************************************/ 23 #include <Windows.h> 24 #ifndef ERROR_ELEVATION_REQUIRED /* Windows Vista and later. */ 25 # define ERROR_ELEVATION_REQUIRED 740 20 26 #endif 21 27 22 #include <windows.h>23 28 #include <stdio.h> 24 #include <tchar.h> 25 26 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); 27 28 LPFN_ISWOW64PROCESS fnIsWow64Process; 29 30 BOOL IsWow64 () 29 #include <string.h> 30 31 32 static BOOL IsWow64(void) 31 33 { 32 34 BOOL bIsWow64 = FALSE; 33 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");34 35 if ( NULL != fnIsWow64Process)35 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL); 36 LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process"); 37 if (fnIsWow64Process != NULL) 36 38 { 37 39 if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64)) 38 40 { 39 _tprintf(_T("ERROR: Could not determine process type!\n"));41 fwprintf(stderr, L"ERROR: Could not determine process type!\n"); 40 42 41 43 /* Error in retrieving process type - assume that we're running on 32bit. */ 42 returnFALSE;44 bIsWow64 = FALSE; 43 45 } 44 46 } … … 46 48 } 47 49 48 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 49 { 50 static void WaitForProcess2(HANDLE hProcess, int *piExitCode) 51 { 52 /* 53 * Wait for the process, make sure the deal with messages. 54 */ 55 for (;;) 56 { 57 DWORD dwRc = MsgWaitForMultipleObjects(1, &hProcess, FALSE, 5000/*ms*/, QS_ALLEVENTS); 58 59 MSG Msg; 60 while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) 61 { 62 TranslateMessage(&Msg); 63 DispatchMessageW(&Msg); 64 } 65 66 if (dwRc == WAIT_OBJECT_0) 67 break; 68 if ( dwRc != WAIT_TIMEOUT 69 && dwRc != WAIT_OBJECT_0 + 1) 70 { 71 fwprintf(stderr, L"ERROR: MsgWaitForMultipleObjects failed: %u (%u)\n", dwRc, GetLastError()); 72 break; 73 } 74 } 75 76 /* 77 * Collect the process info. 78 */ 79 DWORD dwExitCode; 80 if (GetExitCodeProcess(hProcess, &dwExitCode)) 81 *piExitCode = (int)dwExitCode; 82 else 83 { 84 fwprintf(stderr, L"ERROR: GetExitCodeProcess failed: %u\n", GetLastError()); 85 *piExitCode = 16; 86 } 87 } 88 89 static void WaitForProcess(HANDLE hProcess, int *piExitCode) 90 { 91 DWORD WaitRc = WaitForSingleObjectEx(hProcess, INFINITE, TRUE); 92 while ( WaitRc == WAIT_IO_COMPLETION 93 || WaitRc == WAIT_TIMEOUT) 94 WaitRc = WaitForSingleObjectEx(hProcess, INFINITE, TRUE); 95 if (WaitRc == WAIT_OBJECT_0) 96 { 97 DWORD dwExitCode; 98 if (GetExitCodeProcess(hProcess, &dwExitCode)) 99 *piExitCode = (int)dwExitCode; 100 else 101 { 102 fwprintf(stderr, L"ERROR: GetExitCodeProcess failed: %u\n", GetLastError()); 103 *piExitCode = 16; 104 } 105 } 106 else 107 { 108 fwprintf(stderr, L"ERROR: WaitForSingleObjectEx failed: %u (%u)\n", WaitRc, GetLastError()); 109 *piExitCode = 16; 110 } 111 } 112 113 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 114 { 115 /* 116 * Gather the parameters of the real installer program. 117 */ 118 119 SetLastError(NO_ERROR); 120 WCHAR wszCurDir[_MAX_PATH] = { 0 }; 121 DWORD cchCurDir = GetCurrentDirectoryW(sizeof(wszCurDir), wszCurDir); 122 if (cchCurDir == 0 || cchCurDir >= sizeof(wszCurDir)) 123 { 124 fwprintf(stderr, L"ERROR: GetCurrentDirectoryW failed: %u (ret %u)\n", GetLastError(), cchCurDir); 125 return 12; 126 } 127 128 SetLastError(NO_ERROR); 129 WCHAR wszModule[_MAX_PATH] = { 0 }; 130 DWORD cchModule = GetModuleFileNameW(NULL, wszModule, sizeof(wszModule)); 131 if (cchModule == 0 || cchModule >= sizeof(wszModule)) 132 { 133 fwprintf(stderr, L"ERROR: GetModuleFileNameW failed: %u (ret %u)\n", GetLastError(), cchModule); 134 return 13; 135 } 136 137 /* Strip the extension off the module name and construct the arch specific 138 one of the real installer program. */ 139 DWORD off = cchModule - 1; 140 while ( off > 0 141 && ( wszModule[off] != '/' 142 && wszModule[off] != '\\' 143 && wszModule[off] != ':')) 144 { 145 if (wszModule[off] == '.') 146 { 147 wszModule[off] = '\0'; 148 cchModule = off; 149 break; 150 } 151 off--; 152 } 153 154 WCHAR const *pwszSuff = IsWow64() ? L"-amd64.exe" : L"-x86.exe"; 155 size_t cchSuff = wcslen(pwszSuff); 156 if (cchSuff + cchModule >= sizeof(wszModule)) 157 { 158 fwprintf(stderr, L"ERROR: Real installer name is too long (%u chars)\n", cchSuff + cchModule); 159 return 14; 160 } 161 wcscpy(&wszModule[cchModule], pwszSuff); 162 cchModule += cchSuff; 163 164 /* Replace the first argument of the argument list. */ 165 PWCHAR pwszNewCmdLine = NULL; 166 LPCWSTR pwszOrgCmdLine = GetCommandLineW(); 167 if (pwszOrgCmdLine) /* Dunno if this can be NULL, but whatever. */ 168 { 169 /* Skip the first argument in the original. */ 170 /** @todo Is there some ISBLANK or ISSPACE macro/function in Win32 that we could 171 * use here, if it's correct wrt. command line conventions? */ 172 WCHAR wch; 173 while ((wch = *pwszOrgCmdLine) == L' ' || wch == L'\t') 174 pwszOrgCmdLine++; 175 if (wch == L'"') 176 { 177 pwszOrgCmdLine++; 178 while ((wch = *pwszOrgCmdLine) != L'\0') 179 { 180 pwszOrgCmdLine++; 181 if (wch == L'"') 182 break; 183 } 184 } 185 else 186 { 187 while ((wch = *pwszOrgCmdLine) != L'\0') 188 { 189 pwszOrgCmdLine++; 190 if (wch == L' ' || wch == L'\t') 191 break; 192 } 193 } 194 while ((wch = *pwszOrgCmdLine) == L' ' || wch == L'\t') 195 pwszOrgCmdLine++; 196 197 /* Join up "szModule" with the remainder of the original command line. */ 198 size_t cchOrgCmdLine = wcslen(pwszOrgCmdLine); 199 size_t cchNewCmdLine = 1 + cchModule + 1 + 1 + cchOrgCmdLine + 1; 200 PWCHAR pwsz = pwszNewCmdLine = (PWCHAR)LocalAlloc(LPTR, cchNewCmdLine * sizeof(WCHAR)); 201 if (!pwsz) 202 { 203 fwprintf(stderr, L"ERROR: Out of memory (%u bytes)\n", cchNewCmdLine); 204 return 15; 205 } 206 *pwsz++ = L'"'; 207 wcscpy(pwsz, wszModule); 208 pwsz += cchModule; 209 *pwsz++ = L'"'; 210 if (cchOrgCmdLine) 211 { 212 *pwsz++ = L' '; 213 wcscpy(pwsz, pwszOrgCmdLine); 214 } 215 else 216 *pwsz = L'\0'; 217 } 218 219 /* 220 * Start the process. 221 */ 50 222 int iRet = 0; 51 52 LPWSTR *pszArgList = NULL; 53 int nArgs = 0; 54 55 TCHAR szCurDir[_MAX_PATH + 1] = { 0 }; 56 GetCurrentDirectory(_MAX_PATH, szCurDir); 57 58 SHELLEXECUTEINFOW TempInfo = { 0 }; 59 TempInfo.cbSize = sizeof(SHELLEXECUTEINFOW); 60 61 TCHAR szModule[_MAX_PATH + 1] = { 0 }; 62 TCHAR szApp[_MAX_PATH + 1] = { 0 }; 63 TCHAR szProg[_MAX_PATH + 1] = { 0 }; 64 65 pszArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs); 66 if (0 == GetModuleFileName(NULL, szModule, _MAX_PATH)) 67 { 68 /* Module not found, use a default name. */ 69 _stprintf(szModule, _T("%ws"), (pszArgList != NULL) ? pszArgList[0] : _T("VBoxWindowsAdditions.exe")); 70 } 71 72 TCHAR* pcExt = wcsrchr(szModule, _T('.')); 73 if (NULL != pcExt) 74 wcsncpy(szApp, szModule, (pcExt - szModule)); 75 76 if (IsWow64()) /* 64bit Windows. */ 77 { 78 _stprintf(szProg, _T("%ws-amd64.exe"), szApp); 79 } 80 else /* 32bit Windows. */ 81 { 82 _stprintf(szProg, _T("%ws-x86.exe"), szApp); 83 } 84 85 /* Construct parameter list. */ 86 TCHAR *pszParams = (TCHAR*)LocalAlloc(LPTR, _MAX_PATH*sizeof(TCHAR)); 87 TCHAR szDelim = _T(' '); 88 89 if (pszParams) 90 { 91 wcsncat(pszParams, szProg, 92 __min(wcslen(szProg),_MAX_PATH-wcslen(pszParams))); 93 wcsncat(pszParams, &szDelim, 94 __min(1,_MAX_PATH-wcslen(pszParams))); 95 96 if (nArgs > 1) 97 { 98 for (int i=0; i<nArgs-1; i++) 99 { 100 if (i > 0) 101 { 102 wcsncat(pszParams, &szDelim, 103 __min(1,_MAX_PATH-wcslen(pszParams))); 104 } 105 wcsncat(pszParams, pszArgList[i+1], 106 __min(wcslen(pszArgList[i+1]),_MAX_PATH-wcslen(pszParams))); 107 } 108 } 109 } 110 111 /* Struct for ShellExecute. */ 112 TempInfo.fMask = 0; 113 TempInfo.hwnd = NULL; 114 TempInfo.lpVerb =L"runas" ; 115 TempInfo.lpFile = szProg; 116 TempInfo.lpParameters = pszParams; 117 TempInfo.lpDirectory = szCurDir; 118 TempInfo.nShow = SW_NORMAL; 119 120 STARTUPINFOW si; 121 PROCESS_INFORMATION pi; 122 DWORD dwRes = 0; 123 124 ZeroMemory(&si, sizeof(si)); 125 si.cb = sizeof(si); 126 ZeroMemory(&pi, sizeof(pi)); 127 128 dwRes = CreateProcessW(szProg, pszParams, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 129 if (!dwRes && GetLastError() == 740) /* 740 = ERROR_ELEVATION_REQUIRED -> Only for Windows Vista. */ 130 { 131 if (FALSE == ::ShellExecuteExW(&TempInfo)) 132 { 133 _tprintf (_T("ERROR: Could not launch program! Code: %ld\n"), GetLastError()); 134 iRet = 1; 135 } 136 } 137 138 if (pszParams) 139 LocalFree(pszParams); 140 141 if (pszArgList) 142 LocalFree(pszArgList); 143 223 STARTUPINFOW StartupInfo = { sizeof(StartupInfo), 0 }; 224 PROCESS_INFORMATION ProcInfo = { 0 }; 225 SetLastError(740); 226 BOOL fOk = CreateProcessW(wszModule, 227 pwszNewCmdLine, 228 NULL /*pProcessAttributes*/, 229 NULL /*pThreadAttributes*/, 230 TRUE /*fInheritHandles*/, 231 0 /*dwCreationFlags*/, 232 NULL /*pEnvironment*/, 233 NULL /*pCurrentDirectory*/, 234 &StartupInfo, 235 &ProcInfo); 236 if (fOk) 237 { 238 /* Wait for the process to finish. */ 239 CloseHandle(ProcInfo.hThread); 240 WaitForProcess(ProcInfo.hProcess, &iRet); 241 CloseHandle(ProcInfo.hProcess); 242 } 243 else if (GetLastError() == ERROR_ELEVATION_REQUIRED) 244 { 245 /* 246 * Elevation is required. That can be accomplished via ShellExecuteEx 247 * and the runas atom. 248 */ 249 MSG Msg; 250 PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE); 251 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 252 253 SHELLEXECUTEINFOW ShExecInfo = { 0 }; 254 ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); 255 ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 256 ShExecInfo.hwnd = NULL; 257 ShExecInfo.lpVerb = L"runas" ; 258 ShExecInfo.lpFile = wszModule; 259 ShExecInfo.lpParameters = pwszNewCmdLine; 260 ShExecInfo.lpDirectory = wszCurDir; 261 ShExecInfo.nShow = SW_NORMAL; 262 ShExecInfo.hProcess = INVALID_HANDLE_VALUE; 263 if (ShellExecuteExW(&ShExecInfo)) 264 { 265 if (ShExecInfo.hProcess != INVALID_HANDLE_VALUE) 266 { 267 WaitForProcess2(ShExecInfo.hProcess, &iRet); 268 CloseHandle(ShExecInfo.hProcess); 269 } 270 else 271 { 272 fwprintf(stderr, L"ERROR: ShellExecuteExW did not return a valid process handle!\n"); 273 iRet = 1; 274 } 275 } 276 else 277 { 278 fwprintf(stderr, L"ERROR: Failed to execute '%ws' via ShellExecuteExW: %u\n", wszModule, GetLastError()); 279 iRet = 9; 280 } 281 } 282 else 283 { 284 fwprintf(stderr, L"ERROR: Failed to execute '%ws' via CreateProcessW: %u\n", wszModule, GetLastError()); 285 iRet = 8; 286 } 287 288 if (pwszNewCmdLine) 289 LocalFree(pwszNewCmdLine); 290 291 #if 0 292 fwprintf(stderr, L"DEBUG: iRet=%d\n", iRet); 293 fflush(stderr); 294 #endif 144 295 return iRet; 145 296 }
Note:
See TracChangeset
for help on using the changeset viewer.