Bug 2988: slovak translation for downloader by kario@szm.sk
[reactos.git] / reactos / base / shell / explorer-new / desktop.c
1 /*
2 * ReactOS Explorer
3 *
4 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #include <precomp.h>
22
23 #if USE_API_SHCREATEDESKTOP
24
25 typedef struct _DESKCREATEINFO
26 {
27 HANDLE hEvent;
28 ITrayWindow *Tray;
29 HANDLE hDesktop;
30 } DESKCREATEINFO, *PDESKCREATEINFO;
31
32 static DWORD CALLBACK
33 DesktopThreadProc(IN OUT LPVOID lpParameter)
34 {
35 volatile DESKCREATEINFO *DeskCreateInfo = (volatile DESKCREATEINFO *)lpParameter;
36 IShellDesktopTray *pSdt;
37 HANDLE hDesktop;
38 HRESULT hRet;
39
40 hRet = ITrayWindow_QueryInterface(DeskCreateInfo->Tray,
41 &IID_IShellDesktopTray,
42 (PVOID*)&pSdt);
43 if (!SUCCEEDED(hRet))
44 return 1;
45
46 hDesktop = SHCreateDesktop(pSdt);
47
48 IShellDesktopTray_Release(pSdt);
49 if (hDesktop == NULL)
50 return 1;
51
52 (void)InterlockedExchangePointer(&DeskCreateInfo->hDesktop,
53 hDesktop);
54
55 if (!SetEvent(DeskCreateInfo->hEvent))
56 {
57 /* Failed to notify that we initialized successfully, kill ourselves
58 to make the main thread wake up! */
59 return 1;
60 }
61
62 SHDesktopMessageLoop(hDesktop);
63
64 /* FIXME: Properly rundown the main thread! */
65 ExitProcess(0);
66
67 return 0;
68 }
69
70 HANDLE
71 DesktopCreateWindow(IN OUT ITrayWindow *Tray)
72 {
73 HANDLE hThread;
74 HANDLE hEvent;
75 DWORD DesktopThreadId;
76 HANDLE hDesktop = NULL;
77 HANDLE Handles[2];
78 DWORD WaitResult;
79
80 hEvent = CreateEvent(NULL,
81 FALSE,
82 FALSE,
83 NULL);
84 if (hEvent != NULL)
85 {
86 volatile DESKCREATEINFO DeskCreateInfo;
87
88 DeskCreateInfo.hEvent = hEvent;
89 DeskCreateInfo.Tray = Tray;
90 DeskCreateInfo.hDesktop = NULL;
91
92 hThread = CreateThread(NULL,
93 0,
94 DesktopThreadProc,
95 (PVOID)&DeskCreateInfo,
96 0,
97 &DesktopThreadId);
98 if (hThread != NULL)
99 {
100 Handles[0] = hThread;
101 Handles[1] = hEvent;
102
103 for (;;)
104 {
105 WaitResult = MsgWaitForMultipleObjects(sizeof(Handles) / sizeof(Handles[0]),
106 Handles,
107 FALSE,
108 INFINITE,
109 QS_ALLEVENTS);
110 if (WaitResult == WAIT_OBJECT_0 + (sizeof(Handles) / sizeof(Handles[0])))
111 TrayProcessMessages(Tray);
112 else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
113 {
114 hDesktop = DeskCreateInfo.hDesktop;
115 break;
116 }
117 }
118
119 CloseHandle(hThread);
120 }
121
122 CloseHandle(hEvent);
123 }
124
125 return hDesktop;
126 }
127
128 VOID
129 DesktopDestroyShellWindow(IN HANDLE hDesktop)
130 {
131 return;
132 }
133
134 #else /* USE_API_SHCREATEDESKTOP == 0 */
135
136 /*
137 ******************************************************************************
138 * NOTE: This could may be reused in a shell implementation of *
139 * SHCreateShellFolderView(). *
140 ******************************************************************************
141 */
142
143 HRESULT WINAPI
144 SHCreateShellFolderView(
145 const SFV_CREATE *pcsfv,
146 IShellView **ppsv)
147 {
148 CSFV csfv;
149
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);
156 }
157
158
159 /*
160 ******************************************************************************
161 * NOTE: This could may be reused in a shell implementation of *
162 * SHCreateDesktop(). *
163 ******************************************************************************
164 */
165
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)
169
170 #include "undoc.h"
171 #define WM_SHELL_ADDDRIVENOTIFY (WM_USER + 0x100)
172
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;
177
178 /*
179 * IShellBrowser
180 */
181
182 typedef struct
183 {
184 const IShellBrowserVtbl *lpVtbl;
185 const ICommDlgBrowserVtbl *lpVtblCommDlgBrowser;
186 const IServiceProviderVtbl *lpVtblServiceProvider;
187 const IShellFolderViewCBVtbl *lpVtblShellFolderViewCB;
188 LONG Ref;
189
190 IShellView2 *DesktopView2;
191 IShellView *DesktopView;
192 IShellBrowser *DefaultShellBrowser;
193 HWND hWnd;
194 HWND hWndShellView;
195 HWND hWndDesktopListView;
196
197 ITrayWindow *Tray;
198
199 LPITEMIDLIST pidlDesktopDirectory;
200 LPITEMIDLIST pidlDesktop;
201 IDropTarget *DropTarget;
202
203 ULONG ChangeNotificationId;
204 } IDesktopShellBrowserImpl;
205
206 static IUnknown *
207 IUnknown_from_impl(IDesktopShellBrowserImpl *This)
208 {
209 return (IUnknown *)&This->lpVtbl;
210 }
211
212 static IShellBrowser *
213 IShellBrowser_from_impl(IDesktopShellBrowserImpl *This)
214 {
215 return (IShellBrowser *)&This->lpVtbl;
216 }
217
218 static IOleWindow *
219 IOleWindow_from_impl(IDesktopShellBrowserImpl *This)
220 {
221 return (IOleWindow *)&This->lpVtbl;
222 }
223
224 static ICommDlgBrowser *
225 ICommDlgBrowser_from_impl(IDesktopShellBrowserImpl *This)
226 {
227 return (ICommDlgBrowser *)&This->lpVtblCommDlgBrowser;
228 }
229
230 static IServiceProvider *
231 IServiceProvider_from_impl(IDesktopShellBrowserImpl *This)
232 {
233 return (IServiceProvider *)&This->lpVtblServiceProvider;
234 }
235
236 static IShellFolderViewCB *
237 IShellFolderViewCB_from_impl(IDesktopShellBrowserImpl *This)
238 {
239 return (IShellFolderViewCB *)&This->lpVtblShellFolderViewCB;
240 }
241
242 static IDesktopShellBrowserImpl *
243 impl_from_IShellBrowser(IShellBrowser *iface)
244 {
245 return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
246 lpVtbl));
247 }
248
249 static IDesktopShellBrowserImpl *
250 impl_from_ICommDlgBrowser(ICommDlgBrowser *iface)
251 {
252 return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
253 lpVtblCommDlgBrowser));
254 }
255
256 static IDesktopShellBrowserImpl *
257 impl_from_IServiceProvider(IServiceProvider *iface)
258 {
259 return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
260 lpVtblServiceProvider));
261 }
262
263 static IDesktopShellBrowserImpl *
264 impl_from_IShellFolderViewCB(IShellFolderViewCB *iface)
265 {
266 return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
267 lpVtblShellFolderViewCB));
268 }
269
270 static VOID
271 IDesktopShellBrowserImpl_Free(IDesktopShellBrowserImpl *This)
272 {
273 if (This->DropTarget != NULL)
274 {
275 IDropTarget_Release(This->DropTarget);
276 This->DropTarget = NULL;
277 }
278
279 if (This->Tray != NULL)
280 {
281 ITrayWindow_Release(This->Tray);
282 This->Tray = NULL;
283 }
284
285 if (This->pidlDesktopDirectory != NULL)
286 {
287 ILFree(This->pidlDesktopDirectory);
288 This->pidlDesktopDirectory = NULL;
289 }
290
291 if (This->pidlDesktop != NULL)
292 {
293 ILFree(This->pidlDesktop);
294 This->pidlDesktop = NULL;
295 }
296
297 HeapFree(hProcessHeap,
298 0,
299 This);
300 }
301
302 static VOID
303 IDesktopShellBrowserImpl_Destroy(IDesktopShellBrowserImpl *This)
304 {
305 if (This->ChangeNotificationId != 0)
306 {
307 SHChangeNotifyDeregister(This->ChangeNotificationId);
308 This->ChangeNotificationId = 0;
309 }
310
311 if (This->Tray != NULL)
312 {
313 ITrayWindow_Close(This->Tray);
314 This->Tray = NULL;
315 }
316
317 if (This->DropTarget != NULL && This->hWndDesktopListView != NULL)
318 {
319 RevokeDragDrop(This->hWndDesktopListView);
320 This->hWndDesktopListView = NULL;
321 }
322
323 if (This->DesktopView2 != NULL)
324 {
325 IShellView2_Release(This->DesktopView2);
326 }
327
328 if (This->DesktopView != NULL)
329 {
330 if (This->hWndShellView != NULL)
331 {
332 IShellView_DestroyViewWindow(This->DesktopView);
333 }
334
335 IShellView_Release(This->DesktopView);
336 This->DesktopView = NULL;
337 This->hWndShellView = NULL;
338 This->hWndDesktopListView = NULL;
339 }
340 }
341
342 static HRESULT
343 IDesktopShellBrowserImpl_GetNotify(IN OUT IDesktopShellBrowserImpl *This,
344 OUT LPITEMIDLIST *ppidl,
345 OUT LONG *plEvents)
346 {
347 *ppidl = This->pidlDesktopDirectory;
348 *plEvents = SHCNE_DISKEVENTS;
349 return S_OK;
350 }
351
352 static ULONG STDMETHODCALLTYPE
353 IDesktopShellBrowserImpl_Release(IN OUT IShellBrowser *iface)
354 {
355 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
356 ULONG Ret;
357
358 Ret = InterlockedDecrement(&This->Ref);
359 if (Ret == 0)
360 IDesktopShellBrowserImpl_Free(This);
361
362 return Ret;
363 }
364
365 static ULONG STDMETHODCALLTYPE
366 IDesktopShellBrowserImpl_AddRef(IN OUT IShellBrowser *iface)
367 {
368 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
369
370 return InterlockedIncrement(&This->Ref);
371 }
372
373 static HRESULT STDMETHODCALLTYPE
374 IDesktopShellBrowserImpl_QueryInterface(IN OUT IShellBrowser *iface,
375 IN REFIID riid,
376 OUT LPVOID *ppvObj)
377 {
378 IDesktopShellBrowserImpl *This;
379
380 if (ppvObj == NULL)
381 return E_POINTER;
382
383 This = impl_from_IShellBrowser(iface);
384
385 if (IsEqualIID(riid,
386 &IID_IUnknown))
387 {
388 *ppvObj = IUnknown_from_impl(This);
389 }
390 else if (This->DefaultShellBrowser != NULL)
391 {
392 return IShellBrowser_QueryInterface(This->DefaultShellBrowser,
393 riid,
394 ppvObj);
395 }
396 else if (IsEqualIID(riid,
397 &IID_IOleWindow))
398 {
399 *ppvObj = IOleWindow_from_impl(This);
400 }
401 else if (IsEqualIID(riid,
402 &IID_IShellBrowser))
403 {
404 *ppvObj = IShellBrowser_from_impl(This);
405 }
406 else if (IsEqualIID(riid,
407 &IID_ICommDlgBrowser))
408 {
409 *ppvObj = ICommDlgBrowser_from_impl(This);
410 }
411 else if (IsEqualIID(riid,
412 &IID_IServiceProvider))
413 {
414 *ppvObj = IServiceProvider_from_impl(This);
415 }
416 else if (IsEqualIID(riid,
417 &IID_IShellFolderViewCB))
418 {
419 *ppvObj = IShellFolderViewCB_from_impl(This);
420 }
421 else
422 {
423 *ppvObj = NULL;
424 return E_NOINTERFACE;
425 }
426
427 IDesktopShellBrowserImpl_AddRef(iface);
428 return S_OK;
429 }
430
431 static IDesktopShellBrowserImpl *
432 IDesktopShellBrowserImpl_Construct(IN HWND hwndParent,
433 IN LPCREATESTRUCT lpCreateStruct OPTIONAL)
434 {
435 IDesktopShellBrowserImpl *This;
436 IShellBrowser *ShellBrowser;
437 IShellFolder *psfDesktopFolder;
438 #if 1
439 SFV_CREATE csfv;
440 #endif
441 FOLDERSETTINGS fs;
442 HRESULT hr;
443 RECT rcClient;
444 SHChangeNotifyEntry cne;
445
446 This = HeapAlloc(hProcessHeap,
447 0,
448 sizeof(*This));
449 if (This == NULL)
450 return NULL;
451
452 ZeroMemory(This,
453 sizeof(*This));
454 This->lpVtbl = &IDesktopShellBrowserImpl_Vtbl;
455 This->lpVtblCommDlgBrowser = &IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl;
456 This->lpVtblServiceProvider = &IDesktopShellBrowserImpl_IServiceProvider_Vtbl;
457 This->lpVtblShellFolderViewCB = &IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl;
458 This->Ref = 1;
459 This->hWnd = hwndParent;
460
461 ShellBrowser = IShellBrowser_from_impl(This);
462
463 This->pidlDesktopDirectory = SHCloneSpecialIDList(This->hWnd,
464 CSIDL_DESKTOPDIRECTORY,
465 FALSE);
466
467 hr = SHGetSpecialFolderLocation(This->hWnd,
468 CSIDL_DESKTOP,
469 &This->pidlDesktop);
470 if (!SUCCEEDED(hr))
471 goto Fail;
472
473 #if 1
474 hr = SHGetDesktopFolder(&psfDesktopFolder);
475 #else
476 hr = CoCreateInstance(&CLSID_ShellDesktop,
477 NULL,
478 CLSCTX_INPROC,
479 &IID_IShellFolder,
480 (PVOID*)&psfDesktopFolder);
481 #endif
482 if (!SUCCEEDED(hr))
483 goto Fail;
484
485 #if 0
486 hr = IShellFolder_CreateViewObject(psfDesktopFolder,
487 This->hWnd,
488 &IID_IShellView,
489 (PVOID*)&This->DesktopView);
490 #else
491 csfv.cbSize = sizeof(csfv);
492 csfv.pshf = psfDesktopFolder;
493 csfv.psvOuter = NULL;
494
495 hr = IDesktopShellBrowserImpl_QueryInterface(ShellBrowser,
496 &IID_IShellFolderViewCB,
497 (PVOID*)&csfv.psfvcb);
498 if (!SUCCEEDED(hr))
499 csfv.psfvcb = NULL;
500
501 hr = SHCreateShellFolderView(&csfv,
502 &This->DesktopView);
503
504 IShellFolder_Release(psfDesktopFolder);
505
506 if (csfv.psfvcb != NULL)
507 csfv.psfvcb->lpVtbl->Release(csfv.psfvcb);
508 #endif
509 if (!SUCCEEDED(hr))
510 goto Fail;
511
512 hr = IShellView_QueryInterface(This->DesktopView,
513 &IID_IShellView2,
514 (PVOID*)&This->DesktopView2);
515 if (!SUCCEEDED(hr))
516 This->DesktopView2 = NULL;
517
518 if (lpCreateStruct == NULL)
519 {
520 if (!GetClientRect(This->hWnd,
521 &rcClient))
522 {
523 goto Fail;
524 }
525 }
526 else
527 {
528 rcClient.left = 0;
529 rcClient.top = 0;
530 rcClient.right = lpCreateStruct->cx;
531 rcClient.bottom = lpCreateStruct->cy;
532 }
533
534 fs.ViewMode = FVM_ICON;
535 fs.fFlags = FWF_DESKTOP | FWF_NOCLIENTEDGE | FWF_NOSCROLL | FWF_TRANSPARENT;
536 if (This->DesktopView2 != NULL)
537 {
538 SV2CVW2_PARAMS params;
539
540 params.cbSize = sizeof(params);
541 params.psvPrev = NULL;
542 params.pfs = &fs;
543 params.psbOwner = ShellBrowser;
544 params.prcView = &rcClient;
545 params.pvid = &VID_LargeIcons;
546 hr = IShellView2_CreateViewWindow2(This->DesktopView2,
547 &params);
548
549 if (FAILED(hr))
550 goto DefCreateViewWindow;
551 This->hWndShellView = params.hwndView;
552 }
553 else
554 {
555 DefCreateViewWindow:
556 hr = IShellView_CreateViewWindow(This->DesktopView,
557 NULL,
558 &fs,
559 ShellBrowser,
560 &rcClient,
561 &This->hWndShellView);
562 }
563 if (!SUCCEEDED(hr))
564 goto Fail;
565
566 IShellView_EnableModeless(This->DesktopView,
567 TRUE);
568
569 hr = IShellView_UIActivate(This->DesktopView,
570 SVUIA_ACTIVATE_FOCUS);
571 if (!SUCCEEDED(hr))
572 {
573 IShellView_DestroyViewWindow(This->DesktopView);
574
575 Fail:
576 /* NOTE: the other references will be released in the
577 WM_NCDESTROY handler! */
578 IDesktopShellBrowserImpl_Release(ShellBrowser);
579 return NULL;
580 }
581
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,
587 NULL,
588 WC_LISTVIEW,
589 NULL);
590
591 if (This->hWndDesktopListView != NULL)
592 {
593 /* Register drag&drop */
594 hr = IShellView_QueryInterface(This->DesktopView,
595 &IID_IDropTarget,
596 (PVOID*)&This->DropTarget);
597 if (SUCCEEDED(hr))
598 {
599 hr = RegisterDragDrop(This->hWndDesktopListView,
600 This->DropTarget);
601 if (!SUCCEEDED(hr))
602 {
603 IDropTarget_Release(This->DropTarget);
604 This->DropTarget = NULL;
605 }
606 }
607 }
608
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. */
611 cne.pidl = NULL;
612 cne.fRecursive = TRUE;
613 This->ChangeNotificationId = SHChangeNotifyRegister(This->hWnd,
614 SHCNRF_ShellLevel | SHCNRF_NewDelivery,
615 SHCNE_DRIVEADDGUI,
616 WM_SHELL_ADDDRIVENOTIFY,
617 1,
618 &cne);
619
620 /* Create the tray window */
621 This->Tray = CreateTrayWindow();
622 return This;
623 }
624
625 static HRESULT STDMETHODCALLTYPE
626 IDesktopShellBrowserImpl_GetWindow(IN OUT IShellBrowser *iface,
627 OUT HWND *phwnd)
628 {
629 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
630
631 if (This->hWnd != NULL)
632 {
633 *phwnd = This->hWnd;
634 return S_OK;
635 }
636
637 *phwnd = NULL;
638 return E_UNEXPECTED;
639 }
640
641 static HRESULT STDMETHODCALLTYPE
642 IDesktopShellBrowserImpl_ContextSensitiveHelp(IN OUT IShellBrowser *iface,
643 IN BOOL fEnterMode)
644 {
645 return E_NOTIMPL;
646 }
647
648 static HRESULT STDMETHODCALLTYPE
649 IDesktopShellBrowserImpl_InsertMenusSB(IN OUT IShellBrowser *iface,
650 IN HMENU hmenuShared,
651 OUT LPOLEMENUGROUPWIDTHS lpMenuWidths)
652 {
653 return E_NOTIMPL;
654 }
655
656 static HRESULT STDMETHODCALLTYPE
657 IDesktopShellBrowserImpl_SetMenuSB(IN OUT IShellBrowser *iface,
658 IN HMENU hmenuShared,
659 IN HOLEMENU holemenuRes,
660 IN HWND hwndActiveObject)
661 {
662 return E_NOTIMPL;
663 }
664
665 static HRESULT STDMETHODCALLTYPE
666 IDesktopShellBrowserImpl_RemoveMenusSB(IN OUT IShellBrowser *iface,
667 IN HMENU hmenuShared)
668 {
669 return E_NOTIMPL;
670 }
671
672 static HRESULT STDMETHODCALLTYPE
673 IDesktopShellBrowserImpl_SetStatusTextSB(IN OUT IShellBrowser *iface,
674 IN LPCOLESTR lpszStatusText)
675 {
676 return E_NOTIMPL;
677 }
678
679 static HRESULT STDMETHODCALLTYPE
680 IDesktopShellBrowserImpl_EnableModelessSB(IN OUT IShellBrowser *iface,
681 IN BOOL fEnable)
682 {
683 return E_NOTIMPL;
684 }
685
686 static HRESULT STDMETHODCALLTYPE
687 IDesktopShellBrowserImpl_TranslateAcceleratorSB(IN OUT IShellBrowser *iface,
688 IN LPMSG lpmsg,
689 IN WORD wID)
690 {
691 return S_FALSE;
692 }
693
694 static HRESULT STDMETHODCALLTYPE
695 IDesktopShellBrowserImpl_BrowseObject(IN OUT IShellBrowser *iface,
696 IN LPCITEMIDLIST pidl,
697 IN UINT wFlags)
698 {
699 return E_NOTIMPL;
700 }
701
702 static HRESULT STDMETHODCALLTYPE
703 IDesktopShellBrowserImpl_GetViewStateStream(IN OUT IShellBrowser *iface,
704 IN DWORD grfMode,
705 OUT IStream **ppStrm)
706 {
707 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
708 static WCHAR szItemPos[] = L"ItemPos";
709 HRESULT hRet;
710 IPropertyBag *PropBag = NULL;
711 WCHAR szPropName[64];
712
713 /* Determine the name of the property that contains the stream of
714 icon positions */
715 wcscpy(szPropName,
716 szItemPos);
717 hRet = SHGetPerScreenResName(szPropName + wcslen(szPropName),
718 (sizeof(szPropName) / sizeof(szPropName[0])) - wcslen(szPropName),
719 0);
720 if (SUCCEEDED(hRet))
721 {
722 /* Locate the property bag for the desktop */
723 hRet = SHGetViewStatePropertyBag(This->pidlDesktop,
724 L"Desktop",
725 SHGVSPB_FOLDERNODEFAULTS | SHGVSPB_ROAM,
726 &IID_IPropertyBag,
727 (PVOID*)&PropBag);
728
729 if (SUCCEEDED(hRet))
730 {
731 /* Create a stream for the ItemPos property */
732 hRet = SHPropertyBag_ReadStream(PropBag,
733 szPropName,
734 ppStrm);
735
736 IPropertyBag_Release(PropBag);
737
738 if (SUCCEEDED(hRet))
739 {
740 /* FIXME: For some reason the shell doesn't position the icons... */
741 }
742 }
743 }
744
745 return hRet;
746 }
747
748 static HWND
749 DesktopGetWindowControl(IN IDesktopShellBrowserImpl *This,
750 IN UINT id)
751 {
752 switch (id)
753 {
754 case FCW_TOOLBAR:
755 case FCW_STATUS:
756 case FCW_TREE:
757 case FCW_PROGRESS:
758 return NULL;
759
760 default:
761 return NULL;
762 }
763
764 }
765
766 static HRESULT STDMETHODCALLTYPE
767 IDesktopShellBrowserImpl_GetControlWindow(IN OUT IShellBrowser *iface,
768 IN UINT id,
769 OUT HWND *lphwnd)
770 {
771 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
772 HWND hWnd;
773
774 hWnd = DesktopGetWindowControl(This,
775 id);
776 if (hWnd != NULL)
777 {
778 *lphwnd = hWnd;
779 return S_OK;
780 }
781
782 *lphwnd = NULL;
783 return E_NOTIMPL;
784 }
785
786 static HRESULT STDMETHODCALLTYPE
787 IDesktopShellBrowserImpl_SendControlMsg(IN OUT IShellBrowser *iface,
788 IN UINT id,
789 IN UINT uMsg,
790 IN WPARAM wParam,
791 IN LPARAM lParam,
792 OUT LRESULT *pret)
793 {
794 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
795 HWND hWnd;
796
797 if (pret == NULL)
798 return E_POINTER;
799
800 hWnd = DesktopGetWindowControl(This,
801 id);
802 if (hWnd != NULL)
803 {
804 *pret = SendMessage(hWnd,
805 uMsg,
806 wParam,
807 lParam);
808 return S_OK;
809 }
810
811 return E_NOTIMPL;
812 }
813
814 static HRESULT STDMETHODCALLTYPE
815 IDesktopShellBrowserImpl_QueryActiveShellView(IN OUT IShellBrowser *iface,
816 OUT IShellView **ppshv)
817 {
818 IShellView *ActiveView;
819 IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
820
821 ActiveView = This->DesktopView;
822 IDesktopShellBrowserImpl_AddRef(iface);
823 *ppshv = ActiveView;
824
825 return S_OK;
826 }
827
828 static HRESULT STDMETHODCALLTYPE
829 IDesktopShellBrowserImpl_OnViewWindowActive(IN OUT IShellBrowser *iface,
830 IN OUT IShellView *ppshv)
831 {
832 return E_NOTIMPL;
833 }
834
835 static HRESULT STDMETHODCALLTYPE
836 IDesktopShellBrowserImpl_SetToolbarItems(IN OUT IShellBrowser *iface,
837 IN LPTBBUTTON lpButtons,
838 IN UINT nButtons,
839 IN UINT uFlags)
840 {
841 return E_NOTIMPL;
842 }
843
844 static const IShellBrowserVtbl IDesktopShellBrowserImpl_Vtbl =
845 {
846 /* IUnknown */
847 IDesktopShellBrowserImpl_QueryInterface,
848 IDesktopShellBrowserImpl_AddRef,
849 IDesktopShellBrowserImpl_Release,
850 /* IOleWindow */
851 IDesktopShellBrowserImpl_GetWindow,
852 IDesktopShellBrowserImpl_ContextSensitiveHelp,
853 /* IShellBrowser */
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
867 };
868
869 /*
870 * ICommDlgBrowser
871 */
872
873 static HRESULT STDMETHODCALLTYPE
874 IDesktopShellBrowserImpl_ICommDlgBrowser_QueryInterface(IN OUT ICommDlgBrowser *iface,
875 IN REFIID riid,
876 OUT LPVOID *ppvObj)
877 {
878 IDesktopShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
879 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
880
881 return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser,
882 riid,
883 ppvObj);
884 }
885
886 static ULONG STDMETHODCALLTYPE
887 IDesktopShellBrowserImpl_ICommDlgBrowser_Release(IN OUT ICommDlgBrowser *iface)
888 {
889 IDesktopShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
890 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
891
892 return IDesktopShellBrowserImpl_Release(ShellBrowser);
893 }
894
895 static ULONG STDMETHODCALLTYPE
896 IDesktopShellBrowserImpl_ICommDlgBrowser_AddRef(IN OUT ICommDlgBrowser *iface)
897 {
898 IDesktopShellBrowserImpl *This = impl_from_ICommDlgBrowser(iface);
899 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
900
901 return IDesktopShellBrowserImpl_AddRef(ShellBrowser);
902 }
903
904 static HRESULT STDMETHODCALLTYPE
905 IDesktopShellBrowserImpl_ICommDlgBrowser_OnDefaultCommand(IN OUT ICommDlgBrowser *iface,
906 IN OUT IShellView *ppshv)
907 {
908 return E_NOTIMPL;
909 }
910
911 static HRESULT STDMETHODCALLTYPE
912 IDesktopShellBrowserImpl_ICommDlgBrowser_OnStateChange(IN OUT ICommDlgBrowser *iface,
913 IN OUT IShellView *ppshv,
914 IN ULONG uChange)
915 {
916 return S_OK;
917 }
918
919 static HRESULT STDMETHODCALLTYPE
920 IDesktopShellBrowserImpl_ICommDlgBrowser_IncludeObject(IN OUT ICommDlgBrowser *iface,
921 IN OUT IShellView *ppshv,
922 IN LPCITEMIDLIST pidl)
923 {
924 return S_OK;
925 }
926
927 static const ICommDlgBrowserVtbl IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl =
928 {
929 /* IUnknown */
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
937 };
938
939 /*
940 * IServiceProvider
941 */
942
943 static HRESULT STDMETHODCALLTYPE
944 IDesktopShellBrowserImpl_IServiceProvider_QueryInterface(IN OUT IServiceProvider *iface,
945 IN REFIID riid,
946 OUT LPVOID *ppvObj)
947 {
948 IDesktopShellBrowserImpl *This = impl_from_IServiceProvider(iface);
949 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
950
951 return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser,
952 riid,
953 ppvObj);
954 }
955
956 static ULONG STDMETHODCALLTYPE
957 IDesktopShellBrowserImpl_IServiceProvider_Release(IN OUT IServiceProvider *iface)
958 {
959 IDesktopShellBrowserImpl *This = impl_from_IServiceProvider(iface);
960 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
961
962 return IDesktopShellBrowserImpl_Release(ShellBrowser);
963 }
964
965 static ULONG STDMETHODCALLTYPE
966 IDesktopShellBrowserImpl_IServiceProvider_AddRef(IN OUT IServiceProvider *iface)
967 {
968 IDesktopShellBrowserImpl *This = impl_from_IServiceProvider(iface);
969 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
970
971 return IDesktopShellBrowserImpl_AddRef(ShellBrowser);
972 }
973
974 static HRESULT STDMETHODCALLTYPE
975 IDesktopShellBrowserImpl_IServiceProvider_QueryService(IN OUT IServiceProvider *iface,
976 IN REFGUID guidService,
977 IN REFIID riid,
978 OUT PVOID *ppv)
979 {
980 /* FIXME - handle guidService */
981 return IDesktopShellBrowserImpl_IServiceProvider_QueryInterface(iface,
982 riid,
983 ppv);
984 }
985
986 static const IServiceProviderVtbl IDesktopShellBrowserImpl_IServiceProvider_Vtbl =
987 {
988 /* IUnknown */
989 IDesktopShellBrowserImpl_IServiceProvider_QueryInterface,
990 IDesktopShellBrowserImpl_IServiceProvider_AddRef,
991 IDesktopShellBrowserImpl_IServiceProvider_Release,
992 /* IServiceProvider */
993 IDesktopShellBrowserImpl_IServiceProvider_QueryService
994 };
995
996 /*
997 * IShellFolderViewCB
998 */
999
1000 static HRESULT STDMETHODCALLTYPE
1001 IDesktopShellBrowserImpl_IShellFolderViewCB_QueryInterface(IN OUT IShellFolderViewCB *iface,
1002 IN REFIID riid,
1003 OUT LPVOID *ppvObj)
1004 {
1005 IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
1006 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
1007
1008 return IDesktopShellBrowserImpl_QueryInterface(ShellBrowser,
1009 riid,
1010 ppvObj);
1011 }
1012
1013 static ULONG STDMETHODCALLTYPE
1014 IDesktopShellBrowserImpl_IShellFolderViewCB_Release(IN OUT IShellFolderViewCB *iface)
1015 {
1016 IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
1017 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
1018
1019 return IDesktopShellBrowserImpl_Release(ShellBrowser);
1020 }
1021
1022 static ULONG STDMETHODCALLTYPE
1023 IDesktopShellBrowserImpl_IShellFolderViewCB_AddRef(IN OUT IShellFolderViewCB *iface)
1024 {
1025 IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
1026 IShellBrowser *ShellBrowser = IShellBrowser_from_impl(This);
1027
1028 return IDesktopShellBrowserImpl_AddRef(ShellBrowser);
1029 }
1030
1031 static HRESULT STDMETHODCALLTYPE
1032 IDesktopShellBrowserImpl_IShellFolderViewCB_MessageSFVCB(IN OUT IShellFolderViewCB *iface,
1033 IN UINT uMsg,
1034 IN WPARAM wParam,
1035 IN LPARAM lParam)
1036 {
1037 IDesktopShellBrowserImpl *This = impl_from_IShellFolderViewCB(iface);
1038 HRESULT hr = S_OK;
1039 switch (uMsg)
1040 {
1041 case SFVM_GETNOTIFY:
1042 hr = IDesktopShellBrowserImpl_GetNotify(This,
1043 (LPITEMIDLIST *)wParam,
1044 (LONG *)lParam);
1045 break;
1046
1047 case SFVM_FSNOTIFY:
1048 hr = S_OK;
1049 break;
1050
1051 default:
1052 hr = E_NOTIMPL;
1053 break;
1054 }
1055
1056 return hr;
1057 }
1058
1059 static const IShellFolderViewCBVtbl IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl =
1060 {
1061 /* IUnknown */
1062 IDesktopShellBrowserImpl_IShellFolderViewCB_QueryInterface,
1063 IDesktopShellBrowserImpl_IShellFolderViewCB_AddRef,
1064 IDesktopShellBrowserImpl_IShellFolderViewCB_Release,
1065 /* IShellFolderViewCB */
1066 IDesktopShellBrowserImpl_IShellFolderViewCB_MessageSFVCB
1067 };
1068
1069 /*****************************************************************************/
1070
1071 static const TCHAR szProgmanClassName[] = TEXT("Progman");
1072 static const TCHAR szProgmanWindowName[] = TEXT("Program Manager");
1073
1074 static VOID
1075 PositionIcons(IN OUT IDesktopShellBrowserImpl *This,
1076 IN const RECT *prcDesktopRect)
1077 {
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 */
1081 return;
1082 }
1083
1084 static VOID
1085 UpdateWorkArea(IN OUT IDesktopShellBrowserImpl *This,
1086 IN const RECT *prcDesktopRect)
1087 {
1088 RECT rcDesktopRect;
1089 LONG Style;
1090
1091 Style = GetWindowLong(This->hWndDesktopListView,
1092 GWL_STYLE);
1093
1094 if (!(Style & LVS_AUTOARRANGE ) &&
1095 GetWindowRect(This->hWnd,
1096 &rcDesktopRect))
1097 {
1098 /* Only resize the desktop if it was resized to something other
1099 than the virtual screen size/position! */
1100 if (!EqualRect(prcDesktopRect,
1101 &rcDesktopRect))
1102 {
1103 SetWindowPos(This->hWnd,
1104 NULL,
1105 prcDesktopRect->left,
1106 prcDesktopRect->top,
1107 prcDesktopRect->right - prcDesktopRect->left,
1108 prcDesktopRect->bottom - prcDesktopRect->top,
1109 SWP_NOZORDER | SWP_NOACTIVATE);
1110
1111 /* Let's try to rearrange the icons on the desktop. This is
1112 especially neccessary when switching screen resolutions... */
1113 PositionIcons(This,
1114 prcDesktopRect);
1115 }
1116 }
1117 }
1118
1119 static LRESULT CALLBACK
1120 ProgmanWindowProc(IN HWND hwnd,
1121 IN UINT uMsg,
1122 IN WPARAM wParam,
1123 IN LPARAM lParam)
1124 {
1125 IDesktopShellBrowserImpl *This = NULL;
1126 LRESULT Ret = FALSE;
1127
1128 if (uMsg != WM_NCCREATE)
1129 {
1130 This = (IDesktopShellBrowserImpl*)GetWindowLongPtr(hwnd,
1131 0);
1132 }
1133
1134 if (This != NULL || uMsg == WM_NCCREATE)
1135 {
1136 switch (uMsg)
1137 {
1138 case WM_ERASEBKGND:
1139 PaintDesktop((HDC)wParam);
1140 break;
1141
1142 case WM_GETISHELLBROWSER:
1143 Ret = (LRESULT)IShellBrowser_from_impl(This);
1144 break;
1145
1146 case WM_SHELL_ADDDRIVENOTIFY:
1147 {
1148 HANDLE hLock;
1149 LPITEMIDLIST *ppidl;
1150 LONG lEventId;
1151
1152 hLock = SHChangeNotification_Lock((HANDLE)wParam,
1153 (DWORD)lParam,
1154 &ppidl,
1155 &lEventId);
1156 if (hLock != NULL)
1157 {
1158 /* FIXME */
1159 SHChangeNotification_Unlock(hLock);
1160 }
1161 break;
1162 }
1163
1164 case WM_SIZE:
1165 if (wParam == SIZE_MINIMIZED)
1166 {
1167 /* Hey, we're the desktop!!! */
1168 ShowWindow(hwnd,
1169 SW_RESTORE);
1170 }
1171 else
1172 {
1173 RECT rcDesktop;
1174
1175 rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
1176 rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
1177 rcDesktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
1178 rcDesktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
1179
1180 UpdateWorkArea(This,
1181 &rcDesktop);
1182 }
1183 break;
1184
1185 case WM_SYSCOLORCHANGE:
1186 {
1187 InvalidateRect(This->hWnd,
1188 NULL,
1189 TRUE);
1190
1191 if (This->hWndShellView != NULL)
1192 {
1193 /* Forward the message */
1194 SendMessage(This->hWndShellView,
1195 WM_SYSCOLORCHANGE,
1196 wParam,
1197 lParam);
1198 }
1199 break;
1200 }
1201
1202 case WM_NCCREATE:
1203 {
1204 LPCREATESTRUCT CreateStruct = (LPCREATESTRUCT)lParam;
1205 This = IDesktopShellBrowserImpl_Construct(hwnd,
1206 CreateStruct);
1207 if (This == NULL)
1208 break;
1209
1210 SetWindowLongPtr(hwnd,
1211 0,
1212 (LONG_PTR)This);
1213
1214 if (This->hWndShellView != NULL)
1215 SetShellWindowEx(This->hWnd,
1216 This->hWndDesktopListView);
1217 else
1218 SetShellWindow(This->hWnd);
1219
1220 Ret = TRUE;
1221 break;
1222 }
1223
1224 case WM_DESTROY:
1225 {
1226 IDesktopShellBrowserImpl_Destroy(This);
1227 break;
1228 }
1229
1230 case WM_NCDESTROY:
1231 {
1232 IDesktopShellBrowserImpl_Release(IShellBrowser_from_impl(This));
1233
1234 PostQuitMessage(0);
1235 break;
1236 }
1237
1238 default:
1239 Ret = DefWindowProc(hwnd, uMsg, wParam, lParam);
1240 break;
1241 }
1242 }
1243
1244 return Ret;
1245 }
1246
1247 static BOOL
1248 RegisterProgmanWindowClass(VOID)
1249 {
1250 WNDCLASS wcProgman;
1251
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,
1259 IDC_ARROW);
1260 wcProgman.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
1261 wcProgman.lpszMenuName = NULL;
1262 wcProgman.lpszClassName = szProgmanClassName;
1263
1264 return RegisterClass(&wcProgman) != 0;
1265 }
1266
1267 static VOID
1268 UnregisterProgmanWindowClass(VOID)
1269 {
1270 UnregisterClass(szProgmanClassName,
1271 hExplorerInstance);
1272 }
1273
1274 typedef struct _DESKCREATEINFO
1275 {
1276 HANDLE hEvent;
1277 HWND hWndDesktop;
1278 IDesktopShellBrowserImpl *pDesktop;
1279 } DESKCREATEINFO, *PDESKCREATEINFO;
1280
1281 static DWORD CALLBACK
1282 DesktopThreadProc(IN OUT LPVOID lpParameter)
1283 {
1284 volatile DESKCREATEINFO *DeskCreateInfo = (volatile DESKCREATEINFO *)lpParameter;
1285 HWND hwndDesktop;
1286 IDesktopShellBrowserImpl *pDesktop;
1287 MSG Msg;
1288 BOOL Ret;
1289
1290 OleInitialize(NULL);
1291 hwndDesktop = CreateWindowEx(WS_EX_TOOLWINDOW,
1292 szProgmanClassName,
1293 szProgmanWindowName,
1294 WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
1295 0,
1296 0,
1297 GetSystemMetrics(SM_CXVIRTUALSCREEN),
1298 GetSystemMetrics(SM_CYVIRTUALSCREEN),
1299 NULL,
1300 NULL,
1301 hExplorerInstance,
1302 NULL);
1303
1304 DeskCreateInfo->hWndDesktop = hwndDesktop;
1305 if (hwndDesktop == NULL)
1306 return 1;
1307
1308 pDesktop = (IDesktopShellBrowserImpl*)GetWindowLongPtr(hwndDesktop,
1309 0);
1310 (void)InterlockedExchangePointer(&DeskCreateInfo->pDesktop,
1311 pDesktop);
1312
1313 if (!SetEvent(DeskCreateInfo->hEvent))
1314 {
1315 /* Failed to notify that we initialized successfully, kill ourselves
1316 to make the main thread wake up! */
1317 return 1;
1318 }
1319
1320 while (1)
1321 {
1322 Ret = (GetMessage(&Msg,
1323 NULL,
1324 0,
1325 0) != 0);
1326
1327 if (Ret != -1)
1328 {
1329 if (!Ret)
1330 break;
1331
1332 TranslateMessage(&Msg);
1333 DispatchMessage(&Msg);
1334 }
1335 }
1336
1337 OleUninitialize();
1338
1339 /* FIXME: Properly rundown the main thread! */
1340 ExitProcess(0);
1341
1342 return 0;
1343 }
1344
1345 HANDLE
1346 DesktopCreateWindow(IN OUT ITrayWindow *Tray)
1347 {
1348 HANDLE hThread;
1349 HANDLE hEvent;
1350 DWORD DesktopThreadId;
1351 IDesktopShellBrowserImpl *pDesktop = NULL;
1352 HANDLE Handles[2];
1353 DWORD WaitResult;
1354 HWND hWndDesktop = NULL;
1355 IShellDesktopTray *pSdt;
1356 HRESULT hRet;
1357
1358 if (!RegisterProgmanWindowClass())
1359 return NULL;
1360
1361 if (!RegisterTrayWindowClass())
1362 {
1363 UnregisterProgmanWindowClass();
1364 return NULL;
1365 }
1366
1367 if (!RegisterTaskSwitchWndClass())
1368 {
1369 UnregisterProgmanWindowClass();
1370 UnregisterTrayWindowClass();
1371 return NULL;
1372 }
1373
1374 hEvent = CreateEvent(NULL,
1375 FALSE,
1376 FALSE,
1377 NULL);
1378 if (hEvent != NULL)
1379 {
1380 volatile DESKCREATEINFO DeskCreateInfo;
1381
1382 DeskCreateInfo.hEvent = hEvent;
1383 DeskCreateInfo.pDesktop = NULL;
1384
1385 hThread = CreateThread(NULL,
1386 0,
1387 DesktopThreadProc,
1388 (PVOID)&DeskCreateInfo,
1389 0,
1390 &DesktopThreadId);
1391 if (hThread != NULL)
1392 {
1393 Handles[0] = hThread;
1394 Handles[1] = hEvent;
1395
1396 WaitResult = WaitForMultipleObjects(sizeof(Handles) / sizeof(Handles[0]),
1397 Handles,
1398 FALSE,
1399 INFINITE);
1400 if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
1401 {
1402 pDesktop = DeskCreateInfo.pDesktop;
1403 hWndDesktop = DeskCreateInfo.hWndDesktop;
1404 }
1405
1406 CloseHandle(hThread);
1407 }
1408
1409 CloseHandle(hEvent);
1410 }
1411
1412 if (pDesktop != NULL)
1413 {
1414 hRet = ITrayWindow_QueryInterface(Tray,
1415 &IID_IShellDesktopTray,
1416 (PVOID*)&pSdt);
1417 if (SUCCEEDED(hRet))
1418 {
1419 IShellDesktopTray_RegisterDesktopWindow(pSdt,
1420 hWndDesktop);
1421 IShellDesktopTray_Release(pSdt);
1422 }
1423 }
1424 else
1425 {
1426 UnregisterProgmanWindowClass();
1427 UnregisterTrayWindowClass();
1428 UnregisterTaskSwitchWndClass();
1429 }
1430
1431 return (HANDLE)pDesktop;
1432 }
1433
1434 VOID
1435 DesktopDestroyShellWindow(IN HANDLE hDesktop)
1436 {
1437 //IDesktopShellBrowserImpl *pDesktop = (IDesktopShellBrowserImpl *)hDesktop;
1438
1439 /* FIXME - Destroy window (don't use DestroyWindow() as
1440 the window belongs to another thread!) */
1441
1442 UnregisterProgmanWindowClass();
1443 UnregisterTrayWindowClass();
1444 }
1445
1446 #endif /* USE_API_SHCREATEDESKTOP */