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) *** 84 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 127 CDesktopBrowser::CDesktopBrowser(): 128 m_hAccel(NULL), 129 m_hWndShellView(NULL), 130 m_hwndChangeNotifyServer(NULL), 131 m_dwDrives(::GetLogicalDrives()) 132 { 133 SetTopBrowser(); 134 } 135 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 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 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 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 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 272 HRESULT STDMETHODCALLTYPE CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode) 273 { 274 return E_NOTIMPL; 275 } 276 277 HRESULT STDMETHODCALLTYPE CDesktopBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) 278 { 279 return E_NOTIMPL; 280 } 281 282 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject) 283 { 284 return E_NOTIMPL; 285 } 286 287 HRESULT STDMETHODCALLTYPE CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared) 288 { 289 return E_NOTIMPL; 290 } 291 292 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText) 293 { 294 return E_NOTIMPL; 295 } 296 297 HRESULT STDMETHODCALLTYPE CDesktopBrowser::EnableModelessSB(BOOL fEnable) 298 { 299 return E_NOTIMPL; 300 } 301 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 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 320 HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetViewStateStream(DWORD grfMode, IStream **ppStrm) 321 { 322 return E_NOTIMPL; 323 } 324 325 HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetControlWindow(UINT id, HWND *lphwnd) 326 { 327 if (lphwnd == NULL) 328 return E_POINTER; 329 return E_NOTIMPL; 330 } 331 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 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 350 HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnViewWindowActive(IShellView *ppshv) 351 { 352 return E_NOTIMPL; 353 } 354 355 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) 356 { 357 return E_NOTIMPL; 358 } 359 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 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 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 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 408 LRESULT CDesktopBrowser::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 409 { 410 return (LRESULT)PaintDesktop((HDC)wParam); 411 } 412 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 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 449 LRESULT CDesktopBrowser::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 450 { 451 return _NotifyTray(TWM_DOEXITWINDOWS, 0, 0); 452 } 453 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 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. 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 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 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 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 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 */ 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 */ 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 */ 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