Reactos
1/*
2 * Shell Desktop
3 *
4 * Copyright 2008 Thomas Bluemel
5 * Copyright 2020 Katayama Hirofumi MZ
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#include "shelldesktop.h"
23
24// Support for multiple monitors is disabled till LVM_SETWORKAREAS gets implemented
25#ifdef MULTIMONITOR_SUPPORT
26#include <atlcoll.h>
27#endif
28
29#include <dbt.h>
30
31WINE_DEFAULT_DEBUG_CHANNEL(desktop);
32
33static const WCHAR szProgmanClassName[] = L"Progman";
34static const WCHAR szProgmanWindowName[] = L"Program Manager";
35
36static BOOL IsDesktopBrowserForwardShellViewCmd(WORD Cmd)
37{
38 // Note: The normal CShellBrowser forwards the entire FCIDM_SHVIEWFIRST..LAST range, we do not.
39 // Note: Windows allows FCIDM_SHVIEW_SHOWINGROUPS but we don't support it nor does it make sense.
40 return (FCIDM_SHVIEW_CREATELINK <= Cmd && Cmd <= FCIDM_SHVIEW_DESELECTALL) ||
41 (FCIDM_SHVIEW_ARRANGE_AUTO <= Cmd && Cmd <= FCIDM_SHVIEW_ARRANGE_AUTOGRID) ||
42 (Cmd == FCIDM_SHVIEW_REFRESH);
43}
44
45class CDesktopBrowser :
46 public CWindowImpl<CDesktopBrowser, CWindow, CFrameWinTraits>,
47 public CComObjectRootEx<CComMultiThreadModelNoCS>,
48 public IShellBrowser,
49 public IShellBrowserService,
50 public IServiceProvider
51{
52private:
53 HACCEL m_hAccel;
54 HWND m_hWndShellView;
55 CComPtr<IShellDesktopTray> m_Tray;
56 CComPtr<IShellView> m_ShellView;
57
58 CComPtr<IOleWindow> m_ChangeNotifyServer;
59 HWND m_hwndChangeNotifyServer;
60 DWORD m_dwDrives;
61
62 LRESULT _NotifyTray(UINT uMsg, WPARAM wParam, LPARAM lParam);
63 HRESULT _Resize();
64
65public:
66 CDesktopBrowser();
67 ~CDesktopBrowser();
68 HRESULT Initialize(IShellDesktopTray *ShellDeskx);
69
70 // *** IOleWindow methods ***
71 STDMETHOD(GetWindow)(HWND *lphwnd) override;
72 STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override;
73
74 // *** IShellBrowser methods ***
75 STDMETHOD(InsertMenusSB)(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
76 STDMETHOD(SetMenuSB)(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject) override;
77 STDMETHOD(RemoveMenusSB)(HMENU hmenuShared) override;
78 STDMETHOD(SetStatusTextSB)(LPCOLESTR pszStatusText) override;
79 STDMETHOD(EnableModelessSB)(BOOL fEnable) override;
80 STDMETHOD(TranslateAcceleratorSB)(MSG *pmsg, WORD wID) override;
81 STDMETHOD(BrowseObject)(LPCITEMIDLIST pidl, UINT wFlags) override;
82 STDMETHOD(GetViewStateStream)(DWORD grfMode, IStream **ppStrm) override;
83 STDMETHOD(GetControlWindow)(UINT id, HWND *lphwnd) override;
84 STDMETHOD(SendControlMsg)(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret) override;
85 STDMETHOD(QueryActiveShellView)(struct IShellView **ppshv) override;
86 STDMETHOD(OnViewWindowActive)(struct IShellView *ppshv) override;
87 STDMETHOD(SetToolbarItems)(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) override;
88
89 // *** IShellBrowserService methods ***
90 STDMETHOD(GetPropertyBag)(long flags, REFIID riid, void **ppv) override;
91
92 // *** IBrowserService2 methods (fake for now) ***
93 inline void SetTopBrowser() const {}
94
95 // *** IServiceProvider methods ***
96 STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void **ppvObject) override;
97
98 // message handlers
99 LRESULT OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
100 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
101 LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
102 LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
103 LRESULT OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
104 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
105 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
106 LRESULT OnGetChangeNotifyServer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
107 LRESULT OnDeviceChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
108 LRESULT OnShowOptionsDlg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
109 LRESULT OnSaveState(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
110
111DECLARE_WND_CLASS_EX(szProgmanClassName, CS_DBLCLKS, COLOR_DESKTOP)
112
113BEGIN_MSG_MAP(CBaseBar)
114 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
115 MESSAGE_HANDLER(WM_SIZE, OnSize)
116 MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSettingChange)
117 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
118 MESSAGE_HANDLER(WM_CLOSE, OnClose)
119 MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW, OnOpenNewWindow)
120 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
121 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
122 MESSAGE_HANDLER(WM_DESKTOP_GET_CNOTIFY_SERVER, OnGetChangeNotifyServer)
123 MESSAGE_HANDLER(WM_DEVICECHANGE, OnDeviceChange)
124 MESSAGE_HANDLER(WM_PROGMAN_OPENSHELLSETTINGS, OnShowOptionsDlg)
125 MESSAGE_HANDLER(WM_PROGMAN_SAVESTATE, OnSaveState)
126END_MSG_MAP()
127
128BEGIN_COM_MAP(CDesktopBrowser)
129 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
130 COM_INTERFACE_ENTRY_IID(IID_IShellBrowser, IShellBrowser)
131 COM_INTERFACE_ENTRY_IID(IID_IShellBrowserService, IShellBrowserService)
132 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
133END_COM_MAP()
134};
135
136CDesktopBrowser::CDesktopBrowser():
137 m_hAccel(NULL),
138 m_hWndShellView(NULL),
139 m_hwndChangeNotifyServer(NULL),
140 m_dwDrives(::GetLogicalDrives())
141{
142 SetTopBrowser();
143}
144
145CDesktopBrowser::~CDesktopBrowser()
146{
147 if (m_ShellView.p != NULL && m_hWndShellView != NULL)
148 {
149 m_ShellView->DestroyViewWindow();
150 }
151
152 if (m_hwndChangeNotifyServer)
153 {
154 ::DestroyWindow(m_hwndChangeNotifyServer);
155 }
156}
157
158#ifdef MULTIMONITOR_SUPPORT
159BOOL CALLBACK MonitorEnumProc(
160 _In_ HMONITOR hMonitor,
161 _In_ HDC hdcMonitor,
162 _In_ LPRECT lprcMonitor,
163 _In_ LPARAM dwData
164)
165{
166 CAtlList<RECT> *list = (CAtlList<RECT>*)dwData;
167 MONITORINFO MonitorInfo;
168 MonitorInfo.cbSize = sizeof(MonitorInfo);
169 if (::GetMonitorInfoW(hMonitor, &MonitorInfo))
170 {
171 list->AddTail(MonitorInfo.rcWork);
172 }
173
174 return TRUE;
175}
176#endif
177
178HRESULT CDesktopBrowser::_Resize()
179{
180 RECT rcNewSize;
181
182#ifdef MULTIMONITOR_SUPPORT
183
184 UINT cMonitors = GetSystemMetrics(SM_CMONITORS);
185 if (cMonitors == 1)
186 {
187 SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcNewSize, 0);
188 }
189 else
190 {
191 SetRect(&rcNewSize,
192 GetSystemMetrics(SM_XVIRTUALSCREEN),
193 GetSystemMetrics(SM_YVIRTUALSCREEN),
194 GetSystemMetrics(SM_XVIRTUALSCREEN) + GetSystemMetrics(SM_CXVIRTUALSCREEN),
195 GetSystemMetrics(SM_YVIRTUALSCREEN) + GetSystemMetrics(SM_CYVIRTUALSCREEN));
196 }
197
198 ::MoveWindow(m_hWnd, rcNewSize.left, rcNewSize.top, rcNewSize.right - rcNewSize.left, rcNewSize.bottom - rcNewSize.top, TRUE);
199 ::MoveWindow(m_hWndShellView, 0, 0, rcNewSize.right - rcNewSize.left, rcNewSize.bottom - rcNewSize.top, TRUE);
200
201 if (cMonitors != 1)
202 {
203 CAtlList<RECT> list;
204 EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&list);
205 RECT* prcWorkAreas = new RECT[list.GetCount()];
206 int i = 0;
207 for (POSITION it = list.GetHeadPosition(); it; list.GetNext(it))
208 prcWorkAreas[i++] = list.GetAt(it);
209
210 HWND hwndListView = FindWindowExW(m_hWndShellView, NULL, WC_LISTVIEW, NULL);
211
212 ::SendMessageW(hwndListView, LVM_SETWORKAREAS , i, (LPARAM)prcWorkAreas);
213 }
214
215#else
216 SystemParametersInfoW(SPI_GETWORKAREA, 0, &rcNewSize, 0);
217 ::MoveWindow(m_hWnd, rcNewSize.left, rcNewSize.top, rcNewSize.right - rcNewSize.left, rcNewSize.bottom - rcNewSize.top, TRUE);
218 ::MoveWindow(m_hWndShellView, 0, 0, rcNewSize.right - rcNewSize.left, rcNewSize.bottom - rcNewSize.top, TRUE);
219
220#endif
221 return S_OK;
222}
223
224HRESULT CDesktopBrowser::Initialize(IShellDesktopTray *ShellDesk)
225{
226 CComPtr<IShellFolder> psfDesktop;
227 HRESULT hRet;
228 hRet = SHGetDesktopFolder(&psfDesktop);
229 if (FAILED_UNEXPECTEDLY(hRet))
230 return hRet;
231
232 m_Tray = ShellDesk;
233
234 Create(NULL, NULL, szProgmanWindowName, WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_TOOLWINDOW);
235 if (!m_hWnd)
236 return E_FAIL;
237
238 hRet = psfDesktop->CreateViewObject(m_hWnd, IID_PPV_ARG(IShellView, &m_ShellView));
239 if (FAILED_UNEXPECTEDLY(hRet))
240 return hRet;
241
242 m_Tray->RegisterDesktopWindow(m_hWnd);
243 if (FAILED_UNEXPECTEDLY(hRet))
244 return hRet;
245
246 BOOL fHideIcons = SHELL_GetSetting(SSF_HIDEICONS, fHideIcons);
247 FOLDERSETTINGS fs;
248 RECT rcShellView = {0,0,0,0};
249 fs.ViewMode = FVM_ICON;
250 fs.fFlags = FWF_DESKTOP | FWF_NOCLIENTEDGE | FWF_NOSCROLL | FWF_TRANSPARENT |
251 FWF_AUTOARRANGE | (fHideIcons ? FWF_NOICONS : 0);
252 hRet = m_ShellView->CreateViewWindow(NULL, &fs, (IShellBrowser *)this, &rcShellView, &m_hWndShellView);
253 if (FAILED_UNEXPECTEDLY(hRet))
254 return hRet;
255
256 _Resize();
257
258 HWND hwndListView = FindWindowExW(m_hWndShellView, NULL, WC_LISTVIEW, NULL);
259
260 m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_DESKBROWSER));
261
262#if 1
263 /* A Windows8+ specific hack */
264 ::ShowWindow(m_hWndShellView, SW_SHOW);
265 ::ShowWindow(hwndListView, SW_SHOW);
266#endif
267 ShowWindow(SW_SHOW);
268 UpdateWindow();
269
270 return hRet;
271}
272
273HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetWindow(HWND *lphwnd)
274{
275 if (lphwnd == NULL)
276 return E_POINTER;
277 *lphwnd = m_hWnd;
278 return S_OK;
279}
280
281HRESULT STDMETHODCALLTYPE CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode)
282{
283 return E_NOTIMPL;
284}
285
286HRESULT STDMETHODCALLTYPE CDesktopBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
287{
288 return E_NOTIMPL;
289}
290
291HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject)
292{
293 return E_NOTIMPL;
294}
295
296HRESULT STDMETHODCALLTYPE CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared)
297{
298 return E_NOTIMPL;
299}
300
301HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText)
302{
303 return E_NOTIMPL;
304}
305
306HRESULT STDMETHODCALLTYPE CDesktopBrowser::EnableModelessSB(BOOL fEnable)
307{
308 return E_NOTIMPL;
309}
310
311HRESULT STDMETHODCALLTYPE CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID)
312{
313 if (!::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg))
314 return S_FALSE;
315 return S_OK;
316}
317
318HRESULT STDMETHODCALLTYPE CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
319{
320 /*
321 * We should use IShellWindows interface here in order to attempt to
322 * find an open shell window that shows the requested pidl and activate it
323 */
324
325 DWORD dwFlags = ((wFlags & SBSP_EXPLOREMODE) != 0) ? SH_EXPLORER_CMDLINE_FLAG_E : 0;
326 return SHOpenNewFrame(ILClone(pidl), NULL, 0, dwFlags);
327}
328
329HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetViewStateStream(DWORD grfMode, IStream **ppStrm)
330{
331 return E_NOTIMPL;
332}
333
334HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetControlWindow(UINT id, HWND *lphwnd)
335{
336 if (lphwnd == NULL)
337 return E_POINTER;
338 return E_NOTIMPL;
339}
340
341HRESULT STDMETHODCALLTYPE CDesktopBrowser::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret)
342{
343 if (pret == NULL)
344 return E_POINTER;
345 return E_NOTIMPL;
346}
347
348HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryActiveShellView(IShellView **ppshv)
349{
350 if (ppshv == NULL)
351 return E_POINTER;
352 *ppshv = m_ShellView;
353 if (*ppshv != NULL)
354 (*ppshv)->AddRef();
355
356 return S_OK;
357}
358
359HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnViewWindowActive(IShellView *ppshv)
360{
361 return E_NOTIMPL;
362}
363
364HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags)
365{
366 return E_NOTIMPL;
367}
368
369HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetPropertyBag(long flags, REFIID riid, void **ppv)
370{
371 ITEMIDLIST deskpidl = {};
372 return SHGetViewStatePropertyBag(&deskpidl, L"Desktop", flags | SHGVSPB_ROAM, riid, ppv);
373}
374
375HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryService(REFGUID guidService, REFIID riid, PVOID *ppv)
376{
377 /* FIXME - handle guidService (SID_STopLevelBrowser for IShellBrowserService etc) */
378 return QueryInterface(riid, ppv);
379}
380
381LRESULT CDesktopBrowser::_NotifyTray(UINT uMsg, WPARAM wParam, LPARAM lParam)
382{
383 HWND hWndTray;
384 HRESULT hRet;
385
386 hRet = m_Tray->GetTrayWindow(&hWndTray);
387 if (SUCCEEDED(hRet))
388 ::PostMessageW(hWndTray, uMsg, wParam, lParam);
389
390 return 0;
391}
392
393LRESULT CDesktopBrowser::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
394{
395 switch (LOWORD(wParam))
396 {
397 case FCIDM_DESKBROWSER_CLOSE:
398 return _NotifyTray(TWM_DOEXITWINDOWS, 0, 0);
399 case FCIDM_DESKBROWSER_FOCUS:
400 if (GetKeyState(VK_SHIFT))
401 return _NotifyTray(TWM_CYCLEFOCUS, 1, 0xFFFFFFFF);
402 else
403 return _NotifyTray(TWM_CYCLEFOCUS, 1, 1);
404 case FCIDM_DESKBROWSER_SEARCH:
405 SHFindFiles(NULL, NULL);
406 break;
407 case FCIDM_DESKBROWSER_REFRESH:
408 if (m_ShellView)
409 m_ShellView->Refresh();
410 break;
411 default:
412 if (IsDesktopBrowserForwardShellViewCmd(LOWORD(wParam)) && m_hWndShellView)
413 return SendMessageW(m_hWndShellView, uMsg, wParam, lParam);
414 break;
415 }
416 return 0;
417}
418
419
420LRESULT CDesktopBrowser::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
421{
422 return (LRESULT)PaintDesktop((HDC)wParam);
423}
424
425LRESULT CDesktopBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
426{
427 if (wParam == SIZE_MINIMIZED)
428 {
429 /* Hey, we're the desktop!!! */
430 ::ShowWindow(m_hWnd, SW_RESTORE);
431 }
432
433 ::InvalidateRect(m_hWndShellView, NULL, TRUE);
434
435 return 0;
436}
437
438LRESULT CDesktopBrowser::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
439{
440 if (uMsg == WM_SETTINGCHANGE /* == WM_WININICHANGE */ &&
441 lstrcmpiW((LPCWSTR)lParam, L"Environment") == 0)
442 {
443 LPVOID lpEnvironment;
444 RegenerateUserEnvironment(&lpEnvironment, TRUE);
445 }
446 SHSettingsChanged((LPCVOID)wParam, (PCWSTR)lParam); // Invalidate cached restrictions
447
448 if (m_hWndShellView)
449 {
450 /* Forward the message */
451 ::SendMessageW(m_hWndShellView, uMsg, wParam, lParam);
452 }
453
454 if (uMsg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA && m_hWndShellView != NULL)
455 {
456 _Resize();
457 }
458
459 return 0;
460}
461
462LRESULT CDesktopBrowser::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
463{
464 return _NotifyTray(TWM_DOEXITWINDOWS, 0, 0);
465}
466
467LRESULT CDesktopBrowser::OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
468{
469 TRACE("Proxy Desktop message 1035 received.\n");
470 SHOnCWMCommandLine((HANDLE)lParam);
471 return 0;
472}
473
474LRESULT CDesktopBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
475{
476 ::SetFocus(m_hWndShellView);
477 return 0;
478}
479
480// Message WM_DESKTOP_GET_CNOTIFY_SERVER: Get or create the change notification server.
481// wParam: BOOL bCreate; The flag whether it creates or not.
482// lParam: Ignored.
483// return: The window handle of the server window.
484LRESULT CDesktopBrowser::OnGetChangeNotifyServer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
485{
486 BOOL bCreate = (BOOL)wParam;
487 if (bCreate && !::IsWindow(m_hwndChangeNotifyServer))
488 {
489 HRESULT hres = CChangeNotifyServer_CreateInstance(IID_PPV_ARG(IOleWindow, &m_ChangeNotifyServer));
490 if (FAILED_UNEXPECTEDLY(hres))
491 return NULL;
492
493 hres = m_ChangeNotifyServer->GetWindow(&m_hwndChangeNotifyServer);
494 if (FAILED_UNEXPECTEDLY(hres))
495 return NULL;
496 }
497 return (LRESULT)m_hwndChangeNotifyServer;
498}
499
500// Detect DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE
501LRESULT CDesktopBrowser::OnDeviceChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
502{
503 if (wParam != DBT_DEVICEARRIVAL && wParam != DBT_DEVICEREMOVECOMPLETE)
504 return 0;
505
506 DWORD dwDrives = ::GetLogicalDrives();
507 for (INT iDrive = 0; iDrive <= 'Z' - 'A'; ++iDrive)
508 {
509 WCHAR szPath[MAX_PATH];
510 DWORD dwBit = (1 << iDrive);
511 if (!(m_dwDrives & dwBit) && (dwDrives & dwBit)) // The drive is added
512 {
513 PathBuildRootW(szPath, iDrive);
514 SHChangeNotify(SHCNE_DRIVEADD, SHCNF_PATHW, szPath, NULL);
515 }
516 else if ((m_dwDrives & dwBit) && !(dwDrives & dwBit)) // The drive is removed
517 {
518 PathBuildRootW(szPath, iDrive);
519 SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATHW, szPath, NULL);
520 }
521 }
522
523 m_dwDrives = dwDrives;
524 return 0;
525}
526
527extern VOID WINAPI ShowFolderOptionsDialog(UINT Page, BOOL Async);
528
529LRESULT CDesktopBrowser::OnShowOptionsDlg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
530{
531 switch (wParam)
532 {
533 case 0:
534#if (NTDDI_VERSION >= NTDDI_VISTA)
535 case 2:
536 case 7:
537#endif
538 ShowFolderOptionsDialog((UINT)(UINT_PTR)wParam, TRUE);
539 break;
540 case 1:
541 _NotifyTray(WM_COMMAND, TRAYCMD_TASKBAR_PROPERTIES, 0);
542 break;
543 }
544 return 0;
545}
546
547LRESULT CDesktopBrowser::OnSaveState(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
548{
549 if (m_ShellView && !SHRestricted(REST_NOSAVESET))
550 m_ShellView->SaveViewState();
551 return 0;
552}
553
554HRESULT CDesktopBrowser_CreateInstance(IShellDesktopTray *Tray, REFIID riid, void **ppv)
555{
556 return ShellObjectCreatorInit<CDesktopBrowser, IShellDesktopTray*>(Tray, riid, ppv);
557}
558
559/*************************************************************************
560 * SHCreateDesktop [SHELL32.200]
561 *
562 */
563HANDLE WINAPI SHCreateDesktop(IShellDesktopTray *Tray)
564{
565 if (Tray == NULL)
566 {
567 SetLastError(ERROR_INVALID_PARAMETER);
568 return NULL;
569 }
570
571 CComPtr<IShellBrowser> Browser;
572 HRESULT hr = CDesktopBrowser_CreateInstance(Tray, IID_PPV_ARG(IShellBrowser, &Browser));
573 if (FAILED_UNEXPECTEDLY(hr))
574 return NULL;
575
576 return static_cast<HANDLE>(Browser.Detach());
577}
578
579/*************************************************************************
580 * SHCreateDesktop [SHELL32.201]
581 *
582 */
583BOOL WINAPI SHDesktopMessageLoop(HANDLE hDesktop)
584{
585 if (hDesktop == NULL)
586 {
587 SetLastError(ERROR_INVALID_PARAMETER);
588 return FALSE;
589 }
590
591 MSG Msg;
592 BOOL bRet;
593
594 CComPtr<IShellBrowser> browser;
595 CComPtr<IShellView> shellView;
596
597 browser.Attach(static_cast<IShellBrowser*>(hDesktop));
598 HRESULT hr = browser->QueryActiveShellView(&shellView);
599 if (FAILED_UNEXPECTEDLY(hr))
600 return FALSE;
601
602 while ((bRet = ::GetMessageW(&Msg, NULL, 0, 0)) != 0)
603 {
604 if (bRet != -1)
605 {
606 if (shellView->TranslateAcceleratorW(&Msg) != S_OK)
607 {
608 ::TranslateMessage(&Msg);
609 ::DispatchMessageW(&Msg);
610 }
611 }
612 }
613
614 return TRUE;
615}
616
617/*************************************************************************
618 * SHIsTempDisplayMode [SHELL32.724]
619 *
620 * Is the current display settings temporary?
621 */
622EXTERN_C BOOL WINAPI SHIsTempDisplayMode(VOID)
623{
624 TRACE("\n");
625
626 if (GetSystemMetrics(SM_REMOTESESSION) || GetSystemMetrics(SM_REMOTECONTROL))
627 return FALSE;
628
629 DEVMODEW DevMode;
630 ZeroMemory(&DevMode, sizeof(DevMode));
631 DevMode.dmSize = sizeof(DevMode);
632
633 if (!EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &DevMode))
634 return FALSE;
635
636 if (!DevMode.dmPelsWidth || !DevMode.dmPelsHeight)
637 return FALSE;
638
639 HDC hDC = GetDC(NULL);
640 DWORD cxWidth = GetDeviceCaps(hDC, HORZRES);
641 DWORD cyHeight = GetDeviceCaps(hDC, VERTRES);
642 ReleaseDC(NULL, hDC);
643
644 return (cxWidth != DevMode.dmPelsWidth || cyHeight != DevMode.dmPelsHeight);
645}