1 #include "precomp.h" 2 #include <shlwapi.h> 3 #include <shlwapi_undoc.h> 4 5 #define PROXY_DESKTOP_CLASS L"Proxy Desktop" 6 7 BOOL g_SeparateFolders = FALSE; 8 HWND g_hwndProxyDesktop = NULL; 9 10 // fields indented more are unknown ;P 11 struct HNFBlock 12 { 13 UINT cbSize; 14 DWORD offset4; 15 DWORD offset8; 16 DWORD offsetC; 17 DWORD offset10; 18 DWORD offset14; 19 DWORD offset18; 20 DWORD offset1C; 21 DWORD offset20; 22 DWORD offset24; 23 DWORD offset28; 24 DWORD offset2C; 25 DWORD offset30; 26 UINT directoryPidlLength; 27 UINT pidlSize7C; 28 UINT pidlSize80; 29 UINT pathLength; 30 }; 31 32 class CProxyDesktop : 33 public CComObjectRootEx<CComMultiThreadModelNoCS>, 34 public CWindowImpl < CProxyDesktop, CWindow, CFrameWinTraits > 35 { 36 37 public: 38 CProxyDesktop(IEThreadParamBlock * parameters) 39 { 40 } 41 42 virtual ~CProxyDesktop() 43 { 44 } 45 46 LRESULT OnMessage1037(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 47 { 48 TRACE("Proxy Desktop message 1037.\n"); 49 bHandled = TRUE; 50 return TRUE; 51 } 52 53 LRESULT OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 54 { 55 TRACE("Proxy Desktop message 1035 received.\n"); 56 bHandled = TRUE; 57 SHOnCWMCommandLine((HANDLE) lParam); 58 return 0; 59 } 60 61 DECLARE_WND_CLASS_EX(PROXY_DESKTOP_CLASS, CS_SAVEBITS | CS_DROPSHADOW, COLOR_3DFACE) 62 63 BEGIN_MSG_MAP(CProxyDesktop) 64 MESSAGE_HANDLER(WM_EXPLORER_1037, OnMessage1037) 65 MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW, OnOpenNewWindow) 66 END_MSG_MAP() 67 }; 68 69 HWND FindShellProxy(LPITEMIDLIST pidl) 70 { 71 /* If there is a proxy desktop in the current process use it */ 72 if (g_hwndProxyDesktop) 73 return g_hwndProxyDesktop; 74 75 /* Try to find the desktop of the main explorer process */ 76 if (!g_SeparateFolders) 77 { 78 HWND shell = GetShellWindow(); 79 80 if (shell) 81 { 82 TRACE("Found main desktop.\n"); 83 return shell; 84 } 85 } 86 else 87 { 88 TRACE("Separate folders setting enabled. Ignoring main desktop.\n"); 89 } 90 91 /* The main desktop can't be find so try to see if another process has a proxy desktop */ 92 HWND proxy = FindWindow(PROXY_DESKTOP_CLASS, NULL); 93 if (proxy) 94 { 95 TRACE("Found proxy desktop.\n"); 96 return proxy; 97 } 98 99 return NULL; 100 } 101 102 HANDLE MakeSharedPacket(IEThreadParamBlock * threadParams, LPCWSTR strPath, int dwProcessId) 103 { 104 HNFBlock* hnfData; 105 UINT sharedBlockSize = sizeof(*hnfData); 106 UINT directoryPidlLength = 0; 107 UINT pidlSize7C = 0; 108 UINT pidlSize80 = 0; 109 UINT pathLength = 0; 110 LPITEMIDLIST pidl80 = threadParams->offset80; 111 112 // Count the total length of the message packet 113 114 // directory PIDL 115 if (threadParams->directoryPIDL) 116 { 117 directoryPidlLength = ILGetSize(threadParams->directoryPIDL); 118 sharedBlockSize += directoryPidlLength; 119 TRACE("directoryPidlLength=%d\n", directoryPidlLength); 120 } 121 122 // another PIDL 123 if (threadParams->offset7C) 124 { 125 pidlSize7C = ILGetSize(threadParams->offset7C); 126 sharedBlockSize += pidlSize7C; 127 TRACE("pidlSize7C=%d\n", pidlSize7C); 128 } 129 130 // This flag indicates the presence of another pidl? 131 if (!(threadParams->offset84 & 0x8000)) 132 { 133 if (pidl80) 134 { 135 pidlSize80 = ILGetSize(pidl80); 136 sharedBlockSize += pidlSize80; 137 TRACE("pidlSize80=%d\n", pidlSize7C); 138 } 139 } 140 else 141 { 142 TRACE("pidl80 sent by value = %p\n", pidl80); 143 pidlSize80 = 4; 144 sharedBlockSize += pidlSize80; 145 } 146 147 // The path string 148 if (strPath) 149 { 150 pathLength = 2 * lstrlenW(strPath) + 2; 151 sharedBlockSize += pathLength; 152 TRACE("pathLength=%d\n", pidlSize7C); 153 } 154 155 TRACE("sharedBlockSize=%d\n", sharedBlockSize); 156 157 // Allocate and fill the shared section 158 HANDLE hShared = SHAllocShared(0, sharedBlockSize, dwProcessId); 159 if (!hShared) 160 { 161 ERR("Shared section alloc error.\n"); 162 return 0; 163 } 164 165 PBYTE target = (PBYTE) SHLockShared(hShared, dwProcessId); 166 if (!target) 167 { 168 ERR("Shared section lock error. %d\n", GetLastError()); 169 SHFreeShared(hShared, dwProcessId); 170 return 0; 171 } 172 173 // Basic information 174 hnfData = (HNFBlock*) target; 175 hnfData->cbSize = sharedBlockSize; 176 hnfData->offset4 = (DWORD) (threadParams->dwFlags); 177 hnfData->offset8 = (DWORD) (threadParams->offset8); 178 hnfData->offsetC = (DWORD) (threadParams->offset74); 179 hnfData->offset10 = (DWORD) (threadParams->offsetD8); 180 hnfData->offset14 = (DWORD) (threadParams->offset84); 181 hnfData->offset18 = (DWORD) (threadParams->offset88); 182 hnfData->offset1C = (DWORD) (threadParams->offset8C); 183 hnfData->offset20 = (DWORD) (threadParams->offset90); 184 hnfData->offset24 = (DWORD) (threadParams->offset94); 185 hnfData->offset28 = (DWORD) (threadParams->offset98); 186 hnfData->offset2C = (DWORD) (threadParams->offset9C); 187 hnfData->offset30 = (DWORD) (threadParams->offsetA0); 188 hnfData->directoryPidlLength = 0; 189 hnfData->pidlSize7C = 0; 190 hnfData->pidlSize80 = 0; 191 hnfData->pathLength = 0; 192 target += sizeof(*hnfData); 193 194 // Copy the directory pidl contents 195 if (threadParams->directoryPIDL) 196 { 197 memcpy(target, threadParams->directoryPIDL, directoryPidlLength); 198 target += directoryPidlLength; 199 hnfData->directoryPidlLength = directoryPidlLength; 200 } 201 202 // Copy the other pidl contents 203 if (threadParams->offset7C) 204 { 205 memcpy(target, threadParams->offset7C, pidlSize7C); 206 target += pidlSize7C; 207 hnfData->pidlSize7C = pidlSize7C; 208 } 209 210 // copy the third pidl 211 if (threadParams->offset84 & 0x8000) 212 { 213 *(LPITEMIDLIST*) target = pidl80; 214 target += pidlSize80; 215 hnfData->pidlSize80 = pidlSize80; 216 } 217 else if (pidl80) 218 { 219 memcpy(target, pidl80, pidlSize80); 220 target += pidlSize80; 221 hnfData->pidlSize80 = pidlSize80; 222 } 223 224 // and finally the path string 225 if (strPath) 226 { 227 memcpy(target, strPath, pathLength); 228 hnfData->pathLength = pathLength; 229 } 230 231 SHUnlockShared(hnfData); 232 233 return hShared; 234 } 235 236 PIE_THREAD_PARAM_BLOCK ParseSharedPacket(HANDLE hData) 237 { 238 HNFBlock * hnfData; 239 PBYTE block; 240 int pid; 241 PIE_THREAD_PARAM_BLOCK params = NULL; 242 243 if (!hData) 244 goto cleanup0; 245 246 pid = GetCurrentProcessId(); 247 block = (PBYTE) SHLockShared(hData, pid); 248 249 hnfData = (HNFBlock *) block; 250 if (!block) 251 goto cleanup2; 252 253 if (hnfData->cbSize < sizeof(HNFBlock)) 254 goto cleanup2; 255 256 params = SHCreateIETHREADPARAM(0, hnfData->offset8, 0, 0); 257 if (!params) 258 goto cleanup2; 259 260 params->dwFlags = hnfData->offset4; 261 params->offset8 = hnfData->offset8; 262 params->offset74 = hnfData->offsetC; 263 params->offsetD8 = hnfData->offset10; 264 params->offset84 = hnfData->offset14; 265 params->offset88 = hnfData->offset18; 266 params->offset8C = hnfData->offset1C; 267 params->offset90 = hnfData->offset20; 268 params->offset94 = hnfData->offset24; 269 params->offset98 = hnfData->offset28; 270 params->offset9C = hnfData->offset2C; 271 params->offsetA0 = hnfData->offset30; 272 273 block += sizeof(*hnfData); 274 if (hnfData->directoryPidlLength) 275 { 276 LPITEMIDLIST pidl = NULL; 277 if (*block) 278 pidl = ILClone((LPITEMIDLIST) block); 279 params->directoryPIDL = pidl; 280 281 block += hnfData->directoryPidlLength; 282 } 283 284 if (hnfData->pidlSize7C) 285 { 286 LPITEMIDLIST pidl = NULL; 287 if (*block) 288 pidl = ILClone((LPITEMIDLIST) block); 289 params->offset7C = pidl; 290 291 block += hnfData->pidlSize80; 292 } 293 294 if (hnfData->pidlSize80) 295 { 296 if (!(params->offset84 & 0x8000)) 297 { 298 params->offset80 = *(LPITEMIDLIST *) block; 299 } 300 else 301 { 302 LPITEMIDLIST pidl = NULL; 303 if (*block) 304 pidl = ILClone((LPITEMIDLIST) block); 305 params->offset80 = pidl; 306 } 307 308 block += hnfData->pidlSize80; 309 } 310 311 if (hnfData->pathLength) 312 { 313 CComPtr<IShellFolder> psfDesktop; 314 PWSTR strPath = (PWSTR) block; 315 316 if (FAILED(SHGetDesktopFolder(&psfDesktop))) 317 { 318 params->directoryPIDL = NULL; 319 goto cleanup0; 320 } 321 322 if (FAILED(psfDesktop->ParseDisplayName(NULL, NULL, strPath, NULL, ¶ms->directoryPIDL, NULL))) 323 { 324 params->directoryPIDL = NULL; 325 goto cleanup0; 326 } 327 } 328 329 cleanup2: 330 SHUnlockShared(hnfData); 331 SHFreeShared(hData, pid); 332 333 cleanup0: 334 if (!params->directoryPIDL) 335 { 336 SHDestroyIETHREADPARAM(params); 337 return NULL; 338 } 339 340 return params; 341 } 342 343 344 static HRESULT ExplorerMessageLoop(IEThreadParamBlock * parameters) 345 { 346 HRESULT hResult; 347 MSG Msg; 348 BOOL Ret; 349 350 // Tell the thread ref we are using it. 351 if (parameters && parameters->pExplorerInstance) 352 parameters->pExplorerInstance->AddRef(); 353 354 /* Handle /e parameter */ 355 UINT wFlags = 0; 356 if (parameters->dwFlags & SH_EXPLORER_CMDLINE_FLAG_E) 357 wFlags |= SBSP_EXPLOREMODE; 358 359 /* Handle /select parameter */ 360 PUITEMID_CHILD pidlSelect = NULL; 361 if ((parameters->dwFlags & SH_EXPLORER_CMDLINE_FLAG_SELECT) && 362 (ILGetNext(parameters->directoryPIDL) != NULL)) 363 { 364 pidlSelect = ILClone(ILFindLastID(parameters->directoryPIDL)); 365 ILRemoveLastID(parameters->directoryPIDL); 366 } 367 368 CComPtr<IShellBrowser> psb; 369 #if 0 370 if (!(parameters->dwFlags & (SH_EXPLORER_CMDLINE_FLAG_E | SH_EXPLORER_CMDLINE_FLAG_NOREUSE))) 371 { 372 // TODO: IShellWindows::FindWindowSW(...) and reuse the existing IShellBrowser 373 } 374 #endif 375 hResult = CShellBrowser_CreateInstance(IID_PPV_ARG(IShellBrowser, &psb)); 376 if (FAILED_UNEXPECTEDLY(hResult)) 377 return hResult; 378 379 if (parameters->dwFlags & SH_EXPLORER_CMDLINE_FLAG_EMBED) 380 { 381 CComPtr<IBrowserService> pbs; 382 if (SUCCEEDED(psb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs)))) 383 pbs->SetFlags(BSF_UISETBYAUTOMATION, BSF_UISETBYAUTOMATION); 384 } 385 386 hResult = psb->BrowseObject(parameters->directoryPIDL, wFlags); 387 if (FAILED_UNEXPECTEDLY(hResult)) 388 return hResult; 389 390 if (pidlSelect != NULL) 391 { 392 CComPtr<IShellView> shellView; 393 hResult = psb->QueryActiveShellView(&shellView); 394 if (SUCCEEDED(hResult)) 395 { 396 shellView->SelectItem(pidlSelect, SVSI_SELECT | SVSI_FOCUSED | SVSI_ENSUREVISIBLE); 397 } 398 ILFree(pidlSelect); 399 } 400 401 CComPtr<IBrowserService2> browser; 402 hResult = psb->QueryInterface(IID_PPV_ARG(IBrowserService2, &browser)); 403 if (FAILED_UNEXPECTEDLY(hResult)) 404 return hResult; 405 406 psb.Release(); 407 408 while ((Ret = GetMessage(&Msg, NULL, 0, 0)) != 0) 409 { 410 if (Ret == -1) 411 { 412 // Error: continue or exit? 413 break; 414 } 415 416 if (Msg.message == WM_QUIT) 417 break; 418 419 if (browser->v_MayTranslateAccelerator(&Msg) != S_OK) 420 { 421 TranslateMessage(&Msg); 422 DispatchMessage(&Msg); 423 } 424 } 425 426 ReleaseCComPtrExpectZero(browser); 427 428 // Tell the thread ref we are not using it anymore. 429 if (parameters && parameters->pExplorerInstance) 430 parameters->pExplorerInstance->Release(); 431 432 return hResult; 433 } 434 435 static DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter) 436 { 437 IEThreadParamBlock * parameters = (IEThreadParamBlock *) lpThreadParameter; 438 439 OleInitialize(NULL); 440 ExplorerMessageLoop(parameters); 441 442 /* Destroying the parameters releases the thread reference */ 443 SHDestroyIETHREADPARAM(parameters); 444 445 /* Wake up the proxy desktop thread so it can check whether the last browser thread exited */ 446 /* Use PostMessage in order to force GetMessage to return and check if all browser windows have exited */ 447 PostMessageW(FindShellProxy(NULL), WM_EXPLORER_1037, 0, 0); 448 449 OleUninitialize(); 450 451 return 0; 452 } 453 454 /************************************************************************* 455 * SHCreateIETHREADPARAM [BROWSEUI.123] 456 */ 457 extern "C" IEThreadParamBlock *WINAPI SHCreateIETHREADPARAM( 458 long param8, long paramC, IUnknown *param10, IUnknown *param14) 459 { 460 IEThreadParamBlock *result; 461 462 TRACE("SHCreateIETHREADPARAM\n"); 463 464 result = (IEThreadParamBlock *) LocalAlloc(LMEM_ZEROINIT, sizeof(*result)); 465 if (result == NULL) 466 return NULL; 467 result->offset0 = param8; 468 result->offset8 = paramC; 469 result->offsetC = param10; 470 if (param10 != NULL) 471 param10->AddRef(); 472 result->offset14 = param14; 473 if (param14 != NULL) 474 param14->AddRef(); 475 return result; 476 } 477 478 /************************************************************************* 479 * SHCloneIETHREADPARAM [BROWSEUI.124] 480 */ 481 extern "C" IEThreadParamBlock *WINAPI SHCloneIETHREADPARAM(IEThreadParamBlock *param) 482 { 483 IEThreadParamBlock *result; 484 485 TRACE("SHCloneIETHREADPARAM\n"); 486 487 result = (IEThreadParamBlock *) LocalAlloc(LMEM_FIXED, sizeof(*result)); 488 if (result == NULL) 489 return NULL; 490 *result = *param; 491 if (result->directoryPIDL != NULL) 492 result->directoryPIDL = ILClone(result->directoryPIDL); 493 if (result->offset7C != NULL) 494 result->offset7C = ILClone(result->offset7C); 495 if (result->offset80 != NULL) 496 result->offset80 = ILClone(result->offset80); 497 if (result->offset70 != NULL) 498 result->offset70->AddRef(); 499 #if 0 500 if (result->offsetC != NULL) 501 result->offsetC->Method2C(); 502 #endif 503 return result; 504 } 505 506 /************************************************************************* 507 * SHDestroyIETHREADPARAM [BROWSEUI.126] 508 */ 509 extern "C" void WINAPI SHDestroyIETHREADPARAM(IEThreadParamBlock *param) 510 { 511 TRACE("SHDestroyIETHREADPARAM\n"); 512 513 if (param == NULL) 514 return; 515 if (param->directoryPIDL != NULL) 516 ILFree(param->directoryPIDL); 517 if (param->offset7C != NULL) 518 ILFree(param->offset7C); 519 if ((param->dwFlags & 0x80000) == 0 && param->offset80 != NULL) 520 ILFree(param->offset80); 521 if (param->offset14 != NULL) 522 param->offset14->Release(); 523 if (param->offset70 != NULL) 524 param->offset70->Release(); 525 if (param->offset78 != NULL) 526 param->offset78->Release(); 527 if (param->offsetC != NULL) 528 param->offsetC->Release(); 529 if (param->pExplorerInstance != NULL) 530 param->pExplorerInstance->Release(); 531 LocalFree(param); 532 } 533 534 /************************************************************************* 535 * SHOnCWMCommandLine [BROWSEUI.127] 536 */ 537 extern "C" BOOL WINAPI SHOnCWMCommandLine(HANDLE hSharedInfo) 538 { 539 TRACE("SHOnCWMCommandLine\n"); 540 541 PIE_THREAD_PARAM_BLOCK params = ParseSharedPacket(hSharedInfo); 542 543 if (params) 544 return SHOpenFolderWindow(params); 545 546 SHDestroyIETHREADPARAM(params); 547 548 return FALSE; 549 } 550 551 /************************************************************************* 552 * SHOpenFolderWindow [BROWSEUI.102] 553 * see SHOpenNewFrame below for remarks 554 */ 555 extern "C" HRESULT WINAPI SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters) 556 { 557 HANDLE threadHandle; 558 DWORD threadID; 559 560 // Only try to convert the pidl when it is going to be printed 561 if (TRACE_ON(browseui)) 562 { 563 WCHAR debugStr[MAX_PATH + 2] = { 0 }; 564 if (!ILGetDisplayName(parameters->directoryPIDL, debugStr)) 565 { 566 debugStr[0] = UNICODE_NULL; 567 } 568 TRACE("SHOpenFolderWindow %p(%S)\n", parameters->directoryPIDL, debugStr); 569 } 570 571 PIE_THREAD_PARAM_BLOCK paramsCopy = SHCloneIETHREADPARAM(parameters); 572 573 SHGetInstanceExplorer(&(paramsCopy->pExplorerInstance)); 574 threadHandle = CreateThread(NULL, 0x10000, BrowserThreadProc, paramsCopy, 0, &threadID); 575 if (threadHandle != NULL) 576 { 577 CloseHandle(threadHandle); 578 return S_OK; 579 } 580 SHDestroyIETHREADPARAM(paramsCopy); 581 return E_FAIL; 582 } 583 584 // 75FA56C1h 585 // (pidl, 0, -1, 1) 586 // this function should handle creating a new process if needed, but I'm leaving that out for now 587 // this function always opens a new window - it does NOT check for duplicates 588 /************************************************************************* 589 * SHOpenNewFrame [BROWSEUI.103] 590 */ 591 extern "C" HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags) 592 { 593 IEThreadParamBlock *parameters; 594 595 TRACE("SHOpenNewFrame\n"); 596 597 parameters = SHCreateIETHREADPARAM(0, 1, paramC, NULL); 598 if (parameters == NULL) 599 { 600 ILFree(pidl); 601 return E_OUTOFMEMORY; 602 } 603 if (paramC != NULL) 604 parameters->offset10 = param10; 605 parameters->directoryPIDL = pidl; 606 parameters->dwFlags = dwFlags; 607 608 HRESULT hr = SHOpenFolderWindow(parameters); 609 610 SHDestroyIETHREADPARAM(parameters); 611 612 return hr; 613 } 614 615 /************************************************************************* 616 * SHCreateFromDesktop [BROWSEUI.106] 617 * parameter is a FolderInfo 618 */ 619 BOOL WINAPI SHCreateFromDesktop(_In_ PEXPLORER_CMDLINE_PARSE_RESULTS parseResults) 620 { 621 TRACE("SHCreateFromDesktop\n"); 622 623 IEThreadParamBlock * parameters = SHCreateIETHREADPARAM(0, 0, 0, 0); 624 if (!parameters) 625 return FALSE; 626 627 PCWSTR strPath = NULL; 628 if (parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_STRING) 629 { 630 if (parseResults->pidlPath) 631 { 632 WARN("strPath and pidlPath are both assigned. This shouldn't happen.\n"); 633 } 634 635 strPath = parseResults->strPath; 636 } 637 638 parameters->dwFlags = parseResults->dwFlags; 639 parameters->offset8 = parseResults->nCmdShow; 640 641 LPITEMIDLIST pidl = parseResults->pidlPath ? ILClone(parseResults->pidlPath) : NULL; 642 if (!pidl && parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_STRING) 643 { 644 if (parseResults->strPath && parseResults->strPath[0]) 645 { 646 pidl = ILCreateFromPathW(parseResults->strPath); 647 } 648 } 649 650 // HACK! This shouldn't happen! SHExplorerParseCmdLine needs fixing. 651 if (!pidl) 652 { 653 SHGetFolderLocation(NULL, CSIDL_PERSONAL, NULL, NULL, &pidl); 654 } 655 656 parameters->directoryPIDL = pidl; 657 658 // Try to find the owner of the idlist, if we aren't running /SEPARATE 659 HWND desktop = NULL; 660 if (!(parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_SEPARATE)) 661 desktop = FindShellProxy(parameters->directoryPIDL); 662 663 // If found, ask it to open the new window 664 if (desktop) 665 { 666 TRACE("Found desktop hwnd=%p\n", desktop); 667 668 DWORD dwProcessId; 669 670 GetWindowThreadProcessId(desktop, &dwProcessId); 671 AllowSetForegroundWindow(dwProcessId); 672 673 HANDLE hShared = MakeSharedPacket(parameters, strPath, dwProcessId); 674 if (hShared) 675 { 676 TRACE("Sending open message...\n"); 677 678 PostMessageW(desktop, WM_EXPLORER_OPEN_NEW_WINDOW, 0, (LPARAM) hShared); 679 } 680 681 SHDestroyIETHREADPARAM(parameters); 682 return TRUE; 683 } 684 685 TRACE("Desktop not found or separate flag requested.\n"); 686 687 // Else, start our own message loop! 688 HRESULT hr = CoInitialize(NULL); 689 CProxyDesktop * proxy = new CProxyDesktop(parameters); 690 if (proxy) 691 { 692 g_hwndProxyDesktop = proxy->Create(0); 693 694 LONG refCount; 695 CComPtr<IUnknown> thread; 696 if (SHCreateThreadRef(&refCount, &thread) >= 0) 697 { 698 SHSetInstanceExplorer(thread); 699 if (strPath) 700 parameters->directoryPIDL = ILCreateFromPath(strPath); 701 SHOpenFolderWindow(parameters); 702 parameters = NULL; 703 thread.Release(); 704 } 705 706 MSG Msg; 707 while (GetMessageW(&Msg, 0, 0, 0) && refCount) 708 { 709 TranslateMessage(&Msg); 710 DispatchMessageW(&Msg); 711 } 712 713 DestroyWindow(g_hwndProxyDesktop); 714 715 delete proxy; 716 } 717 718 if (SUCCEEDED(hr)) 719 CoUninitialize(); 720 721 SHDestroyIETHREADPARAM(parameters); 722 723 return TRUE; 724 } 725