3 #include <shlwapi_undoc.h>
5 #define PROXY_DESKTOP_CLASS L"Proxy Desktop"
7 BOOL g_SeparateFolders
= FALSE
;
9 // fields indented more are unknown ;P
25 UINT directoryPidlLength
;
31 extern DWORD WINAPI
BrowserThreadProc(LPVOID lpThreadParameter
);
34 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
35 public CWindowImpl
< CProxyDesktop
, CWindow
, CFrameWinTraits
>
37 IEThreadParamBlock
* m_Parameters
;
39 LPITEMIDLIST m_rootPidl
;
42 CProxyDesktop(IEThreadParamBlock
* parameters
) :
43 m_Parameters(parameters
)
48 virtual ~CProxyDesktop()
52 LRESULT
OnMessage1037(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
54 TRACE("Proxy Desktop message 1037.\n");
59 LRESULT
OnOpenNewWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
& bHandled
)
61 TRACE("Proxy Desktop message 1035 received.\n");
63 SHOnCWMCommandLine((HANDLE
) lParam
);
67 DECLARE_WND_CLASS_EX(PROXY_DESKTOP_CLASS
, CS_SAVEBITS
| CS_DROPSHADOW
, COLOR_3DFACE
)
69 BEGIN_MSG_MAP(CProxyDesktop
)
70 MESSAGE_HANDLER(WM_EXPLORER_1037
, OnMessage1037
)
71 MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW
, OnOpenNewWindow
)
75 static CProxyDesktop
* CreateProxyDesktop(IEThreadParamBlock
* parameters
)
77 return new CProxyDesktop(parameters
);
80 HWND
FindShellProxy(LPITEMIDLIST pidl
)
82 if (!g_SeparateFolders
)
84 HWND shell
= GetShellWindow();
88 TRACE("Found main desktop.\n");
94 TRACE("Separate folders setting enabled. Ignoring main desktop.\n");
97 HWND proxy
= FindWindow(PROXY_DESKTOP_CLASS
, NULL
);
100 TRACE("Found proxy desktop.\n");
107 HANDLE
MakeSharedPacket(IEThreadParamBlock
* threadParams
, LPCWSTR strPath
, int dwProcessId
)
110 UINT sharedBlockSize
= sizeof(*hnfData
);
111 UINT directoryPidlLength
= 0;
115 LPITEMIDLIST pidl80
= threadParams
->offset80
;
117 // Count the total length of the message packet
120 if (threadParams
->directoryPIDL
)
122 directoryPidlLength
= ILGetSize(threadParams
->directoryPIDL
);
123 sharedBlockSize
+= directoryPidlLength
;
124 TRACE("directoryPidlLength=%d\n", directoryPidlLength
);
128 if (threadParams
->offset7C
)
130 pidlSize7C
= ILGetSize(threadParams
->offset7C
);
131 sharedBlockSize
+= pidlSize7C
;
132 TRACE("pidlSize7C=%d\n", pidlSize7C
);
135 // This flag indicates the presence of another pidl?
136 if (!(threadParams
->offset84
& 0x8000))
140 pidlSize80
= ILGetSize(pidl80
);
141 sharedBlockSize
+= pidlSize80
;
142 TRACE("pidlSize80=%d\n", pidlSize7C
);
147 TRACE("pidl80 sent by value = %p\n", pidl80
);
149 sharedBlockSize
+= pidlSize80
;
155 pathLength
= 2 * lstrlenW(strPath
) + 2;
156 sharedBlockSize
+= pathLength
;
157 TRACE("pathLength=%d\n", pidlSize7C
);
160 TRACE("sharedBlockSize=%d\n", sharedBlockSize
);
162 // Allocate and fill the shared section
163 HANDLE hShared
= SHAllocShared(0, sharedBlockSize
, dwProcessId
);
166 ERR("Shared section alloc error.\n");
170 PBYTE target
= (PBYTE
) SHLockShared(hShared
, dwProcessId
);
173 ERR("Shared section lock error. %d\n", GetLastError());
174 SHFreeShared(hShared
, dwProcessId
);
179 hnfData
= (HNFBlock
*) target
;
180 hnfData
->cbSize
= sharedBlockSize
;
181 hnfData
->offset4
= (DWORD
) (threadParams
->dwFlags
);
182 hnfData
->offset8
= (DWORD
) (threadParams
->offset8
);
183 hnfData
->offsetC
= (DWORD
) (threadParams
->offset74
);
184 hnfData
->offset10
= (DWORD
) (threadParams
->offsetD8
);
185 hnfData
->offset14
= (DWORD
) (threadParams
->offset84
);
186 hnfData
->offset18
= (DWORD
) (threadParams
->offset88
);
187 hnfData
->offset1C
= (DWORD
) (threadParams
->offset8C
);
188 hnfData
->offset20
= (DWORD
) (threadParams
->offset90
);
189 hnfData
->offset24
= (DWORD
) (threadParams
->offset94
);
190 hnfData
->offset28
= (DWORD
) (threadParams
->offset98
);
191 hnfData
->offset2C
= (DWORD
) (threadParams
->offset9C
);
192 hnfData
->offset30
= (DWORD
) (threadParams
->offsetA0
);
193 hnfData
->directoryPidlLength
= 0;
194 hnfData
->pidlSize7C
= 0;
195 hnfData
->pidlSize80
= 0;
196 hnfData
->pathLength
= 0;
197 target
+= sizeof(*hnfData
);
199 // Copy the directory pidl contents
200 if (threadParams
->directoryPIDL
)
202 memcpy(target
, threadParams
->directoryPIDL
, directoryPidlLength
);
203 target
+= directoryPidlLength
;
204 hnfData
->directoryPidlLength
= directoryPidlLength
;
207 // Copy the other pidl contents
208 if (threadParams
->offset7C
)
210 memcpy(target
, threadParams
->offset7C
, pidlSize7C
);
211 target
+= pidlSize7C
;
212 hnfData
->pidlSize7C
= pidlSize7C
;
215 // copy the third pidl
216 if (threadParams
->offset84
& 0x8000)
218 *(LPITEMIDLIST
*) target
= pidl80
;
219 target
+= pidlSize80
;
220 hnfData
->pidlSize80
= pidlSize80
;
224 memcpy(target
, pidl80
, pidlSize80
);
225 target
+= pidlSize80
;
226 hnfData
->pidlSize80
= pidlSize80
;
229 // and finally the path string
232 memcpy(target
, strPath
, pathLength
);
233 hnfData
->pathLength
= pathLength
;
236 SHUnlockShared(hnfData
);
241 PIE_THREAD_PARAM_BLOCK
ParseSharedPacket(HANDLE hData
)
246 PIE_THREAD_PARAM_BLOCK params
= NULL
;
251 pid
= GetCurrentProcessId();
252 block
= (PBYTE
) SHLockShared(hData
, pid
);
254 hnfData
= (HNFBlock
*) block
;
258 if (hnfData
->cbSize
< sizeof(HNFBlock
))
261 params
= SHCreateIETHREADPARAM(0, hnfData
->offset8
, 0, 0);
265 params
->dwFlags
= hnfData
->offset4
;
266 params
->offset8
= hnfData
->offset8
;
267 params
->offset74
= hnfData
->offsetC
;
268 params
->offsetD8
= hnfData
->offset10
;
269 params
->offset84
= hnfData
->offset14
;
270 params
->offset88
= hnfData
->offset18
;
271 params
->offset8C
= hnfData
->offset1C
;
272 params
->offset90
= hnfData
->offset20
;
273 params
->offset94
= hnfData
->offset24
;
274 params
->offset98
= hnfData
->offset28
;
275 params
->offset9C
= hnfData
->offset2C
;
276 params
->offsetA0
= hnfData
->offset30
;
278 block
+= sizeof(*hnfData
);
279 if (hnfData
->directoryPidlLength
)
281 LPITEMIDLIST pidl
= NULL
;
283 pidl
= ILClone((LPITEMIDLIST
) block
);
284 params
->directoryPIDL
= pidl
;
286 block
+= hnfData
->directoryPidlLength
;
289 if (hnfData
->pidlSize7C
)
291 LPITEMIDLIST pidl
= NULL
;
293 pidl
= ILClone((LPITEMIDLIST
) block
);
294 params
->offset7C
= pidl
;
296 block
+= hnfData
->pidlSize80
;
299 if (hnfData
->pidlSize80
)
301 if (!(params
->offset84
& 0x8000))
303 params
->offset80
= *(LPITEMIDLIST
*) block
;
307 LPITEMIDLIST pidl
= NULL
;
309 pidl
= ILClone((LPITEMIDLIST
) block
);
310 params
->offset80
= pidl
;
313 block
+= hnfData
->pidlSize80
;
316 if (hnfData
->pathLength
)
318 CComPtr
<IShellFolder
> psfDesktop
;
319 PWSTR strPath
= (PWSTR
) block
;
321 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
323 params
->directoryPIDL
= NULL
;
327 if (FAILED(psfDesktop
->ParseDisplayName(NULL
, NULL
, strPath
, NULL
, ¶ms
->directoryPIDL
, NULL
)))
329 params
->directoryPIDL
= NULL
;
335 SHUnlockShared(hnfData
);
336 SHFreeShared(hData
, pid
);
339 if (!params
->directoryPIDL
)
341 SHDestroyIETHREADPARAM(params
);
348 /*************************************************************************
349 * SHCreateIETHREADPARAM [BROWSEUI.123]
351 extern "C" IEThreadParamBlock
*WINAPI
SHCreateIETHREADPARAM(
352 long param8
, long paramC
, IUnknown
*param10
, IUnknown
*param14
)
354 IEThreadParamBlock
*result
;
356 TRACE("SHCreateIETHREADPARAM\n");
358 result
= (IEThreadParamBlock
*) LocalAlloc(LMEM_ZEROINIT
, 256);
361 result
->offset0
= param8
;
362 result
->offset8
= paramC
;
363 result
->offsetC
= param10
;
366 result
->offset14
= param14
;
372 /*************************************************************************
373 * SHCloneIETHREADPARAM [BROWSEUI.124]
375 extern "C" IEThreadParamBlock
*WINAPI
SHCloneIETHREADPARAM(IEThreadParamBlock
*param
)
377 IEThreadParamBlock
*result
;
379 TRACE("SHCloneIETHREADPARAM\n");
381 result
= (IEThreadParamBlock
*) LocalAlloc(LMEM_FIXED
, 256);
384 memcpy(result
, param
, 0x40 * 4);
385 if (result
->directoryPIDL
!= NULL
)
386 result
->directoryPIDL
= ILClone(result
->directoryPIDL
);
387 if (result
->offset7C
!= NULL
)
388 result
->offset7C
= ILClone(result
->offset7C
);
389 if (result
->offset80
!= NULL
)
390 result
->offset80
= ILClone(result
->offset80
);
391 if (result
->offset70
!= NULL
)
392 result
->offset70
->AddRef();
394 if (result
->offsetC
!= NULL
)
395 result
->offsetC
->Method2C();
400 /*************************************************************************
401 * SHDestroyIETHREADPARAM [BROWSEUI.126]
403 extern "C" void WINAPI
SHDestroyIETHREADPARAM(IEThreadParamBlock
*param
)
405 TRACE("SHDestroyIETHREADPARAM\n");
409 if (param
->directoryPIDL
!= NULL
)
410 ILFree(param
->directoryPIDL
);
411 if (param
->offset7C
!= NULL
)
412 ILFree(param
->offset7C
);
413 if ((param
->dwFlags
& 0x80000) == 0 && param
->offset80
!= NULL
)
414 ILFree(param
->offset80
);
415 if (param
->offset14
!= NULL
)
416 param
->offset14
->Release();
417 if (param
->offset70
!= NULL
)
418 param
->offset70
->Release();
419 if (param
->offset78
!= NULL
)
420 param
->offset78
->Release();
421 if (param
->offsetC
!= NULL
)
422 param
->offsetC
->Release();
423 if (param
->offsetF8
!= NULL
)
424 param
->offsetF8
->Release();
428 /*************************************************************************
429 * SHOnCWMCommandLine [BROWSEUI.127]
431 extern "C" BOOL WINAPI
SHOnCWMCommandLine(HANDLE hSharedInfo
)
433 TRACE("SHOnCWMCommandLine\n");
435 PIE_THREAD_PARAM_BLOCK params
= ParseSharedPacket(hSharedInfo
);
438 return SHOpenFolderWindow(params
);
440 SHDestroyIETHREADPARAM(params
);
445 /*************************************************************************
446 * SHOpenFolderWindow [BROWSEUI.102]
447 * see SHOpenNewFrame below for remarks
449 extern "C" HRESULT WINAPI
SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters
)
454 WCHAR debugStr
[MAX_PATH
+ 1];
455 SHGetPathFromIDListW(parameters
->directoryPIDL
, debugStr
);
457 TRACE("SHOpenFolderWindow %p(%S)\n", parameters
->directoryPIDL
, debugStr
);
459 PIE_THREAD_PARAM_BLOCK paramsCopy
= SHCloneIETHREADPARAM(parameters
);
461 SHGetInstanceExplorer(&(paramsCopy
->offsetF8
));
462 threadHandle
= CreateThread(NULL
, 0x10000, BrowserThreadProc
, paramsCopy
, 0, &threadID
);
463 if (threadHandle
!= NULL
)
465 CloseHandle(threadHandle
);
468 SHDestroyIETHREADPARAM(paramsCopy
);
474 // this function should handle creating a new process if needed, but I'm leaving that out for now
475 // this function always opens a new window - it does NOT check for duplicates
476 /*************************************************************************
477 * SHOpenNewFrame [BROWSEUI.103]
479 extern "C" HRESULT WINAPI
SHOpenNewFrame(LPITEMIDLIST pidl
, IUnknown
*paramC
, long param10
, DWORD dwFlags
)
481 IEThreadParamBlock
*parameters
;
483 TRACE("SHOpenNewFrame\n");
485 parameters
= SHCreateIETHREADPARAM(0, 1, paramC
, NULL
);
486 if (parameters
== NULL
)
489 return E_OUTOFMEMORY
;
492 parameters
->offset10
= param10
;
493 parameters
->directoryPIDL
= pidl
;
494 parameters
->dwFlags
= dwFlags
;
496 HRESULT hr
= SHOpenFolderWindow(parameters
);
498 SHDestroyIETHREADPARAM(parameters
);
503 /*************************************************************************
504 * SHCreateFromDesktop [BROWSEUI.106]
505 * parameter is a FolderInfo
507 BOOL WINAPI
SHCreateFromDesktop(ExplorerCommandLineParseResults
* parseResults
)
509 TRACE("SHCreateFromDesktop\n");
511 IEThreadParamBlock
* parameters
= SHCreateIETHREADPARAM(0, 0, 0, 0);
515 PCWSTR strPath
= NULL
;
516 if (parseResults
->dwFlags
& SH_EXPLORER_CMDLINE_FLAG_STRING
)
518 if (parseResults
->pidlPath
)
520 WARN("strPath and pidlPath are both assigned. This shouldn't happen.\n");
523 strPath
= parseResults
->strPath
;
526 parameters
->dwFlags
= parseResults
->dwFlags
;
527 parameters
->offset8
= parseResults
->offsetC
;
529 LPITEMIDLIST pidl
= parseResults
->pidlPath
? ILClone(parseResults
->pidlPath
) : NULL
;
530 if (!pidl
&& parseResults
->dwFlags
& SH_EXPLORER_CMDLINE_FLAG_STRING
)
532 if (parseResults
->strPath
&& parseResults
->strPath
[0])
534 pidl
= ILCreateFromPathW(parseResults
->strPath
);
538 parameters
->directoryPIDL
= pidl
;
540 // Try to find the owner of the idlist, if we aren't running /SEPARATE
542 if (!(parseResults
->dwFlags
& SH_EXPLORER_CMDLINE_FLAG_SEPARATE
))
543 desktop
= FindShellProxy(parameters
->directoryPIDL
);
545 // If found, ask it to open the new window
548 TRACE("Found desktop hwnd=%p\n", desktop
);
552 GetWindowThreadProcessId(desktop
, &dwProcessId
);
553 AllowSetForegroundWindow(dwProcessId
);
555 HANDLE hShared
= MakeSharedPacket(parameters
, strPath
, dwProcessId
);
558 TRACE("Sending open message...\n");
560 PostMessageW(desktop
, WM_EXPLORER_OPEN_NEW_WINDOW
, 0, (LPARAM
) hShared
);
563 SHDestroyIETHREADPARAM(parameters
);
567 TRACE("Desktop not found or separate flag requested.\n");
569 // Else, start our own message loop!
570 HRESULT hr
= CoInitialize(NULL
);
571 CProxyDesktop
* proxy
= CreateProxyDesktop(parameters
);
575 CComPtr
<IUnknown
> thread
;
576 if (SHCreateThreadRef(&refCount
, &thread
) >= 0)
578 SHSetInstanceExplorer(thread
);
580 parameters
->directoryPIDL
= ILCreateFromPath(strPath
);
581 SHOpenFolderWindow(parameters
);
587 while (GetMessageW(&Msg
, 0, 0, 0) && refCount
)
589 TranslateMessage(&Msg
);
590 DispatchMessageW(&Msg
);
599 SHDestroyIETHREADPARAM(parameters
);