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