4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #if USE_API_SHCREATEDESKTOP
25 typedef struct _DESKCREATEINFO
30 } DESKCREATEINFO
, *PDESKCREATEINFO
;
33 DesktopThreadProc(IN OUT LPVOID lpParameter
)
35 volatile DESKCREATEINFO
*DeskCreateInfo
= (volatile DESKCREATEINFO
*)lpParameter
;
36 IShellDesktopTray
*pSdt
;
40 hRet
= ITrayWindow_QueryInterface(DeskCreateInfo
->Tray
,
41 &IID_IShellDesktopTray
,
46 hDesktop
= SHCreateDesktop(pSdt
);
48 IShellDesktopTray_Release(pSdt
);
52 (void)InterlockedExchangePointer(&DeskCreateInfo
->hDesktop
,
55 if (!SetEvent(DeskCreateInfo
->hEvent
))
57 /* Failed to notify that we initialized successfully, kill ourselves
58 to make the main thread wake up! */
62 SHDesktopMessageLoop(hDesktop
);
64 /* FIXME: Properly rundown the main thread! */
71 DesktopCreateWindow(IN OUT ITrayWindow
*Tray
)
75 DWORD DesktopThreadId
;
76 HANDLE hDesktop
= NULL
;
80 hEvent
= CreateEvent(NULL
,
86 volatile DESKCREATEINFO DeskCreateInfo
;
88 DeskCreateInfo
.hEvent
= hEvent
;
89 DeskCreateInfo
.Tray
= Tray
;
90 DeskCreateInfo
.hDesktop
= NULL
;
92 hThread
= CreateThread(NULL
,
95 (PVOID
)&DeskCreateInfo
,
100 Handles
[0] = hThread
;
105 WaitResult
= MsgWaitForMultipleObjects(sizeof(Handles
) / sizeof(Handles
[0]),
110 if (WaitResult
== WAIT_OBJECT_0
+ (sizeof(Handles
) / sizeof(Handles
[0])))
111 TrayProcessMessages(Tray
);
112 else if (WaitResult
!= WAIT_FAILED
&& WaitResult
!= WAIT_OBJECT_0
)
114 hDesktop
= DeskCreateInfo
.hDesktop
;
119 CloseHandle(hThread
);
129 DesktopDestroyShellWindow(IN HANDLE hDesktop
)
134 #else /* USE_API_SHCREATEDESKTOP == 0 */
137 ******************************************************************************
138 * NOTE: This could may be reused in a shell implementation of *
139 * SHCreateShellFolderView(). *
140 ******************************************************************************
144 SHCreateShellFolderView(
145 const SFV_CREATE
*pcsfv
,
150 ZeroMemory(&csfv
, sizeof(CSFV
));
151 csfv
.cbSize
= sizeof(CSFV
);
152 csfv
.pshf
= pcsfv
->pshf
;
153 csfv
.psvOuter
= pcsfv
->psvOuter
;
154 /* FIXME: handle pcsfv->psfvcb */
155 return SHCreateShellFolderViewEx(&csfv
, ppsv
);
160 ******************************************************************************
161 * NOTE: This could may be reused in a shell implementation of *
162 * SHCreateDesktop(). *
163 ******************************************************************************
166 #define IShellView2 IShellView
167 #define IShellView2_Release(This) IShellView_Release((This))
168 #define IShellView2_CreateViewWindow2(This, Params) IShellView_CreateViewWindow((This), (Params)->psvPrev, (Params)->pfs, (Params)->psbOwner, (Params)->prcView, &(Params)->hwndView)
171 #define WM_SHELL_ADDDRIVENOTIFY (WM_USER + 0x100)
173 static const IShellBrowserVtbl IDesktopShellBrowserImpl_Vtbl
;
174 static const ICommDlgBrowserVtbl IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl
;
175 static const IServiceProviderVtbl IDesktopShellBrowserImpl_IServiceProvider_Vtbl
;
176 static const IShellFolderViewCBVtbl IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl
;
184 const IShellBrowserVtbl
*lpVtbl
;
185 const ICommDlgBrowserVtbl
*lpVtblCommDlgBrowser
;
186 const IServiceProviderVtbl
*lpVtblServiceProvider
;
187 const IShellFolderViewCBVtbl
*lpVtblShellFolderViewCB
;
190 IShellView2
*DesktopView2
;
191 IShellView
*DesktopView
;
192 IShellBrowser
*DefaultShellBrowser
;
195 HWND hWndDesktopListView
;
199 LPITEMIDLIST pidlDesktopDirectory
;
200 LPITEMIDLIST pidlDesktop
;
201 IDropTarget
*DropTarget
;
203 ULONG ChangeNotificationId
;
204 } IDesktopShellBrowserImpl
;
207 IUnknown_from_impl(IDesktopShellBrowserImpl
*This
)
209 return (IUnknown
*)&This
->lpVtbl
;
212 static IShellBrowser
*
213 IShellBrowser_from_impl(IDesktopShellBrowserImpl
*This
)
215 return (IShellBrowser
*)&This
->lpVtbl
;
219 IOleWindow_from_impl(IDesktopShellBrowserImpl
*This
)
221 return (IOleWindow
*)&This
->lpVtbl
;
224 static ICommDlgBrowser
*
225 ICommDlgBrowser_from_impl(IDesktopShellBrowserImpl
*This
)
227 return (ICommDlgBrowser
*)&This
->lpVtblCommDlgBrowser
;
230 static IServiceProvider
*
231 IServiceProvider_from_impl(IDesktopShellBrowserImpl
*This
)
233 return (IServiceProvider
*)&This
->lpVtblServiceProvider
;
236 static IShellFolderViewCB
*
237 IShellFolderViewCB_from_impl(IDesktopShellBrowserImpl
*This
)
239 return (IShellFolderViewCB
*)&This
->lpVtblShellFolderViewCB
;
242 static IDesktopShellBrowserImpl
*
243 impl_from_IShellBrowser(IShellBrowser
*iface
)
245 return (IDesktopShellBrowserImpl
*)((ULONG_PTR
)iface
- FIELD_OFFSET(IDesktopShellBrowserImpl
,
249 static IDesktopShellBrowserImpl
*
250 impl_from_ICommDlgBrowser(ICommDlgBrowser
*iface
)
252 return (IDesktopShellBrowserImpl
*)((ULONG_PTR
)iface
- FIELD_OFFSET(IDesktopShellBrowserImpl
,
253 lpVtblCommDlgBrowser
));
256 static IDesktopShellBrowserImpl
*
257 impl_from_IServiceProvider(IServiceProvider
*iface
)
259 return (IDesktopShellBrowserImpl
*)((ULONG_PTR
)iface
- FIELD_OFFSET(IDesktopShellBrowserImpl
,
260 lpVtblServiceProvider
));
263 static IDesktopShellBrowserImpl
*
264 impl_from_IShellFolderViewCB(IShellFolderViewCB
*iface
)
266 return (IDesktopShellBrowserImpl
*)((ULONG_PTR
)iface
- FIELD_OFFSET(IDesktopShellBrowserImpl
,
267 lpVtblShellFolderViewCB
));
271 IDesktopShellBrowserImpl_Free(IDesktopShellBrowserImpl
*This
)
273 if (This
->DropTarget
!= NULL
)
275 IDropTarget_Release(This
->DropTarget
);
276 This
->DropTarget
= NULL
;
279 if (This
->Tray
!= NULL
)
281 ITrayWindow_Release(This
->Tray
);
285 if (This
->pidlDesktopDirectory
!= NULL
)
287 ILFree(This
->pidlDesktopDirectory
);
288 This
->pidlDesktopDirectory
= NULL
;
291 if (This
->pidlDesktop
!= NULL
)
293 ILFree(This
->pidlDesktop
);
294 This
->pidlDesktop
= NULL
;
297 HeapFree(hProcessHeap
,
303 IDesktopShellBrowserImpl_Destroy(IDesktopShellBrowserImpl
*This
)
305 if (This
->ChangeNotificationId
!= 0)
307 SHChangeNotifyDeregister(This
->ChangeNotificationId
);
308 This
->ChangeNotificationId
= 0;
311 if (This
->Tray
!= NULL
)
313 ITrayWindow_Close(This
->Tray
);
317 if (This
->DropTarget
!= NULL
&& This
->hWndDesktopListView
!= NULL
)
319 RevokeDragDrop(This
->hWndDesktopListView
);
320 This
->hWndDesktopListView
= NULL
;
323 if (This
->DesktopView2
!= NULL
)
325 IShellView2_Release(This
->DesktopView2
);
328 if (This
->DesktopView
!= NULL
)
330 if (This
->hWndShellView
!= NULL
)
332 IShellView_DestroyViewWindow(This
->DesktopView
);
335 IShellView_Release(This
->DesktopView
);
336 This
->DesktopView
= NULL
;
337 This
->hWndShellView
= NULL
;
338 This
->hWndDesktopListView
= NULL
;
343 IDesktopShellBrowserImpl_GetNotify(IN OUT IDesktopShellBrowserImpl
*This
,
344 OUT LPITEMIDLIST
*ppidl
,
347 *ppidl
= This
->pidlDesktopDirectory
;
348 *plEvents
= SHCNE_DISKEVENTS
;
352 static ULONG STDMETHODCALLTYPE
353 IDesktopShellBrowserImpl_Release(IN OUT IShellBrowser
*iface
)
355 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
358 Ret
= InterlockedDecrement(&This
->Ref
);
360 IDesktopShellBrowserImpl_Free(This
);
365 static ULONG STDMETHODCALLTYPE
366 IDesktopShellBrowserImpl_AddRef(IN OUT IShellBrowser
*iface
)
368 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
370 return InterlockedIncrement(&This
->Ref
);
373 static HRESULT STDMETHODCALLTYPE
374 IDesktopShellBrowserImpl_QueryInterface(IN OUT IShellBrowser
*iface
,
378 IDesktopShellBrowserImpl
*This
;
383 This
= impl_from_IShellBrowser(iface
);
388 *ppvObj
= IUnknown_from_impl(This
);
390 else if (This
->DefaultShellBrowser
!= NULL
)
392 return IShellBrowser_QueryInterface(This
->DefaultShellBrowser
,
396 else if (IsEqualIID(riid
,
399 *ppvObj
= IOleWindow_from_impl(This
);
401 else if (IsEqualIID(riid
,
404 *ppvObj
= IShellBrowser_from_impl(This
);
406 else if (IsEqualIID(riid
,
407 &IID_ICommDlgBrowser
))
409 *ppvObj
= ICommDlgBrowser_from_impl(This
);
411 else if (IsEqualIID(riid
,
412 &IID_IServiceProvider
))
414 *ppvObj
= IServiceProvider_from_impl(This
);
416 else if (IsEqualIID(riid
,
417 &IID_IShellFolderViewCB
))
419 *ppvObj
= IShellFolderViewCB_from_impl(This
);
424 return E_NOINTERFACE
;
427 IDesktopShellBrowserImpl_AddRef(iface
);
431 static IDesktopShellBrowserImpl
*
432 IDesktopShellBrowserImpl_Construct(IN HWND hwndParent
,
433 IN LPCREATESTRUCT lpCreateStruct OPTIONAL
)
435 IDesktopShellBrowserImpl
*This
;
436 IShellBrowser
*ShellBrowser
;
437 IShellFolder
*psfDesktopFolder
;
444 SHChangeNotifyEntry cne
;
446 This
= HeapAlloc(hProcessHeap
,
454 This
->lpVtbl
= &IDesktopShellBrowserImpl_Vtbl
;
455 This
->lpVtblCommDlgBrowser
= &IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl
;
456 This
->lpVtblServiceProvider
= &IDesktopShellBrowserImpl_IServiceProvider_Vtbl
;
457 This
->lpVtblShellFolderViewCB
= &IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl
;
459 This
->hWnd
= hwndParent
;
461 ShellBrowser
= IShellBrowser_from_impl(This
);
463 This
->pidlDesktopDirectory
= SHCloneSpecialIDList(This
->hWnd
,
464 CSIDL_DESKTOPDIRECTORY
,
467 hr
= SHGetSpecialFolderLocation(This
->hWnd
,
474 hr
= SHGetDesktopFolder(&psfDesktopFolder
);
476 hr
= CoCreateInstance(&CLSID_ShellDesktop
,
480 (PVOID
*)&psfDesktopFolder
);
486 hr
= IShellFolder_CreateViewObject(psfDesktopFolder
,
489 (PVOID
*)&This
->DesktopView
);
491 csfv
.cbSize
= sizeof(csfv
);
492 csfv
.pshf
= psfDesktopFolder
;
493 csfv
.psvOuter
= NULL
;
495 hr
= IDesktopShellBrowserImpl_QueryInterface(ShellBrowser
,
496 &IID_IShellFolderViewCB
,
497 (PVOID
*)&csfv
.psfvcb
);
501 hr
= SHCreateShellFolderView(&csfv
,
504 IShellFolder_Release(psfDesktopFolder
);
506 if (csfv
.psfvcb
!= NULL
)
507 csfv
.psfvcb
->lpVtbl
->Release(csfv
.psfvcb
);
512 hr
= IShellView_QueryInterface(This
->DesktopView
,
514 (PVOID
*)&This
->DesktopView2
);
516 This
->DesktopView2
= NULL
;
518 if (lpCreateStruct
== NULL
)
520 if (!GetClientRect(This
->hWnd
,
530 rcClient
.right
= lpCreateStruct
->cx
;
531 rcClient
.bottom
= lpCreateStruct
->cy
;
534 fs
.ViewMode
= FVM_ICON
;
535 fs
.fFlags
= FWF_DESKTOP
| FWF_NOCLIENTEDGE
| FWF_NOSCROLL
| FWF_TRANSPARENT
;
536 if (This
->DesktopView2
!= NULL
)
538 SV2CVW2_PARAMS params
;
540 params
.cbSize
= sizeof(params
);
541 params
.psvPrev
= NULL
;
543 params
.psbOwner
= ShellBrowser
;
544 params
.prcView
= &rcClient
;
545 params
.pvid
= &VID_LargeIcons
;
546 hr
= IShellView2_CreateViewWindow2(This
->DesktopView2
,
550 goto DefCreateViewWindow
;
551 This
->hWndShellView
= params
.hwndView
;
556 hr
= IShellView_CreateViewWindow(This
->DesktopView
,
561 &This
->hWndShellView
);
566 IShellView_EnableModeless(This
->DesktopView
,
569 hr
= IShellView_UIActivate(This
->DesktopView
,
570 SVUIA_ACTIVATE_FOCUS
);
573 IShellView_DestroyViewWindow(This
->DesktopView
);
576 /* NOTE: the other references will be released in the
577 WM_NCDESTROY handler! */
578 IDesktopShellBrowserImpl_Release(ShellBrowser
);
582 /* Now get the real window handle to the list view control!
583 We need to assume it is the child window of the default
584 shell view window. There doesn't seem to be another way
585 to get to the list view window handle... */
586 This
->hWndDesktopListView
= FindWindowEx(This
->hWndShellView
,
591 if (This
->hWndDesktopListView
!= NULL
)
593 /* Register drag&drop */
594 hr
= IShellView_QueryInterface(This
->DesktopView
,
596 (PVOID
*)&This
->DropTarget
);
599 hr
= RegisterDragDrop(This
->hWndDesktopListView
,
603 IDropTarget_Release(This
->DropTarget
);
604 This
->DropTarget
= NULL
;
609 /* Register a notification that is triggered when a new drive is added and the shell
610 should open that drive in a new window, such as USB sticks. */
612 cne
.fRecursive
= TRUE
;
613 This
->ChangeNotificationId
= SHChangeNotifyRegister(This
->hWnd
,
614 SHCNRF_ShellLevel
| SHCNRF_NewDelivery
,
616 WM_SHELL_ADDDRIVENOTIFY
,
620 /* Create the tray window */
621 This
->Tray
= CreateTrayWindow();
625 static HRESULT STDMETHODCALLTYPE
626 IDesktopShellBrowserImpl_GetWindow(IN OUT IShellBrowser
*iface
,
629 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
631 if (This
->hWnd
!= NULL
)
641 static HRESULT STDMETHODCALLTYPE
642 IDesktopShellBrowserImpl_ContextSensitiveHelp(IN OUT IShellBrowser
*iface
,
648 static HRESULT STDMETHODCALLTYPE
649 IDesktopShellBrowserImpl_InsertMenusSB(IN OUT IShellBrowser
*iface
,
650 IN HMENU hmenuShared
,
651 OUT LPOLEMENUGROUPWIDTHS lpMenuWidths
)
656 static HRESULT STDMETHODCALLTYPE
657 IDesktopShellBrowserImpl_SetMenuSB(IN OUT IShellBrowser
*iface
,
658 IN HMENU hmenuShared
,
659 IN HOLEMENU holemenuRes
,
660 IN HWND hwndActiveObject
)
665 static HRESULT STDMETHODCALLTYPE
666 IDesktopShellBrowserImpl_RemoveMenusSB(IN OUT IShellBrowser
*iface
,
667 IN HMENU hmenuShared
)
672 static HRESULT STDMETHODCALLTYPE
673 IDesktopShellBrowserImpl_SetStatusTextSB(IN OUT IShellBrowser
*iface
,
674 IN LPCOLESTR lpszStatusText
)
679 static HRESULT STDMETHODCALLTYPE
680 IDesktopShellBrowserImpl_EnableModelessSB(IN OUT IShellBrowser
*iface
,
686 static HRESULT STDMETHODCALLTYPE
687 IDesktopShellBrowserImpl_TranslateAcceleratorSB(IN OUT IShellBrowser
*iface
,
694 static HRESULT STDMETHODCALLTYPE
695 IDesktopShellBrowserImpl_BrowseObject(IN OUT IShellBrowser
*iface
,
696 IN LPCITEMIDLIST pidl
,
702 static HRESULT STDMETHODCALLTYPE
703 IDesktopShellBrowserImpl_GetViewStateStream(IN OUT IShellBrowser
*iface
,
705 OUT IStream
**ppStrm
)
707 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
708 static WCHAR szItemPos
[] = L
"ItemPos";
710 IPropertyBag
*PropBag
= NULL
;
711 WCHAR szPropName
[64];
713 /* Determine the name of the property that contains the stream of
717 hRet
= SHGetPerScreenResName(szPropName
+ wcslen(szPropName
),
718 (sizeof(szPropName
) / sizeof(szPropName
[0])) - wcslen(szPropName
),
722 /* Locate the property bag for the desktop */
723 hRet
= SHGetViewStatePropertyBag(This
->pidlDesktop
,
725 SHGVSPB_FOLDERNODEFAULTS
| SHGVSPB_ROAM
,
731 /* Create a stream for the ItemPos property */
732 hRet
= SHPropertyBag_ReadStream(PropBag
,
736 IPropertyBag_Release(PropBag
);
740 /* FIXME: For some reason the shell doesn't position the icons... */
749 DesktopGetWindowControl(IN IDesktopShellBrowserImpl
*This
,
766 static HRESULT STDMETHODCALLTYPE
767 IDesktopShellBrowserImpl_GetControlWindow(IN OUT IShellBrowser
*iface
,
771 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
774 hWnd
= DesktopGetWindowControl(This
,
786 static HRESULT STDMETHODCALLTYPE
787 IDesktopShellBrowserImpl_SendControlMsg(IN OUT IShellBrowser
*iface
,
794 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
800 hWnd
= DesktopGetWindowControl(This
,
804 *pret
= SendMessage(hWnd
,
814 static HRESULT STDMETHODCALLTYPE
815 IDesktopShellBrowserImpl_QueryActiveShellView(IN OUT IShellBrowser
*iface
,
816 OUT IShellView
**ppshv
)
818 IShellView
*ActiveView
;
819 IDesktopShellBrowserImpl
*This
= impl_from_IShellBrowser(iface
);
821 ActiveView
= This
->DesktopView
;
822 IDesktopShellBrowserImpl_AddRef(iface
);
828 static HRESULT STDMETHODCALLTYPE
829 IDesktopShellBrowserImpl_OnViewWindowActive(IN OUT IShellBrowser
*iface
,
830 IN OUT IShellView
*ppshv
)
835 static HRESULT STDMETHODCALLTYPE
836 IDesktopShellBrowserImpl_SetToolbarItems(IN OUT IShellBrowser
*iface
,
837 IN LPTBBUTTON lpButtons
,
844 static const IShellBrowserVtbl IDesktopShellBrowserImpl_Vtbl
=
847 IDesktopShellBrowserImpl_QueryInterface
,
848 IDesktopShellBrowserImpl_AddRef
,
849 IDesktopShellBrowserImpl_Release
,
851 IDesktopShellBrowserImpl_GetWindow
,
852 IDesktopShellBrowserImpl_ContextSensitiveHelp
,
854 IDesktopShellBrowserImpl_InsertMenusSB
,
855 IDesktopShellBrowserImpl_SetMenuSB
,
856 IDesktopShellBrowserImpl_RemoveMenusSB
,
857 IDesktopShellBrowserImpl_SetStatusTextSB
,
858 IDesktopShellBrowserImpl_EnableModelessSB
,
859 IDesktopShellBrowserImpl_TranslateAcceleratorSB
,
860 IDesktopShellBrowserImpl_BrowseObject
,
861 IDesktopShellBrowserImpl_GetViewStateStream
,
862 IDesktopShellBrowserImpl_GetControlWindow
,
863 IDesktopShellBrowserImpl_SendControlMsg
,
864 IDesktopShellBrowserImpl_QueryActiveShellView
,
865 IDesktopShellBrowserImpl_OnViewWindowActive
,
866 IDesktopShellBrowserImpl_SetToolbarItems
873 static HRESULT STDMETHODCALLTYPE
874 IDesktopShellBrowserImpl_ICommDlgBrowser_QueryInterface(IN OUT ICommDlgBrowser
*iface
,
878 IDesktopShellBrowserImpl
*This
= impl_from_ICommDlgBrowser(iface
);
879 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
881 return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser
,
886 static ULONG STDMETHODCALLTYPE
887 IDesktopShellBrowserImpl_ICommDlgBrowser_Release(IN OUT ICommDlgBrowser
*iface
)
889 IDesktopShellBrowserImpl
*This
= impl_from_ICommDlgBrowser(iface
);
890 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
892 return IDesktopShellBrowserImpl_Release(ShellBrowser
);
895 static ULONG STDMETHODCALLTYPE
896 IDesktopShellBrowserImpl_ICommDlgBrowser_AddRef(IN OUT ICommDlgBrowser
*iface
)
898 IDesktopShellBrowserImpl
*This
= impl_from_ICommDlgBrowser(iface
);
899 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
901 return IDesktopShellBrowserImpl_AddRef(ShellBrowser
);
904 static HRESULT STDMETHODCALLTYPE
905 IDesktopShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(IN OUT ICommDlgBrowser
*iface
,
906 IN OUT IShellView
*ppshv
)
911 static HRESULT STDMETHODCALLTYPE
912 IDesktopShellBrowserImpl_ICommDlgBrowser_OnStateChange(IN OUT ICommDlgBrowser
*iface
,
913 IN OUT IShellView
*ppshv
,
919 static HRESULT STDMETHODCALLTYPE
920 IDesktopShellBrowserImpl_ICommDlgBrowser_IncludeObject(IN OUT ICommDlgBrowser
*iface
,
921 IN OUT IShellView
*ppshv
,
922 IN LPCITEMIDLIST pidl
)
927 static const ICommDlgBrowserVtbl IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl
=
930 IDesktopShellBrowserImpl_ICommDlgBrowser_QueryInterface
,
931 IDesktopShellBrowserImpl_ICommDlgBrowser_AddRef
,
932 IDesktopShellBrowserImpl_ICommDlgBrowser_Release
,
933 /* ICommDlgBrowser */
934 IDesktopShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand
,
935 IDesktopShellBrowserImpl_ICommDlgBrowser_OnStateChange
,
936 IDesktopShellBrowserImpl_ICommDlgBrowser_IncludeObject
943 static HRESULT STDMETHODCALLTYPE
944 IDesktopShellBrowserImpl_IServiceProvider_QueryInterface(IN OUT IServiceProvider
*iface
,
948 IDesktopShellBrowserImpl
*This
= impl_from_IServiceProvider(iface
);
949 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
951 return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser
,
956 static ULONG STDMETHODCALLTYPE
957 IDesktopShellBrowserImpl_IServiceProvider_Release(IN OUT IServiceProvider
*iface
)
959 IDesktopShellBrowserImpl
*This
= impl_from_IServiceProvider(iface
);
960 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
962 return IDesktopShellBrowserImpl_Release(ShellBrowser
);
965 static ULONG STDMETHODCALLTYPE
966 IDesktopShellBrowserImpl_IServiceProvider_AddRef(IN OUT IServiceProvider
*iface
)
968 IDesktopShellBrowserImpl
*This
= impl_from_IServiceProvider(iface
);
969 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
971 return IDesktopShellBrowserImpl_AddRef(ShellBrowser
);
974 static HRESULT STDMETHODCALLTYPE
975 IDesktopShellBrowserImpl_IServiceProvider_QueryService(IN OUT IServiceProvider
*iface
,
976 IN REFGUID guidService
,
980 /* FIXME - handle guidService */
981 return IDesktopShellBrowserImpl_IServiceProvider_QueryInterface(iface
,
986 static const IServiceProviderVtbl IDesktopShellBrowserImpl_IServiceProvider_Vtbl
=
989 IDesktopShellBrowserImpl_IServiceProvider_QueryInterface
,
990 IDesktopShellBrowserImpl_IServiceProvider_AddRef
,
991 IDesktopShellBrowserImpl_IServiceProvider_Release
,
992 /* IServiceProvider */
993 IDesktopShellBrowserImpl_IServiceProvider_QueryService
1000 static HRESULT STDMETHODCALLTYPE
1001 IDesktopShellBrowserImpl_IShellFolderViewCB_QueryInterface(IN OUT IShellFolderViewCB
*iface
,
1005 IDesktopShellBrowserImpl
*This
= impl_from_IShellFolderViewCB(iface
);
1006 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
1008 return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser
,
1013 static ULONG STDMETHODCALLTYPE
1014 IDesktopShellBrowserImpl_IShellFolderViewCB_Release(IN OUT IShellFolderViewCB
*iface
)
1016 IDesktopShellBrowserImpl
*This
= impl_from_IShellFolderViewCB(iface
);
1017 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
1019 return IDesktopShellBrowserImpl_Release(ShellBrowser
);
1022 static ULONG STDMETHODCALLTYPE
1023 IDesktopShellBrowserImpl_IShellFolderViewCB_AddRef(IN OUT IShellFolderViewCB
*iface
)
1025 IDesktopShellBrowserImpl
*This
= impl_from_IShellFolderViewCB(iface
);
1026 IShellBrowser
*ShellBrowser
= IShellBrowser_from_impl(This
);
1028 return IDesktopShellBrowserImpl_AddRef(ShellBrowser
);
1031 static HRESULT STDMETHODCALLTYPE
1032 IDesktopShellBrowserImpl_IShellFolderViewCB_MessageSFVCB(IN OUT IShellFolderViewCB
*iface
,
1037 IDesktopShellBrowserImpl
*This
= impl_from_IShellFolderViewCB(iface
);
1041 case SFVM_GETNOTIFY
:
1042 hr
= IDesktopShellBrowserImpl_GetNotify(This
,
1043 (LPITEMIDLIST
*)wParam
,
1059 static const IShellFolderViewCBVtbl IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl
=
1062 IDesktopShellBrowserImpl_IShellFolderViewCB_QueryInterface
,
1063 IDesktopShellBrowserImpl_IShellFolderViewCB_AddRef
,
1064 IDesktopShellBrowserImpl_IShellFolderViewCB_Release
,
1065 /* IShellFolderViewCB */
1066 IDesktopShellBrowserImpl_IShellFolderViewCB_MessageSFVCB
1069 /*****************************************************************************/
1071 static const TCHAR szProgmanClassName
[] = TEXT("Progman");
1072 static const TCHAR szProgmanWindowName
[] = TEXT("Program Manager");
1075 PositionIcons(IN OUT IDesktopShellBrowserImpl
*This
,
1076 IN
const RECT
*prcDesktopRect
)
1078 /* FIXME - Move all icons and align them on the destop. Before moving, we should
1079 check if we're moving an icon above an existing one. If so, we should
1080 let the list view control arrange the icons */
1085 UpdateWorkArea(IN OUT IDesktopShellBrowserImpl
*This
,
1086 IN
const RECT
*prcDesktopRect
)
1091 Style
= GetWindowLong(This
->hWndDesktopListView
,
1094 if (!(Style
& LVS_AUTOARRANGE
) &&
1095 GetWindowRect(This
->hWnd
,
1098 /* Only resize the desktop if it was resized to something other
1099 than the virtual screen size/position! */
1100 if (!EqualRect(prcDesktopRect
,
1103 SetWindowPos(This
->hWnd
,
1105 prcDesktopRect
->left
,
1106 prcDesktopRect
->top
,
1107 prcDesktopRect
->right
- prcDesktopRect
->left
,
1108 prcDesktopRect
->bottom
- prcDesktopRect
->top
,
1109 SWP_NOZORDER
| SWP_NOACTIVATE
);
1111 /* Let's try to rearrange the icons on the desktop. This is
1112 especially neccessary when switching screen resolutions... */
1119 static LRESULT CALLBACK
1120 ProgmanWindowProc(IN HWND hwnd
,
1125 IDesktopShellBrowserImpl
*This
= NULL
;
1126 LRESULT Ret
= FALSE
;
1128 if (uMsg
!= WM_NCCREATE
)
1130 This
= (IDesktopShellBrowserImpl
*)GetWindowLongPtr(hwnd
,
1134 if (This
!= NULL
|| uMsg
== WM_NCCREATE
)
1139 PaintDesktop((HDC
)wParam
);
1142 case WM_GETISHELLBROWSER
:
1143 Ret
= (LRESULT
)IShellBrowser_from_impl(This
);
1146 case WM_SHELL_ADDDRIVENOTIFY
:
1149 LPITEMIDLIST
*ppidl
;
1152 hLock
= SHChangeNotification_Lock((HANDLE
)wParam
,
1159 SHChangeNotification_Unlock(hLock
);
1165 if (wParam
== SIZE_MINIMIZED
)
1167 /* Hey, we're the desktop!!! */
1175 rcDesktop
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
1176 rcDesktop
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
1177 rcDesktop
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
1178 rcDesktop
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
1180 UpdateWorkArea(This
,
1185 case WM_SYSCOLORCHANGE
:
1187 InvalidateRect(This
->hWnd
,
1191 if (This
->hWndShellView
!= NULL
)
1193 /* Forward the message */
1194 SendMessage(This
->hWndShellView
,
1204 LPCREATESTRUCT CreateStruct
= (LPCREATESTRUCT
)lParam
;
1205 This
= IDesktopShellBrowserImpl_Construct(hwnd
,
1210 SetWindowLongPtr(hwnd
,
1214 if (This
->hWndShellView
!= NULL
)
1215 SetShellWindowEx(This
->hWnd
,
1216 This
->hWndDesktopListView
);
1218 SetShellWindow(This
->hWnd
);
1226 IDesktopShellBrowserImpl_Destroy(This
);
1232 IDesktopShellBrowserImpl_Release(IShellBrowser_from_impl(This
));
1239 Ret
= DefWindowProc(hwnd
, uMsg
, wParam
, lParam
);
1248 RegisterProgmanWindowClass(VOID
)
1252 wcProgman
.style
= CS_DBLCLKS
;
1253 wcProgman
.lpfnWndProc
= ProgmanWindowProc
;
1254 wcProgman
.cbClsExtra
= 0;
1255 wcProgman
.cbWndExtra
= sizeof(IDesktopShellBrowserImpl
*);
1256 wcProgman
.hInstance
= hExplorerInstance
;
1257 wcProgman
.hIcon
= NULL
;
1258 wcProgman
.hCursor
= LoadCursor(NULL
,
1260 wcProgman
.hbrBackground
= (HBRUSH
)(COLOR_BACKGROUND
+ 1);
1261 wcProgman
.lpszMenuName
= NULL
;
1262 wcProgman
.lpszClassName
= szProgmanClassName
;
1264 return RegisterClass(&wcProgman
) != 0;
1268 UnregisterProgmanWindowClass(VOID
)
1270 UnregisterClass(szProgmanClassName
,
1274 typedef struct _DESKCREATEINFO
1278 IDesktopShellBrowserImpl
*pDesktop
;
1279 } DESKCREATEINFO
, *PDESKCREATEINFO
;
1281 static DWORD CALLBACK
1282 DesktopThreadProc(IN OUT LPVOID lpParameter
)
1284 volatile DESKCREATEINFO
*DeskCreateInfo
= (volatile DESKCREATEINFO
*)lpParameter
;
1286 IDesktopShellBrowserImpl
*pDesktop
;
1290 OleInitialize(NULL
);
1291 hwndDesktop
= CreateWindowEx(WS_EX_TOOLWINDOW
,
1293 szProgmanWindowName
,
1294 WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
1297 GetSystemMetrics(SM_CXVIRTUALSCREEN
),
1298 GetSystemMetrics(SM_CYVIRTUALSCREEN
),
1304 DeskCreateInfo
->hWndDesktop
= hwndDesktop
;
1305 if (hwndDesktop
== NULL
)
1308 pDesktop
= (IDesktopShellBrowserImpl
*)GetWindowLongPtr(hwndDesktop
,
1310 (void)InterlockedExchangePointer(&DeskCreateInfo
->pDesktop
,
1313 if (!SetEvent(DeskCreateInfo
->hEvent
))
1315 /* Failed to notify that we initialized successfully, kill ourselves
1316 to make the main thread wake up! */
1322 Ret
= (GetMessage(&Msg
,
1332 TranslateMessage(&Msg
);
1333 DispatchMessage(&Msg
);
1339 /* FIXME: Properly rundown the main thread! */
1346 DesktopCreateWindow(IN OUT ITrayWindow
*Tray
)
1350 DWORD DesktopThreadId
;
1351 IDesktopShellBrowserImpl
*pDesktop
= NULL
;
1354 HWND hWndDesktop
= NULL
;
1355 IShellDesktopTray
*pSdt
;
1358 if (!RegisterProgmanWindowClass())
1361 if (!RegisterTrayWindowClass())
1363 UnregisterProgmanWindowClass();
1367 if (!RegisterTaskSwitchWndClass())
1369 UnregisterProgmanWindowClass();
1370 UnregisterTrayWindowClass();
1374 hEvent
= CreateEvent(NULL
,
1380 volatile DESKCREATEINFO DeskCreateInfo
;
1382 DeskCreateInfo
.hEvent
= hEvent
;
1383 DeskCreateInfo
.pDesktop
= NULL
;
1385 hThread
= CreateThread(NULL
,
1388 (PVOID
)&DeskCreateInfo
,
1391 if (hThread
!= NULL
)
1393 Handles
[0] = hThread
;
1394 Handles
[1] = hEvent
;
1396 WaitResult
= WaitForMultipleObjects(sizeof(Handles
) / sizeof(Handles
[0]),
1400 if (WaitResult
!= WAIT_FAILED
&& WaitResult
!= WAIT_OBJECT_0
)
1402 pDesktop
= DeskCreateInfo
.pDesktop
;
1403 hWndDesktop
= DeskCreateInfo
.hWndDesktop
;
1406 CloseHandle(hThread
);
1409 CloseHandle(hEvent
);
1412 if (pDesktop
!= NULL
)
1414 hRet
= ITrayWindow_QueryInterface(Tray
,
1415 &IID_IShellDesktopTray
,
1417 if (SUCCEEDED(hRet
))
1419 IShellDesktopTray_RegisterDesktopWindow(pSdt
,
1421 IShellDesktopTray_Release(pSdt
);
1426 UnregisterProgmanWindowClass();
1427 UnregisterTrayWindowClass();
1428 UnregisterTaskSwitchWndClass();
1431 return (HANDLE
)pDesktop
;
1435 DesktopDestroyShellWindow(IN HANDLE hDesktop
)
1437 //IDesktopShellBrowserImpl *pDesktop = (IDesktopShellBrowserImpl *)hDesktop;
1439 /* FIXME - Destroy window (don't use DestroyWindow() as
1440 the window belongs to another thread!) */
1442 UnregisterProgmanWindowClass();
1443 UnregisterTrayWindowClass();
1446 #endif /* USE_API_SHCREATEDESKTOP */