Changeset 59367 in vbox for trunk/src/VBox/Main/src-all/win
- Timestamp:
- Jan 17, 2016 5:45:36 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 105055
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-all/win/VBoxProxyStub.c
r59363 r59367 24 24 *********************************************************************************************************************************/ 25 25 #define PROXY_DELEGATION /* see generated dlldata.c */ 26 #include <iprt/nt/nt-and-windows.h> 26 27 #include <rpcproxy.h> 27 #include <Windows.h>28 28 #include <Shlwapi.h> 29 29 #include <stdio.h> 30 30 31 31 #include "VirtualBox.h" 32 #include <iprt/alloca.h> 32 33 #include <iprt/assert.h> 33 34 #include <iprt/path.h> 34 35 #include <iprt/string.h> 36 #include <iprt/uuid.h> 35 37 36 38 … … 42 44 #if 1 /*defined(DEBUG) && !defined(VBOX_IN_32_ON_64_MAIN_API) - needed on testboxes (and obviously dev boxes)! */ 43 45 # define WITH_MANUAL_CLEANUP 46 #endif 47 48 #ifdef DEBUG_bird 49 # define VBSP_LOG_ENABLED 50 #endif 51 52 #ifdef VBSP_LOG_ENABLED 53 # define VBSP_LOG_VALUE_CHANGE(a) RTAssertMsg2 a 54 #else 55 # define VBSP_LOG_VALUE_CHANGE(a) do { } while (0) 56 #endif 57 58 #ifdef VBSP_LOG_ENABLED 59 # define VBSP_LOG_SET_VALUE(a) RTAssertMsg2 a 60 #else 61 # define VBSP_LOG_SET_VALUE(a) do { } while (0) 62 #endif 63 64 #ifdef VBSP_LOG_ENABLED 65 # define VBSP_LOG_NEW_KEY(a) RTAssertMsg2 a 66 #else 67 # define VBSP_LOG_NEW_KEY(a) do { } while (0) 44 68 #endif 45 69 … … 117 141 { 118 142 case DLL_PROCESS_ATTACH: 143 /* Save the DLL handle so we can get the path to this DLL during 144 registration and updating. */ 119 145 g_hDllSelf = hInstance; 146 147 /* We don't need callbacks for thread creation and destruction. */ 120 148 DisableThreadLibraryCalls(hInstance); 149 121 150 /* We don't use IPRT, so no need to init it! */ 122 151 break; … … 138 167 *ppapInfo = &g_apProxyFiles[0]; 139 168 *ppClsid = &g_ProxyClsId; 140 } ;169 } 141 170 142 171 … … 219 248 220 249 250 #ifdef VBSP_LOG_ENABLED 251 # include <iprt/asm.h> 252 253 /** For logging full key names. */ 254 static PCRTUTF16 vbpsDebugKeyToWSZ(HKEY hKey) 255 { 256 static union 257 { 258 KEY_NAME_INFORMATION NameInfo; 259 WCHAR awchPadding[260]; 260 } s_aBufs[4]; 261 static uint32_t volatile iNext = 0; 262 uint32_t i = ASMAtomicIncU32(&iNext) % RT_ELEMENTS(s_aBufs); 263 ULONG cbRet = 0; 264 NTSTATUS rcNt; 265 266 memset(&s_aBufs[i], 0, sizeof(s_aBufs[i])); 267 rcNt = NtQueryKey(hKey, KeyNameInformation, &s_aBufs[i], sizeof(s_aBufs[i]) - sizeof(WCHAR), &cbRet); 268 if (!NT_SUCCESS(rcNt)) 269 s_aBufs[i].NameInfo.NameLength = 0; 270 s_aBufs[i].NameInfo.Name[s_aBufs[i].NameInfo.NameLength] = '\0'; 271 return s_aBufs[i].NameInfo.Name; 272 } 273 #endif 274 221 275 /** 222 276 * Registry modifier state. … … 228 282 /** The handle to the CLSID key under hkeyClassesRootDst. */ 229 283 HKEY hkeyClsidRootDst; 230 /** For logging purposes. */ 231 const char *pszLogRoot; 232 233 /** Alternative location where duplicates must always be unregistered from. */ 234 HKEY hkeyAltClassesRootsUnreg; 235 /** The handle to the CLSID key under hkeyAltClassesRootsUnreg. */ 236 HKEY hkeyAltClsidRootsUnreg; 284 /** The handle to the Interface key under hkeyClassesRootDst. */ 285 HKEY hkeyInterfaceRootDst; 286 287 /** Alternative locations where data needs to be deleted, but never updated. */ 288 struct 289 { 290 /** The classes root key handle. */ 291 HKEY hkeyClasses; 292 /** The classes/CLSID key handle. */ 293 HKEY hkeyClsid; 294 /** The classes/Interface key handle. */ 295 HKEY hkeyInterface; 296 } aAltDeletes[3]; 297 /** Alternative delete locations. */ 298 uint32_t cAltDeletes; 237 299 238 300 /** The current total result. */ … … 242 304 * almost the work from one process (at least W7+ due to aliases). */ 243 305 DWORD fSamWow; 244 /** Desired key Access when only unregistring. */ 245 DWORD fSamUnreg; 246 /** Desired key Access when both unregistring and registering. */ 306 /** Desired key access when only deleting. */ 307 DWORD fSamDelete; 308 /** Desired key access when only doing updates. */ 309 DWORD fSamUpdate; 310 /** Desired key access when both deleting and updating. */ 247 311 DWORD fSamBoth; 248 /** Set if we're only unregistering. */ 249 bool fUnregisterOnly; 312 /** Whether to delete registrations first. */ 313 bool fDelete; 314 /** Whether to update registry value and keys. */ 315 bool fUpdate; 316 250 317 } VBPSREGSTATE; 251 318 … … 261 328 * @param pszSubRoot The path to the where the classes are registered, 262 329 * NULL if @a hkeyRoot. 263 * @param pszLogRoot For error logging/debugging?264 330 * @param hkeyAltRoot The registry root tree constant for the alternative 265 331 * registrations (remove only). 266 332 * @param pszAltSubRoot The path to where classes could also be registered, 267 333 * but shouldn't be in our setup. 268 * @param fUnregisterOnly If true, only unregister. If false, also register. 334 * @param fDelete Whether to delete registrations first. 335 * @param fUpdate Whether to update registrations. 269 336 * @param fSamWow KEY_WOW64_32KEY or 0. 270 337 */ 271 static LSTATUS vbpsRegInit(VBPSREGSTATE *pState, HKEY hkeyRoot, const char *pszSubRoot, const char *pszLogRoot, 272 HKEY hkeyAltRoot, const char *pszAltSubRoot, bool fUnregisterOnly, DWORD fSamWow) 338 static LSTATUS vbpsRegInit(VBPSREGSTATE *pState, HKEY hkeyRoot, const char *pszSubRoot, bool fDelete, bool fUpdate, DWORD fSamWow) 273 339 { 274 340 LSTATUS rc; 275 REGSAM fAccess = !fUnregisterOnly 276 ? DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY 277 : DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE; 278 341 unsigned i = 0; 342 343 /* 344 * Initialize the whole structure first so we can safely call vbpsRegTerm on failure. 345 */ 279 346 pState->hkeyClassesRootDst = NULL; 280 347 pState->hkeyClsidRootDst = NULL; 281 pState->pszLogRoot = pszLogRoot; 282 pState->hkeyAltClassesRootsUnreg = NULL; 283 pState->hkeyAltClsidRootsUnreg = NULL; 284 pState->fUnregisterOnly = fUnregisterOnly; 348 pState->hkeyInterfaceRootDst = NULL; 349 for (i = 0; i < RT_ELEMENTS(pState->aAltDeletes); i++) 350 { 351 pState->aAltDeletes[i].hkeyClasses = NULL; 352 pState->aAltDeletes[i].hkeyClsid = NULL; 353 pState->aAltDeletes[i].hkeyInterface = NULL; 354 } 355 pState->cAltDeletes = 0; 356 pState->rc = ERROR_SUCCESS; 357 pState->fDelete = fDelete; 358 pState->fUpdate = fUpdate; 285 359 pState->fSamWow = fSamWow; 286 pState->fSamUnreg = pState->fSamWow | DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE; 287 pState->fSamBoth = pState->fSamUnreg | (!fUnregisterOnly ? KEY_SET_VALUE | KEY_CREATE_SUB_KEY : 0); 288 pState->rc = ERROR_SUCCESS; 289 360 pState->fSamDelete = 0; 361 if (fDelete) 362 pState->fSamDelete = pState->fSamWow | DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE 363 | STANDARD_RIGHTS_READ | STANDARD_RIGHTS_WRITE; 364 pState->fSamUpdate = 0; 365 if (fUpdate) 366 pState->fSamUpdate = pState->fSamWow | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY 367 | STANDARD_RIGHTS_READ | STANDARD_RIGHTS_WRITE; 368 pState->fSamBoth = pState->fSamDelete | pState->fSamUpdate; 369 370 /* 371 * Open the root keys. 372 */ 290 373 rc = RegOpenKeyExA(hkeyRoot, pszSubRoot, 0 /*fOptions*/, pState->fSamBoth, &pState->hkeyClassesRootDst); 291 374 AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 292 375 rc = RegOpenKeyExA(pState->hkeyClassesRootDst, "CLSID", 0 /*fOptions*/, pState->fSamBoth, &pState->hkeyClsidRootDst); 293 376 AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 294 if (hkeyAltRoot) 295 { 296 rc = RegOpenKeyExA(hkeyAltRoot, pszAltSubRoot, 0 /*fOptions*/, pState->fSamUnreg, &pState->hkeyAltClassesRootsUnreg); 297 AssertMsgReturn(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 298 if (pState->hkeyAltClassesRootsUnreg) 299 { 300 rc = RegOpenKeyExA(pState->hkeyAltClassesRootsUnreg, "CLSID", 0 /*fOptions*/, pState->fSamUnreg, 301 &pState->hkeyAltClsidRootsUnreg); 302 AssertMsgReturn(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 303 } 304 } 377 305 378 return ERROR_SUCCESS; 306 379 } … … 327 400 pState->hkeyClsidRootDst = NULL; 328 401 } 329 if (pState->hkey AltClassesRootsUnreg)330 { 331 rc = RegCloseKey(pState->hkey AltClassesRootsUnreg);402 if (pState->hkeyInterfaceRootDst) 403 { 404 rc = RegCloseKey(pState->hkeyInterfaceRootDst); 332 405 Assert(rc == ERROR_SUCCESS); 333 pState->hkeyAltClassesRootsUnreg = NULL; 334 } 335 if (pState->hkeyAltClsidRootsUnreg) 336 { 337 rc = RegCloseKey(pState->hkeyAltClsidRootsUnreg); 338 Assert(rc == ERROR_SUCCESS); 339 pState->hkeyAltClsidRootsUnreg = NULL; 340 } 406 pState->hkeyInterfaceRootDst = NULL; 407 } 408 409 while (pState->cAltDeletes > 0 && pState->cAltDeletes <= RT_ELEMENTS(pState->aAltDeletes)) 410 { 411 unsigned i = --pState->cAltDeletes; 412 if (pState->aAltDeletes[i].hkeyClasses) 413 { 414 rc = RegCloseKey(pState->aAltDeletes[i].hkeyClasses); 415 Assert(rc == ERROR_SUCCESS); 416 pState->aAltDeletes[i].hkeyClasses = NULL; 417 } 418 if (pState->aAltDeletes[i].hkeyClsid) 419 { 420 rc = RegCloseKey(pState->aAltDeletes[i].hkeyClsid); 421 Assert(rc == ERROR_SUCCESS); 422 pState->aAltDeletes[i].hkeyClsid = NULL; 423 } 424 if (pState->aAltDeletes[i].hkeyInterface) 425 { 426 rc = RegCloseKey(pState->aAltDeletes[i].hkeyInterface); 427 Assert(rc == ERROR_SUCCESS); 428 pState->aAltDeletes[i].hkeyInterface = NULL; 429 } 430 } 431 } 432 433 434 /** 435 * Add an alternative registry classes tree from which to remove keys. 436 * 437 * @returns ERROR_SUCCESS if we successfully opened the destination root, other 438 * wise windows error code (remebered). 439 * @param pState The registry modifier state. 440 * @param hkeyAltRoot The root of the alternate registry classes 441 * location. 442 * @param pszAltSubRoot The path to the 'classes' sub-key, or NULL if 443 * hkeyAltRoot is it. 444 */ 445 static LSTATUS vbpsRegAddAltDelete(VBPSREGSTATE *pState, HKEY hkeyAltRoot, const char *pszAltSubRoot) 446 { 447 unsigned i; 448 LSTATUS rc; 449 450 /* Ignore call if not in delete mode. */ 451 if (!pState->fDelete) 452 return ERROR_SUCCESS; 453 454 /* Check that there is space in the state. */ 455 i = pState->cAltDeletes; 456 AssertReturn(i < RT_ELEMENTS(pState->aAltDeletes), pState->rc = ERROR_TOO_MANY_NAMES); 457 458 459 /* Open the root. */ 460 rc = RegOpenKeyExA(hkeyAltRoot, pszAltSubRoot, 0 /*fOptions*/, pState->fSamDelete, 461 &pState->aAltDeletes[i].hkeyClasses); 462 if (rc == ERROR_SUCCESS) 463 { 464 /* Try open the CLSID subkey, it's fine if it doesn't exists. */ 465 rc = RegOpenKeyExA(pState->aAltDeletes[i].hkeyClasses, "CLSID", 0 /*fOptions*/, pState->fSamDelete, 466 &pState->aAltDeletes[i].hkeyClsid); 467 if (rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND) 468 { 469 if (rc == ERROR_FILE_NOT_FOUND) 470 pState->aAltDeletes[i].hkeyClsid = NULL; 471 pState->cAltDeletes = i + 1; 472 return ERROR_SUCCESS; 473 } 474 AssertMsgFailed(("%u\n", rc)); 475 RegCloseKey(pState->aAltDeletes[i].hkeyClasses); 476 } 477 /* No need to add non-existing alternative roots, nothing to delete in the void. */ 478 else if (rc == ERROR_FILE_NOT_FOUND) 479 rc = ERROR_SUCCESS; 480 else 481 { 482 AssertMsgFailed(("%u\n", rc)); 483 pState->rc = rc; 484 } 485 486 pState->aAltDeletes[i].hkeyClasses = NULL; 487 pState->aAltDeletes[i].hkeyClsid = NULL; 488 return rc; 489 } 490 491 492 /** 493 * Open the 'Interface' keys under the current classes roots. 494 * 495 * We don't do this during vbpsRegInit as it's only needed for updating. 496 * 497 * @returns ERROR_SUCCESS if we successfully opened the destination root, other 498 * wise windows error code (remebered). 499 * @param pState The registry modifier state. 500 */ 501 static LSTATUS vbpsRegOpenInterfaceKeys(VBPSREGSTATE *pState) 502 { 503 unsigned i; 504 LSTATUS rc; 505 506 /* 507 * Under the root destination. 508 */ 509 if (pState->hkeyInterfaceRootDst == NULL) 510 { 511 rc = RegOpenKeyExA(pState->hkeyClassesRootDst, "Interface", 0 /*fOptions*/, pState->fSamBoth, &pState->hkeyInterfaceRootDst); 512 AssertMsgReturnStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->hkeyInterfaceRootDst = NULL, pState->rc = rc); 513 } 514 515 /* 516 * Under the alternative delete locations. 517 */ 518 i = pState->cAltDeletes; 519 while (i-- > 0) 520 if (pState->aAltDeletes[i].hkeyInterface == NULL) 521 { 522 rc = RegOpenKeyExA(pState->aAltDeletes[i].hkeyClasses, "Interface", 0 /*fOptions*/, pState->fSamDelete, 523 &pState->aAltDeletes[i].hkeyInterface); 524 if (rc != ERROR_SUCCESS) 525 { 526 AssertMsgStmt(rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 527 pState->aAltDeletes[i].hkeyInterface = NULL; 528 } 529 } 530 531 return ERROR_SUCCESS; 341 532 } 342 533 343 534 344 535 /** The destination buffer size required by vbpsFormatUuidInCurly. */ 345 #define CURLY_UUID_STR_BUF_SIZE 4 8536 #define CURLY_UUID_STR_BUF_SIZE 40 346 537 347 538 /** 348 539 * Formats a UUID to a string, inside curly braces. 349 540 * 350 * @returns ERROR_SUCCESS on success, otherwise windows error code. 351 * @param pszUuid Output buffer of size CURLY_UUID_STR_BUF_SIZE. 352 * @param pUuid The UUID to format. 353 */ 354 static LSTATUS vbpsFormatUuidInCurly(char *pszUuid, const CLSID *pUuid) 355 { 356 unsigned char *pszTmpStr = NULL; 357 size_t cchTmpStr; 358 RPC_STATUS rc = UuidToStringA((UUID *)pUuid, &pszTmpStr); 359 AssertReturnStmt(rc == RPC_S_OK, *pszUuid = '\0', ERROR_OUTOFMEMORY); 360 361 cchTmpStr = strlen((const char *)pszTmpStr); 362 AssertReturnStmt(cchTmpStr == 36 && cchTmpStr < CURLY_UUID_STR_BUF_SIZE - 3, RpcStringFreeA(&pszTmpStr), ERROR_INVALID_DATA); 363 364 pszUuid[0] = '{'; 365 memcpy(pszUuid + 1, pszTmpStr, cchTmpStr); 366 pszUuid[1 + cchTmpStr] = '}'; 367 pszUuid[1 + cchTmpStr + 1] = '\0'; 368 369 RpcStringFreeA(&pszTmpStr); 370 return ERROR_SUCCESS; 371 } 372 373 374 /** 375 * Sets a registry string value. 541 * @returns @a pszString 542 * @param pszString Output buffer of size CURLY_UUID_STR_BUF_SIZE. 543 * @param pUuidIn The UUID to format. 544 */ 545 static const char *vbpsFormatUuidInCurly(char pszString[CURLY_UUID_STR_BUF_SIZE], const CLSID *pUuidIn) 546 { 547 static const char s_achDigits[17] = "0123456789abcdef"; 548 PCRTUUID pUuid = (PCRTUUID)pUuidIn; 549 uint32_t u32TimeLow; 550 unsigned u; 551 552 pszString[ 0] = '{'; 553 u32TimeLow = RT_H2LE_U32(pUuid->Gen.u32TimeLow); 554 pszString[ 1] = s_achDigits[(u32TimeLow >> 28)/*& 0xf*/]; 555 pszString[ 2] = s_achDigits[(u32TimeLow >> 24) & 0xf]; 556 pszString[ 3] = s_achDigits[(u32TimeLow >> 20) & 0xf]; 557 pszString[ 4] = s_achDigits[(u32TimeLow >> 16) & 0xf]; 558 pszString[ 5] = s_achDigits[(u32TimeLow >> 12) & 0xf]; 559 pszString[ 6] = s_achDigits[(u32TimeLow >> 8) & 0xf]; 560 pszString[ 7] = s_achDigits[(u32TimeLow >> 4) & 0xf]; 561 pszString[ 8] = s_achDigits[(u32TimeLow/*>>0*/)& 0xf]; 562 pszString[ 9] = '-'; 563 u = RT_H2LE_U16(pUuid->Gen.u16TimeMid); 564 pszString[10] = s_achDigits[(u >> 12)/*& 0xf*/]; 565 pszString[11] = s_achDigits[(u >> 8) & 0xf]; 566 pszString[12] = s_achDigits[(u >> 4) & 0xf]; 567 pszString[13] = s_achDigits[(u/*>>0*/)& 0xf]; 568 pszString[14] = '-'; 569 u = RT_H2LE_U16(pUuid->Gen.u16TimeHiAndVersion); 570 pszString[15] = s_achDigits[(u >> 12)/*& 0xf*/]; 571 pszString[16] = s_achDigits[(u >> 8) & 0xf]; 572 pszString[17] = s_achDigits[(u >> 4) & 0xf]; 573 pszString[18] = s_achDigits[(u/*>>0*/)& 0xf]; 574 pszString[19] = '-'; 575 pszString[20] = s_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved >> 4]; 576 pszString[21] = s_achDigits[pUuid->Gen.u8ClockSeqHiAndReserved & 0xf]; 577 pszString[22] = s_achDigits[pUuid->Gen.u8ClockSeqLow >> 4]; 578 pszString[23] = s_achDigits[pUuid->Gen.u8ClockSeqLow & 0xf]; 579 pszString[24] = '-'; 580 pszString[25] = s_achDigits[pUuid->Gen.au8Node[0] >> 4]; 581 pszString[26] = s_achDigits[pUuid->Gen.au8Node[0] & 0xf]; 582 pszString[27] = s_achDigits[pUuid->Gen.au8Node[1] >> 4]; 583 pszString[28] = s_achDigits[pUuid->Gen.au8Node[1] & 0xf]; 584 pszString[29] = s_achDigits[pUuid->Gen.au8Node[2] >> 4]; 585 pszString[30] = s_achDigits[pUuid->Gen.au8Node[2] & 0xf]; 586 pszString[31] = s_achDigits[pUuid->Gen.au8Node[3] >> 4]; 587 pszString[32] = s_achDigits[pUuid->Gen.au8Node[3] & 0xf]; 588 pszString[33] = s_achDigits[pUuid->Gen.au8Node[4] >> 4]; 589 pszString[34] = s_achDigits[pUuid->Gen.au8Node[4] & 0xf]; 590 pszString[35] = s_achDigits[pUuid->Gen.au8Node[5] >> 4]; 591 pszString[36] = s_achDigits[pUuid->Gen.au8Node[5] & 0xf]; 592 pszString[37] = '}'; 593 pszString[38] = '\0'; 594 595 return pszString; 596 597 } 598 599 600 /** 601 * Sets a registry string value, wide char variant. 376 602 * 377 603 * @returns See RegSetValueExA (errors are remembered in the state). 378 604 * @param pState The registry modifier state. 379 * @param hKey The key to add the value to. 605 * @param hkey The key to add the value to. 606 * @param pwszValueNm The value name. NULL for setting the default. 607 * @param pwszValue The value string. 608 * @param uLine The line we're called from. 609 */ 610 static LSTATUS vbpsSetRegValueWW(VBPSREGSTATE *pState, HKEY hkey, PCRTUTF16 pwszValueNm, PCRTUTF16 pwszValue, unsigned uLine) 611 { 612 DWORD const cbValue = (DWORD)((RTUtf16Len(pwszValue) + 1) * sizeof(RTUTF16)); 613 LSTATUS rc; 614 Assert(pState->fUpdate); 615 616 /* 617 * If we're not deleting the key prior to updating, we're in gentle update 618 * mode where we will query if the existing value matches the incoming one. 619 */ 620 if (!pState->fDelete) 621 { 622 DWORD cbExistingData = cbValue + 128; 623 PRTUTF16 pwszExistingData = (PRTUTF16)alloca(cbExistingData); 624 DWORD dwExistingType; 625 rc = RegQueryValueExW(hkey, pwszValueNm, 0 /*Reserved*/, &dwExistingType, (BYTE *)pwszExistingData, &cbExistingData); 626 if (rc == ERROR_SUCCESS) 627 { 628 if ( dwExistingType == REG_SZ 629 && cbExistingData == cbValue) 630 { 631 if (memcmp(pwszValue, pwszExistingData, cbValue) == 0) 632 return ERROR_SUCCESS; 633 } 634 VBSP_LOG_VALUE_CHANGE(("vbpsSetRegValueWW: Value difference: dwExistingType=%d cbExistingData=%#x cbValue=%#x\n" 635 " hkey=%#x %ls; value name=%ls\n" 636 "existing: %.*Rhxs (%.*ls)\n" 637 " new: %.*Rhxs (%ls)\n", 638 dwExistingType, cbExistingData, cbValue, 639 hkey, vbpsDebugKeyToWSZ(hkey), pwszValueNm ? pwszValueNm : L"(default)", 640 cbExistingData, pwszExistingData, cbExistingData / sizeof(RTUTF16), pwszExistingData, 641 cbValue, pwszValue, pwszValue)); 642 } 643 else 644 Assert(rc == ERROR_FILE_NOT_FOUND || rc == ERROR_MORE_DATA); 645 } 646 647 /* 648 * Set the value. 649 */ 650 rc = RegSetValueExW(hkey, pwszValueNm, 0 /*Reserved*/, REG_SZ, (const BYTE *)pwszValue, cbValue); 651 if (rc == ERROR_SUCCESS) 652 { 653 VBSP_LOG_SET_VALUE(("vbpsSetRegValueWW: %ls/%ls=%ls (at %d)\n", 654 vbpsDebugKeyToWSZ(hkey), pwszValueNm ? pwszValueNm : L"(Default)", pwszValue, uLine)); 655 return ERROR_SUCCESS; 656 } 657 658 AssertMsgFailed(("%d: '%ls'='%ls' -> %u\n", uLine, pwszValueNm, pwszValue, rc)); 659 pState->rc = rc; 660 return rc; 661 } 662 663 664 /** 665 * Sets a registry string value. 666 * 667 * @returns See RegSetValueExA (errors are remembered in the state). 668 * @param pState The registry modifier state. 669 * @param hkey The key to add the value to. 380 670 * @param pszValueNm The value name. NULL for setting the default. 381 671 * @param pszValue The value string. 382 672 * @param uLine The line we're called from. 383 673 */ 384 static LSTATUS vbpsSetRegValueAA(VBPSREGSTATE *pState, HKEY hKey, const char *pszValueNm, const char *pszValue, unsigned uLine) 385 { 386 LSTATUS rc = RegSetValueExA(hKey, pszValueNm, 0 /*Reserved*/, REG_SZ, pszValue, (DWORD)strlen(pszValue) + 1); 674 static LSTATUS vbpsSetRegValueAA(VBPSREGSTATE *pState, HKEY hkey, const char *pszValueNm, const char *pszValue, unsigned uLine) 675 { 676 DWORD const cbValue = (DWORD)strlen(pszValue) + 1; 677 LSTATUS rc; 678 Assert(pState->fUpdate); 679 680 /* 681 * If we're not deleting the key prior to updating, we're in gentle update 682 * mode where we will query if the existing value matches the incoming one. 683 */ 684 if (!pState->fDelete) 685 { 686 DWORD cbExistingData = cbValue + 128; 687 char *pszExistingData = alloca(cbExistingData); 688 DWORD dwExistingType; 689 rc = RegQueryValueExA(hkey, pszValueNm, 0 /*Reserved*/, &dwExistingType, pszExistingData, &cbExistingData); 690 if (rc == ERROR_SUCCESS) 691 { 692 if ( dwExistingType == REG_SZ 693 && cbExistingData == cbValue) 694 { 695 if (memcmp(pszValue, pszExistingData, cbValue) == 0) 696 return ERROR_SUCCESS; 697 if (memicmp(pszValue, pszExistingData, cbValue) == 0) 698 return ERROR_SUCCESS; 699 } 700 VBSP_LOG_VALUE_CHANGE(("vbpsSetRegValueAA: Value difference: dwExistingType=%d cbExistingData=%#x cbValue=%#x\n" 701 " hkey=%#x %ls; value name=%s\n" 702 "existing: %.*Rhxs (%.*s)\n" 703 " new: %.*Rhxs (%s)\n", 704 dwExistingType, cbExistingData, cbValue, 705 hkey, vbpsDebugKeyToWSZ(hkey), pszValueNm ? pszValueNm : "(default)", 706 cbExistingData, pszExistingData, cbExistingData, pszExistingData, 707 cbValue, pszValue, pszValue)); 708 } 709 else 710 Assert(rc == ERROR_FILE_NOT_FOUND || rc == ERROR_MORE_DATA); 711 } 712 713 /* 714 * Set the value. 715 */ 716 rc = RegSetValueExA(hkey, pszValueNm, 0 /*Reserved*/, REG_SZ, pszValue, cbValue); 717 if (rc == ERROR_SUCCESS) 718 { 719 VBSP_LOG_SET_VALUE(("vbpsSetRegValueAA: %ls/%s=%s (at %d)\n", 720 vbpsDebugKeyToWSZ(hkey), pszValueNm ? pszValueNm : "(Default)", pszValue, uLine)); 721 return ERROR_SUCCESS; 722 } 723 724 AssertMsgFailed(("%d: '%s'='%s' -> %u\n", uLine, pszValueNm, pszValue, rc)); 725 pState->rc = rc; 726 return rc; 727 } 728 729 730 /** 731 * Closes a registry key. 732 * 733 * @returns See RegCloseKey (errors are remembered in the state). 734 * @param pState The registry modifier state. 735 * @param hkey The key to close. 736 * @param uLine The line we're called from. 737 */ 738 static LSTATUS vbpsCloseKey(VBPSREGSTATE *pState, HKEY hkey, unsigned uLine) 739 { 740 LSTATUS rc = RegCloseKey(hkey); 387 741 if (rc == ERROR_SUCCESS) 388 742 return ERROR_SUCCESS; 389 AssertMsgFailed(("%d: '%s'='%s' -> %u\n", uLine, pszValueNm, pszValue, rc)); 390 return pState->rc = rc; 391 } 743 744 AssertMsgFailed(("%d: close key -> %u\n", uLine, rc)); 745 pState->rc = rc; 746 return rc; 747 } 748 392 749 393 750 /** … … 397 754 * state). 398 755 * @param pState The registry modifier state. 399 * @param h KeyParent The parent key.400 * @param pszKey The new key under @a h KeyParent.401 * @param ph Key Where to return the handle to the new key.756 * @param hkeyParent The parent key. 757 * @param pszKey The new key under @a hkeyParent. 758 * @param phkey Where to return the handle to the new key. 402 759 * @param uLine The line we're called from. 403 760 */ 404 static LSTATUS vbpsCreateRegKeyA(VBPSREGSTATE *pState, HKEY hKeyParent, const char *pszKey, PHKEY phKey, unsigned uLine) 405 { 761 static LSTATUS vbpsCreateRegKeyA(VBPSREGSTATE *pState, HKEY hkeyParent, const char *pszKey, PHKEY phkey, unsigned uLine) 762 { 763 /* 764 * This will open if it exists and create if new, which is exactly what we want. 765 */ 406 766 HKEY hNewKey; 407 LSTATUS rc = RegCreateKeyExA(hKeyParent, pszKey, 0 /*Reserved*/, NULL /*pszClass*/, 0 /*fOptions*/, 408 pState->fSamBoth, NULL /*pSecAttr*/, &hNewKey, NULL /*pdwDisposition*/); 767 DWORD dwDisposition = 0; 768 LSTATUS rc = RegCreateKeyExA(hkeyParent, pszKey, 0 /*Reserved*/, NULL /*pszClass*/, 0 /*fOptions*/, 769 pState->fSamBoth, NULL /*pSecAttr*/, &hNewKey, &dwDisposition); 409 770 if (rc == ERROR_SUCCESS) 410 *phKey = hNewKey; 771 { 772 *phkey = hNewKey; 773 if (dwDisposition == REG_CREATED_NEW_KEY) 774 VBSP_LOG_NEW_KEY(("vbpsCreateRegKeyA: %ls/%s (at %d)\n", vbpsDebugKeyToWSZ(hkeyParent), pszKey, uLine)); 775 } 411 776 else 412 777 { 413 778 AssertMsgFailed(("%d: create key '%s' -> %u\n", uLine, pszKey, rc)); 414 779 pState->rc = rc; 415 *ph Key = NULL;780 *phkey = NULL; 416 781 } 417 782 return rc; … … 425 790 * state). 426 791 * @param pState The registry modifier state. 427 * @param h KeyParent The parent key.428 * @param pszKey The new key under @a h KeyParent.792 * @param hkeyParent The parent key. 793 * @param pszKey The new key under @a hkeyParent. 429 794 * @param pszValue The value string. 430 795 * @param uLine The line we're called from. 431 796 */ 432 static LSTATUS vbpsCreateRegKeyWithDefaultValueAA(VBPSREGSTATE *pState, HKEY h KeyParent, const char *pszKey,797 static LSTATUS vbpsCreateRegKeyWithDefaultValueAA(VBPSREGSTATE *pState, HKEY hkeyParent, const char *pszKey, 433 798 const char *pszValue, unsigned uLine) 434 799 { 435 800 HKEY hNewKey; 436 LSTATUS rc = vbpsCreateRegKeyA(pState, h KeyParent, pszKey, &hNewKey, uLine);801 LSTATUS rc = vbpsCreateRegKeyA(pState, hkeyParent, pszKey, &hNewKey, uLine); 437 802 if (rc == ERROR_SUCCESS) 438 803 { 439 804 rc = vbpsSetRegValueAA(pState, hNewKey, NULL /*pszValueNm*/, pszValue, uLine); 440 RegCloseKey(hNewKey);805 vbpsCloseKey(pState, hNewKey, uLine); 441 806 } 442 807 else … … 450 815 451 816 /** 452 * Creates a registry key with a default string value, return the key.817 * Creates a registry key with a default wide string value. 453 818 * 454 819 * @returns See RegCreateKeyA and RegSetValueExA (errors are remembered in the 455 820 * state). 456 821 * @param pState The registry modifier state. 457 * @param hKeyParent The parent key. 458 * @param pszKey The new key under @a hKeyParent. 822 * @param hkeyParent The parent key. 823 * @param pszKey The new key under @a hkeyParent. 824 * @param pwszValue The value string. 825 * @param uLine The line we're called from. 826 */ 827 static LSTATUS vbpsCreateRegKeyWithDefaultValueAW(VBPSREGSTATE *pState, HKEY hkeyParent, const char *pszKey, 828 PCRTUTF16 pwszValue, unsigned uLine) 829 { 830 HKEY hNewKey; 831 LSTATUS rc = vbpsCreateRegKeyA(pState, hkeyParent, pszKey, &hNewKey, uLine); 832 if (rc == ERROR_SUCCESS) 833 { 834 rc = vbpsSetRegValueWW(pState, hNewKey, NULL /*pwszValueNm*/, pwszValue, uLine); 835 vbpsCloseKey(pState, hNewKey, uLine); 836 } 837 else 838 { 839 AssertMsgFailed(("%d: create key '%s'(/Default='%ls') -> %u\n", uLine, pszKey, pwszValue, rc)); 840 pState->rc = rc; 841 } 842 return rc; 843 } 844 845 846 /** 847 * Creates a registry key with a default string value, return the key. 848 * 849 * @returns See RegCreateKeyA and RegSetValueExA (errors are remembered in the 850 * state). 851 * @param pState The registry modifier state. 852 * @param hkeyParent The parent key. 853 * @param pszKey The new key under @a hkeyParent. 459 854 * @param pszValue The value string. 460 * @param ph Key Where to return the handle to the new key.855 * @param phkey Where to return the handle to the new key. 461 856 * @param uLine The line we're called from. 462 857 */ 463 static LSTATUS vbpsCreateRegKeyWithDefaultValueAAEx(VBPSREGSTATE *pState, HKEY h KeyParent, const char *pszKey,464 const char *pszValue, PHKEY ph Key, unsigned uLine)858 static LSTATUS vbpsCreateRegKeyWithDefaultValueAAEx(VBPSREGSTATE *pState, HKEY hkeyParent, const char *pszKey, 859 const char *pszValue, PHKEY phkey, unsigned uLine) 465 860 { 466 861 HKEY hNewKey; 467 LSTATUS rc = vbpsCreateRegKeyA(pState, h KeyParent, pszKey, &hNewKey, uLine);862 LSTATUS rc = vbpsCreateRegKeyA(pState, hkeyParent, pszKey, &hNewKey, uLine); 468 863 if (rc == ERROR_SUCCESS) 469 864 { 470 865 rc = vbpsSetRegValueAA(pState, hNewKey, NULL /*pszValueNm*/, pszValue, uLine); 471 *ph Key = hNewKey;866 *phkey = hNewKey; 472 867 } 473 868 else … … 475 870 AssertMsgFailed(("%d: create key '%s'(/Default='%s') -> %u\n", uLine, pszKey, pszValue, rc)); 476 871 pState->rc = rc; 477 *phKey = NULL; 478 } 872 *phkey = NULL; 873 } 874 return rc; 875 } 876 877 878 /** 879 * Recursively deletes a registry key. 880 * 881 * @returns See SHDeleteKeyA (errors are remembered in the state). 882 * @param pState The registry modifier state. 883 * @param hkeyParent The parent key. 884 * @param pszKey The key under @a hkeyParent that should be 885 * deleted. 886 * @param uLine The line we're called from. 887 */ 888 static LSTATUS vbpsDeleteKeyRecursiveA(VBPSREGSTATE *pState, HKEY hkeyParent, const char *pszKey, unsigned uLine) 889 { 890 LSTATUS rc; 891 892 Assert(pState->fDelete); 893 Assert(pszKey); 894 AssertReturn(*pszKey != '\0', pState->rc = ERROR_INVALID_PARAMETER); 895 896 rc = SHDeleteKeyA(hkeyParent, pszKey); 897 if (rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND) 898 return ERROR_SUCCESS; 899 900 AssertMsgFailed(("%d: delete key '%s' -> %u\n", uLine, pszKey, rc)); 901 pState->rc = rc; 479 902 return rc; 480 903 } … … 495 918 Assert(*pszAppId == '{'); 496 919 497 /* Always unregister. */ 498 if (pState->hkeyAltClassesRootsUnreg) 499 { 500 rc = RegOpenKeyExW(pState->hkeyAltClassesRootsUnreg, L"AppID", 0 /*fOptions*/, pState->fSamUnreg, &hkeyAppIds); 501 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 502 if (rc == ERROR_SUCCESS) 920 /* 921 * Delete. 922 */ 923 if (pState->fDelete) 924 { 925 unsigned i = pState->cAltDeletes; 926 while (i-- > 0) 503 927 { 504 rc = SHDeleteKeyA(hkeyAppIds, pszAppId);928 rc = RegOpenKeyExW(pState->aAltDeletes[i].hkeyClasses, L"AppID", 0 /*fOptions*/, pState->fSamDelete, &hkeyAppIds); 505 929 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 506 RegCloseKey(hkeyAppIds); 930 if (rc == ERROR_SUCCESS) 931 { 932 vbpsDeleteKeyRecursiveA(pState, hkeyAppIds, pszAppId, __LINE__); 933 vbpsCloseKey(pState, hkeyAppIds, __LINE__); 934 } 507 935 } 508 936 } … … 510 938 rc = RegOpenKeyExW(pState->hkeyClassesRootDst, L"AppID", 0 /*fOptions*/, pState->fSamBoth, &hkeyAppIds); 511 939 AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 512 if (rc == ERROR_SUCCESS) 513 {514 rc = SHDeleteKeyA(hkeyAppIds, pszAppId);515 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 516 }517 518 /* Register*/519 if ( !pState->fUnregisterOnly)940 941 if (pState->fDelete) 942 vbpsDeleteKeyRecursiveA(pState, hkeyAppIds, pszAppId, __LINE__); 943 944 /* 945 * Update. 946 */ 947 if (pState->fUpdate) 520 948 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyAppIds, pszAppId, pszDescription, __LINE__); 521 949 522 RegCloseKey(hkeyAppIds);950 vbpsCloseKey(pState, hkeyAppIds, __LINE__); 523 951 524 952 return pState->rc; … … 544 972 545 973 /* 546 * Always unregister. 547 */ 548 if (pState->hkeyAltClassesRootsUnreg) 549 { 550 rc = SHDeleteKeyA(pState->hkeyAltClassesRootsUnreg, pszClassName); 551 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 552 } 553 554 rc = SHDeleteKeyA(pState->hkeyClassesRootDst, pszClassName); 555 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 556 557 if (!pState->fUnregisterOnly) 558 { 559 /* 560 * Register 561 */ 974 * Delete. 975 */ 976 if (pState->fDelete) 977 { 978 unsigned i = pState->cAltDeletes; 979 while (i-- > 0) 980 vbpsDeleteKeyRecursiveA(pState, pState->aAltDeletes[i].hkeyClasses, pszClassName, __LINE__); 981 vbpsDeleteKeyRecursiveA(pState, pState->hkeyClassesRootDst, pszClassName, __LINE__); 982 } 983 984 /* 985 * Update. 986 */ 987 if (pState->fUpdate) 988 { 562 989 /* pszClassName/Default = description. */ 563 990 HKEY hkeyClass; … … 569 996 570 997 /* CLSID/Default = pClsId. */ 571 rc = vbpsFormatUuidInCurly(szClsId, pClsId); 572 AssertMsgStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 573 if (rc == ERROR_SUCCESS) 574 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "CLSID", szClsId, __LINE__); 998 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "CLSID", vbpsFormatUuidInCurly(szClsId, pClsId), __LINE__); 575 999 576 1000 /* CurVer/Default = pszClassName+Suffix. */ … … 586 1010 } 587 1011 588 RegCloseKey(hkeyClass);1012 vbpsCloseKey(pState, hkeyClass, __LINE__); 589 1013 } 590 1014 } … … 623 1047 LSTATUS rc; 624 1048 char szClsId[CURLY_UUID_STR_BUF_SIZE]; 625 char szTypeLibId[CURLY_UUID_STR_BUF_SIZE];626 1049 627 1050 Assert(!pszAppId || *pszAppId == '{'); 628 Assert((pwszVBoxDir == NULL && pState->fUnregisterOnly) || pwszVBoxDir[RTUtf16Len(pwszVBoxDir) - 1] == '\\'); 629 630 /* 631 * Format the UUID first to get it over with. We always need CLSID. 632 */ 633 rc = vbpsFormatUuidInCurly(szClsId, pClsId); 634 AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 635 if (pTypeLibId) 636 { 637 rc = vbpsFormatUuidInCurly(szTypeLibId, pTypeLibId); 638 AssertMsgReturn(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 639 } 640 else 641 szTypeLibId[0] = '\0'; 642 643 /* 644 * Always unregister. 645 */ 646 if (pState->hkeyAltClsidRootsUnreg) 647 { 648 rc = SHDeleteKeyA(pState->hkeyAltClsidRootsUnreg, szClsId); 649 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 650 } 651 652 rc = SHDeleteKeyA(pState->hkeyClsidRootDst, szClsId); 653 AssertMsgStmt(rc == ERROR_SUCCESS || rc == ERROR_FILE_NOT_FOUND, ("%u\n", rc), pState->rc = rc); 654 655 if (!pState->fUnregisterOnly) 656 { 657 /* 658 * Register 659 */ 1051 Assert((pwszVBoxDir == NULL && !pState->fUpdate) || pwszVBoxDir[RTUtf16Len(pwszVBoxDir) - 1] == '\\'); 1052 1053 /* 1054 * We need this, whatever we end up having to do. 1055 */ 1056 vbpsFormatUuidInCurly(szClsId, pClsId); 1057 1058 /* 1059 * Delete. 1060 */ 1061 if (pState->fDelete) 1062 { 1063 unsigned i = pState->cAltDeletes; 1064 while (i-- > 0) 1065 vbpsDeleteKeyRecursiveA(pState, pState->aAltDeletes[i].hkeyClsid, szClsId, __LINE__); 1066 vbpsDeleteKeyRecursiveA(pState, pState->hkeyClsidRootDst, szClsId, __LINE__); 1067 } 1068 1069 /* 1070 * Update. 1071 */ 1072 if (pState->fUpdate) 1073 { 660 1074 HKEY hkeyClass; 661 1075 rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, pState->hkeyClsidRootDst, szClsId, pszDescription, … … 685 1099 *pwszCur++ = '\0'; /* included, so ++. */ 686 1100 687 rc = RegSetValueExW(hkeyServerType, NULL /*pszValueNm*/, 0 /*Reserved*/, 688 REG_SZ, (const BYTE *)&wszModule[0], (DWORD)((uintptr_t)pwszCur - (uintptr_t)&wszModule[0])); 689 AssertMsgStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 1101 vbpsSetRegValueWW(pState, hkeyServerType, NULL /*pszValueNm*/, wszModule, __LINE__); 690 1102 691 1103 /* pszServerType/ThreadingModel = pszThreading Model. */ … … 693 1105 vbpsSetRegValueAA(pState, hkeyServerType, "ThreadingModel", pszThreadingModel, __LINE__); 694 1106 695 RegCloseKey(hkeyServerType);1107 vbpsCloseKey(pState, hkeyServerType, __LINE__); 696 1108 } 697 1109 … … 712 1124 /* TypeLib/Default = pTypeLibId. */ 713 1125 if (pTypeLibId) 714 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "TypeLib", szTypeLibId, __LINE__); 715 716 RegCloseKey(hkeyClass); 1126 { 1127 char szTypeLibId[CURLY_UUID_STR_BUF_SIZE]; 1128 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyClass, "TypeLib", 1129 vbpsFormatUuidInCurly(szTypeLibId, pTypeLibId), __LINE__); 1130 } 1131 1132 vbpsCloseKey(pState, hkeyClass, __LINE__); 717 1133 } 718 1134 } … … 754 1170 "VirtualBox.VirtualBoxClient", ".1", 755 1171 &LIBID_VirtualBox, "InprocServer32", pwszVBoxDir, pszInprocDll, "Free"); 756 757 } 758 759 #ifndef VBOX_PROXY_STUB_32_ON_64 760 void RegisterOtherProxyStubAndTypelibDll(VBPSREGSTATE *pState, PCRTUTF16 pwszVBoxDir, bool fIs32On64) 761 { 762 if (!pState->fUnregisterOnly) 763 { 764 const char *pszWinXx = !fIs32On64 ? "win64" : "win32"; 765 const char *pszPsDll = !fIs32On64 ? "VBoxProxyStub.dll" : "VBoxProxyStub-x86.dll"; 766 char szTypeLibId[CURLY_UUID_STR_BUF_SIZE]; 1172 } 1173 1174 1175 /** 1176 * Updates the VBox type lib registration. 1177 * 1178 * This is only used when updating COM registrations during com::Initialize. 1179 * For normal registration and unregistrations we use the RegisterTypeLib and 1180 * UnRegisterTypeLib APIs. 1181 * 1182 * @param pState The registry modifier state. 1183 * @param pwszVBoxDir The VirtualBox install directory (unicode), 1184 * trailing slash. 1185 * @param fIs32On64 Set if we're registering the 32-bit proxy stub 1186 * on a 64-bit system. 1187 */ 1188 static void vbpsUpdateTypeLibRegistration(VBPSREGSTATE *pState, PCRTUTF16 pwszVBoxDir, bool fIs32On64) 1189 { 1190 const char * const pszTypeLibDll = !fIs32On64 ? "VBoxProxyStub.dll" : "x86\\VBoxProxyStub-x86.dll"; 1191 const char * const pszWinXx = !fIs32On64 ? "win64" : "win32"; 1192 const char * const pszDescription = "VirtualBox Type Library"; 1193 1194 char szTypeLibId[CURLY_UUID_STR_BUF_SIZE]; 1195 HKEY hkeyTypeLibs; 1196 HKEY hkeyTypeLibId; 1197 LSTATUS rc; 1198 1199 Assert(pState->fUpdate && !pState->fDelete); 1200 1201 /* 1202 * Type library registration (w/o interfaces). 1203 */ 1204 1205 /* Open Classes/TypeLib/. */ 1206 rc = vbpsCreateRegKeyA(pState, pState->hkeyClassesRootDst, "TypeLib", &hkeyTypeLibs, __LINE__); 1207 AssertReturnVoid(rc == ERROR_SUCCESS); 1208 1209 /* Create TypeLib/{UUID}. */ 1210 rc = vbpsCreateRegKeyA(pState, hkeyTypeLibs, vbpsFormatUuidInCurly(szTypeLibId, &LIBID_VirtualBox), &hkeyTypeLibId, __LINE__); 1211 if (rc == ERROR_SUCCESS) 1212 { 1213 /* {UUID}/Major.Minor/Default = pszDescription. */ 1214 HKEY hkeyMajMin; 767 1215 char szMajMin[64]; 768 HKEY hKeyTypeLibs;769 HKEY hKeyTypeLibId;770 HKEY hKeyMajMin;771 HKEY hKey0;772 HKEY hKeyWinXx;773 LSTATUS rc;774 775 /* Proxy stub factory class ID. */776 VbpsRegisterClassId(pState, &g_ProxyClsId, "PSFactoryBuffer", NULL /*pszAppId*/,777 NULL /*pszClassName*/, NULL /*pszCurClassNameVerSuffix*/, NULL /*pTypeLibId*/,778 "InprocServer32", pwszVBoxDir, pszPsDll, "Both");779 780 /*781 * Typelib DLL.782 */783 rc = vbpsFormatUuidInCurly(szTypeLibId, &LIBID_VirtualBox);784 AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);785 786 rc = RegOpenKeyExA(pState->hkeyClassesRootDst, "TypeLib", 0 /*fOptions*/, pState->fSamBoth, &hKeyTypeLibs);787 AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);788 rc = RegOpenKeyExA(hKeyTypeLibs, szTypeLibId, 0 /*fOptions*/, pState->fSamBoth, &hKeyTypeLibId);789 if (rc == ERROR_FILE_NOT_FOUND)790 rc = vbpsCreateRegKeyA(pState, hKeyTypeLibs, szTypeLibId, &hKeyTypeLibId, __LINE__);791 RegCloseKey(hKeyTypeLibs);792 793 AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc);794 795 /* Major.Minor/Default = Name. */796 1216 sprintf(szMajMin, "%u.%u", kTypeLibraryMajorVersion, kTypeLibraryMinorVersion); 797 rc = RegOpenKeyExA(hKeyTypeLibId, szMajMin, 0 /*fOptions*/, pState->fSamBoth, &hKeyMajMin); 798 if (rc == ERROR_FILE_NOT_FOUND) 799 rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, hKeyTypeLibId, szMajMin, "VirtualBox Type Library", 800 &hKeyMajMin, __LINE__); 801 RegCloseKey(hKeyTypeLibId); 802 AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 803 804 /* 0/. */ 805 rc = RegOpenKeyExA(hKeyMajMin, "0", 0 /*fOptions*/, pState->fSamBoth, &hKey0); 806 if (rc == ERROR_FILE_NOT_FOUND) 807 rc = vbpsCreateRegKeyA(pState, hKeyMajMin, "0", &hKey0, __LINE__); 808 RegCloseKey(hKeyMajMin); 809 AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 810 811 /* winXx/Default = VBoxProxyStub. */ 812 rc = RegOpenKeyExA(hKey0, pszWinXx, 0 /*fOptions*/, pState->fSamBoth, &hKeyWinXx); 813 if (rc == ERROR_FILE_NOT_FOUND) 1217 rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, hkeyTypeLibId, szMajMin, pszDescription, &hkeyMajMin, __LINE__); 1218 if (rc == ERROR_SUCCESS) 814 1219 { 815 RTUTF16 wsz DllPath[MAX_PATH * 2];816 817 rc = RTUtf16Copy(wszDllPath, MAX_PATH, pwszVBoxDir); AssertRC(rc); 818 rc = RTUtf16CatAscii(wszDllPath, MAX_PATH * 2, pszPsDll); AssertRC(rc);819 820 rc = vbpsCreateRegKeyA(pState, h Key0, pszWinXx, &hKeyWinXx, __LINE__);1220 RTUTF16 wszBuf[MAX_PATH * 2]; 1221 size_t off; 1222 1223 /* {UUID}/Major.Minor/0. */ 1224 HKEY hkey0; 1225 rc = vbpsCreateRegKeyA(pState, hkeyMajMin, "0", &hkey0, __LINE__); 821 1226 if (rc == ERROR_SUCCESS) 822 1227 { 823 rc = RegSetValueExW(hKeyWinXx, NULL /*pszValueNm*/, 0 /*Reserved*/, 824 REG_SZ, (const BYTE *)&wszDllPath[0], (DWORD)((RTUtf16Len(wszDllPath) + 1 )* 2)); 825 AssertMsgStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 1228 /* {UUID}/Major.Minor/0/winXX/Default = VBoxProxyStub. */ 1229 rc = RTUtf16Copy(wszBuf, MAX_PATH, pwszVBoxDir); AssertRC(rc); 1230 rc = RTUtf16CatAscii(wszBuf, MAX_PATH * 2, pszTypeLibDll); AssertRC(rc); 1231 1232 vbpsCreateRegKeyWithDefaultValueAW(pState, hkey0, pszWinXx, wszBuf, __LINE__); 1233 vbpsCloseKey(pState, hkey0, __LINE__); 1234 } 1235 1236 /* {UUID}/Major.Minor/FLAGS */ 1237 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyMajMin, "FLAGS", "0", __LINE__); 1238 1239 /* {UUID}/Major.Minor/HELPDIR */ 1240 rc = RTUtf16Copy(wszBuf, MAX_PATH, pwszVBoxDir); AssertRC(rc); 1241 off = RTUtf16Len(wszBuf); 1242 while (off > 2 && wszBuf[off - 2] != ':' && RTPATH_IS_SLASH(wszBuf[off - 1])) 1243 off--; 1244 wszBuf[off] = '\0'; 1245 vbpsCreateRegKeyWithDefaultValueAW(pState, hkeyMajMin, "HELPDIR", wszBuf, __LINE__); 1246 1247 vbpsCloseKey(pState, hkeyMajMin, __LINE__); 1248 } 1249 vbpsCloseKey(pState, hkeyTypeLibId, __LINE__); 1250 } 1251 vbpsCloseKey(pState, hkeyTypeLibs, __LINE__); 1252 } 1253 1254 1255 /** 1256 * Update the VBox proxy stub registration. 1257 * 1258 * This is only used when updating COM registrations during com::Initialize. 1259 * For normal registration and unregistrations we use the NdrDllRegisterProxy 1260 * and NdrDllUnregisterProxy. 1261 * 1262 * @param pState The registry modifier state. 1263 * @param pwszVBoxDir The VirtualBox install directory (unicode), 1264 * trailing slash. 1265 * @param fIs32On64 Set if we're registering the 32-bit proxy stub 1266 * on a 64-bit system. 1267 */ 1268 static void vbpsUpdateProxyStubRegistration(VBPSREGSTATE *pState, PCRTUTF16 pwszVBoxDir, bool fIs32On64) 1269 { 1270 /* 1271 * Register the proxy stub factory class ID. 1272 * It's simple compared to the VBox classes, thus all the NULL parameters. 1273 */ 1274 const char *pszPsDll = !fIs32On64 ? "VBoxProxyStub.dll" : "x86\\VBoxProxyStub-x86.dll"; 1275 Assert(pState->fUpdate && !pState->fDelete); 1276 VbpsRegisterClassId(pState, &g_ProxyClsId, "PSFactoryBuffer", NULL /*pszAppId*/, 1277 NULL /*pszClassName*/, NULL /*pszCurClassNameVerSuffix*/, NULL /*pTypeLibId*/, 1278 "InprocServer32", pwszVBoxDir, pszPsDll, "Both"); 1279 } 1280 1281 1282 /** 1283 * Updates the VBox interface registrations. 1284 * 1285 * This is only used when updating COM registrations during com::Initialize. 1286 * For normal registration and unregistrations we use the NdrDllRegisterProxy 1287 * and NdrDllUnregisterProxy. 1288 * 1289 * @param pState The registry modifier state. 1290 * @param pwszVBoxDir The VirtualBox install directory (unicode), 1291 * trailing slash. 1292 * @param fIs32On64 Set if we're registering the 32-bit proxy stub 1293 * on a 64-bit system. 1294 */ 1295 static void vbpsUpdateInterfaceRegistrations(VBPSREGSTATE *pState) 1296 { 1297 const ProxyFileInfo **ppProxyFile = &g_apProxyFiles[0]; 1298 const ProxyFileInfo *pProxyFile; 1299 LSTATUS rc; 1300 char szProxyClsId[CURLY_UUID_STR_BUF_SIZE]; 1301 1302 vbpsFormatUuidInCurly(szProxyClsId, &g_ProxyClsId); 1303 1304 Assert(pState->fUpdate && !pState->fDelete); 1305 rc = vbpsRegOpenInterfaceKeys(pState); 1306 AssertReturnVoid(rc == ERROR_SUCCESS); 1307 1308 /* 1309 * We walk the proxy file list (even if we only have one). 1310 */ 1311 while ((pProxyFile = *ppProxyFile++) != NULL) 1312 { 1313 const PCInterfaceStubVtblList * const papStubVtbls = pProxyFile->pStubVtblList; 1314 const char * const *papszNames = pProxyFile->pNamesArray; 1315 unsigned iIf = pProxyFile->TableSize; 1316 AssertStmt(iIf < 1024, iIf = 0); 1317 Assert(pProxyFile->TableVersion == 2); 1318 1319 /* 1320 * Walk the interfaces in that file, picking data from the various tables. 1321 */ 1322 while (iIf-- > 0) 1323 { 1324 char szIfId[CURLY_UUID_STR_BUF_SIZE]; 1325 const char * const pszIfNm = papszNames[iIf]; 1326 size_t const cchIfNm = RT_VALID_PTR(pszIfNm) ? strlen(pszIfNm) : 0; 1327 char szMethods[32]; 1328 uint32_t const cMethods = papStubVtbls[iIf]->header.DispatchTableCount; 1329 HKEY hkeyIfId; 1330 1331 AssertReturnVoidStmt(cchIfNm >= 3 && cchIfNm <= 72, pState->rc = ERROR_INVALID_DATA); 1332 1333 AssertReturnVoidStmt(cMethods >= 3 && cMethods < 1024, pState->rc = ERROR_INVALID_DATA); 1334 sprintf(szMethods, "%u", cMethods); 1335 1336 AssertReturnVoid(rc == ERROR_SUCCESS); 1337 1338 rc = vbpsCreateRegKeyWithDefaultValueAAEx(pState, pState->hkeyInterfaceRootDst, 1339 vbpsFormatUuidInCurly(szIfId, papStubVtbls[iIf]->header.piid), 1340 pszIfNm, &hkeyIfId, __LINE__); 1341 if (rc == ERROR_SUCCESS) 1342 { 1343 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyIfId, "ProxyStubClsid32", szProxyClsId, __LINE__); 1344 vbpsCreateRegKeyWithDefaultValueAA(pState, hkeyIfId, "NumMethods", szMethods, __LINE__); 1345 /** @todo Not having the typelib here means we'll have to fix the orphan cleanup 1346 * code below. */ 1347 1348 vbpsCloseKey(pState, hkeyIfId, __LINE__); 826 1349 } 827 1350 } 828 RegCloseKey(hKey0); 829 AssertMsgReturnVoidStmt(rc == ERROR_SUCCESS, ("%u\n", rc), pState->rc = rc); 830 RegCloseKey(hKeyWinXx); 831 } 832 833 } 1351 } 1352 } 1353 1354 1355 static bool vbpsIsUpToDate(VBPSREGSTATE *pState) 1356 { 1357 /** @todo read some registry key and */ 1358 NOREF(pState); 1359 return false; 1360 } 1361 1362 static bool vbpsMarkUpToDate(VBPSREGSTATE *pState) 1363 { 1364 /** @todo write the key vbpsIsUpToDate uses, if pState indicates success. */ 1365 NOREF(pState); 1366 return false; 1367 } 1368 1369 1370 1371 /** 1372 * Strips the stub dll name and any x86 subdir off the full DLL path to get a 1373 * path to the VirtualBox application directory. 1374 * 1375 * @param pwszDllPath The path to strip, returns will end with a slash. 1376 */ 1377 static void vbpsDllPathToVBoxDir(PRTUTF16 pwszDllPath) 1378 { 1379 RTUTF16 wc; 1380 size_t off = RTUtf16Len(pwszDllPath); 1381 while ( off > 0 1382 && ( (wc = pwszDllPath[off - 1]) >= 127U 1383 || !RTPATH_IS_SEP((unsigned char)wc))) 1384 off--; 1385 1386 #ifdef VBOX_IN_32_ON_64_MAIN_API 1387 /* 1388 * The -x86 variant is in a x86 subdirectory, drop it. 1389 */ 1390 while ( off > 0 1391 && ( (wc = pwszDllPath[off - 1]) < 127U 1392 && RTPATH_IS_SEP((unsigned char)wc))) 1393 off--; 1394 while ( off > 0 1395 && ( (wc = pwszDllPath[off - 1]) >= 127U 1396 || !RTPATH_IS_SEP((unsigned char)wc))) 1397 off--; 834 1398 #endif 835 836 837 HRESULT RegisterXidlModulesAndClasses(PRTUTF16 pwszDllName, bool fUnregisterOnly) 838 { 839 VBPSREGSTATE State; 840 LSTATUS rc; 841 842 /* 843 * Drop the filename and get the directory containing the DLL. 844 */ 845 if (!fUnregisterOnly) 846 { 847 RTUTF16 wc; 848 size_t off = RTUtf16Len(pwszDllName); 849 while ( off > 0 850 && ( (wc = pwszDllName[off - 1]) >= 127U 851 || !RTPATH_IS_SEP((unsigned char)wc))) 852 off--; 853 #ifdef VBOX_PROXY_STUB_32_ON_64 854 /* The -x86 variant is in a x86 subdirectory, drop it. */ 855 while ( off > 0 856 && ( (wc = pwszDllName[off - 1]) < 127U 857 && RTPATH_IS_SEP((unsigned char)wc))) 858 off--; 859 while ( off > 0 860 && ( (wc = pwszDllName[off - 1]) >= 127U 861 || !RTPATH_IS_SEP((unsigned char)wc))) 862 off--; 1399 pwszDllPath[off] = '\0'; 1400 } 1401 1402 1403 /** 1404 * Wrapper around RegisterXidlModulesAndClassesGenerated for the convenience of 1405 * the standard registration entry points. 1406 * 1407 * @returns COM status code. 1408 * @param pwszVBoxDir The VirtualBox install directory (unicode), 1409 * trailing slash. 1410 * @param fDelete Whether to delete registration keys and values. 1411 * @param fUpdate Whether to update registration keys and values. 1412 */ 1413 HRESULT RegisterXidlModulesAndClasses(PRTUTF16 pwszVBoxDir, bool fDelete, bool fUpdate) 1414 { 1415 #ifdef VBOX_IN_32_ON_64_MAIN_API 1416 bool const fIs32On64 = true; 1417 #else 1418 bool const fIs32On64 = false; 863 1419 #endif 864 pwszDllName[off] = '\0';865 }1420 VBPSREGSTATE State; 1421 LSTATUS rc; 866 1422 867 1423 /* 868 1424 * Do registration for the current execution mode of the DLL. 869 1425 */ 870 rc = vbpsRegInit(&State, 871 HKEY_CLASSES_ROOT, NULL, "HKCR", /* HKEY_LOCAL_MACHINE, "Software\\Classes", "HKLM\\Software\\Classes", */ 872 HKEY_CURRENT_USER, "Software\\Classes", 873 fUnregisterOnly, 0); 1426 rc = vbpsRegInit(&State, HKEY_CLASSES_ROOT, NULL /* Alt: HKEY_LOCAL_MACHINE, "Software\\Classes", */, fDelete, fUpdate, 0); 874 1427 if (rc == ERROR_SUCCESS) 875 1428 { 876 #ifdef VBOX_PROXY_STUB_32_ON_64 877 RegisterXidlModulesAndClassesGenerated(&State, pwszDllName, true); 878 #else 879 RegisterXidlModulesAndClassesGenerated(&State, pwszDllName, false); 880 #endif 1429 if (!fUpdate) 1430 { 1431 /* When only unregistering, really purge everything twice or trice. :-) */ 1432 vbpsRegAddAltDelete(&State, HKEY_LOCAL_MACHINE, "Software\\Classes"); 1433 vbpsRegAddAltDelete(&State, HKEY_CURRENT_USER, "Software\\Classes"); 1434 vbpsRegAddAltDelete(&State, HKEY_CLASSES_ROOT, NULL); 1435 } 1436 1437 RegisterXidlModulesAndClassesGenerated(&State, pwszVBoxDir, fIs32On64); 881 1438 rc = State.rc; 882 1439 } 883 884 1440 vbpsRegTerm(&State); 885 886 #ifndef VBOX_PROXY_STUB_32_ON_64887 /*888 * Do the WOW6432Node registrations too.889 */890 if (rc == ERROR_SUCCESS)891 {892 rc = vbpsRegInit(&State,893 HKEY_CLASSES_ROOT, "Wow6432Node", "HKCR\\Wow6432Node",894 HKEY_CURRENT_USER, "Software\\Classes",895 fUnregisterOnly, KEY_WOW64_32KEY);896 if (rc == ERROR_SUCCESS)897 {898 RegisterXidlModulesAndClassesGenerated(&State, pwszDllName, true);899 RegisterOtherProxyStubAndTypelibDll(&State, pwszDllName, true);900 rc = State.rc;901 }902 vbpsRegTerm(&State);903 }904 #endif905 1441 906 1442 /* … … 910 1446 return S_OK; 911 1447 return E_FAIL; 912 }913 914 915 /**916 * Register the interfaces proxied by this DLL, and to avoid duplication and917 * minimize work the VBox type library, classes and servers are also registered.918 *919 * @returns COM status code.920 */921 HRESULT STDAPICALLTYPE DllRegisterServer(void)922 {923 HRESULT hrc;924 925 /*926 * Register the type library first.927 */928 ITypeLib *pITypeLib;929 WCHAR wszDllName[MAX_PATH];930 DWORD cwcRet = GetModuleFileNameW(g_hDllSelf, wszDllName, RT_ELEMENTS(wszDllName));931 AssertReturn(cwcRet > 0 && cwcRet < RT_ELEMENTS(wszDllName), CO_E_PATHTOOLONG);932 933 hrc = LoadTypeLib(wszDllName, &pITypeLib);934 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);935 hrc = RegisterTypeLib(pITypeLib, wszDllName, NULL /*pszHelpDir*/);936 pITypeLib->lpVtbl->Release(pITypeLib);937 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);938 939 /*940 * Register proxy stub.941 */942 hrc = NdrDllRegisterProxy(g_hDllSelf, &g_apProxyFiles[0], &g_ProxyClsId); /* see DLLREGISTRY_ROUTINES in RpcProxy.h */943 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);944 945 /*946 * Register the VBox modules and classes.947 */948 hrc = RegisterXidlModulesAndClasses(wszDllName, false /*fUnregisterOnly*/);949 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc);950 951 return S_OK;952 }953 954 955 /**956 * Reverse of DllRegisterServer.957 *958 * @returns COM status code.959 */960 HRESULT STDAPICALLTYPE DllUnregisterServer(void)961 {962 HRESULT hrc = S_OK;963 HRESULT hrc2;964 965 /*966 * Unregister the type library.967 *968 * We ignore TYPE_E_REGISTRYACCESS as that is what is returned if the969 * type lib hasn't been registered (W10).970 */971 hrc2 = UnRegisterTypeLib(&LIBID_VirtualBox, kTypeLibraryMajorVersion, kTypeLibraryMinorVersion,972 0 /*LCid*/, RT_CONCAT(SYS_WIN, ARCH_BITS));973 AssertMsgStmt(SUCCEEDED(hrc2) || hrc2 == TYPE_E_REGISTRYACCESS, ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2);974 975 /*976 * Unregister the proxy stub.977 *978 * We ignore ERROR_FILE_NOT_FOUND as that is returned if not registered (W10).979 */980 hrc2 = NdrDllUnregisterProxy(g_hDllSelf, &g_apProxyFiles[0], &g_ProxyClsId); /* see DLLREGISTRY_ROUTINES in RpcProxy.h */981 AssertMsgStmt( SUCCEEDED(hrc2)982 || hrc2 == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND),983 ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2);984 985 /*986 * Register the VBox modules and classes.987 */988 hrc2 = RegisterXidlModulesAndClasses(NULL, true /*fUnregisterOnly*/);989 AssertMsgStmt(SUCCEEDED(hrc2), ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2);990 991 #ifdef WITH_MANUAL_CLEANUP992 /*993 * Purge old mess.994 */995 removeOldMess();996 #endif997 998 return hrc;999 1448 } 1000 1449 … … 1272 1721 #endif /* WITH_MANUAL_CLEANUP */ 1273 1722 1723 1724 /** 1725 * Register the interfaces proxied by this DLL, and to avoid duplication and 1726 * minimize work the VBox type library, classes and servers are also registered. 1727 * 1728 * This is normally only used by developers via comregister.cmd and the heat.exe 1729 * tool during MSI creation. The only situation where users may end up here is 1730 * if they're playing around or we recommend it as a solution to COM problems. 1731 * So, no problem if this approach is less gentle, though we leave the cleaning 1732 * up of orphaned interfaces to DllUnregisterServer. 1733 * 1734 * @returns COM status code. 1735 */ 1736 HRESULT STDAPICALLTYPE DllRegisterServer(void) 1737 { 1738 HRESULT hrc; 1739 1740 /* 1741 * Register the type library first. 1742 */ 1743 ITypeLib *pITypeLib; 1744 WCHAR wszDllName[MAX_PATH]; 1745 DWORD cwcRet = GetModuleFileNameW(g_hDllSelf, wszDllName, RT_ELEMENTS(wszDllName)); 1746 AssertReturn(cwcRet > 0 && cwcRet < RT_ELEMENTS(wszDllName), CO_E_PATHTOOLONG); 1747 1748 hrc = LoadTypeLib(wszDllName, &pITypeLib); 1749 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc); 1750 hrc = RegisterTypeLib(pITypeLib, wszDllName, NULL /*pszHelpDir*/); 1751 pITypeLib->lpVtbl->Release(pITypeLib); 1752 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc); 1753 1754 /* 1755 * Register proxy stub. 1756 */ 1757 hrc = NdrDllRegisterProxy(g_hDllSelf, &g_apProxyFiles[0], &g_ProxyClsId); /* see DLLREGISTRY_ROUTINES in RpcProxy.h */ 1758 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc); 1759 1760 /* 1761 * Register the VBox modules and classes. 1762 */ 1763 vbpsDllPathToVBoxDir(wszDllName); 1764 hrc = RegisterXidlModulesAndClasses(wszDllName, true /*fDelete*/, true /*fUpdate*/); 1765 AssertMsgReturn(SUCCEEDED(hrc), ("%Rhrc\n", hrc), hrc); 1766 1767 return S_OK; 1768 } 1769 1770 1771 /** 1772 * Reverse of DllRegisterServer. 1773 * 1774 * This is normally only used by developers via comregister.cmd. Users may be 1775 * asked to perform it in order to fix some COM issue. So, it's OK if we spend 1776 * some extra time and clean up orphaned interfaces, because developer boxes 1777 * will end up with a bunch of those as interface UUIDs changes. 1778 * 1779 * @returns COM status code. 1780 */ 1781 HRESULT STDAPICALLTYPE DllUnregisterServer(void) 1782 { 1783 HRESULT hrc = S_OK; 1784 HRESULT hrc2; 1785 1786 /* 1787 * Unregister the type library. 1788 * 1789 * We ignore TYPE_E_REGISTRYACCESS as that is what is returned if the 1790 * type lib hasn't been registered (W10). 1791 */ 1792 hrc2 = UnRegisterTypeLib(&LIBID_VirtualBox, kTypeLibraryMajorVersion, kTypeLibraryMinorVersion, 1793 0 /*LCid*/, RT_CONCAT(SYS_WIN, ARCH_BITS)); 1794 AssertMsgStmt(SUCCEEDED(hrc2) || hrc2 == TYPE_E_REGISTRYACCESS, ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2); 1795 1796 /* 1797 * Unregister the proxy stub. 1798 * 1799 * We ignore ERROR_FILE_NOT_FOUND as that is returned if not registered (W10). 1800 */ 1801 hrc2 = NdrDllUnregisterProxy(g_hDllSelf, &g_apProxyFiles[0], &g_ProxyClsId); /* see DLLREGISTRY_ROUTINES in RpcProxy.h */ 1802 AssertMsgStmt( SUCCEEDED(hrc2) 1803 || hrc2 == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_FILE_NOT_FOUND), 1804 ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2); 1805 1806 /* 1807 * Register the VBox modules and classes. 1808 */ 1809 hrc2 = RegisterXidlModulesAndClasses(NULL, true /*fDelete*/, false /*fUpdate*/); 1810 AssertMsgStmt(SUCCEEDED(hrc2), ("%Rhrc\n", hrc2), if (SUCCEEDED(hrc)) hrc = hrc2); 1811 1812 #ifdef WITH_MANUAL_CLEANUP 1813 /* 1814 * Purge old mess. 1815 */ 1816 removeOldMess(); 1817 #endif 1818 1819 return hrc; 1820 } 1821 1822 1823 /** 1824 * Gently update the COM registrations for VirtualBox. 1825 * 1826 * API that com::Initialize (VBoxCOM/initterm.cpp) calls the first time COM is 1827 * initialized in a process. ASSUMES that the caller has initialized IPRT. 1828 * 1829 * @returns Windows error code. 1830 */ 1831 DECLEXPORT(uint32_t) VbpsUpdateRegistrations(void) 1832 { 1833 LSTATUS rc; 1834 VBPSREGSTATE State; 1835 #ifdef VBOX_IN_32_ON_64_MAIN_API 1836 bool const fIs32On64 = true; 1837 #else 1838 bool const fIs32On64 = false; 1839 #endif 1840 1841 /* 1842 * Find the VirtualBox application directory first. 1843 */ 1844 WCHAR wszVBoxDir[MAX_PATH]; 1845 DWORD cwcRet = GetModuleFileNameW(g_hDllSelf, wszVBoxDir, RT_ELEMENTS(wszVBoxDir)); 1846 AssertReturn(cwcRet > 0 && cwcRet < RT_ELEMENTS(wszVBoxDir), ERROR_BUFFER_OVERFLOW); 1847 vbpsDllPathToVBoxDir(wszVBoxDir); 1848 1849 /* 1850 * Update registry entries for the current CPU bitness. 1851 */ 1852 rc = vbpsRegInit(&State, HKEY_CLASSES_ROOT, NULL, false /*fDelete*/, true /*fUpdate*/, 0); 1853 if (rc == ERROR_SUCCESS && !vbpsIsUpToDate(&State)) 1854 { 1855 vbpsUpdateTypeLibRegistration(&State, wszVBoxDir, fIs32On64); 1856 vbpsUpdateProxyStubRegistration(&State, wszVBoxDir, fIs32On64); 1857 vbpsUpdateInterfaceRegistrations(&State); 1858 RegisterXidlModulesAndClassesGenerated(&State, wszVBoxDir, fIs32On64); 1859 vbpsMarkUpToDate(&State); 1860 rc = State.rc; 1861 } 1862 vbpsRegTerm(&State); 1863 1864 1865 //#if defined(VBOX_IN_32_ON_64_MAIN_API) || (ARCH_BITS == 64 && defined(VBOX_WITH_32_ON_64_MAIN_API)) 1866 #ifndef VBOX_IN_32_ON_64_MAIN_API 1867 /* 1868 * Update registry entries for the other CPU bitness. 1869 */ 1870 if (rc == ERROR_SUCCESS) 1871 { 1872 //rc = vbpsRegInit(&State, HKEY_CLASSES_ROOT, "Wow6432Node", fDelete, fUpdate, KEY_WOW64_32KEY); 1873 rc = vbpsRegInit(&State, HKEY_CLASSES_ROOT, NULL, false /*fDelete*/, true /*fUpdate*/, 1874 !fIs32On64 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY); 1875 if (rc == ERROR_SUCCESS && !vbpsIsUpToDate(&State)) 1876 { 1877 vbpsUpdateTypeLibRegistration(&State, wszVBoxDir, !fIs32On64); 1878 vbpsUpdateProxyStubRegistration(&State, wszVBoxDir, !fIs32On64); 1879 vbpsUpdateInterfaceRegistrations(&State); 1880 RegisterXidlModulesAndClassesGenerated(&State, wszVBoxDir, !fIs32On64); 1881 vbpsMarkUpToDate(&State); 1882 rc = State.rc; 1883 } 1884 vbpsRegTerm(&State); 1885 } 1886 #endif 1887 1888 return VINF_SUCCESS; 1889 } 1890
Note:
See TracChangeset
for help on using the changeset viewer.