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 CSFV csfv = {sizeof(CSFV), psfDesktop}; 230 hRet = SHCreateShellFolderViewEx(&csfv, &m_ShellView); 231 if (FAILED_UNEXPECTEDLY(hRet)) 232 return hRet; 233 234 m_Tray->RegisterDesktopWindow(m_hWnd); 235 if (FAILED_UNEXPECTEDLY(hRet)) 236 return hRet; 237 238 BOOL fHideIcons = SHELL_GetSetting(SSF_HIDEICONS, fHideIcons); 239 FOLDERSETTINGS fs; 240 RECT rcShellView = {0,0,0,0}; 241 fs.ViewMode = FVM_ICON; 242 fs.fFlags = FWF_DESKTOP | FWF_NOCLIENTEDGE | FWF_NOSCROLL | FWF_TRANSPARENT | 243 FWF_AUTOARRANGE | (fHideIcons ? FWF_NOICONS : 0); 244 hRet = m_ShellView->CreateViewWindow(NULL, &fs, (IShellBrowser *)this, &rcShellView, &m_hWndShellView); 245 if (FAILED_UNEXPECTEDLY(hRet)) 246 return hRet; 247 248 _Resize(); 249 250 HWND hwndListView = FindWindowExW(m_hWndShellView, NULL, WC_LISTVIEW, NULL); 251 252 m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_DESKBROWSER)); 253 254 #if 1 255 /* A Windows8+ specific hack */ 256 ::ShowWindow(m_hWndShellView, SW_SHOW); 257 ::ShowWindow(hwndListView, SW_SHOW); 258 #endif 259 ShowWindow(SW_SHOW); 260 UpdateWindow(); 261 262 return hRet; 263 } 264 265 HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetWindow(HWND *lphwnd) 266 { 267 if (lphwnd == NULL) 268 return E_POINTER; 269 *lphwnd = m_hWnd; 270 return S_OK; 271 } 272 273 HRESULT STDMETHODCALLTYPE CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode) 274 { 275 return E_NOTIMPL; 276 } 277 278 HRESULT STDMETHODCALLTYPE CDesktopBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) 279 { 280 return E_NOTIMPL; 281 } 282 283 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject) 284 { 285 return E_NOTIMPL; 286 } 287 288 HRESULT STDMETHODCALLTYPE CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared) 289 { 290 return E_NOTIMPL; 291 } 292 293 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText) 294 { 295 return E_NOTIMPL; 296 } 297 298 HRESULT STDMETHODCALLTYPE CDesktopBrowser::EnableModelessSB(BOOL fEnable) 299 { 300 return E_NOTIMPL; 301 } 302 303 HRESULT STDMETHODCALLTYPE CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID) 304 { 305 if (!::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg)) 306 return S_FALSE; 307 return S_OK; 308 } 309 310 HRESULT STDMETHODCALLTYPE CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags) 311 { 312 /* 313 * We should use IShellWindows interface here in order to attempt to 314 * find an open shell window that shows the requested pidl and activate it 315 */ 316 317 DWORD dwFlags = ((wFlags & SBSP_EXPLOREMODE) != 0) ? SH_EXPLORER_CMDLINE_FLAG_E : 0; 318 return SHOpenNewFrame(ILClone(pidl), NULL, 0, dwFlags); 319 } 320 321 HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetViewStateStream(DWORD grfMode, IStream **ppStrm) 322 { 323 return E_NOTIMPL; 324 } 325 326 HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetControlWindow(UINT id, HWND *lphwnd) 327 { 328 if (lphwnd == NULL) 329 return E_POINTER; 330 return E_NOTIMPL; 331 } 332 333 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret) 334 { 335 if (pret == NULL) 336 return E_POINTER; 337 return E_NOTIMPL; 338 } 339 340 HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryActiveShellView(IShellView **ppshv) 341 { 342 if (ppshv == NULL) 343 return E_POINTER; 344 *ppshv = m_ShellView; 345 if (*ppshv != NULL) 346 (*ppshv)->AddRef(); 347 348 return S_OK; 349 } 350 351 HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnViewWindowActive(IShellView *ppshv) 352 { 353 return E_NOTIMPL; 354 } 355 356 HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags) 357 { 358 return E_NOTIMPL; 359 } 360 361 HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetPropertyBag(long flags, REFIID riid, void **ppv) 362 { 363 ITEMIDLIST deskpidl = {}; 364 return SHGetViewStatePropertyBag(&deskpidl, L"Desktop", flags | SHGVSPB_ROAM, riid, ppv); 365 } 366 367 HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryService(REFGUID guidService, REFIID riid, PVOID *ppv) 368 { 369 /* FIXME - handle guidService (SID_STopLevelBrowser for IShellBrowserService etc) */ 370 return QueryInterface(riid, ppv); 371 } 372 373 LRESULT CDesktopBrowser::_NotifyTray(UINT uMsg, WPARAM wParam, LPARAM lParam) 374 { 375 HWND hWndTray; 376 HRESULT hRet; 377 378 hRet = m_Tray->GetTrayWindow(&hWndTray); 379 if (SUCCEEDED(hRet)) 380 ::PostMessageW(hWndTray, uMsg, wParam, lParam); 381 382 return 0; 383 } 384 385 LRESULT CDesktopBrowser::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 386 { 387 switch (LOWORD(wParam)) 388 { 389 case FCIDM_DESKBROWSER_CLOSE: 390 return _NotifyTray(TWM_DOEXITWINDOWS, 0, 0); 391 case FCIDM_DESKBROWSER_FOCUS: 392 if (GetKeyState(VK_SHIFT)) 393 return _NotifyTray(TWM_CYCLEFOCUS, 1, 0xFFFFFFFF); 394 else 395 return _NotifyTray(TWM_CYCLEFOCUS, 1, 1); 396 case FCIDM_DESKBROWSER_SEARCH: 397 SHFindFiles(NULL, NULL); 398 break; 399 case FCIDM_DESKBROWSER_REFRESH: 400 if (m_ShellView) 401 m_ShellView->Refresh(); 402 break; 403 } 404 405 return 0; 406 } 407 408 409 LRESULT CDesktopBrowser::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 410 { 411 return (LRESULT)PaintDesktop((HDC)wParam); 412 } 413 414 LRESULT CDesktopBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 415 { 416 if (wParam == SIZE_MINIMIZED) 417 { 418 /* Hey, we're the desktop!!! */ 419 ::ShowWindow(m_hWnd, SW_RESTORE); 420 } 421 422 ::InvalidateRect(m_hWndShellView, NULL, TRUE); 423 424 return 0; 425 } 426 427 LRESULT CDesktopBrowser::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 428 { 429 if (uMsg == WM_SETTINGCHANGE /* == WM_WININICHANGE */ && 430 lstrcmpiW((LPCWSTR)lParam, L"Environment") == 0) 431 { 432 LPVOID lpEnvironment; 433 RegenerateUserEnvironment(&lpEnvironment, TRUE); 434 } 435 436 if (m_hWndShellView) 437 { 438 /* Forward the message */ 439 ::SendMessageW(m_hWndShellView, uMsg, wParam, lParam); 440 } 441 442 if (uMsg == WM_SETTINGCHANGE && wParam == SPI_SETWORKAREA && m_hWndShellView != NULL) 443 { 444 _Resize(); 445 } 446 447 return 0; 448 } 449 450 LRESULT CDesktopBrowser::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 451 { 452 return _NotifyTray(TWM_DOEXITWINDOWS, 0, 0); 453 } 454 455 LRESULT CDesktopBrowser::OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 456 { 457 TRACE("Proxy Desktop message 1035 received.\n"); 458 SHOnCWMCommandLine((HANDLE)lParam); 459 return 0; 460 } 461 462 LRESULT CDesktopBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 463 { 464 ::SetFocus(m_hWndShellView); 465 return 0; 466 } 467 468 // Message WM_DESKTOP_GET_CNOTIFY_SERVER: Get or create the change notification server. 469 // wParam: BOOL bCreate; The flag whether it creates or not. 470 // lParam: Ignored. 471 // return: The window handle of the server window. 472 LRESULT CDesktopBrowser::OnGetChangeNotifyServer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 473 { 474 BOOL bCreate = (BOOL)wParam; 475 if (bCreate && !::IsWindow(m_hwndChangeNotifyServer)) 476 { 477 HRESULT hres = CChangeNotifyServer_CreateInstance(IID_PPV_ARG(IOleWindow, &m_ChangeNotifyServer)); 478 if (FAILED_UNEXPECTEDLY(hres)) 479 return NULL; 480 481 hres = m_ChangeNotifyServer->GetWindow(&m_hwndChangeNotifyServer); 482 if (FAILED_UNEXPECTEDLY(hres)) 483 return NULL; 484 } 485 return (LRESULT)m_hwndChangeNotifyServer; 486 } 487 488 // Detect DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE 489 LRESULT CDesktopBrowser::OnDeviceChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 490 { 491 if (wParam != DBT_DEVICEARRIVAL && wParam != DBT_DEVICEREMOVECOMPLETE) 492 return 0; 493 494 DWORD dwDrives = ::GetLogicalDrives(); 495 for (INT iDrive = 0; iDrive <= 'Z' - 'A'; ++iDrive) 496 { 497 WCHAR szPath[MAX_PATH]; 498 DWORD dwBit = (1 << iDrive); 499 if (!(m_dwDrives & dwBit) && (dwDrives & dwBit)) // The drive is added 500 { 501 PathBuildRootW(szPath, iDrive); 502 SHChangeNotify(SHCNE_DRIVEADD, SHCNF_PATHW, szPath, NULL); 503 } 504 else if ((m_dwDrives & dwBit) && !(dwDrives & dwBit)) // The drive is removed 505 { 506 PathBuildRootW(szPath, iDrive); 507 SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATHW, szPath, NULL); 508 } 509 } 510 511 m_dwDrives = dwDrives; 512 return 0; 513 } 514 515 extern VOID WINAPI ShowFolderOptionsDialog(UINT Page, BOOL Async); 516 517 LRESULT CDesktopBrowser::OnShowOptionsDlg(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 518 { 519 switch (wParam) 520 { 521 case 0: 522 #if (NTDDI_VERSION >= NTDDI_VISTA) 523 case 2: 524 case 7: 525 #endif 526 ShowFolderOptionsDialog((UINT)(UINT_PTR)wParam, TRUE); 527 break; 528 case 1: 529 _NotifyTray(WM_COMMAND, TRAYCMD_TASKBAR_PROPERTIES, 0); 530 break; 531 } 532 return 0; 533 } 534 535 LRESULT CDesktopBrowser::OnSaveState(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 536 { 537 if (m_ShellView && !SHRestricted(REST_NOSAVESET)) 538 m_ShellView->SaveViewState(); 539 return 0; 540 } 541 542 HRESULT CDesktopBrowser_CreateInstance(IShellDesktopTray *Tray, REFIID riid, void **ppv) 543 { 544 return ShellObjectCreatorInit<CDesktopBrowser, IShellDesktopTray*>(Tray, riid, ppv); 545 } 546 547 /************************************************************************* 548 * SHCreateDesktop [SHELL32.200] 549 * 550 */ 551 HANDLE WINAPI SHCreateDesktop(IShellDesktopTray *Tray) 552 { 553 if (Tray == NULL) 554 { 555 SetLastError(ERROR_INVALID_PARAMETER); 556 return NULL; 557 } 558 559 CComPtr<IShellBrowser> Browser; 560 HRESULT hr = CDesktopBrowser_CreateInstance(Tray, IID_PPV_ARG(IShellBrowser, &Browser)); 561 if (FAILED_UNEXPECTEDLY(hr)) 562 return NULL; 563 564 return static_cast<HANDLE>(Browser.Detach()); 565 } 566 567 /************************************************************************* 568 * SHCreateDesktop [SHELL32.201] 569 * 570 */ 571 BOOL WINAPI SHDesktopMessageLoop(HANDLE hDesktop) 572 { 573 if (hDesktop == NULL) 574 { 575 SetLastError(ERROR_INVALID_PARAMETER); 576 return FALSE; 577 } 578 579 MSG Msg; 580 BOOL bRet; 581 582 CComPtr<IShellBrowser> browser; 583 CComPtr<IShellView> shellView; 584 585 browser.Attach(static_cast<IShellBrowser*>(hDesktop)); 586 HRESULT hr = browser->QueryActiveShellView(&shellView); 587 if (FAILED_UNEXPECTEDLY(hr)) 588 return FALSE; 589 590 while ((bRet = ::GetMessageW(&Msg, NULL, 0, 0)) != 0) 591 { 592 if (bRet != -1) 593 { 594 if (shellView->TranslateAcceleratorW(&Msg) != S_OK) 595 { 596 ::TranslateMessage(&Msg); 597 ::DispatchMessageW(&Msg); 598 } 599 } 600 } 601 602 return TRUE; 603 } 604 605 /************************************************************************* 606 * SHIsTempDisplayMode [SHELL32.724] 607 * 608 * Is the current display settings temporary? 609 */ 610 EXTERN_C BOOL WINAPI SHIsTempDisplayMode(VOID) 611 { 612 TRACE("\n"); 613 614 if (GetSystemMetrics(SM_REMOTESESSION) || GetSystemMetrics(SM_REMOTECONTROL)) 615 return FALSE; 616 617 DEVMODEW DevMode; 618 ZeroMemory(&DevMode, sizeof(DevMode)); 619 DevMode.dmSize = sizeof(DevMode); 620 621 if (!EnumDisplaySettingsW(NULL, ENUM_REGISTRY_SETTINGS, &DevMode)) 622 return FALSE; 623 624 if (!DevMode.dmPelsWidth || !DevMode.dmPelsHeight) 625 return FALSE; 626 627 HDC hDC = GetDC(NULL); 628 DWORD cxWidth = GetDeviceCaps(hDC, HORZRES); 629 DWORD cyHeight = GetDeviceCaps(hDC, VERTRES); 630 ReleaseDC(NULL, hDC); 631 632 return (cxWidth != DevMode.dmPelsWidth || cyHeight != DevMode.dmPelsHeight); 633 } 634