xref: /reactos/dll/win32/browseui/desktopipc.cpp (revision 5b78381a)
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:
CProxyDesktop(IEThreadParamBlock * parameters)38     CProxyDesktop(IEThreadParamBlock * parameters)
39     {
40     }
41 
~CProxyDesktop()42     virtual ~CProxyDesktop()
43     {
44     }
45 
OnMessage1037(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)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 
OnOpenNewWindow(UINT uMsg,WPARAM wParam,LPARAM lParam,BOOL & bHandled)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 
FindShellProxy(LPITEMIDLIST pidl)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 
MakeSharedPacket(IEThreadParamBlock * threadParams,LPCWSTR strPath,int dwProcessId)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 
ParseSharedPacket(HANDLE hData)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, &params->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 
ExplorerMessageLoop(IEThreadParamBlock * parameters)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 
BrowserThreadProc(LPVOID lpThreadParameter)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 */
SHCreateIETHREADPARAM(long param8,long paramC,IUnknown * param10,IUnknown * param14)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 */
SHCloneIETHREADPARAM(IEThreadParamBlock * param)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 */
SHDestroyIETHREADPARAM(IEThreadParamBlock * param)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 */
SHOnCWMCommandLine(HANDLE hSharedInfo)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 */
SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters)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 */
SHOpenNewFrame(LPITEMIDLIST pidl,IUnknown * paramC,long param10,DWORD dwFlags)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 */
SHCreateFromDesktop(_In_ PEXPLORER_CMDLINE_PARSE_RESULTS parseResults)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