Changeset 27513 in vbox for trunk/src/VBox/Runtime/r3/win
- Timestamp:
- Mar 19, 2010 2:19:41 AM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 59016
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/process-win.cpp
r27512 r27513 84 84 } PROCESSINFOCLASS; 85 85 86 typedef WINADVAPI BOOL WINAPI CREATEPROCESSWITHLOGON(LPCWSTR,87 LPCWSTR,88 LPCWSTR,89 DWORD,90 LPCWSTR,91 LPWSTR,92 DWORD,93 LPVOID,94 LPCWSTR,95 LPSTARTUPINFOW,96 LPPROCESS_INFORMATION);97 typedef CREATEPROCESSWITHLOGON *PCREATEPROCESSWITHLOGON;98 99 86 extern "C" LONG WINAPI 100 87 NtQueryInformationProcess( … … 105 92 OUT PULONG ReturnLength OPTIONAL); 106 93 94 typedef WINADVAPI BOOL WINAPI FNCREATEPROCESSWITHLOGON(LPCWSTR, 95 LPCWSTR, 96 LPCWSTR, 97 DWORD, 98 LPCWSTR, 99 LPWSTR, 100 DWORD, 101 LPVOID, 102 LPCWSTR, 103 LPSTARTUPINFOW, 104 LPPROCESS_INFORMATION); 105 typedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON; 106 107 108 #if 0 /** @todo Andy, could you enable and test this, please? It should work, but I don't have a full windows install to test it on. */ 109 RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess) 110 { 111 return RTProcCreateEx(pszExec, papszArgs, Env, fFlags, 112 NULL, NULL, NULL, /* standard handles */ 113 NULL /*pszAsUser*/, NULL /* pszPassword*/, 114 pProcess); 115 } 116 #else 107 117 /** @todo r=michael This function currently does not work correctly if the arguments 108 118 contain spaces. */ … … 181 191 return rc; 182 192 } 183 193 #endif 194 195 196 static int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine, 197 PRTUTF16 pwszzBlock, STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo) 198 { 199 /* 200 * The following rights are needed in order to use LogonUserW and 201 * CreateProcessAsUserW, so the local policy has to be modified to: 202 * - SE_TCB_NAME = Act as part of the operating system 203 * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object 204 * - SE_INCREASE_QUOTA_NAME 205 * 206 * We may fail here with ERROR_PRIVILEGE_NOT_HELD. 207 */ 208 int rc; 209 DWORD dwErr = NO_ERROR; 210 HANDLE hToken = INVALID_HANDLE_VALUE; 211 BOOL fRc = LogonUserW(pwszUser, 212 NULL, /* lpDomain */ 213 pwszPassword, 214 LOGON32_LOGON_INTERACTIVE, 215 LOGON32_PROVIDER_DEFAULT, 216 &hToken); 217 if (fRc) 218 { 219 fRc = CreateProcessAsUserW(hToken, 220 pwszExec, 221 pwszCmdLine, 222 NULL, /* pProcessAttributes */ 223 NULL, /* pThreadAttributes */ 224 TRUE, /* fInheritHandles */ 225 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */ 226 pwszzBlock, 227 NULL, /* pCurrentDirectory */ 228 pStartupInfo, 229 pProcInfo); 230 if (!fRc) 231 dwErr = GetLastError(); 232 CloseHandle(hToken); 233 } 234 else 235 dwErr = GetLastError(); 236 237 #ifndef IPRT_TARGET_NT4 /* We could dispense with the tediuos dynamic loading here if we wanted. */ 238 /* 239 * If we don't hold enough priviledges to spawn a new process with 240 * different credentials we have to use CreateProcessWithLogonW here. This 241 * API is W2K+ and uses a system service for spawning the process. 242 */ 243 /** @todo Use fFlags to either use this feature or just fail. */ 244 if (dwErr == ERROR_PRIVILEGE_NOT_HELD) 245 { 246 RTLDRMOD hAdvAPI32; 247 rc = RTLdrLoad("Advapi32.dll", &hAdvAPI32); 248 if (RT_SUCCESS(rc)) 249 { 250 /* This may fail on too old (NT4) platforms. */ 251 PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW; 252 rc = RTLdrGetSymbol(hAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW); 253 if (RT_SUCCESS(rc)) 254 { 255 fRc = pfnCreateProcessWithLogonW(pwszUser, 256 NULL, /* lpDomain*/ 257 pwszPassword, 258 1 /*LOGON_WITH_PROFILE*/, /* dwLogonFlags */ 259 pwszExec, 260 pwszCmdLine, 261 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */ 262 pwszzBlock, 263 NULL, /* pCurrentDirectory */ 264 pStartupInfo, 265 pProcInfo); 266 if (fRc) 267 dwErr = NO_ERROR; 268 else 269 dwErr = GetLastError(); 270 } 271 RTLdrClose(hAdvAPI32); 272 } 273 } 274 #endif 275 276 if (dwErr != NO_ERROR) 277 rc = RTErrConvertFromWin32(dwErr); 278 else 279 rc = VINF_SUCCESS; 280 return rc; 281 } 184 282 185 283 RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags, … … 299 397 PROCESS_INFORMATION ProcInfo; 300 398 RT_ZERO(ProcInfo); 301 BOOL fRc;302 399 if (pszAsUser == NULL) 303 fRc = CreateProcessW(pwszExec, 304 pwszCmdLine, 305 NULL, /* pProcessAttributes */ 306 NULL, /* pThreadAttributes */ 307 TRUE, /* fInheritHandles */ 308 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */ 309 pwszzBlock, 310 NULL, /* pCurrentDirectory */ 311 &StartupInfo, 312 &ProcInfo); 400 { 401 if (CreateProcessW(pwszExec, 402 pwszCmdLine, 403 NULL, /* pProcessAttributes */ 404 NULL, /* pThreadAttributes */ 405 TRUE, /* fInheritHandles */ 406 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */ 407 pwszzBlock, 408 NULL, /* pCurrentDirectory */ 409 &StartupInfo, 410 &ProcInfo)) 411 rc = VINF_SUCCESS; 412 else 413 rc = RTErrConvertFromWin32(GetLastError()); 414 } 313 415 else 314 416 { 315 HANDLE hToken = INVALID_HANDLE_VALUE; 417 /* 418 * Convert the additional parameters and use a helper 419 * function to do the actual work. 420 */ 316 421 PRTUTF16 pwszUser; 317 318 422 rc = RTStrToUtf16(pszAsUser, &pwszUser); 319 423 if (RT_SUCCESS(rc)) 320 424 { 321 425 PRTUTF16 pwszPassword; 322 rc = RTStrToUtf16(pszPassword , &pwszPassword);426 rc = RTStrToUtf16(pszPassword ? pszPassword : "", &pwszPassword); 323 427 if (RT_SUCCESS(rc)) 324 428 { 325 /* 326 * User needs to be specified in UPN format because we 327 * don't fill a domain name. 328 */ 329 330 /* 331 * The following rights are needed in order to use 332 * LogonUserW and CreateProcessAsUserW, 333 * so the local policy has to be modified to: 334 * - SE_TCB_NAME = Act as part of the operating system 335 * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object 336 * - SE_INCREASE_QUOTA_NAME 337 */ 338 fRc = LogonUserW(pwszUser, 339 NULL, /* lpDomain */ 340 pszPassword ? pwszPassword : L"", 341 LOGON32_LOGON_INTERACTIVE, 342 LOGON32_PROVIDER_DEFAULT, 343 &hToken); 344 /** @todo Add SecureZeroMemory() here for wiping the password? */ 345 if (fRc) 346 { 347 fRc = CreateProcessAsUserW(hToken, 348 pwszExec, 349 pwszCmdLine, 350 NULL, /* pProcessAttributes */ 351 NULL, /* pThreadAttributes */ 352 TRUE, /* fInheritHandles */ 353 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */ 354 pwszzBlock, 355 NULL, /* pCurrentDirectory */ 356 &StartupInfo, 357 &ProcInfo); 358 CloseHandle(hToken); 359 } 360 361 /* If call above failed (ERROR_PRIVILEGE_NOT_HELD or else, might happen on W2K), 362 * try a newer method. */ 363 if (!fRc) 364 { 365 DWORD dwErr = GetLastError(); 366 367 /* 368 * If we don't hold enough priviledges to spawn a new 369 * process with different credentials we have to use 370 * CreateProcessWithLogonW here. 371 * 372 * Note that NT4 does *not* support this API, thus we have 373 * to load it dynamically (W2K+) to not blow up things. 374 * 375 * @todo Use fFlags to either use this feature or just fail. 376 */ 377 if (ERROR_PRIVILEGE_NOT_HELD == dwErr) 378 { 379 RTLDRMOD modAdvAPI32; 380 rc = RTLdrLoad("Advapi32.dll", &modAdvAPI32); 381 PCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW; 382 if (RT_SUCCESS(rc)) 383 { 384 /* This may fail on too old (NT4) platforms. */ 385 rc = RTLdrGetSymbol(modAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW); 386 if (RT_SUCCESS(rc)) 387 { 388 fRc = pfnCreateProcessWithLogonW(pwszUser, 389 NULL, /* lpDomain*/ 390 pwszPassword, 391 1 /*LOGON_WITH_PROFILE*/, /* dwLogonFlags */ 392 pwszExec, 393 pwszCmdLine, 394 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */ 395 pwszzBlock, 396 NULL, /* pCurrentDirectory */ 397 &StartupInfo, 398 &ProcInfo); 399 } 400 RTLdrClose(modAdvAPI32); 401 } 402 } 403 } 429 rc = rtProcCreateAsUserHlp(pwszUser, pwszPassword, 430 pwszExec, pwszCmdLine, pwszzBlock, 431 &StartupInfo, &ProcInfo); 432 404 433 RTUtf16Free(pwszPassword); 405 434 } … … 407 436 } 408 437 } 409 410 if (fRc) 438 if (RT_SUCCESS(rc)) 411 439 { 412 440 CloseHandle(ProcInfo.hThread); … … 420 448 rc = VINF_SUCCESS; 421 449 } 422 else423 rc = RTErrConvertFromWin32(GetLastError());424 450 RTUtf16Free(pwszExec); 425 451 }
Note:
See TracChangeset
for help on using the changeset viewer.