Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3903 lines
131 KiB

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "bitbuck.h"
  4. #include <iethread.h>
  5. #include "apithk.h"
  6. #include "mtpt.h"
  7. #include "..\util.h"
  8. #include "fassoc.h"
  9. #include "..\filetbl.h"
  10. #define DM_FOCUS 0 // focus
  11. #define DM_SHUTDOWN DM_TRACE // shutdown
  12. #define TF_SHDAUTO 0
  13. #define DM_MISC DM_TRACE // misc/tmp
  14. #define IDT_STARTBACKGROUNDSHELLTASKS 7
  15. #define IDT_TASKBARWAKEUP 8
  16. #define ENABLE_CHANNELS
  17. #define DESKTOPCLASS
  18. STDAPI_(void) CheckWinIniForAssocs();
  19. BOOL GetOldWorkAreas(LPRECT lprc, DWORD* pdwNoOfOldWA);
  20. void SaveOldWorkAreas(LPCRECT lprc, DWORD nOldWA);
  21. BOOL UpdateAllDesktopSubscriptions(IADesktopP2 *);
  22. //This is in deskreg.cpp
  23. BOOL AdjustDesktopComponents(LPCRECT prcNewWorkAreas, int nNewWorkAreas,
  24. LPCRECT prcOldMonitors, LPCRECT prcOldWorkAreas, int nOldWorkAreas);
  25. // in defview.cpp
  26. BOOL IsFolderWindow(HWND hwnd);
  27. // copied from tray.c if changing here, change there also
  28. #define GHID_FIRST 500
  29. #define g_xVirtualScreen GetSystemMetrics(SM_XVIRTUALSCREEN)
  30. #define g_yVirtualScreen GetSystemMetrics(SM_YVIRTUALSCREEN)
  31. #define g_cxVirtualScreen GetSystemMetrics(SM_CXVIRTUALSCREEN)
  32. #define g_cyVirtualScreen GetSystemMetrics(SM_CYVIRTUALSCREEN)
  33. #define g_cxEdge GetSystemMetrics(SM_CXEDGE)
  34. #define g_cyEdge GetSystemMetrics(SM_CYEDGE)
  35. // TOID_Desktop 6aec6a60-b7a4-11d1-be89-0000f805ca57 is the id for ShellTasks added by the desktop
  36. const GUID TOID_Desktop = { 0x6aec6a60, 0xb7a4, 0x11d1, {0xbe, 0x89, 0x00, 0x00, 0xf8, 0x05, 0xca, 0x57} };
  37. // these are the CLSIDs that are supported for creating LocalServer thread
  38. // objects. the shell supports these in the RunDll32 and then the
  39. // invocation of a thread on the desktop object.
  40. CLSID const *c_localServers[] =
  41. {
  42. &CLSID_ShellDesktop,
  43. &CLSID_NetCrawler,
  44. &CLSID_HWShellExecute,
  45. &CLSID_ShellAutoplay,
  46. };
  47. typedef struct
  48. {
  49. INT iLocalServer; // index into the local server table
  50. DWORD *pdwThreadID; // where to stash the thread id
  51. } LOCALSERVERDATA;
  52. // Private interface to talk to explorer.exe
  53. IDeskTray* g_pdtray = NULL;
  54. void FireEventSz(LPCTSTR szEvent)
  55. {
  56. HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, szEvent);
  57. if (hEvent)
  58. {
  59. SetEvent(hEvent);
  60. CloseHandle(hEvent);
  61. }
  62. }
  63. #define PERF_ENABLESETMARK
  64. #ifdef PERF_ENABLESETMARK
  65. void DoSetMark(LPCSTR pszMark, ULONG cbSz);
  66. #define PERFSETMARK(text) DoSetMark(text, sizeof(text))
  67. #else
  68. #define PERFSETMARK(text)
  69. #endif // PERF_ENABLESETMARK
  70. #ifdef PERF_ENABLESETMARK
  71. #include <wmistr.h>
  72. #include <ntwmi.h> // PWMI_SET_MARK_INFORMATION is defined in ntwmi.h
  73. #include <wmiumkm.h>
  74. #define NTPERF
  75. #include <ntperf.h>
  76. void DoSetMark(LPCSTR pszMark, ULONG cbSz)
  77. {
  78. PWMI_SET_MARK_INFORMATION MarkInfo;
  79. HANDLE hTemp;
  80. ULONG cbBufferSize;
  81. ULONG cbReturnSize;
  82. cbBufferSize = FIELD_OFFSET(WMI_SET_MARK_INFORMATION, Mark) + cbSz;
  83. MarkInfo = (PWMI_SET_MARK_INFORMATION) LocalAlloc(LPTR, cbBufferSize);
  84. // Failed to init, no big deal
  85. if (MarkInfo == NULL)
  86. return;
  87. BYTE *pMarkBuffer = (BYTE *) (&MarkInfo->Mark[0]);
  88. memcpy(pMarkBuffer, pszMark, cbSz);
  89. // WMI_SET_MARK_WITH_FLUSH will flush the working set when setting the mark
  90. MarkInfo->Flag = PerformanceMmInfoMark;
  91. hTemp = CreateFile(WMIDataDeviceName,
  92. GENERIC_READ | GENERIC_WRITE,
  93. 0,
  94. NULL,
  95. OPEN_EXISTING,
  96. FILE_ATTRIBUTE_NORMAL |
  97. FILE_FLAG_OVERLAPPED,
  98. NULL);
  99. if (hTemp != INVALID_HANDLE_VALUE)
  100. {
  101. // here's the piece that actually puts the mark in the buffer
  102. BOOL fIoctlSuccess = DeviceIoControl(hTemp,
  103. IOCTL_WMI_SET_MARK,
  104. MarkInfo,
  105. cbBufferSize,
  106. NULL,
  107. 0,
  108. &cbReturnSize,
  109. NULL);
  110. CloseHandle(hTemp);
  111. }
  112. LocalFree(MarkInfo);
  113. }
  114. #endif // PERF_ENABLESETMARK
  115. // MISC stuff duplicated in browseui {
  116. HRESULT _ConvertPathToPidlW(IBrowserService2 *pbs, HWND hwnd, LPCWSTR pszPath, LPITEMIDLIST * ppidl)
  117. {
  118. WCHAR wszCmdLine[MAX_URL_STRING]; // must be with pszPath
  119. TCHAR szFixedUrl[MAX_URL_STRING];
  120. TCHAR szParsedUrl[MAX_URL_STRING] = {'\0'};
  121. DWORD dwUrlLen = ARRAYSIZE(szParsedUrl);
  122. // Copy the command line into a temporary buffer
  123. // so we can remove the surrounding quotes (if
  124. // they exist)
  125. SHUnicodeToTChar(pszPath, szFixedUrl, ARRAYSIZE(szFixedUrl));
  126. PathUnquoteSpaces(szFixedUrl);
  127. HRESULT hr = S_OK;
  128. if (ParseURLFromOutsideSource(szFixedUrl, szParsedUrl, &dwUrlLen, NULL))
  129. SHTCharToUnicode(szParsedUrl, wszCmdLine, ARRAYSIZE(wszCmdLine));
  130. else
  131. hr = StringCchCopy(wszCmdLine, ARRAYSIZE(wszCmdLine), pszPath);
  132. if (SUCCEEDED(hr))
  133. {
  134. hr = pbs->IEParseDisplayName(CP_ACP, wszCmdLine, ppidl);
  135. }
  136. pbs->DisplayParseError(hr, wszCmdLine);
  137. return hr;
  138. }
  139. // END of MISC stuff duplicated in browseui }
  140. // Several places rely on the fact that IShellBrowser is the first interface
  141. // we inherit (and therefore is what we use as our canonical IUnknown).
  142. // Grep for IUnknownIdentity to find them.
  143. class CDesktopBrowser :
  144. public IShellBrowser
  145. ,public IServiceProvider
  146. ,public IOleCommandTarget
  147. ,public IDockingWindowSite
  148. ,public IInputObjectSite
  149. ,public IDropTarget
  150. ,public IDockingWindowFrame
  151. ,public IMultiMonitorDockingSite
  152. ,public IBrowserService2
  153. ,public IShellBrowserService
  154. {
  155. public:
  156. // IUnknown
  157. STDMETHOD(QueryInterface)(REFIID riid, void * *ppvObj);
  158. virtual STDMETHODIMP_(ULONG) AddRef(void);
  159. virtual STDMETHODIMP_(ULONG) Release(void);
  160. // IShellBrowser (same as IOleInPlaceFrame)
  161. virtual STDMETHODIMP GetWindow(HWND * lphwnd);
  162. virtual STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
  163. virtual STDMETHODIMP InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
  164. virtual STDMETHODIMP SetMenuSB(HMENU hmenuShared, HOLEMENU holemenu, HWND hwnd);
  165. virtual STDMETHODIMP RemoveMenusSB(HMENU hmenuShared);
  166. virtual STDMETHODIMP SetStatusTextSB(LPCOLESTR lpszStatusText);
  167. virtual STDMETHODIMP EnableModelessSB(BOOL fEnable);
  168. virtual STDMETHODIMP TranslateAcceleratorSB(LPMSG lpmsg, WORD wID);
  169. virtual STDMETHODIMP BrowseObject(LPCITEMIDLIST pidl, UINT wFlags);
  170. virtual STDMETHODIMP GetViewStateStream(DWORD grfMode, LPSTREAM *ppStrm);
  171. virtual STDMETHODIMP GetControlWindow(UINT id, HWND * lphwnd);
  172. virtual STDMETHODIMP SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret);
  173. virtual STDMETHODIMP QueryActiveShellView(struct IShellView ** ppshv);
  174. virtual STDMETHODIMP OnViewWindowActive(struct IShellView * ppshv);
  175. virtual STDMETHODIMP SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags);
  176. // IServiceProvider
  177. virtual STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppvObj);
  178. // IOleCommandTarget
  179. virtual STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext);
  180. virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  181. // IDockingWindowSite (also IOleWindow)
  182. virtual STDMETHODIMP GetBorderDW(IUnknown* punkSrc, LPRECT lprectBorder);
  183. virtual STDMETHODIMP RequestBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths);
  184. virtual STDMETHODIMP SetBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths);
  185. // IInputObjectSite
  186. virtual STDMETHODIMP OnFocusChangeIS(IUnknown* punkSrc, BOOL fSetFocus);
  187. // IDropTarget
  188. virtual STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  189. virtual STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  190. virtual STDMETHODIMP DragLeave(void);
  191. virtual STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  192. // IDockingWindowFrame (also IOleWindow)
  193. virtual STDMETHODIMP AddToolbar(IUnknown* punkSrc, LPCWSTR pwszItem, DWORD dwReserved);
  194. virtual STDMETHODIMP RemoveToolbar(IUnknown* punkSrc, DWORD dwFlags);
  195. virtual STDMETHODIMP FindToolbar(LPCWSTR pwszItem, REFIID riid, void **ppvObj);
  196. // IMultiMonitorDockingSite
  197. virtual STDMETHODIMP GetMonitor(IUnknown* punkSrc, HMONITOR * phMon);
  198. virtual STDMETHODIMP RequestMonitor(IUnknown* punkSrc, HMONITOR * phMon);
  199. virtual STDMETHODIMP SetMonitor(IUnknown* punkSrc, HMONITOR hMon, HMONITOR * phMonOld);
  200. static LRESULT CALLBACK DesktopWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  201. static LRESULT CALLBACK RaisedWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  202. void _MessageLoop();
  203. HWND GetTrayWindow(void) { return _hwndTray; }
  204. HWND GetDesktopWindow(void) { return _pbbd->_hwnd; }
  205. // IBrowserService
  206. // *** IBrowserService specific methods ***
  207. virtual STDMETHODIMP GetParentSite(IOleInPlaceSite** ppipsite);
  208. virtual STDMETHODIMP SetTitle(IShellView* psv, LPCWSTR pszName);
  209. virtual STDMETHODIMP GetTitle(IShellView* psv, LPWSTR pszName, DWORD cchName);
  210. virtual STDMETHODIMP GetOleObject( IOleObject** ppobjv);
  211. virtual STDMETHODIMP GetTravelLog(ITravelLog** pptl);
  212. virtual STDMETHODIMP ShowControlWindow(UINT id, BOOL fShow);
  213. virtual STDMETHODIMP IsControlWindowShown(UINT id, BOOL *pfShown);
  214. virtual STDMETHODIMP IEGetDisplayName(LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags);
  215. virtual STDMETHODIMP IEParseDisplayName(UINT uiCP, LPCWSTR pwszPath, LPITEMIDLIST * ppidlOut);
  216. virtual STDMETHODIMP DisplayParseError(HRESULT hres, LPCWSTR pwszPath);
  217. virtual STDMETHODIMP NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF);
  218. virtual STDMETHODIMP SetNavigateState(BNSTATE bnstate);
  219. virtual STDMETHODIMP GetNavigateState (BNSTATE *pbnstate);
  220. virtual STDMETHODIMP NotifyRedirect ( IShellView* psv, LPCITEMIDLIST pidl, BOOL *pfDidBrowse);
  221. virtual STDMETHODIMP UpdateWindowList ();
  222. virtual STDMETHODIMP UpdateBackForwardState ();
  223. virtual STDMETHODIMP SetFlags(DWORD dwFlags, DWORD dwFlagMask);
  224. virtual STDMETHODIMP GetFlags(DWORD *pdwFlags);
  225. virtual STDMETHODIMP CanNavigateNow ();
  226. virtual STDMETHODIMP GetPidl(LPITEMIDLIST *ppidl);
  227. virtual STDMETHODIMP SetReferrer (LPITEMIDLIST pidl);
  228. virtual STDMETHODIMP_(DWORD) GetBrowserIndex();
  229. virtual STDMETHODIMP GetBrowserByIndex(DWORD dwID, IUnknown **ppunk);
  230. virtual STDMETHODIMP GetHistoryObject(IOleObject **ppole, IStream **pstm, IBindCtx **ppbc);
  231. virtual STDMETHODIMP SetHistoryObject(IOleObject *pole, BOOL fIsLocalAnchor);
  232. virtual STDMETHODIMP CacheOLEServer(IOleObject *pole);
  233. virtual STDMETHODIMP GetSetCodePage(VARIANT* pvarIn, VARIANT* pvarOut);
  234. virtual STDMETHODIMP OnHttpEquiv(IShellView* psv, BOOL fDone, VARIANT* pvarargIn, VARIANT* pvarargOut);
  235. virtual STDMETHODIMP GetPalette( HPALETTE * hpal);
  236. virtual STDMETHODIMP RegisterWindow(BOOL fUnregister, int swc);
  237. virtual STDMETHODIMP_(LRESULT) WndProcBS(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  238. virtual STDMETHODIMP OnSize(WPARAM wParam);
  239. virtual STDMETHODIMP OnCreate(LPCREATESTRUCT pcs);
  240. virtual STDMETHODIMP_(LRESULT) OnCommand(WPARAM wParam, LPARAM lParam);
  241. virtual STDMETHODIMP OnDestroy();
  242. virtual STDMETHODIMP_(LRESULT) OnNotify(NMHDR * pnm);
  243. virtual STDMETHODIMP OnSetFocus();
  244. virtual STDMETHODIMP OnFrameWindowActivateBS(BOOL fActive);
  245. virtual STDMETHODIMP ReleaseShellView();
  246. virtual STDMETHODIMP ActivatePendingView();
  247. virtual STDMETHODIMP CreateViewWindow(IShellView* psvNew, IShellView* psvOld, LPRECT prcView, HWND* phwnd);
  248. virtual STDMETHODIMP GetBaseBrowserData(LPCBASEBROWSERDATA* ppbd);
  249. virtual STDMETHODIMP_(LPBASEBROWSERDATA) PutBaseBrowserData();
  250. virtual STDMETHODIMP SetAsDefFolderSettings() { ASSERT(FALSE); return E_NOTIMPL;}
  251. virtual STDMETHODIMP SetTopBrowser();
  252. virtual STDMETHODIMP UpdateSecureLockIcon(int eSecureLock);
  253. virtual STDMETHODIMP Offline(int iCmd);
  254. virtual STDMETHODIMP InitializeDownloadManager();
  255. virtual STDMETHODIMP InitializeTransitionSite();
  256. virtual STDMETHODIMP GetFolderSetData(struct tagFolderSetData* pfsd) { *pfsd = _fsd; return S_OK; };
  257. virtual STDMETHODIMP _OnFocusChange(UINT itb);
  258. virtual STDMETHODIMP v_ShowHideChildWindows(BOOL fChildOnly);
  259. virtual STDMETHODIMP CreateBrowserPropSheetExt(THIS_ REFIID riid, void **ppvObj);
  260. virtual STDMETHODIMP SetActivateState(UINT uActivate);
  261. virtual STDMETHODIMP AllowViewResize(BOOL f);
  262. virtual STDMETHODIMP _Initialize(HWND hwnd, IUnknown *pauto);
  263. virtual STDMETHODIMP_(UINT) _get_itbLastFocus();
  264. virtual STDMETHODIMP _put_itbLastFocus(UINT itbLastFocus);
  265. virtual STDMETHODIMP _UIActivateView(UINT uState);
  266. virtual STDMETHODIMP _CancelPendingNavigationAsync();
  267. virtual STDMETHODIMP _MaySaveChanges();
  268. virtual STDMETHODIMP _PauseOrResumeView(BOOL fPaused);
  269. virtual STDMETHODIMP _DisableModeless();
  270. virtual STDMETHODIMP _NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags);
  271. virtual STDMETHODIMP _TryShell2Rename(IShellView* psv, LPCITEMIDLIST pidlNew);
  272. virtual STDMETHODIMP _SwitchActivationNow();
  273. virtual STDMETHODIMP _CancelPendingView();
  274. virtual STDMETHODIMP _ExecChildren(IUnknown *punkBar, BOOL fBroadcast,
  275. const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  276. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  277. virtual STDMETHODIMP _SendChildren(HWND hwndBar, BOOL fBroadcast,
  278. UINT uMsg, WPARAM wParam, LPARAM lParam);
  279. virtual STDMETHODIMP v_MayGetNextToolbarFocus(LPMSG lpMsg, UINT itbNext, int citb, LPTOOLBARITEM * pptbi, HWND * phwnd);
  280. virtual STDMETHODIMP _SetFocus(LPTOOLBARITEM ptbi, HWND hwnd, LPMSG lpMsg) { ASSERT(FALSE); return E_NOTIMPL; }
  281. virtual STDMETHODIMP _GetViewBorderRect(RECT* prc);
  282. virtual STDMETHODIMP _UpdateViewRectSize();
  283. virtual STDMETHODIMP _ResizeNextBorder(UINT itb);
  284. virtual STDMETHODIMP _ResizeView();
  285. virtual STDMETHODIMP _GetEffectiveClientArea(LPRECT lprectBorder, HMONITOR hmon);
  286. virtual STDMETHODIMP GetCurrentFolderSettings(DEFFOLDERSETTINGS *pdfs, int cbDfs) { ASSERT(FALSE); return E_NOTIMPL; }
  287. virtual STDMETHODIMP GetViewRect(RECT* prc);
  288. virtual STDMETHODIMP GetViewWindow(HWND * phwndView);
  289. virtual STDMETHODIMP InitializeTravelLog(ITravelLog* ptl, DWORD dw);
  290. //IShellBrowserService
  291. virtual STDMETHODIMP GetPropertyBag(DWORD dwFlags, REFIID riid, void** ppv);
  292. // Desktop needs to override these:
  293. virtual STDMETHODIMP_(IStream*) v_GetViewStream(LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pwszName);
  294. // Desktop needs access to these:
  295. virtual STDMETHODIMP_(LRESULT) ForwardViewMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { ASSERT(FALSE); return 0; };
  296. virtual STDMETHODIMP SetAcceleratorMenu(HACCEL hacc) { ASSERT(FALSE); return E_FAIL; }
  297. virtual STDMETHODIMP_(int) _GetToolbarCount(THIS) { ASSERT(FALSE); return 0; }
  298. virtual STDMETHODIMP_(LPTOOLBARITEM) _GetToolbarItem(THIS_ int itb) { ASSERT(FALSE); return NULL; }
  299. virtual STDMETHODIMP _SaveToolbars(IStream* pstm) { ASSERT(FALSE); return E_NOTIMPL; }
  300. virtual STDMETHODIMP _LoadToolbars(IStream* pstm) { ASSERT(FALSE); return E_NOTIMPL; }
  301. virtual STDMETHODIMP _CloseAndReleaseToolbars(BOOL fClose) { ASSERT(FALSE); return E_NOTIMPL; }
  302. virtual STDMETHODIMP_(UINT) _FindTBar(IUnknown* punkSrc) { ASSERT(FALSE); return (UINT)-1; };
  303. virtual STDMETHODIMP v_MayTranslateAccelerator(MSG* pmsg) { ASSERT(FALSE); return E_NOTIMPL; }
  304. virtual STDMETHODIMP _GetBorderDWHelper(IUnknown* punkSrc, LPRECT lprectBorder, BOOL bUseHmonitor) { ASSERT(FALSE); return E_NOTIMPL; }
  305. // Shell browser overrides this.
  306. virtual STDMETHODIMP v_CheckZoneCrossing(LPCITEMIDLIST pidl) {return S_OK;};
  307. // Desktop and basesb need access to these:
  308. virtual STDMETHODIMP _ResizeNextBorderHelper(UINT itb, BOOL bUseHmonitor);
  309. // it just for us of course!
  310. void StartBackgroundShellTasks(void);
  311. void TaskbarWakeup(void);
  312. protected:
  313. CDesktopBrowser();
  314. ~CDesktopBrowser();
  315. friend HRESULT CDesktopBrowser_CreateInstance(HWND hwnd, void **ppsb);
  316. HRESULT SetInner(IUnknown* punk);
  317. long _cRef;
  318. // cached pointers on inner object
  319. IUnknown* _punkInner;
  320. IBrowserService2* _pbsInner;
  321. IShellBrowser* _psbInner;
  322. IServiceProvider* _pspInner;
  323. IOleCommandTarget* _pctInner;
  324. IDockingWindowSite* _pdwsInner;
  325. IDockingWindowFrame* _pdwfInner;
  326. IInputObjectSite* _piosInner;
  327. IDropTarget* _pdtInner;
  328. LPCBASEBROWSERDATA _pbbd;
  329. LRESULT _RaisedWndProc(UINT msg, WPARAM wParam, LPARAM lParam);
  330. void _SetViewArea();
  331. void _GetViewBorderRects(int nRects, LPRECT prc); // does not have the tool bars
  332. void _SetWorkAreas(int nWorkAreas, RECT * prcWork);
  333. void _SubtractBottommostTray(LPRECT prc);
  334. void _SaveState();
  335. void _InitDeskbars();
  336. void _SaveDesktopToolbars();
  337. void _OnRaise(WPARAM wParam, LPARAM lParam);
  338. void _SetupAppRan(WPARAM wParam, LPARAM lParam);
  339. BOOL _QueryHKCRChanged(HWND hwnd, LPDWORD pdwCookie);
  340. void _Lower();
  341. void _Raise();
  342. void _SwapParents(HWND hwndOldParent, HWND hwndNewParent);
  343. BOOL _OnCopyData(PCOPYDATASTRUCT pcds);
  344. void _OnAddToRecent(HANDLE hMem, DWORD dwProcId);
  345. BOOL _InitScheduler(void);
  346. HRESULT _AddDesktopTask(IRunnableTask *ptask, DWORD dwPriority);
  347. BOOL _PtOnDesktopEdge(POINTL* ppt, LPUINT puEdge);
  348. #ifdef DEBUG
  349. void _CreateDeskbars();
  350. #endif
  351. HRESULT _CreateDeskBarForBand(UINT uEdge, IUnknown *punk, POINTL *pptl, IBandSite **pbs);
  352. virtual void v_PropagateMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fSend);
  353. HRESULT _OnFocusMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
  354. HRESULT _CreateDesktopView();
  355. HRESULT _GetPropertyBag(LPCITEMIDLIST pidl, DWORD dwFlags, REFIID riid, void** ppv);
  356. HWND _GetDesktopListview();
  357. UINT _PeekForAMessage();
  358. void _InitMonitors();
  359. #ifdef ENABLE_CHANNELS
  360. void _MaybeLaunchChannelBand(void);
  361. #endif
  362. virtual void _ViewChange(DWORD dwAspect, LONG lindex);
  363. HWND _hwndTray;
  364. int _iWaitCount;
  365. ULONG _uNotifyID;
  366. DWORD _dwThreadIdTray; // Used to wakeup tray thread when the machine is really stressed
  367. int _iTrayPriority;
  368. DWORD _grfKeyState;
  369. DWORD _dwEffectOnEdge; // what's the drop effect that desktop should return on dragging over the edge
  370. BOOL _fRaised;
  371. HWND _hwndRaised; // this is the parent of all of desktop's children when raised
  372. struct tagFolderSetData _fsd;
  373. int _nMonitors; // number of monitors on this desktop
  374. HMONITOR _hMonitors[LV_MAX_WORKAREAS]; // the order of these hmonitors need to be preserved
  375. RECT _rcWorkArea; // cached work-area
  376. RECT _rcOldWorkAreas[LV_MAX_WORKAREAS]; // Old work areas before settings change
  377. DWORD _nOldWork;
  378. RECT _rcOldMonitors[LV_MAX_WORKAREAS]; // Old monitor sizes before settings change
  379. // for _OnAddToRecent()
  380. IShellTaskScheduler *_psched;
  381. DWORD _idLocalServerThreads[ARRAYSIZE(c_localServers)];
  382. DWORD _cChangeEvents;
  383. HANDLE _rghChangeEvents[2]; // we watch HKCR and HKCR\CLSID
  384. DWORD _dwChangeCookie;
  385. DWORD _rgdwQHKCRCookies[QHKCRID_MAX - QHKCRID_MIN];
  386. HKEY _hkClsid;
  387. WCHAR _wzDesktopTitle[64]; // Localized Title
  388. // IUnknownIdentity - for uniformity w.r.t. aggregation
  389. // We are not aggregatable, so we are our own Outer.
  390. IUnknown *_GetOuter() { return SAFECAST(this, IShellBrowser*); }
  391. };
  392. HRESULT CDesktopBrowser_CreateInstance(HWND hwnd, void **ppsb)
  393. {
  394. HRESULT hr = E_OUTOFMEMORY;
  395. CDesktopBrowser *pdb = new CDesktopBrowser();
  396. if (pdb)
  397. {
  398. hr = pdb->_Initialize(hwnd, NULL); // aggregation, etc.
  399. if (FAILED(hr))
  400. ATOMICRELEASE(pdb);
  401. }
  402. *ppsb = pdb;
  403. return hr;
  404. }
  405. CDesktopBrowser::CDesktopBrowser() : _cRef(1)
  406. {
  407. TraceMsg(TF_LIFE, "ctor CDesktopBrowser %x", this);
  408. for (INT i = 0; i < ARRAYSIZE(_idLocalServerThreads); i++)
  409. _idLocalServerThreads[i] = -1;
  410. }
  411. CDesktopBrowser::~CDesktopBrowser()
  412. {
  413. SaveOldWorkAreas(_rcOldWorkAreas, _nOldWork);
  414. // cleanup for QueryHKCRChanged()
  415. for (int i = 0; i < ARRAYSIZE(_rghChangeEvents); i++)
  416. {
  417. if (_rghChangeEvents[i])
  418. CloseHandle(_rghChangeEvents[i]);
  419. }
  420. if (_hkClsid)
  421. RegCloseKey(_hkClsid);
  422. // close down the local server threads that may be running
  423. for (i = 0; i < ARRAYSIZE(_idLocalServerThreads); i++)
  424. {
  425. if (_idLocalServerThreads[i] != -1)
  426. PostThreadMessage(_idLocalServerThreads[i], WM_QUIT, 0, 0);
  427. }
  428. TraceMsg(TF_LIFE, "dtor CDesktopBrowser %x", this);
  429. }
  430. HRESULT CDesktopBrowser::_Initialize(HWND hwnd, IUnknown* pauto)
  431. {
  432. IUnknown* punk;
  433. HRESULT hres = CoCreateInstance(CLSID_CCommonBrowser, _GetOuter(), CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &punk));
  434. if (SUCCEEDED(hres))
  435. {
  436. hres = SetInner(punk); // paired w/ Release in outer (TBS::Release)
  437. if (SUCCEEDED(hres))
  438. {
  439. // we must initialize the inner guy BEFORE we call through any of these pointers.
  440. hres = _pbsInner->_Initialize(hwnd, pauto);
  441. if (SUCCEEDED(hres))
  442. {
  443. _pbsInner->GetBaseBrowserData(&_pbbd);
  444. ASSERT(_pbbd);
  445. // Restore the old settings from the registry that we persist.
  446. if (!GetOldWorkAreas(_rcOldWorkAreas, &_nOldWork) || _nOldWork == 0)
  447. {
  448. // We didn't find it in the registry
  449. _nOldWork = 0; // Since this is 0, we don't have to set _rcOldWorkAreas.
  450. //We will recover from this in _SetWorkAreas()
  451. }
  452. SetTopBrowser();
  453. _put_itbLastFocus(ITB_VIEW); // focus on desktop (w95 compat)
  454. HACCEL hacc = LoadAccelerators(HINST_THISDLL, MAKEINTRESOURCE(ACCEL_DESKTOP));
  455. ASSERT(hacc);
  456. _pbsInner->SetAcceleratorMenu(hacc);
  457. // Perf: never fire events from the desktop.
  458. ASSERT(_pbbd->_pautoEDS);
  459. ATOMICRELEASE(const_cast<IExpDispSupport *>(_pbbd->_pautoEDS));
  460. _InitMonitors();
  461. // Initialise _rcOldMonitors
  462. for (int i = 0; i < _nMonitors; i++)
  463. {
  464. GetMonitorRect(_hMonitors[i], &_rcOldMonitors[i]);
  465. }
  466. // NOTE: if we have any more keys to watch, then
  467. // we should create a static struct to walk
  468. // so that it is easier to add more event/key pairs
  469. _rghChangeEvents[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
  470. _rghChangeEvents[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
  471. if (_rghChangeEvents[0] && _rghChangeEvents[1])
  472. {
  473. if (ERROR_SUCCESS == RegNotifyChangeKeyValue(HKEY_CLASSES_ROOT, TRUE,
  474. REG_NOTIFY_CHANGE_LAST_SET |REG_NOTIFY_CHANGE_NAME, _rghChangeEvents[0], TRUE))
  475. {
  476. _cChangeEvents = 1;
  477. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("CLSID"), 0, MAXIMUM_ALLOWED, &_hkClsid)
  478. && ERROR_SUCCESS == RegNotifyChangeKeyValue(_hkClsid, TRUE, REG_NOTIFY_CHANGE_LAST_SET |REG_NOTIFY_CHANGE_NAME, _rghChangeEvents[1], TRUE))
  479. {
  480. // we need to leave the key open,
  481. // or the event is signaled right away
  482. _cChangeEvents++;
  483. }
  484. }
  485. }
  486. }
  487. }
  488. }
  489. return hres;
  490. }
  491. //
  492. // The refcount in the punk is transferred to us. We do not need to
  493. // and indeed should not AddRef it.
  494. //
  495. // If any of these steps fails, we will clean up in our destructor.
  496. //
  497. HRESULT CDesktopBrowser::SetInner(IUnknown* punk)
  498. {
  499. HRESULT hres;
  500. ASSERT(_punkInner == NULL);
  501. _punkInner = punk;
  502. #define INNERCACHE(iid, p) do { \
  503. hres = SHQueryInnerInterface(_GetOuter(), punk, iid, (void **)&p); \
  504. if (!EVAL(SUCCEEDED(hres))) return E_FAIL; \
  505. } while (0)
  506. INNERCACHE(IID_IBrowserService2, _pbsInner);
  507. INNERCACHE(IID_IShellBrowser, _psbInner);
  508. INNERCACHE(IID_IServiceProvider, _pspInner);
  509. INNERCACHE(IID_IOleCommandTarget, _pctInner);
  510. INNERCACHE(IID_IDockingWindowSite, _pdwsInner);
  511. INNERCACHE(IID_IDockingWindowFrame, _pdwfInner);
  512. INNERCACHE(IID_IInputObjectSite, _piosInner);
  513. INNERCACHE(IID_IDropTarget, _pdtInner);
  514. #undef INNERCACHE
  515. return S_OK;
  516. }
  517. ULONG CDesktopBrowser::AddRef()
  518. {
  519. return InterlockedIncrement(&_cRef);
  520. }
  521. ULONG CDesktopBrowser::Release()
  522. {
  523. ASSERT( 0 != _cRef );
  524. ULONG cRef = InterlockedDecrement(&_cRef);
  525. if ( 0 == cRef )
  526. {
  527. _cRef = 1000; // guard against recursion
  528. RELEASEINNERINTERFACE(_GetOuter(), _pbsInner);
  529. RELEASEINNERINTERFACE(_GetOuter(), _psbInner);
  530. RELEASEINNERINTERFACE(_GetOuter(), _pspInner);
  531. RELEASEINNERINTERFACE(_GetOuter(), _pctInner);
  532. RELEASEINNERINTERFACE(_GetOuter(), _pdwsInner);
  533. RELEASEINNERINTERFACE(_GetOuter(), _pdwfInner);
  534. RELEASEINNERINTERFACE(_GetOuter(), _piosInner);
  535. RELEASEINNERINTERFACE(_GetOuter(), _pdtInner);
  536. // this must come last
  537. ATOMICRELEASE(_punkInner); // paired w/ CCI aggregation
  538. ASSERT(_cRef == 1000);
  539. delete this;
  540. }
  541. return cRef;
  542. }
  543. HRESULT CDesktopBrowser::QueryInterface(REFIID riid, void **ppvObj)
  544. {
  545. // IUnknownIdentity - The interface we use for IUnknown must come first.
  546. static const QITAB qit[] = {
  547. QITABENT(CDesktopBrowser, IShellBrowser),
  548. QITABENT(CDesktopBrowser, IBrowserService2),
  549. QITABENTMULTI(CDesktopBrowser, IBrowserService, IBrowserService2),
  550. QITABENTMULTI(CDesktopBrowser, IOleWindow, IShellBrowser),
  551. QITABENTMULTI2(CDesktopBrowser, SID_SShellDesktop, IShellBrowser), // effectively an IUnknown supported only by this class
  552. QITABENT(CDesktopBrowser, IServiceProvider),
  553. QITABENT(CDesktopBrowser, IShellBrowserService),
  554. QITABENT(CDesktopBrowser, IOleCommandTarget),
  555. QITABENT(CDesktopBrowser, IDockingWindowSite),
  556. QITABENT(CDesktopBrowser, IInputObjectSite),
  557. QITABENT(CDesktopBrowser, IMultiMonitorDockingSite),
  558. QITABENT(CDesktopBrowser, IDropTarget),
  559. { 0 },
  560. };
  561. HRESULT hres = QISearch(this, qit, riid, ppvObj);
  562. if (FAILED(hres))
  563. {
  564. if (_punkInner)
  565. {
  566. // don't let these get through to our base class...
  567. // IID_IOleCommandTarget, IID_IOleInPlaceUIWindow
  568. // 970414 adp: spoke to SatoNa, these *can* go thru
  569. // i'll remove this week
  570. // It's been working like this for a while now.
  571. if (IsEqualIID(riid, IID_IOleInPlaceUIWindow))
  572. {
  573. *ppvObj = NULL;
  574. hres = E_NOINTERFACE;
  575. }
  576. else
  577. {
  578. hres = _punkInner->QueryInterface(riid, ppvObj);
  579. }
  580. }
  581. }
  582. return hres;
  583. }
  584. void _InitDesktopMetrics(WPARAM wParam, LPCTSTR pszSection)
  585. {
  586. BOOL fForce = (!pszSection || !*pszSection);
  587. if (fForce || (wParam == SPI_SETNONCLIENTMETRICS) || !lstrcmpi(pszSection, TEXT("WindowMetrics")))
  588. {
  589. FileIconInit(TRUE); // Tell the shell we want to play with a full deck
  590. }
  591. }
  592. typedef struct
  593. {
  594. int iMonitors;
  595. HMONITOR * phMonitors;
  596. } EnumMonitorsData;
  597. BOOL CALLBACK MultiMonEnumCallBack(HMONITOR hMonitor, HDC hdc, LPRECT lprc, LPARAM lData)
  598. {
  599. EnumMonitorsData * pEmd = (EnumMonitorsData *)lData;
  600. if (pEmd->iMonitors > LV_MAX_WORKAREAS - 1)
  601. //ignore the other monitors because we can only handle up to LV_MAX_WORKAREAS
  602. //REARCHITECT: should we dynamically allocated this?
  603. return FALSE;
  604. pEmd->phMonitors[pEmd->iMonitors++] = hMonitor;
  605. return TRUE;
  606. }
  607. // Initialize the number of monitors and the hmonitors array
  608. void CDesktopBrowser::_InitMonitors()
  609. {
  610. HMONITOR hMonPrimary = GetPrimaryMonitor();
  611. EnumMonitorsData emd;
  612. emd.iMonitors = 0;
  613. emd.phMonitors = _hMonitors;
  614. EnumDisplayMonitors(NULL, NULL, MultiMonEnumCallBack, (LPARAM)&emd);
  615. _nMonitors = GetNumberOfMonitors();
  616. // Always move the primary monitor to the first location.
  617. if (_hMonitors[0] != hMonPrimary)
  618. {
  619. for (int iMon = 1; iMon < _nMonitors; iMon++)
  620. {
  621. if (_hMonitors[iMon] == hMonPrimary)
  622. {
  623. _hMonitors[iMon] = _hMonitors[0];
  624. _hMonitors[0] = hMonPrimary;
  625. break;
  626. }
  627. }
  628. }
  629. }
  630. // Gets the persisted old work areas, from the registry
  631. BOOL GetOldWorkAreas(LPRECT lprc, DWORD* pdwNoOfOldWA)
  632. {
  633. BOOL fRet = FALSE;
  634. *pdwNoOfOldWA = 0;
  635. HKEY hkey;
  636. if (RegOpenKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP_OLDWORKAREAS, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  637. {
  638. DWORD dwType, cbSize = sizeof(*pdwNoOfOldWA);
  639. // Read in the no of old work areas
  640. if (SHQueryValueEx(hkey, REG_VAL_OLDWORKAREAS_COUNT, NULL, &dwType, (LPBYTE)pdwNoOfOldWA, &cbSize) == ERROR_SUCCESS)
  641. {
  642. // Read in the old work area rects
  643. cbSize = sizeof(*lprc) * (*pdwNoOfOldWA);
  644. if (SHQueryValueEx(hkey, REG_VAL_OLDWORKAREAS_RECTS, NULL, &dwType, (LPBYTE)lprc, &cbSize) == ERROR_SUCCESS)
  645. {
  646. fRet = TRUE;
  647. }
  648. }
  649. RegCloseKey(hkey);
  650. }
  651. return fRet;
  652. }
  653. // Saves the old work areas into the registry
  654. void SaveOldWorkAreas(LPCRECT lprc, DWORD nOldWA)
  655. {
  656. // Recreate the registry key.
  657. HKEY hkey;
  658. if (RegCreateKey(HKEY_CURRENT_USER, REG_DESKCOMP_OLDWORKAREAS, &hkey) == ERROR_SUCCESS)
  659. {
  660. // Write out the no. of old work areas
  661. RegSetValueEx(hkey, REG_VAL_OLDWORKAREAS_COUNT, 0, REG_DWORD, (LPBYTE)&nOldWA, sizeof(nOldWA));
  662. // Write out the no work area rectangles
  663. RegSetValueEx(hkey, REG_VAL_OLDWORKAREAS_RECTS, 0, REG_BINARY, (LPBYTE)lprc, sizeof(*lprc) * nOldWA);
  664. // Close out the reg key
  665. RegCloseKey(hkey);
  666. }
  667. }
  668. //*** CDesktopBrowser::IOleCommandTarget::* {
  669. STDMETHODIMP CDesktopBrowser::QueryStatus(const GUID *pguidCmdGroup,
  670. ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  671. {
  672. return E_NOTIMPL;
  673. }
  674. STDMETHODIMP CDesktopBrowser::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
  675. DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  676. {
  677. if (pguidCmdGroup == NULL)
  678. {
  679. /*NOTHING*/
  680. }
  681. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  682. {
  683. switch (nCmdID)
  684. {
  685. case SHDVID_RAISE:
  686. // n.b.: DTRF_RAISE/DTRF_LOWER go down; DTRF_QUERY goes up
  687. ASSERT(pvarargIn != NULL && pvarargIn->vt == VT_I4);
  688. if (pvarargIn->vt == VT_I4 && pvarargIn->lVal == DTRF_QUERY)
  689. {
  690. ASSERT(pvarargOut != NULL);
  691. pvarargOut->vt = VT_I4;
  692. pvarargOut->lVal = _fRaised ? DTRF_RAISE : DTRF_LOWER;
  693. return S_OK;
  694. }
  695. // o.w. let parent handle it
  696. break;
  697. case SHDVID_UPDATEOFFLINEDESKTOP:
  698. UpdateAllDesktopSubscriptions(NULL);
  699. return S_OK;
  700. }
  701. }
  702. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  703. {
  704. switch (nCmdID)
  705. {
  706. case SBCMDID_OPTIONS:
  707. case SBCMDID_ADDTOFAVORITES:
  708. return _pctInner->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  709. }
  710. }
  711. // do *not* forward up to SUPERCLASS::Exec (see QI's cryptic commment
  712. // about "don't let these get thru to our base class")
  713. return OLECMDERR_E_NOTSUPPORTED;
  714. }
  715. // }
  716. STDMETHODIMP CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
  717. {
  718. // Force SBSP_NEWBROWSER, SBSP_ABSOLUTE, and SBSP_NOTRANSFERHIST
  719. wFlags &= ~(SBSP_DEFBROWSER | SBSP_SAMEBROWSER | SBSP_RELATIVE | SBSP_PARENT);
  720. wFlags |= (SBSP_NEWBROWSER | SBSP_ABSOLUTE | SBSP_NOTRANSFERHIST);
  721. return _psbInner->BrowseObject(pidl, wFlags);
  722. }
  723. IStream *GetDesktopViewStream(DWORD grfMode, LPCTSTR pszName)
  724. {
  725. HKEY hkStreams;
  726. if (RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\Streams"), &hkStreams) == ERROR_SUCCESS)
  727. {
  728. IStream *pstm = OpenRegStream(hkStreams, TEXT("Desktop"), pszName, grfMode);
  729. RegCloseKey(hkStreams);
  730. return pstm;
  731. }
  732. return NULL;
  733. }
  734. void DeleteDesktopViewStream(LPCTSTR pszName)
  735. {
  736. SHDeleteValue(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\Streams\\Desktop"), pszName);
  737. }
  738. IStream *CDesktopBrowser::v_GetViewStream(LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pszName)
  739. {
  740. return GetDesktopViewStream(grfMode, pszName);
  741. }
  742. HRESULT CDesktopBrowser::_GetPropertyBag(LPCITEMIDLIST pidl, DWORD dwFlags, REFIID riid, void** ppv)
  743. {
  744. return SHGetViewStatePropertyBag(pidl, VS_BAGSTR_DESKTOP, dwFlags | SHGVSPB_ROAM, riid, ppv);
  745. }
  746. HRESULT CDesktopBrowser::GetPropertyBag(DWORD dwFlags, REFIID riid, void** ppv)
  747. {
  748. HRESULT hr;
  749. LPITEMIDLIST pidl;
  750. hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl);
  751. if (SUCCEEDED(hr))
  752. {
  753. hr = _GetPropertyBag(pidl, dwFlags, riid, ppv);
  754. ILFree(pidl);
  755. }
  756. return hr;
  757. }
  758. LRESULT CDesktopBrowser::OnCommand(WPARAM wParam, LPARAM lParam)
  759. {
  760. switch (GET_WM_COMMAND_ID(wParam, lParam))
  761. {
  762. case FCIDM_FINDFILES:
  763. SHFindFiles(_pbbd->_pidlCur, NULL);
  764. break;
  765. case FCIDM_REFRESH:
  766. {
  767. VARIANT v = {0};
  768. v.vt = VT_I4;
  769. v.lVal = OLECMDIDF_REFRESH_NO_CACHE|OLECMDIDF_REFRESH_PROMPTIFOFFLINE;
  770. // Our Exec is neutered (on purpose), so call our parent
  771. _pctInner->Exec(NULL, OLECMDID_REFRESH, OLECMDEXECOPT_DONTPROMPTUSER, &v, NULL);
  772. break;
  773. }
  774. case IDC_KBSTART:
  775. case FCIDM_NEXTCTL:
  776. if (_hwndTray)
  777. {
  778. // n.b. VK_TAB handled this way (among other things)
  779. SendMessage(_hwndTray, WM_COMMAND, wParam, lParam);
  780. }
  781. break;
  782. case IDM_CLOSE:
  783. PostMessage(_hwndTray, TM_DOEXITWINDOWS, 0, 0);
  784. break;
  785. default:
  786. _pbsInner->OnCommand(wParam, lParam);
  787. break;
  788. }
  789. return S_OK;
  790. }
  791. // Create desktop IShellView instance
  792. HRESULT CDesktopBrowser::_CreateDesktopView()
  793. {
  794. LPCITEMIDLIST pidl = SHCloneSpecialIDList(NULL, CSIDL_DESKTOP, TRUE);
  795. if (pidl)
  796. {
  797. IPropertyBag* ppb;
  798. if (0 == GetSystemMetrics(SM_CLEANBOOT) &&
  799. SUCCEEDED(_GetPropertyBag(pidl, SHGVSPB_PERUSER | SHGVSPB_PERFOLDER, IID_PPV_ARG(IPropertyBag, &ppb))))
  800. {
  801. SHPropertyBag_ReadDWORDDef(ppb, VS_PROPSTR_FFLAGS, reinterpret_cast<DWORD*>(&_fsd._fs.fFlags), FWF_DESKTOP | FWF_NOCLIENTEDGE | FWF_SNAPTOGRID);
  802. ppb->Release();
  803. }
  804. else
  805. {
  806. _fsd._fs.fFlags = FWF_DESKTOP | FWF_NOCLIENTEDGE | FWF_SNAPTOGRID; // default
  807. }
  808. _fsd._fs.ViewMode = FVM_ICON; // can't change this, sorry
  809. SHELLSTATE ss = {0};
  810. SHGetSetSettings(&ss, SSF_HIDEICONS, FALSE);
  811. if (ss.fHideIcons)
  812. _fsd._fs.fFlags |= FWF_NOICONS;
  813. else
  814. _fsd._fs.fFlags &= ~FWF_NOICONS;
  815. // We keep the active desktop in offline mode!
  816. ASSERT(_pbbd->_pautoWB2);
  817. _pbbd->_pautoWB2->put_Offline(TRUE);
  818. return _psbInner->BrowseObject(pidl, SBSP_SAMEBROWSER);
  819. }
  820. else
  821. {
  822. TCHAR szYouLoose[256];
  823. LoadString(HINST_THISDLL, IDS_YOULOSE, szYouLoose, ARRAYSIZE(szYouLoose));
  824. MessageBox(NULL, szYouLoose, NULL, MB_ICONSTOP);
  825. return E_FAIL;
  826. }
  827. }
  828. HRESULT CDesktopBrowser::ActivatePendingView(void)
  829. {
  830. HRESULT hres = _pbsInner->ActivatePendingView();
  831. if (SUCCEEDED(hres))
  832. {
  833. // calling SetShellWindow will cause the desktop
  834. // to initially paint white, then the background window.
  835. // This causes an ugly white trail when you move windows
  836. // around until the desktop finally paints.
  837. //
  838. // Calling SetShellWindowEx resolves this problem.
  839. //
  840. SHSetShellWindowEx(_pbbd->_hwnd, _GetDesktopListview());
  841. }
  842. return hres;
  843. }
  844. #ifdef DEBUG
  845. void CDesktopBrowser::_CreateDeskbars()
  846. {
  847. HRESULT hres;
  848. BOOL fCreate = FALSE;
  849. HKEY hkey;
  850. if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER TEXT("\\DeskBar\\Bands"), &hkey))
  851. {
  852. fCreate = TRUE;
  853. RegCloseKey(hkey);
  854. }
  855. if (fCreate)
  856. {
  857. IPersistStreamInit *ppstm;
  858. hres = CoCreateInstance(CLSID_DeskBarApp, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IPersistStreamInit, &ppstm));
  859. if (SUCCEEDED(hres)) {
  860. hres = ppstm->InitNew();
  861. AddToolbar(ppstm, L"test", NULL); // "Microsoft.DeskBarApp"
  862. ppstm->Release();
  863. }
  864. }
  865. }
  866. #endif
  867. void CDesktopBrowser::_InitDeskbars()
  868. {
  869. //
  870. // Load toolbars
  871. //
  872. // 1st, try persisted state
  873. IStream* pstm = GetDesktopViewStream(STGM_READ, TEXT("Toolbars"));
  874. HRESULT hres = E_FAIL;
  875. if (pstm)
  876. {
  877. hres = _pbsInner->_LoadToolbars(pstm);
  878. pstm->Release();
  879. }
  880. // 2nd, if there is none (or if version mismatch or other failure),
  881. // try settings from setup
  882. // NOTE: this works fine for ie4 where we have no old toolbars,
  883. // but for future releases we'll need some kind of merging scheme,
  884. // so we probably want to change this after ie4-beta-1.
  885. if (FAILED(hres))
  886. {
  887. // n.b. HKLM not HKCU
  888. // like GetDesktopViewStream but for HKLM
  889. HKEY hk = SHGetShellKey(SHELLKEY_HKLM_EXPLORER, TEXT("Streams\\Desktop"), TRUE);
  890. if (hk)
  891. {
  892. pstm = OpenRegStream(hk, NULL, TEXT("Default Toolbars"), STGM_READ);
  893. if (pstm)
  894. {
  895. hres = _pbsInner->_LoadToolbars(pstm);
  896. pstm->Release();
  897. }
  898. RegCloseKey(hk);
  899. }
  900. }
  901. // o.w., throw up our hands
  902. if (FAILED(hres))
  903. {
  904. ASSERT(0);
  905. #ifdef DEBUG
  906. // but for debug, need a way to bootstrap the entire process
  907. _CreateDeskbars();
  908. #endif
  909. }
  910. }
  911. // Handle creation of a new Desktop folder window. Creates everything except
  912. // the viewer part.
  913. // Returns -1 if something goes wrong.
  914. HWND g_hwndTray = NULL;
  915. HRESULT CDesktopBrowser::OnCreate(CREATESTRUCT *pcs)
  916. {
  917. LRESULT lr;
  918. g_pdtray->GetTrayWindow(&_hwndTray);
  919. g_hwndTray = _hwndTray;
  920. g_pdtray->SetDesktopWindow(_pbbd->_hwnd);
  921. SetTimer(_pbbd->_hwnd, IDT_ENUMHKCR, 5 * 60 * 1000, NULL);
  922. //
  923. // Notify IEDDE that the automation services are now available.
  924. //
  925. IEOnFirstBrowserCreation(NULL);
  926. ASSERT(_hwndTray);
  927. // REARCHITECT: we need to split out "ie registry settings" into a
  928. // browser component and a shell component.
  929. //
  930. //EnsureWebViewRegSettings();
  931. if (SUCCEEDED(_CreateDesktopView()))
  932. {
  933. lr = _pbsInner->OnCreate(pcs); // success
  934. PostMessage(_pbbd->_hwnd, DTM_CREATESAVEDWINDOWS, 0, 0);
  935. return (HRESULT) lr;
  936. }
  937. return (LRESULT)-1; // failure
  938. }
  939. UINT GetDDEExecMsg()
  940. {
  941. static UINT uDDEExec = 0;
  942. if (!uDDEExec)
  943. uDDEExec = RegisterWindowMessage(TEXT("DDEEXECUTESHORTCIRCUIT"));
  944. return uDDEExec;
  945. }
  946. LRESULT CDesktopBrowser::OnNotify(NMHDR * pnm)
  947. {
  948. switch (pnm->code)
  949. {
  950. case SEN_DDEEXECUTE:
  951. if (pnm->idFrom == 0)
  952. {
  953. // short cut notifier around the dde conv.
  954. LPNMVIEWFOLDER pnmPost = DDECreatePostNotify((LPNMVIEWFOLDER)pnm);
  955. if (pnmPost)
  956. {
  957. PostMessage(_pbbd->_hwnd, GetDDEExecMsg(), 0, (LPARAM)pnmPost);
  958. return TRUE;
  959. }
  960. }
  961. break;
  962. case NM_STARTWAIT:
  963. case NM_ENDWAIT:
  964. _iWaitCount += (pnm->code == NM_STARTWAIT ? 1 :-1);
  965. ASSERT(_iWaitCount >= 0);
  966. // Don't let it go negative or we'll never get rid of it.
  967. if (_iWaitCount < 0)
  968. _iWaitCount = 0;
  969. // what we really want is for user to simulate a mouse move/setcursor
  970. SetCursor(LoadCursor(NULL, _iWaitCount ? IDC_APPSTARTING : IDC_ARROW));
  971. break;
  972. default:
  973. return _pbsInner->OnNotify(pnm);
  974. }
  975. return 0;
  976. }
  977. // HACKHACK: this hard codes in that we know a listview is the child
  978. // of the view.
  979. HWND CDesktopBrowser::_GetDesktopListview()
  980. {
  981. HWND hwndView = _pbbd->_hwndView ? _pbbd->_hwndView : _pbbd->_hwndViewPending;
  982. if (!hwndView)
  983. return NULL;
  984. return FindWindowEx(hwndView, NULL, WC_LISTVIEW, NULL);
  985. }
  986. #ifndef ENUM_REGISTRY_SETTINGS
  987. #define ENUM_REGISTRY_SETTINGS ((DWORD)-2)
  988. #endif
  989. STDAPI_(BOOL) SHIsTempDisplayMode()
  990. {
  991. BOOL fTempMode = FALSE;
  992. DEVMODE dm = {0};
  993. dm.dmSize = sizeof(dm);
  994. if (EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm) &&
  995. dm.dmPelsWidth > 0 && dm.dmPelsHeight > 0)
  996. {
  997. HDC hdc = GetDC(NULL);
  998. int xres = GetDeviceCaps(hdc, HORZRES);
  999. int yres = GetDeviceCaps(hdc, VERTRES);
  1000. ReleaseDC(NULL, hdc);
  1001. if (xres != (int)dm.dmPelsWidth || yres != (int)dm.dmPelsHeight)
  1002. fTempMode = TRUE;
  1003. }
  1004. return fTempMode;
  1005. }
  1006. // NOTE: this is the hack andyp put in
  1007. // (dli) Currently, bottommost Tray is really wierd, it is not treated as toolbars.
  1008. // In a sense, it has higher priority than those toolbars. So they should be taken
  1009. // off the EffectiveClientArea
  1010. void CDesktopBrowser::_SubtractBottommostTray(LPRECT prc)
  1011. {
  1012. LRESULT lTmp;
  1013. APPBARDATA abd;
  1014. abd.cbSize = sizeof(APPBARDATA);
  1015. abd.hWnd = _hwndTray;
  1016. // lTmp = SHAppBarMessage(ABM_GETSTATE, &abd);
  1017. lTmp = g_pdtray->AppBarGetState();
  1018. if ((lTmp & (ABS_ALWAYSONTOP|ABS_AUTOHIDE)) == 0) {
  1019. // tray is on bottom and takes 'real' space
  1020. RECT rcTray = {0};
  1021. GetWindowRect(_hwndTray, &rcTray);
  1022. IntersectRect(&rcTray, prc, &rcTray);
  1023. SubtractRect(prc, prc, &rcTray);
  1024. }
  1025. }
  1026. HRESULT CDesktopBrowser::_GetEffectiveClientArea(LPRECT lprectBorder, HMONITOR hmon)
  1027. {
  1028. //
  1029. // Cache the work area if
  1030. // (1) this is the very first call
  1031. // (2) cached value is blew off by WM_SIZE (in _OnSize)
  1032. //
  1033. if (hmon) {
  1034. GetMonitorWorkArea(hmon, lprectBorder);
  1035. }
  1036. else {
  1037. if (::IsRectEmpty(&_rcWorkArea)) {
  1038. ::SystemParametersInfo(SPI_GETWORKAREA, 0, &_rcWorkArea, 0);
  1039. }
  1040. *lprectBorder = _rcWorkArea;
  1041. }
  1042. _SubtractBottommostTray(lprectBorder);
  1043. MapWindowPoints(NULL, _pbbd->_hwnd, (LPPOINT)lprectBorder, 2);
  1044. return S_OK;
  1045. }
  1046. BOOL EqualRects(LPRECT prcNew, LPRECT prcOld, int nRects)
  1047. {
  1048. int i;
  1049. for (i = 0; i < nRects; i++)
  1050. if (!EqualRect(&prcNew[i], &prcOld[i]))
  1051. return FALSE;
  1052. return TRUE;
  1053. }
  1054. //
  1055. // When Snap-To-Grid is on, we want to reduce the size of gutter space around the primary monitor.
  1056. // We achieve that by adding a few pixels to the grid size sothat the gutter size left out is
  1057. // as small as possible.
  1058. // Note: This is currently done only for Desktop listview.
  1059. //
  1060. // fMinimizeCutterSpace == FALSE => Nothing to do. Just return.
  1061. // fMinimizeGutterSpace == TRUE => We calculate and set the icon spacing so as to minimize gutter.
  1062. //
  1063. void UpdateGridSizes(BOOL fDesktop, HWND hwndListview, int nWorkAreas, LPRECT prcWork, BOOL fMinimizeGutterSpace)
  1064. {
  1065. if(!fDesktop) //If this is not desktop, we do not change any of this.
  1066. return;
  1067. // Trying to reset the icon spacing to system icon spacing results in ReComputing everything.
  1068. // So, just return without doing anything!
  1069. if(!fMinimizeGutterSpace)
  1070. return; //If we don't have to minimize the gutter space, nothing to do!
  1071. int cxSysIconSpacing = GetSystemMetrics(SM_CXICONSPACING);
  1072. if (cxSysIconSpacing <= 0) cxSysIconSpacing = 1; // avoid div0
  1073. int cySysIconSpacing = GetSystemMetrics(SM_CYICONSPACING);
  1074. if (cySysIconSpacing <= 0) cySysIconSpacing = 1; // avoid div0
  1075. int cxNewIconSpacing = 0, cyNewIconSpacing = 0;
  1076. RECT rcWorkAreas[LV_MAX_WORKAREAS];
  1077. //If the work areas are not given, we need to get them.
  1078. if(prcWork == NULL)
  1079. {
  1080. prcWork = &rcWorkAreas[0];
  1081. ListView_GetNumberOfWorkAreas(hwndListview, &nWorkAreas);
  1082. if(nWorkAreas > 0)
  1083. ListView_GetWorkAreas(hwndListview, nWorkAreas, prcWork);
  1084. else
  1085. ListView_GetViewRect(hwndListview, prcWork);
  1086. }
  1087. //Get the primary work area.
  1088. for(int iPrimary = 0; iPrimary < nWorkAreas; iPrimary++)
  1089. {
  1090. //LATER: Is this check enough! What about when tray is at the top or left?
  1091. if((prcWork[iPrimary].left == 0) && (prcWork[iPrimary].top == 0))
  1092. break;
  1093. }
  1094. if(iPrimary == nWorkAreas)
  1095. iPrimary = 0; //Assume that the first work area is primary work area.
  1096. //Find the number of columns based on current system horizontal icon spacing.
  1097. int nCols = (prcWork[iPrimary].right - prcWork[iPrimary].left)/cxSysIconSpacing;
  1098. if (nCols <= 0) nCols = 1; // avoid div0
  1099. //Divide the remaining pixels and add them to each column to minimize the reminder area.
  1100. cxNewIconSpacing = cxSysIconSpacing + ((prcWork[iPrimary].right - prcWork[iPrimary].left)%cxSysIconSpacing)/nCols;
  1101. if (cxNewIconSpacing <= 0) cxNewIconSpacing = 1; // avoid div0
  1102. //Find the number of Rows based on current system vertical icon spacing.
  1103. int nRows = (prcWork[iPrimary].bottom - prcWork[iPrimary].top)/cySysIconSpacing;
  1104. if (nRows <= 0) nRows = 1; // avoid div0
  1105. //Divide the remaining pixles and add them to each row to minimize the reminder area.
  1106. cyNewIconSpacing = cySysIconSpacing + ((prcWork[iPrimary].bottom - prcWork[iPrimary].top)%cySysIconSpacing)/nRows;
  1107. if (cyNewIconSpacing <= 0) cyNewIconSpacing = 1; // avoid div0
  1108. //Set the new icon spacing to the desktop's listview.
  1109. ListView_SetIconSpacing(hwndListview, cxNewIconSpacing, cyNewIconSpacing);
  1110. }
  1111. void CDesktopBrowser::_SetWorkAreas(int nWorkAreas, LPRECT prcWork)
  1112. {
  1113. RECT rcListViewWork[LV_MAX_WORKAREAS];
  1114. RECT rcNewWork[LV_MAX_WORKAREAS];
  1115. int nListViewWork = 0;
  1116. HWND hwndList;
  1117. int i;
  1118. ASSERT(prcWork);
  1119. ASSERT(nWorkAreas <= LV_MAX_WORKAREAS);
  1120. ASSERT(nWorkAreas > 0);
  1121. if (nWorkAreas <= 0)
  1122. return;
  1123. if (SHIsTempDisplayMode())
  1124. return;
  1125. hwndList = _GetDesktopListview();
  1126. ASSERT(IsWindow(hwndList));
  1127. ListView_GetNumberOfWorkAreas(hwndList, &nListViewWork);
  1128. BOOL fUpgradeGridSize = (BOOL)((ListView_GetExtendedListViewStyle(hwndList)) & LVS_EX_SNAPTOGRID);
  1129. BOOL fRedraw = FALSE;
  1130. if (nListViewWork > 0)
  1131. {
  1132. ListView_GetWorkAreas(hwndList, nListViewWork, rcListViewWork);
  1133. // Map these rects back to DESKTOP coordinate
  1134. // We need to convert the following only if WorkAreas > 1
  1135. if (nListViewWork > 1)
  1136. {
  1137. // [msadek]; MapWindowPoints() is mirroring-aware only if you pass two points
  1138. for(i = 0; i < nListViewWork; i++)
  1139. {
  1140. MapWindowPoints(hwndList, HWND_DESKTOP, (LPPOINT)(&rcListViewWork[i]), 2);
  1141. }
  1142. }
  1143. if(nListViewWork == nWorkAreas && EqualRects(prcWork, rcListViewWork, nWorkAreas))
  1144. return;
  1145. }
  1146. else if (_nOldWork > 1)
  1147. // In single monitor case, listview workares always starts from (0,0)
  1148. // It will be wrong to set the persisted workarea.
  1149. {
  1150. for (nListViewWork = 0; nListViewWork < (int)_nOldWork && nListViewWork < LV_MAX_WORKAREAS; nListViewWork++)
  1151. CopyRect(&rcListViewWork[nListViewWork], &_rcOldWorkAreas[nListViewWork]);
  1152. // This may not be needed, because at this point, ListView is in Desktop coordinate
  1153. // [msadek]; MapWindowPoints() is mirroring-aware only if you pass two points
  1154. for(i = 0; i < nListViewWork; i++)
  1155. {
  1156. MapWindowPoints(HWND_DESKTOP, hwndList, (LPPOINT)(&rcListViewWork[i]), 2);
  1157. }
  1158. //Before setting the WorkAreas, change the grid-size if needed.
  1159. if(fUpgradeGridSize)
  1160. {
  1161. // We set the grid size based on the new work area. This way Recycle-Bin gets snapped
  1162. // to the correct location just once and we don't need to change it later.
  1163. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  1164. fRedraw = TRUE;
  1165. UpdateGridSizes(TRUE, hwndList, nWorkAreas, prcWork, TRUE);
  1166. fUpgradeGridSize = FALSE; //Don't need to do it again!
  1167. }
  1168. // This call to SetWorkAreas sets the old work areas in the listview, which is not persisted there.
  1169. ListView_SetWorkAreas(hwndList, nListViewWork, rcListViewWork);
  1170. }
  1171. //Make a copy of the new work area array because it gets modified by
  1172. // the MapWindowPoints below.
  1173. for(i = 0; i < nWorkAreas; i++)
  1174. rcNewWork[i] = *(prcWork + i);
  1175. // It's already in ListView coordinate if we just have one monitor
  1176. if (nWorkAreas > 1)
  1177. {
  1178. for(i = 0; i < nWorkAreas; i++)
  1179. {
  1180. MapWindowPoints(HWND_DESKTOP, hwndList, (LPPOINT)(&prcWork[i]), 2);
  1181. }
  1182. }
  1183. //Because the work areas change, update the grid size to reduce the gutter area.
  1184. if(fUpgradeGridSize) //If we haven't done already!
  1185. {
  1186. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  1187. fRedraw = TRUE;
  1188. UpdateGridSizes(TRUE, hwndList, nWorkAreas, prcWork, TRUE);
  1189. }
  1190. // We need to set the new work area before we call AdjustDesktopComponents below
  1191. // because that function results in a refresh and that ends up setting
  1192. // the work areas again to the same values.
  1193. ListView_SetWorkAreas(hwndList, nWorkAreas, prcWork);
  1194. if (fRedraw)
  1195. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  1196. if (nWorkAreas == 1)
  1197. MapWindowPoints(hwndList, HWND_DESKTOP, (LPPOINT)rcNewWork, 2 * nWorkAreas);
  1198. //Move and size desktop components based on the new work areas.
  1199. AdjustDesktopComponents((LPCRECT)rcNewWork, nWorkAreas, (LPCRECT)_rcOldMonitors, (LPCRECT)_rcOldWorkAreas, _nOldWork);
  1200. // Backup the new Monitor rect's in _rcOldMonitors
  1201. for (i = 0; i < _nMonitors; i++)
  1202. {
  1203. GetMonitorRect(_hMonitors[i], &_rcOldMonitors[i]);
  1204. }
  1205. // Backup the new workareas in _rcOldWorkAreas
  1206. for (i = 0; i < nWorkAreas; i++)
  1207. {
  1208. _rcOldWorkAreas[i] = rcNewWork[i];
  1209. }
  1210. _nOldWork = nWorkAreas;
  1211. static const LPTSTR lpszSubkey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ScreenResFixer");
  1212. static const LPTSTR lpszValue = TEXT("AdjustRecycleBinPosition");
  1213. //Check if we need to change the recycle bin position because of this work-area change
  1214. // 0 => Recycle-bin hasn't been positioned because of resolution fixer.
  1215. // 1 => Recycle-bin needs to be repositioned. It has't happened yet!
  1216. // 2 => Recycle-bin has already been re-positioned. Nothing needs to be done here!
  1217. DWORD dwAdjustPos = 2; //Assume that Recycle-bin has been already positioned.
  1218. DWORD dwSize = sizeof(dwAdjustPos);
  1219. SHRegGetUSValue(lpszSubkey, lpszValue, NULL, &dwAdjustPos, &dwSize, FALSE, &dwAdjustPos, dwSize);
  1220. //If the AdjustRecycleBinPosition value has 1, that means we need to reposition recyclebin.
  1221. if(dwAdjustPos == 1)
  1222. {
  1223. //Move the recycle-bin to default position
  1224. SendMessage(_pbbd->_hwndView, WM_DSV_ADJUSTRECYCLEBINPOSITION, 0, 0);
  1225. dwAdjustPos = 2; //We have moved this just now! No need to move it anymore!
  1226. SHRegSetUSValue(lpszSubkey, lpszValue, REG_DWORD, &dwAdjustPos, sizeof(dwAdjustPos), SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  1227. }
  1228. }
  1229. // Get all the view border rectangles (not including toolbars) for the monitors
  1230. // this is used for multi-monitor case only.
  1231. void CDesktopBrowser::_GetViewBorderRects(int nRects, LPRECT prcBorders)
  1232. {
  1233. int iMon;
  1234. HMONITOR hmonTray;
  1235. Tray_GetHMonitor(_hwndTray, &hmonTray);
  1236. for (iMon = 0; iMon < min(_nMonitors, nRects); iMon++)
  1237. {
  1238. GetMonitorWorkArea(_hMonitors[iMon], &prcBorders[iMon]);
  1239. if (hmonTray == _hMonitors[iMon])
  1240. {
  1241. _SubtractBottommostTray(&prcBorders[iMon]);
  1242. }
  1243. // Extract the border taken by all "frame" toolbars
  1244. for (int itb=0; itb < _pbsInner->_GetToolbarCount(); itb++)
  1245. {
  1246. LPTOOLBARITEM ptbi = _pbsInner->_GetToolbarItem(itb);
  1247. if (ptbi && ptbi->hMon == _hMonitors[iMon])
  1248. {
  1249. prcBorders[iMon].left += ptbi->rcBorderTool.left;
  1250. prcBorders[iMon].top += ptbi->rcBorderTool.top;
  1251. prcBorders[iMon].right -= ptbi->rcBorderTool.right;
  1252. prcBorders[iMon].bottom -= ptbi->rcBorderTool.bottom;
  1253. }
  1254. }
  1255. }
  1256. }
  1257. HRESULT CDesktopBrowser::_UpdateViewRectSize()
  1258. {
  1259. HWND hwndView = _pbbd->_hwndView;
  1260. if (!hwndView && ((hwndView = _pbbd->_hwndViewPending) == NULL))
  1261. return S_FALSE;
  1262. _pbsInner->_UpdateViewRectSize();
  1263. if (_nMonitors <= 1)
  1264. {
  1265. RECT rcView, rcWork;
  1266. GetViewRect(&rcView);
  1267. rcWork.top = rcWork.left = 0;
  1268. rcWork.right = RECTWIDTH(rcView);
  1269. rcWork.bottom = RECTHEIGHT(rcView);
  1270. _SetWorkAreas(1, &rcWork);
  1271. }
  1272. else
  1273. {
  1274. RECT rcWorks[LV_MAX_WORKAREAS];
  1275. _GetViewBorderRects(_nMonitors, rcWorks);
  1276. _SetWorkAreas(_nMonitors, rcWorks);
  1277. }
  1278. return S_OK;
  1279. }
  1280. void CDesktopBrowser::_SetViewArea()
  1281. {
  1282. //
  1283. // Invalidate the cached work area size
  1284. //
  1285. ::SetRectEmpty(&_rcWorkArea);
  1286. v_ShowHideChildWindows(FALSE);
  1287. }
  1288. // we get called here when new drives come and go;
  1289. // things like net connections, hot insertions, etc.
  1290. void _OnDeviceBroadcast(HWND hwnd, ULONG_PTR code, DEV_BROADCAST_HDR *pbh)
  1291. {
  1292. // do a bunch of this stuff here in desktop so it only happens
  1293. // once...
  1294. switch (code)
  1295. {
  1296. case DBT_DEVICEREMOVECOMPLETE: // drive or media went away
  1297. case DBT_DEVICEARRIVAL: // new drive or media (or UNC) has arrived
  1298. case DBT_DEVICEQUERYREMOVE: // drive or media about to go away
  1299. case DBT_DEVICEQUERYREMOVEFAILED: // drive or media didn't go away
  1300. {
  1301. BOOL fFilteredOut = FALSE;
  1302. // Don't process if we are being shutdown...
  1303. if (!IsWindowVisible(hwnd))
  1304. break;
  1305. // Filter this one out
  1306. if (DBT_DEVICEARRIVAL == code)
  1307. {
  1308. if (DBT_DEVTYP_NET == pbh->dbch_devicetype)
  1309. {
  1310. LPITEMIDLIST pidl;
  1311. // Tell the hood to update as things have probably changed!
  1312. // PERF: this can be slow in the case of the nethood FS folder
  1313. // no longer exists. this hangs the desktop/tray. this is a robustness bug
  1314. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_NETHOOD, &pidl)))
  1315. {
  1316. SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
  1317. SHFree(pidl);
  1318. }
  1319. // use UNCToNetID(loop if (pbn->dbcn_resource)
  1320. fFilteredOut = TRUE;
  1321. }
  1322. }
  1323. if (!fFilteredOut)
  1324. {
  1325. CMountPoint::HandleWMDeviceChange(code, pbh);
  1326. }
  1327. break;
  1328. }
  1329. }
  1330. }
  1331. // Note: this overrides the one in CBaseBrowser
  1332. HRESULT CDesktopBrowser::GetViewRect(RECT* prc)
  1333. {
  1334. //
  1335. // Check if we are on a multiple-monitor system. In multiple monitors the
  1336. // view needs to cover all displays (ie the size of _pbbd->_hwnd) while on
  1337. // single-monitor systems the view just needs to cover the work area (like
  1338. // in Win95).
  1339. //
  1340. if (_nMonitors <= 1)
  1341. _pbsInner->GetViewRect(prc);
  1342. else
  1343. GetClientRect(_pbbd->_hwnd, prc);
  1344. return S_OK;
  1345. }
  1346. HRESULT CDesktopBrowser::ReleaseShellView()
  1347. {
  1348. _SaveState();
  1349. return _pbsInner->ReleaseShellView();
  1350. }
  1351. void CDesktopBrowser::_ViewChange(DWORD dwAspect, LONG lindex)
  1352. {
  1353. // do nothing here...
  1354. }
  1355. void CDesktopBrowser::_SaveDesktopToolbars()
  1356. {
  1357. IStream * pstm = GetDesktopViewStream(STGM_WRITE, TEXT("Toolbars"));
  1358. if (pstm)
  1359. {
  1360. _pbsInner->_SaveToolbars(pstm);
  1361. pstm->Release();
  1362. }
  1363. }
  1364. void CDesktopBrowser::_SaveState()
  1365. {
  1366. // save off the Recycle Bin information to the registry
  1367. SaveRecycleBinInfo();
  1368. if (!SHRestricted(REST_NOSAVESET) && _pbbd->_psv)
  1369. {
  1370. if (0 == GetSystemMetrics(SM_CLEANBOOT))
  1371. {
  1372. FOLDERSETTINGS fs;
  1373. _pbbd->_psv->GetCurrentInfo(&fs);
  1374. IPropertyBag* ppb;
  1375. if (SUCCEEDED(GetPropertyBag(SHGVSPB_PERUSER | SHGVSPB_PERFOLDER, IID_PPV_ARG(IPropertyBag, &ppb))))
  1376. {
  1377. SHPropertyBag_WriteInt(ppb, VS_PROPSTR_FFLAGS, fs.fFlags);
  1378. ppb->Release();
  1379. }
  1380. }
  1381. _pbbd->_psv->SaveViewState();
  1382. _SaveDesktopToolbars();
  1383. }
  1384. }
  1385. HRESULT CDesktopBrowser::OnSize(WPARAM wParam)
  1386. {
  1387. if (wParam == SIZE_MINIMIZED)
  1388. {
  1389. TraceMsg(DM_TRACE, "c.dwp: Desktop minimized by somebody!");
  1390. // Put it back.
  1391. ShowWindow(_pbbd->_hwnd, SW_RESTORE);
  1392. }
  1393. _SetViewArea();
  1394. return S_OK;
  1395. }
  1396. HRESULT CDesktopBrowser::OnDestroy()
  1397. {
  1398. TraceMsg(DM_SHUTDOWN, "cdtb._od (WM_DESTROY)");
  1399. if (_uNotifyID)
  1400. {
  1401. SHChangeNotifyDeregister(_uNotifyID);
  1402. _uNotifyID = 0;
  1403. }
  1404. if (_hwndRaised)
  1405. DestroyWindow(_hwndRaised);
  1406. // get rid of the scheduler and the desktop tasks
  1407. if (_psched)
  1408. {
  1409. _psched->RemoveTasks(TOID_Desktop, 0, TRUE);
  1410. ATOMICRELEASE(_psched);
  1411. }
  1412. _pbsInner->OnDestroy();
  1413. _pbsInner->_CloseAndReleaseToolbars(TRUE);
  1414. return S_OK;
  1415. }
  1416. #define DM_SWAP DM_TRACE
  1417. void CDesktopBrowser::_SwapParents(HWND hwndOldParent, HWND hwndNewParent)
  1418. {
  1419. HWND hwnd = ::GetWindow(hwndOldParent, GW_CHILD);
  1420. while (hwnd)
  1421. {
  1422. //
  1423. // Note that we must get the next sibling BEFORE we set the new
  1424. // parent.
  1425. //
  1426. HWND hwndNext = ::GetWindow(hwnd, GW_HWNDNEXT);
  1427. ::SetParent(hwnd, hwndNewParent);
  1428. hwnd = hwndNext;
  1429. }
  1430. }
  1431. LRESULT CDesktopBrowser::RaisedWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1432. {
  1433. CDesktopBrowser *psb = (CDesktopBrowser*)GetWindowLongPtr(hwnd, 0);
  1434. return psb->_RaisedWndProc(uMsg, wParam, lParam);
  1435. }
  1436. LRESULT CDesktopBrowser::_RaisedWndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1437. {
  1438. switch (uMsg)
  1439. {
  1440. case WM_ACTIVATE:
  1441. break;
  1442. case WM_SIZE:
  1443. if (wParam == SIZE_MINIMIZED)
  1444. ShowWindow(_hwndRaised, SW_RESTORE);
  1445. break;
  1446. case WM_NOTIFY:
  1447. case WM_ERASEBKGND:
  1448. goto SendToDesktop;
  1449. default:
  1450. if (uMsg >= WM_USER)
  1451. {
  1452. SendToDesktop:
  1453. return SendMessage(_pbbd->_hwnd, uMsg, wParam, lParam);
  1454. }
  1455. else
  1456. {
  1457. return ::SHDefWindowProc(_hwndRaised, uMsg, wParam, lParam);
  1458. }
  1459. }
  1460. return 0;
  1461. }
  1462. void CDesktopBrowser::_Raise()
  1463. {
  1464. RECT rc;
  1465. HWND hwndDesktop = GetDesktopWindow();
  1466. BOOL fLocked;
  1467. HWND hwndLastActive = GetLastActivePopup(_pbbd->_hwnd);
  1468. if (SHIsRestricted(NULL, REST_NODESKTOP))
  1469. return;
  1470. if (hwndLastActive != _pbbd->_hwnd)
  1471. {
  1472. SetForegroundWindow(hwndLastActive);
  1473. return;
  1474. }
  1475. if (!_hwndRaised)
  1476. _hwndRaised = SHCreateWorkerWindow(RaisedWndProc, NULL, WS_EX_TOOLWINDOW, WS_POPUP | WS_CLIPCHILDREN, NULL, this);
  1477. //SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
  1478. //rc.left = 0; // need to always start from 0, 0 to get the wallpaper centered right
  1479. //rc.top = 0;
  1480. fLocked = LockWindowUpdate(hwndDesktop);
  1481. _SwapParents(_pbbd->_hwnd, _hwndRaised);
  1482. // set the view window to the bottom of the z order
  1483. SetWindowPos(_pbbd->_hwndView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1484. GetWindowRect(_pbbd->_hwnd, &rc);
  1485. SetWindowPos(_hwndRaised, HWND_TOP, rc.left, rc.top, RECTWIDTH(rc), RECTHEIGHT(rc), SWP_SHOWWINDOW);
  1486. SetForegroundWindow(_hwndRaised);
  1487. if (fLocked)
  1488. LockWindowUpdate(NULL);
  1489. THR(RegisterDragDrop(_hwndRaised, (IDropTarget *)this));
  1490. SetFocus(_pbbd->_hwndView);
  1491. //SetWindowPos(_hwndTray, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE);
  1492. _fRaised = TRUE;
  1493. }
  1494. void CDesktopBrowser::_Lower()
  1495. {
  1496. BOOL fLocked;
  1497. fLocked = LockWindowUpdate(_hwndRaised);
  1498. _SwapParents(_hwndRaised, _pbbd->_hwnd);
  1499. // set the view window to the bottom of the z order
  1500. SetWindowPos(_pbbd->_hwndView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  1501. ShowWindow(_hwndRaised, SW_HIDE);
  1502. if (fLocked)
  1503. LockWindowUpdate(NULL);
  1504. RevokeDragDrop(_hwndRaised);
  1505. _fRaised = FALSE;
  1506. }
  1507. void CDesktopBrowser::_OnRaise(WPARAM wParam, LPARAM lParam)
  1508. {
  1509. VARIANTARG vaIn;
  1510. VariantInit(&vaIn);
  1511. vaIn.vt = VT_I4;
  1512. vaIn.lVal = (DWORD) lParam;
  1513. switch (lParam) {
  1514. case DTRF_RAISE:
  1515. _Raise();
  1516. _ExecChildren(NULL, TRUE, &CGID_ShellDocView, SHDVID_RAISE, 0, &vaIn, NULL);
  1517. break;
  1518. case DTRF_LOWER:
  1519. _ExecChildren(NULL, TRUE, &CGID_ShellDocView, SHDVID_RAISE, 0, &vaIn, NULL);
  1520. _Lower();
  1521. break;
  1522. }
  1523. VariantClear(&vaIn);
  1524. if (!wParam) {
  1525. wParam = (WPARAM)_hwndTray;
  1526. }
  1527. PostMessage((HWND)wParam, TM_DESKTOPSTATE, 0, _fRaised ? DTRF_RAISE : DTRF_LOWER);
  1528. }
  1529. BOOL CDesktopBrowser::_QueryHKCRChanged(HWND hwnd, DWORD *pdwCookie)
  1530. {
  1531. // we assume that the key has changed if
  1532. // we were unable to init correctly
  1533. BOOL fRet = TRUE;
  1534. ASSERT(pdwCookie);
  1535. if (_cChangeEvents)
  1536. {
  1537. DWORD dw = WaitForMultipleObjects(_cChangeEvents, _rghChangeEvents, FALSE, 0);
  1538. dw -= WAIT_OBJECT_0;
  1539. // Note: Since "dw" is a DWORD, an underflow in the line above
  1540. // will result in dw becoming a huge value, so the test below will
  1541. // fail.
  1542. if (dw < _cChangeEvents)
  1543. {
  1544. // this means the key changed...
  1545. ResetEvent(_rghChangeEvents[dw]);
  1546. _dwChangeCookie = GetTickCount();
  1547. PostMessage(hwnd, DTM_SETUPAPPRAN, 0, NULL);
  1548. }
  1549. //
  1550. // if nothing has changed yet, or if nothing has changed
  1551. // since the client last checked,
  1552. // than this client doesnt need to update its cache
  1553. //
  1554. if (!_dwChangeCookie || (*pdwCookie && *pdwCookie == _dwChangeCookie))
  1555. fRet = FALSE;
  1556. // update the cookie
  1557. *pdwCookie = _dwChangeCookie;
  1558. }
  1559. return fRet;
  1560. }
  1561. // This msg gets posted to us after a setup application runs so that we can
  1562. // fix things up.
  1563. void CDesktopBrowser::_SetupAppRan(WPARAM wParam, LPARAM lParam)
  1564. {
  1565. // Lotus 123R5 sometimes gets confused when installing over IE4 and
  1566. // they leave their country setting blank. Detect this case and put
  1567. // in USA so that they at least boot.
  1568. {
  1569. TCHAR szPath[MAX_PATH];
  1570. GetWindowsDirectory(szPath, ARRAYSIZE(szPath));
  1571. if (PathAppend(szPath, TEXT("123r5.ini")) && PathFileExistsAndAttributes(szPath, NULL))
  1572. {
  1573. TCHAR szData[100];
  1574. GetPrivateProfileString(TEXT("Country"), TEXT("driver"), TEXT(""), szData, ARRAYSIZE(szData), TEXT("123r5.ini"));
  1575. if (!szData[0])
  1576. {
  1577. WritePrivateProfileString(TEXT("Country"), TEXT("driver"), TEXT("L1WUSF"), TEXT("123r5.ini"));
  1578. }
  1579. }
  1580. }
  1581. // this location in the registry is a good place to cache info
  1582. // that needs to be invalided once
  1583. SHDeleteKey(HKEY_CURRENT_USER, STRREG_DISCARDABLE STRREG_POSTSETUP);
  1584. HKEY hk = SHGetShellKey(SHELLKEY_HKCULM_MUICACHE, NULL, FALSE);
  1585. if (hk)
  1586. {
  1587. SHDeleteKeyA(hk, NULL);
  1588. RegCloseKey(hk);
  1589. }
  1590. // Take this opportunity to freshen our component categories cache:
  1591. IShellTaskScheduler* pScheduler ;
  1592. if(SUCCEEDED(CoCreateInstance(CLSID_SharedTaskScheduler, NULL, CLSCTX_INPROC_SERVER,
  1593. IID_PPV_ARG(IShellTaskScheduler, &pScheduler))))
  1594. {
  1595. #ifdef _WIN64
  1596. // Before creating 64-bit component cache, we should delete the 32-bit cache,
  1597. // because we used to erroneously cache 64-bit components in the 32-bit cache,
  1598. // and it won't get rebuilt with correc 32-bit components unless we delete it now.
  1599. SHDeleteKey(HKEY_CURRENT_USER, STRREG_DISCARDABLE STRREG_POSTSETUP TEXT("\\Component Categories"));
  1600. #endif
  1601. IRunnableTask* pTask ;
  1602. if(SUCCEEDED(CoCreateInstance(CLSID_ComCatCacheTask, NULL, CLSCTX_INPROC_SERVER,
  1603. IID_PPV_ARG(IRunnableTask, &pTask))))
  1604. {
  1605. pScheduler->AddTask(pTask, CLSID_ComCatCacheTask, 0L, ITSAT_DEFAULT_PRIORITY);
  1606. pTask->Release(); // Scheduler has AddRef'd him
  1607. }
  1608. if (SUCCEEDED(CTaskEnumHKCR_Create(&pTask)))
  1609. {
  1610. pScheduler->AddTask(pTask, CLSID_QueryAssociations, 0L, ITSAT_DEFAULT_PRIORITY);
  1611. pTask->Release(); // Scheduler has AddRef'd him
  1612. }
  1613. pScheduler->Release(); // OK to release global task scheduler.
  1614. }
  1615. // We get this notification from the OS that a setup app ran.
  1616. // Legacy app support for freshly written entries under [extensions] section;
  1617. // Scoop these up and shove into registry. (re: bug 140986)
  1618. CheckWinIniForAssocs();
  1619. }
  1620. //-----------------------------------------------------------------------------
  1621. struct propagatemsg
  1622. {
  1623. UINT uMsg;
  1624. WPARAM wParam;
  1625. LPARAM lParam;
  1626. BOOL fSend;
  1627. };
  1628. BOOL PropagateCallback(HWND hwndChild, LPARAM lParam)
  1629. {
  1630. struct propagatemsg *pmsg = (struct propagatemsg*)lParam;
  1631. if (pmsg->fSend)
  1632. SendMessage(hwndChild, pmsg->uMsg, pmsg->wParam, pmsg->lParam);
  1633. else
  1634. PostMessage(hwndChild, pmsg->uMsg, pmsg->wParam, pmsg->lParam);
  1635. return TRUE;
  1636. }
  1637. void PropagateMessage(HWND hwndParent, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fSend)
  1638. {
  1639. if (!hwndParent)
  1640. return;
  1641. struct propagatemsg msg = { uMsg, wParam, lParam, fSend };
  1642. EnumChildWindows(hwndParent, PropagateCallback, (LPARAM)&msg);
  1643. }
  1644. void CDesktopBrowser::v_PropagateMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL fSend)
  1645. {
  1646. // WARNING: We can't propagate the message to a NULL hwnd because it will
  1647. // turn into a broadcast. This will come back to us and we will re-send it
  1648. // causing an infinite loop. BryanSt.
  1649. if (_fRaised && _hwndRaised)
  1650. PropagateMessage(_hwndRaised, uMsg, wParam, lParam, fSend);
  1651. else if (_pbbd->_hwnd)
  1652. PropagateMessage(_pbbd->_hwnd, uMsg, wParam, lParam, fSend);
  1653. }
  1654. //***
  1655. // NOTES
  1656. // in the tray case, we actually do SetFocus etc.
  1657. HRESULT CDesktopBrowser::v_MayGetNextToolbarFocus(LPMSG lpMsg,
  1658. UINT itbCur, int citb,
  1659. LPTOOLBARITEM * pptbi, HWND * phwnd)
  1660. {
  1661. HRESULT hr;
  1662. // _fTrayHack?
  1663. if (itbCur == ITB_VIEW) {
  1664. if (citb == -1) {
  1665. TraceMsg(DM_FOCUS, "cdtb.v_mgntf: ITB_VIEW,-1 => tray");
  1666. goto Ltray;
  1667. }
  1668. }
  1669. hr = _pbsInner->v_MayGetNextToolbarFocus(lpMsg, itbCur, citb, pptbi, phwnd);
  1670. TraceMsg(DM_FOCUS, "cdtb.v_mgntf: SUPER hr=%x", hr);
  1671. if (SUCCEEDED(hr)) {
  1672. // S_OK: we got and handled a candidate
  1673. // S_FALSE: we got a candidate and our parent will finish up
  1674. ASSERT(hr != S_OK); // currently never happens (but should work)
  1675. return hr;
  1676. }
  1677. // E_xxx: no candidate
  1678. ASSERT(citb == 1 || citb == -1);
  1679. *pptbi = NULL;
  1680. if (citb == 1) {
  1681. Ltray:
  1682. *phwnd = _hwndTray;
  1683. // AndyP REVIEW: why do we do this here instead of overriding
  1684. // _SetFocus and letting commonsb call that function? Sure, this
  1685. // is one less override, but why have different code paths?
  1686. SendMessage(_hwndTray, TM_UIACTIVATEIO, TRUE, citb);
  1687. return S_OK;
  1688. }
  1689. else
  1690. {
  1691. //Lview:
  1692. *phwnd = _pbbd->_hwndView;
  1693. return S_FALSE;
  1694. }
  1695. /*NOTREACHED*/
  1696. ASSERT(0);
  1697. }
  1698. //
  1699. // NOTE: Please think before calling this function, in a multi-monitor system this function
  1700. // returns TRUE if you are within a certain edge for any monitor, so puEdge means puEdge
  1701. // of a certain monitor instead of the whole desktop. -- dli
  1702. //
  1703. BOOL CDesktopBrowser::_PtOnDesktopEdge(POINTL* ppt, LPUINT puEdge)
  1704. {
  1705. RECT rcMonitor;
  1706. POINT pt = {ppt->x, ppt->y};
  1707. HMONITOR hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
  1708. // We got this point from drop, so it definitely should belong to a valid monitor -- dli
  1709. ASSERT(hMon);
  1710. GetMonitorRect(hMon, &rcMonitor);
  1711. // if it's near/on the edge on this monitor
  1712. if (ppt->x < rcMonitor.left + g_cxEdge) {
  1713. *puEdge = ABE_LEFT;
  1714. } else if (ppt->x > rcMonitor.right - g_cxEdge) {
  1715. *puEdge = ABE_RIGHT;
  1716. } else if (ppt->y < rcMonitor.top + g_cyEdge) {
  1717. *puEdge = ABE_TOP;
  1718. } else if (ppt->y > rcMonitor.bottom - g_cyEdge) {
  1719. *puEdge = ABE_BOTTOM;
  1720. } else {
  1721. *puEdge = (UINT)-1;
  1722. return FALSE;
  1723. }
  1724. return TRUE;
  1725. }
  1726. UINT g_cfDeskBand = 0;
  1727. HRESULT CDesktopBrowser::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  1728. {
  1729. ASSERT(pdtobj);
  1730. if (!g_cfDeskBand)
  1731. g_cfDeskBand = RegisterClipboardFormat(TEXT("DeskBand"));
  1732. FORMATETC fmte = { (CLIPFORMAT) g_cfDeskBand, NULL, 0, -1, TYMED_ISTREAM};
  1733. if (pdtobj->QueryGetData(&fmte) == S_OK) {
  1734. _dwEffectOnEdge = DROPEFFECT_COPY | DROPEFFECT_MOVE;
  1735. } else {
  1736. _dwEffectOnEdge = DROPEFFECT_NONE;
  1737. }
  1738. _grfKeyState = grfKeyState;
  1739. HRESULT hr;
  1740. if (_pdtInner)
  1741. hr = _pdtInner->DragEnter(pdtobj, grfKeyState, ptl, pdwEffect);
  1742. else
  1743. {
  1744. DAD_DragEnterEx3(_pbbd->_hwndView, ptl, pdtobj);
  1745. hr = S_OK;
  1746. }
  1747. return hr;
  1748. }
  1749. HRESULT CDesktopBrowser::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  1750. {
  1751. HRESULT hr = S_OK;
  1752. DAD_DragMoveEx(_pbbd->_hwndView, ptl);
  1753. _grfKeyState = grfKeyState;
  1754. if (_dwEffectOnEdge != DROPEFFECT_NONE) {
  1755. *pdwEffect &= _dwEffectOnEdge;
  1756. return S_OK;
  1757. }
  1758. if (_pdtInner)
  1759. hr = _pdtInner->DragOver(grfKeyState, ptl, pdwEffect);
  1760. return hr;
  1761. }
  1762. HRESULT DeskBarApp_Create(IUnknown** ppunkBar, IUnknown** ppunkBandSite)
  1763. {
  1764. IDeskBar* pdb;
  1765. HRESULT hres = CoCreateInstance(CLSID_DeskBarApp, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDeskBar, &pdb));
  1766. *ppunkBar = pdb;
  1767. if (SUCCEEDED(hres))
  1768. {
  1769. pdb->GetClient(ppunkBandSite);
  1770. }
  1771. return hres;
  1772. }
  1773. //***
  1774. // ENTRY/EXIT
  1775. // hres AddBand result on success; o.w. failure code
  1776. // NOTES
  1777. // n.b. on success we *must* return AddBand's hres (which is a dwBandID)
  1778. HRESULT CDesktopBrowser::_CreateDeskBarForBand(UINT uEdge, IUnknown *punk, POINTL *pptl, IBandSite **ppbsOut)
  1779. {
  1780. IBandSite *pbs;
  1781. IUnknown *punkBar;
  1782. IUnknown *punkBandSite;
  1783. HRESULT hres;
  1784. #ifdef DEBUG
  1785. HRESULT hresRet = -1;
  1786. #endif
  1787. if (ppbsOut)
  1788. *ppbsOut = NULL;
  1789. hres = DeskBarApp_Create(&punkBar, &punkBandSite);
  1790. if (SUCCEEDED(hres))
  1791. {
  1792. IDockingBarPropertyBagInit* ppbi;
  1793. if (SUCCEEDED(CoCreateInstance(CLSID_CDockingBarPropertyBag, NULL, CLSCTX_INPROC_SERVER,
  1794. IID_PPV_ARG(IDockingBarPropertyBagInit, &ppbi))))
  1795. {
  1796. if ((UINT)uEdge != -1)
  1797. {
  1798. ppbi->SetDataDWORD(PROPDATA_MODE, WBM_BOTTOMMOST);
  1799. ppbi->SetDataDWORD(PROPDATA_SIDE, uEdge);
  1800. }
  1801. else
  1802. {
  1803. ppbi->SetDataDWORD(PROPDATA_MODE, WBM_FLOATING);
  1804. }
  1805. ppbi->SetDataDWORD(PROPDATA_X, pptl->x);
  1806. ppbi->SetDataDWORD(PROPDATA_Y, pptl->y);
  1807. IPropertyBag * ppb;
  1808. if (SUCCEEDED(ppbi->QueryInterface(IID_PPV_ARG(IPropertyBag, &ppb))))
  1809. {
  1810. SHLoadFromPropertyBag(punkBar, ppb);
  1811. punkBandSite->QueryInterface(IID_PPV_ARG(IBandSite, &pbs));
  1812. if (pbs)
  1813. {
  1814. hres = pbs->AddBand(punk);
  1815. #ifdef DEBUG
  1816. hresRet = hres;
  1817. #endif
  1818. AddToolbar(punkBar, L"", NULL);
  1819. if (ppbsOut)
  1820. {
  1821. // IUnknown_Set (sort of...)
  1822. *ppbsOut = pbs;
  1823. (*ppbsOut)->AddRef();
  1824. }
  1825. pbs->Release();
  1826. if (_fRaised)
  1827. {
  1828. VARIANTARG vaIn = { 0 };
  1829. vaIn.vt = VT_I4;
  1830. vaIn.lVal = DTRF_RAISE;
  1831. ASSERT(punkBar != NULL); // o.w. we'd do a broadcast
  1832. _ExecChildren(punkBar, FALSE, &CGID_ShellDocView, SHDVID_RAISE, 0, &vaIn, NULL);
  1833. }
  1834. }
  1835. ppb->Release();
  1836. }
  1837. ppbi->Release();
  1838. }
  1839. punkBandSite->Release();
  1840. punkBar->Release();
  1841. }
  1842. ASSERT(hres == hresRet || FAILED(hres));
  1843. return hres;
  1844. }
  1845. HRESULT CDesktopBrowser::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  1846. {
  1847. UINT uEdge;
  1848. HRESULT hres = E_FAIL;
  1849. if (((_PtOnDesktopEdge(&pt, &uEdge) && (_grfKeyState & MK_LBUTTON)) ||
  1850. (_dwEffectOnEdge != DROPEFFECT_NONE)) && !SHRestricted(REST_NOCLOSE_DRAGDROPBAND))
  1851. {
  1852. // if the point is on the edge of the desktop and the item dropped was
  1853. // a single url object, then create a webbar
  1854. // TODO: (reuse) w/ a little restructuring we might share this code
  1855. // w/ CBandSite::Drop etc.
  1856. FORMATETC fmte = {(CLIPFORMAT)g_cfDeskBand, NULL, 0, -1, TYMED_ISTREAM};
  1857. STGMEDIUM stg;
  1858. LPITEMIDLIST pidl;
  1859. IUnknown* punk = NULL;
  1860. // we can move a band from bar to bar, but we can only copy or link a folder
  1861. // because the creation of a band relies on the source still abeing there
  1862. if ((*pdwEffect & (DROPEFFECT_COPY | DROPEFFECT_MOVE)) &&
  1863. SUCCEEDED(pdtobj->GetData(&fmte, &stg)))
  1864. {
  1865. // this is a drag of a band from another bar, create it!
  1866. hres = OleLoadFromStream(stg.pstm, IID_PPV_ARG(IUnknown, &punk));
  1867. if (SUCCEEDED(hres))
  1868. {
  1869. if (*pdwEffect & DROPEFFECT_COPY)
  1870. *pdwEffect = DROPEFFECT_COPY;
  1871. else
  1872. *pdwEffect = DROPEFFECT_MOVE;
  1873. }
  1874. ReleaseStgMedium(&stg);
  1875. }
  1876. else if ((*pdwEffect & (DROPEFFECT_COPY | DROPEFFECT_LINK)) &&
  1877. SUCCEEDED(SHPidlFromDataObject(pdtobj, &pidl, NULL, 0)))
  1878. {
  1879. hres = SHCreateBandForPidl(pidl, &punk, (grfKeyState & (MK_CONTROL | MK_SHIFT)) == (MK_CONTROL | MK_SHIFT));
  1880. ILFree(pidl);
  1881. if (SUCCEEDED(hres))
  1882. {
  1883. if (*pdwEffect & DROPEFFECT_LINK)
  1884. *pdwEffect = DROPEFFECT_LINK;
  1885. else
  1886. *pdwEffect = DROPEFFECT_COPY;
  1887. }
  1888. }
  1889. if (SUCCEEDED(hres))
  1890. {
  1891. if (punk)
  1892. {
  1893. BOOL fCreateRebarWindow = TRUE;
  1894. IDeskBandEx* pdbex;
  1895. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IDeskBandEx, &pdbex))))
  1896. {
  1897. fCreateRebarWindow = (pdbex->MoveBand() == S_OK) ? TRUE : FALSE;
  1898. pdbex->Release();
  1899. }
  1900. if (fCreateRebarWindow)
  1901. {
  1902. IBandSite *pbs;
  1903. hres = _CreateDeskBarForBand(uEdge, punk, &pt, &pbs);
  1904. if (SUCCEEDED(hres))
  1905. {
  1906. DWORD dwState = IDataObject_GetDeskBandState(pdtobj);
  1907. pbs->SetBandState(ShortFromResult(hres), BSSF_NOTITLE, dwState & BSSF_NOTITLE);
  1908. pbs->Release();
  1909. }
  1910. punk->Release();
  1911. }
  1912. }
  1913. IDropTarget *pdtView;
  1914. HRESULT hr = E_FAIL;
  1915. //Get the view's drop target
  1916. if (_pbbd->_psv)
  1917. {
  1918. hr = _pbbd->_psv->QueryInterface(IID_PPV_ARG(IDropTarget, &pdtView));
  1919. if (SUCCEEDED(hr))
  1920. {
  1921. pdtView->DragLeave();
  1922. pdtView->Release();
  1923. }
  1924. }
  1925. return hres;
  1926. }
  1927. // if we failed, pass this on to our child.
  1928. // this allows things like d/d of wallpaper to the edge to do
  1929. // right thing
  1930. }
  1931. if (_pdtInner)
  1932. hres = _pdtInner->Drop(pdtobj, grfKeyState, pt, pdwEffect);
  1933. return hres;
  1934. }
  1935. BOOL CDesktopBrowser::_OnCopyData(PCOPYDATASTRUCT pcds)
  1936. {
  1937. IETHREADPARAM *piei = SHCreateIETHREADPARAM(NULL, (ULONG)pcds->dwData, NULL, NULL);
  1938. if (piei)
  1939. {
  1940. LPCWSTR pwszSrc = (LPCWSTR)pcds->lpData;
  1941. LPCWSTR pwszDdeRegEvent = NULL;
  1942. LPCWSTR pwszCloseEvent = NULL;
  1943. DWORD cchSrc = pcds->cbData / sizeof(WCHAR);
  1944. piei->uFlags = COF_NORMAL | COF_WAITFORPENDING | COF_IEXPLORE;
  1945. //
  1946. // Remember where the command line parameters are.
  1947. //
  1948. LPCWSTR pszCmd = pwszSrc;
  1949. int cch = lstrlenW(pwszSrc) + 1;
  1950. pwszSrc += cch;
  1951. cchSrc -= cch;
  1952. TraceMsg(TF_SHDAUTO, "CDB::_OnCopyData got %hs", pszCmd);
  1953. //
  1954. // Get the dde reg event name into piei->szDdeRegEvent.
  1955. //
  1956. // NOTE: this is now conditional because we now launch the channel band from the desktop
  1957. // NOTE: as a fake WM_COPYDATA command
  1958. if (cchSrc)
  1959. {
  1960. ASSERT(cchSrc);
  1961. pwszDdeRegEvent = pwszSrc;
  1962. StrCpyNW(piei->szDdeRegEvent, pwszSrc, ARRAYSIZE(piei->szDdeRegEvent));
  1963. cch = lstrlenW(pwszSrc) + 1;
  1964. pwszSrc += cch;
  1965. cchSrc -= cch;
  1966. piei->uFlags |= COF_FIREEVENTONDDEREG;
  1967. //
  1968. // Get the name of the event to fire on close, if any.
  1969. //
  1970. if (cchSrc)
  1971. {
  1972. pwszCloseEvent = pwszSrc;
  1973. StrCpyNW(piei->szCloseEvent, pwszSrc, ARRAYSIZE(piei->szCloseEvent));
  1974. cch = lstrlenW(pwszSrc) + 1;
  1975. pwszSrc += cch;
  1976. cchSrc -= cch;
  1977. piei->uFlags |= COF_FIREEVENTONCLOSE;
  1978. }
  1979. }
  1980. ASSERT(cchSrc == 0);
  1981. if (pszCmd && pszCmd[0])
  1982. {
  1983. // for compatibility with apps that spawn the browser with a command line
  1984. // tell wininet to refresh its proxy settings. (this is particularly needed
  1985. // for TravelSoft WebEx)
  1986. MyInternetSetOption(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
  1987. if (SHParseIECommandLine(&pszCmd, piei))
  1988. piei->uFlags |= COF_NOFINDWINDOW;
  1989. if (pszCmd[0] && FAILED(_ConvertPathToPidlW(_pbsInner, _pbbd->_hwnd, pszCmd, &piei->pidl)))
  1990. piei->pidl = NULL;
  1991. }
  1992. else
  1993. {
  1994. piei->fCheckFirstOpen = TRUE;
  1995. }
  1996. // SHOpenFolderWindow takes ownership of piei
  1997. BOOL fRes = SHOpenFolderWindow(piei);
  1998. if (!fRes)
  1999. {
  2000. //
  2001. // Something went wrong creating the browser,
  2002. // let's fire all the events ourselves.
  2003. //
  2004. if (pwszDdeRegEvent)
  2005. FireEventSz(pwszDdeRegEvent);
  2006. if (pwszCloseEvent)
  2007. FireEventSz(pwszCloseEvent);
  2008. }
  2009. }
  2010. else
  2011. {
  2012. TraceMsg(TF_WARNING, "OnCopyData unable to create IETHREADPARAM");
  2013. }
  2014. return TRUE;
  2015. }
  2016. BOOL CDesktopBrowser::_InitScheduler(void)
  2017. {
  2018. if (!_psched)
  2019. {
  2020. // get the system background scheduler thread
  2021. CoCreateInstance(CLSID_SharedTaskScheduler, NULL, CLSCTX_INPROC,
  2022. IID_PPV_ARG(IShellTaskScheduler, &_psched));
  2023. }
  2024. return (_psched != NULL);
  2025. }
  2026. HRESULT CDesktopBrowser::_AddDesktopTask(IRunnableTask *ptask, DWORD dwPriority)
  2027. {
  2028. if (_InitScheduler())
  2029. return _psched->AddTask(ptask, TOID_Desktop, 0, dwPriority);
  2030. return E_FAIL;
  2031. }
  2032. void CDesktopBrowser::_OnAddToRecent(HANDLE hMem, DWORD dwProcId)
  2033. {
  2034. IRunnableTask *ptask;
  2035. if (SUCCEEDED(CTaskAddDoc_Create(hMem, dwProcId, &ptask)))
  2036. {
  2037. _AddDesktopTask(ptask, ITSAT_DEFAULT_PRIORITY);
  2038. ptask->Release();
  2039. }
  2040. }
  2041. //
  2042. // local server handling
  2043. //
  2044. DWORD WINAPI _LocalServerThread(void *pv)
  2045. {
  2046. LOCALSERVERDATA *ptd = (LOCALSERVERDATA *)pv;
  2047. CLSID clsid = *c_localServers[ptd->iLocalServer];
  2048. IUnknown *punk;
  2049. if (SUCCEEDED(DllGetClassObject(clsid, IID_PPV_ARG(IUnknown, &punk))))
  2050. {
  2051. DWORD dwReg;
  2052. if (SUCCEEDED(CoRegisterClassObject(clsid, punk, CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE, &dwReg)))
  2053. {
  2054. __try
  2055. {
  2056. MSG msg;
  2057. while(GetMessage(&msg, NULL, 0, 0))
  2058. {
  2059. TranslateMessage(&msg);
  2060. DispatchMessage(&msg);
  2061. }
  2062. }
  2063. __except (EXCEPTION_EXECUTE_HANDLER)
  2064. {
  2065. // we only send the message on an exception,
  2066. // because otherwise we got a WM_QUIT which
  2067. // means the desktop is being destroyed.
  2068. PostMessage(GetShellWindow(), CWM_CREATELOCALSERVER, FALSE, ptd->iLocalServer);
  2069. }
  2070. CoRevokeClassObject(dwReg);
  2071. }
  2072. }
  2073. LocalFree(ptd);
  2074. return 0;
  2075. }
  2076. DWORD WINAPI _SetThreadID(void *pv)
  2077. {
  2078. LOCALSERVERDATA *ptd = (LOCALSERVERDATA *)pv;
  2079. *ptd->pdwThreadID = GetCurrentThreadId();
  2080. return 0;
  2081. }
  2082. STDAPI_(HWND) SCNGetWindow(BOOL fUseDesktop);
  2083. LRESULT CDesktopBrowser::WndProcBS(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2084. {
  2085. INSTRUMENT_WNDPROC(SHCNFI_DESKTOP_WNDPROC, _pbbd->_hwnd, uMsg, wParam, lParam);
  2086. ASSERT(IsWindowTchar(hwnd));
  2087. switch (uMsg)
  2088. {
  2089. #ifdef DEBUG
  2090. case WM_QUERYENDSESSION:
  2091. TraceMsg(DM_SHUTDOWN, "cdtb.wp: WM_QUERYENDSESSION");
  2092. goto DoDefault;
  2093. #endif
  2094. case WM_ENDSESSION:
  2095. TraceMsg(DM_SHUTDOWN, "cdtb.wp: WM_ENDSESSION wP=%d lP=%d", wParam, lParam);
  2096. if (wParam)
  2097. {
  2098. #ifdef DEBUG
  2099. // call out inner an give him a chance to set _fMightBeShuttingDown so we
  2100. // don't assert later on in the case where the system is shutting down
  2101. _pbsInner->WndProcBS(hwnd, uMsg, wParam, lParam);
  2102. #endif
  2103. SHELLSTATE ss = {0};
  2104. // When we shut down, if the desktop is in WebView, we leave some temp
  2105. // files undeleted because we never get the WM_DESTROY message below.
  2106. // So, I just destroy the shellview which in turn destroys the temp
  2107. // file here. Note: This is done only if we are in web view.
  2108. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); //Get the desktop_html flag
  2109. if (ss.fDesktopHTML)
  2110. {
  2111. ReleaseShellView();
  2112. }
  2113. g_pdtray->SetVar(SVTRAY_EXITEXPLORER, FALSE); // don't exit process
  2114. // flush log before we exit
  2115. if (StopWatchMode())
  2116. {
  2117. StopWatchFlush();
  2118. }
  2119. // Kill this window so that we free active desktop threads properly
  2120. DestroyWindow(hwnd);
  2121. }
  2122. TraceMsg(DM_SHUTDOWN, "cdtb.wp: WM_ENDSESSION return 0");
  2123. break;
  2124. case WM_ERASEBKGND:
  2125. PaintDesktop((HDC)wParam);
  2126. return 1;
  2127. case WM_TIMER:
  2128. switch (wParam)
  2129. {
  2130. case IDT_DDETIMEOUT:
  2131. DDEHandleTimeout(_pbbd->_hwnd);
  2132. break;
  2133. case IDT_ENUMHKCR:
  2134. KillTimer(_pbbd->_hwnd, IDT_ENUMHKCR);
  2135. {
  2136. IShellTaskScheduler* pScheduler ;
  2137. if(SUCCEEDED(CoCreateInstance(CLSID_SharedTaskScheduler, NULL, CLSCTX_INPROC_SERVER,
  2138. IID_PPV_ARG(IShellTaskScheduler, &pScheduler))))
  2139. {
  2140. IRunnableTask* pTask ;
  2141. if (SUCCEEDED(CTaskEnumHKCR_Create(&pTask)))
  2142. {
  2143. pScheduler->AddTask(pTask, CLSID_QueryAssociations, 0L, ITSAT_DEFAULT_PRIORITY);
  2144. pTask->Release(); // Scheduler has AddRef'd him
  2145. }
  2146. pScheduler->Release(); // OK to release global task scheduler.
  2147. }
  2148. }
  2149. break;
  2150. default:
  2151. goto DoDefault;
  2152. break;
  2153. }
  2154. break;
  2155. case WM_SHELLNOTIFY:
  2156. switch(wParam)
  2157. {
  2158. case SHELLNOTIFY_WALLPAPERCHANGED:
  2159. // this is done only to the shell window when someone sets
  2160. // the wall paper but doesn't specify to broadcast
  2161. _pbsInner->ForwardViewMsg(uMsg, wParam, lParam);
  2162. break;
  2163. }
  2164. break;
  2165. case WM_PALETTECHANGED:
  2166. case WM_QUERYNEWPALETTE:
  2167. //
  2168. // in Win95 the desktop wndproc will invalidate the shell window when
  2169. // a palette change occurs so we didn't have to do anything here before
  2170. //
  2171. // in Nashville the desktop can be HTML and needs the palette messages
  2172. //
  2173. // so now we fall through and propagate...
  2174. //
  2175. case WM_ACTIVATEAPP:
  2176. if (!_pbbd->_hwndView)
  2177. goto DoDefault;
  2178. return _pbsInner->ForwardViewMsg(uMsg, wParam, lParam);
  2179. case WM_DEVICECHANGE:
  2180. _pbsInner->ForwardViewMsg(uMsg, wParam, lParam);
  2181. _OnDeviceBroadcast(_pbbd->_hwnd, wParam, (DEV_BROADCAST_HDR *)lParam);
  2182. goto DoDefault;
  2183. case WM_WINDOWPOSCHANGING:
  2184. #define ppos ((LPWINDOWPOS)lParam)
  2185. ppos->x = g_xVirtualScreen;
  2186. ppos->y = g_yVirtualScreen;
  2187. ppos->cx = g_cxVirtualScreen;
  2188. ppos->cy = g_cyVirtualScreen;
  2189. break;
  2190. case WM_HOTKEY:
  2191. // NOTE: forward hotkeys to the tray. This fixes the logitech mouseman who sends
  2192. // NOTE: hotkeys directly to the desktop.
  2193. // SPECIAL NOTE: the offset for GHID_FIRST is added because hotkeys that are sent to the
  2194. // SPECIAL NOTE: desktop are not proper hotkeys generated from the keyboard, they are
  2195. // SPECIAL NOTE: sent by an app, and the IDs have changed since win95....
  2196. ASSERT(g_hwndTray);
  2197. ASSERT(wParam < GHID_FIRST);
  2198. PostMessage(g_hwndTray, uMsg, wParam + GHID_FIRST, lParam);
  2199. return 0;
  2200. case WM_SYSCOMMAND:
  2201. switch (wParam & 0xFFF0) {
  2202. // NB Dashboard 1.0 sends a WM_SYSCOMMAND SC_CLOSE to the desktop when it starts up.
  2203. // What it was trying to do was to close down any non-shell versions of Progman. The
  2204. // proper shell version would just ignore the close. Under Chicago, they think that
  2205. // the desktop is Progman and send it the close, so we put up the exit windows dialog!
  2206. // Dashboard 2.0 has been fixed to avoid this bogisity.
  2207. case SC_CLOSE:
  2208. break;
  2209. // America alive tries to minimise Progman after installing - they end up minimising
  2210. // the desktop on Chicago!
  2211. case SC_MINIMIZE:
  2212. break;
  2213. default:
  2214. goto DoDefault;
  2215. }
  2216. break;
  2217. case WM_SETCURSOR:
  2218. // REVIEW: is this really needed?
  2219. if (_iWaitCount)
  2220. {
  2221. SetCursor(LoadCursor(NULL, IDC_APPSTARTING));
  2222. return TRUE;
  2223. }
  2224. else
  2225. goto DoDefault;
  2226. case WM_CLOSE:
  2227. SendMessage(_hwndTray, TM_DOEXITWINDOWS, 0, 0);
  2228. return 0;
  2229. // REVIEW: do we need this, can all of these cases be the same?
  2230. case WM_DRAWITEM:
  2231. case WM_MEASUREITEM:
  2232. if (!_pbsInner->ForwardViewMsg(uMsg, wParam, lParam))
  2233. goto DoDefault;
  2234. break;
  2235. case WM_INITMENUPOPUP:
  2236. case WM_ENTERMENULOOP:
  2237. case WM_EXITMENULOOP:
  2238. // let the fsview deal with any popup menus it created
  2239. _pbsInner->ForwardViewMsg(uMsg, wParam, lParam);
  2240. break;
  2241. // Looking at messages to try to capture when the workarea may
  2242. // have changed...
  2243. case WM_DISPLAYCHANGE:
  2244. lParam = 0;
  2245. if (GetNumberOfMonitors() != _nMonitors)
  2246. _InitMonitors();
  2247. // fall through
  2248. case WM_WININICHANGE:
  2249. _InitDesktopMetrics(wParam, (LPCTSTR)lParam);
  2250. if (wParam == SPI_SETNONCLIENTMETRICS)
  2251. {
  2252. VARIANTARG varIn;
  2253. VARIANTARG varOut = {0};
  2254. varIn.vt = VT_BOOL;
  2255. varIn.boolVal = VARIANT_TRUE;
  2256. _pctInner->Exec(&CGID_Explorer, SBCMDID_CACHEINETZONEICON, OLECMDEXECOPT_DODEFAULT , &varIn, &varOut);
  2257. }
  2258. if (lParam)
  2259. {
  2260. if (lstrcmpi((LPCTSTR)lParam, TEXT("Extensions")) == 0)
  2261. {
  2262. // Post a message to our selves so we can do more stuff
  2263. // slightly delayed.
  2264. PostMessage(hwnd, DTM_SETUPAPPRAN, 0, 0);
  2265. }
  2266. else if (lstrcmpi((LPCTSTR)lParam, TEXT("ShellState")) == 0)
  2267. {
  2268. // this should cover external apps changing
  2269. // our settings.
  2270. SHRefreshSettings();
  2271. }
  2272. else
  2273. {
  2274. // SPI_GETICONTITLELONGFONT is broadcast from IE when the home page is changed. We look for that so
  2275. // we can be sure to update the MyCurrentHomePage component.
  2276. if((wParam == SPI_SETDESKWALLPAPER) || (wParam == SPI_SETDESKPATTERN) || (wParam == SPI_GETICONTITLELOGFONT))
  2277. {
  2278. // Some desktop attribute has changed. So, regenerate desktop.
  2279. if(lstrcmpi((LPCTSTR)lParam, TEXT("ToggleDesktop")) &&
  2280. lstrcmpi((LPCTSTR)lParam, TEXT("RefreshDesktop")) &&
  2281. lstrcmpi((LPCTSTR)lParam, TEXT("BufferedRefresh")))
  2282. {
  2283. DWORD dwFlags = AD_APPLY_HTMLGEN | AD_APPLY_REFRESH;
  2284. switch (wParam)
  2285. {
  2286. case SPI_SETDESKPATTERN:
  2287. dwFlags |= (AD_APPLY_FORCE | AD_APPLY_DYNAMICREFRESH);
  2288. break;
  2289. case SPI_SETDESKWALLPAPER:
  2290. dwFlags |= AD_APPLY_SAVE;
  2291. break;
  2292. case SPI_GETICONTITLELOGFONT:
  2293. dwFlags |= AD_APPLY_FORCE;
  2294. break;
  2295. }
  2296. PokeWebViewDesktop(dwFlags);
  2297. // If we are not currently in ActiveDesktop Mode, then we need to set the dirty bit
  2298. // sothat a new HTML file will be generated showing the new wallpaper,
  2299. // the next time the active desktop is turned ON!
  2300. if (wParam == SPI_SETDESKWALLPAPER)
  2301. {
  2302. SHELLSTATE ss = {0};
  2303. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); //Get the desktop_html flag
  2304. if (!ss.fDesktopHTML)
  2305. SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY);
  2306. }
  2307. }
  2308. }
  2309. }
  2310. }
  2311. // control panel applet that allows users to change the
  2312. // environment with-which to spawn new applications. On NT, we need
  2313. // to pick up that environment change so that anything we spawn in
  2314. // the future will pick up those updated environment values.
  2315. //
  2316. if (lParam && (lstrcmpi((LPTSTR)lParam, TEXT("Environment")) == 0))
  2317. {
  2318. void *pv;
  2319. RegenerateUserEnvironment(&pv, TRUE);
  2320. }
  2321. v_PropagateMessage(uMsg, wParam, lParam, TRUE);
  2322. SetWindowPos(_pbbd->_hwnd, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER);
  2323. if ((uMsg == WM_DISPLAYCHANGE) || (wParam == SPI_SETWORKAREA))
  2324. _SetViewArea();
  2325. SHSettingsChanged(wParam, lParam);
  2326. break;
  2327. case WM_SYSCOLORCHANGE:
  2328. //
  2329. // In memphis, when apps go into low-res mode, we get this message. We should not re-generate
  2330. // desktop.htt in this scenario, or else the centered wallpaper gets messed up because we do not
  2331. // get the message when the app exists and the resoultion goes up. So, we make the following check.
  2332. //
  2333. if(!SHIsTempDisplayMode())
  2334. OnDesktopSysColorChange();
  2335. //This is done sothat the defview can set the listview in proper
  2336. //colors.
  2337. _pbsInner->ForwardViewMsg(uMsg, wParam, lParam);
  2338. break;
  2339. // Don't go to default wnd proc for this one...
  2340. case WM_INPUTLANGCHANGEREQUEST:
  2341. if (wParam)
  2342. goto DoDefault;
  2343. else
  2344. return 0;
  2345. case WM_COPYDATA:
  2346. return _OnCopyData((PCOPYDATASTRUCT)lParam);
  2347. case CWM_COMMANDLINE:
  2348. SHOnCWMCommandLine(lParam);
  2349. break;
  2350. case CWM_GETSCNWINDOW:
  2351. return (LRESULT) SCNGetWindow(FALSE);
  2352. break;
  2353. case CWM_ADDTORECENT:
  2354. _OnAddToRecent((HANDLE)wParam, (DWORD) lParam);
  2355. return 0;
  2356. case CWM_WAITOP:
  2357. SHWaitOp_Operate((HANDLE)wParam, (DWORD)lParam);
  2358. return 0;
  2359. case CWM_CREATELOCALSERVER:
  2360. {
  2361. // wParam = TRUE to create, FALSE to mark as terminated
  2362. // lParam = (INT) index into LocalServer table
  2363. INT i = (INT)lParam;
  2364. if ((i >= 0) && (i < ARRAYSIZE(_idLocalServerThreads)))
  2365. {
  2366. if (wParam)
  2367. {
  2368. if (_idLocalServerThreads[i] == -1)
  2369. {
  2370. LOCALSERVERDATA *ptd = (LOCALSERVERDATA *)LocalAlloc(LPTR, sizeof(*ptd));
  2371. if (ptd)
  2372. {
  2373. ptd->iLocalServer = i;
  2374. ptd->pdwThreadID = &_idLocalServerThreads[i];
  2375. if (!SHCreateThread(_LocalServerThread, ptd, CTF_COINIT, _SetThreadID))
  2376. {
  2377. LocalFree(ptd);
  2378. }
  2379. }
  2380. }
  2381. }
  2382. else
  2383. {
  2384. _idLocalServerThreads[i] = -1;
  2385. }
  2386. }
  2387. return 0;
  2388. }
  2389. case CWM_SHOWFOLDEROPT:
  2390. switch (wParam)
  2391. {
  2392. case CWMW_FOLDEROPTIONS: // appwiz.cpl used to send this message to us
  2393. // now it's done by FolderOptionsRunDll
  2394. DoGlobalFolderOptions();
  2395. break;
  2396. case CWMW_TASKBAROPTIONS: // TaskbarOptionsRunDll sends this message
  2397. PostMessage(_hwndTray, TM_DOTRAYPROPERTIES, 0, 0);
  2398. break;
  2399. default:
  2400. break;
  2401. }
  2402. return 0;
  2403. case CWM_TASKBARWAKEUP:
  2404. _dwThreadIdTray = (DWORD)wParam;
  2405. if (_dwThreadIdTray)
  2406. {
  2407. _iTrayPriority = HIWORD(lParam);
  2408. SetTimer(hwnd, IDT_TASKBARWAKEUP, LOWORD(lParam), NULL);
  2409. }
  2410. break;
  2411. case DTM_CREATESAVEDWINDOWS:
  2412. _InitDeskbars();
  2413. SHCreateSavedWindows();
  2414. #ifdef ENABLE_CHANNELS
  2415. _MaybeLaunchChannelBand();
  2416. #endif
  2417. // we need to update the recycle bin icon because the recycle bin
  2418. // is per user on NTFS, and thus the state could change w/ each new user
  2419. // who logs in.
  2420. SHUpdateRecycleBinIcon();
  2421. break;
  2422. case DTM_SAVESTATE:
  2423. TraceMsg(DM_SHUTDOWN, "cdtb.wp: DTM_SAVESTATE");
  2424. _SaveState();
  2425. break;
  2426. case DTM_RAISE:
  2427. _OnRaise(wParam, lParam);
  2428. break;
  2429. #ifdef DEBUG
  2430. case DTM_NEXTCTL:
  2431. #endif
  2432. case DTM_UIACTIVATEIO:
  2433. case DTM_ONFOCUSCHANGEIS:
  2434. _OnFocusMsg(uMsg, wParam, lParam);
  2435. break;
  2436. case DTM_SETUPAPPRAN:
  2437. _SetupAppRan(wParam, lParam);
  2438. break;
  2439. case DTM_QUERYHKCRCHANGED:
  2440. // some clients are out of process, so we
  2441. // can cache their cookies for them.
  2442. if (!lParam && wParam > QHKCRID_NONE && wParam < QHKCRID_MAX)
  2443. lParam = (LPARAM)&_rgdwQHKCRCookies[wParam - QHKCRID_MIN];
  2444. return _QueryHKCRChanged(hwnd, (LPDWORD)lParam);
  2445. case DTM_UPDATENOW:
  2446. UpdateWindow(hwnd);
  2447. break;
  2448. case DTM_GETVIEWAREAS:
  2449. {
  2450. // wParam is an in/out param. in - the max. # of areas, out - the actual # of areas.
  2451. // if "in" value < "out" value, lParam is not set.
  2452. // The ViewAreas are already stored in the desktop Listview.
  2453. int* pnViewAreas = (int*) wParam;
  2454. LPRECT lprcViewAreas = (LPRECT) lParam;
  2455. if (pnViewAreas)
  2456. {
  2457. int nMaxAreas = *pnViewAreas;
  2458. HWND hwndList = _GetDesktopListview();
  2459. ASSERT(IsWindow(hwndList));
  2460. ListView_GetNumberOfWorkAreas(hwndList, pnViewAreas);
  2461. if (*pnViewAreas >= 0 && *pnViewAreas <= nMaxAreas && lprcViewAreas)
  2462. {
  2463. ListView_GetWorkAreas(hwndList, *pnViewAreas, lprcViewAreas);
  2464. // These are in Listview co-ordinates. We have to map them to screen co-ordinates.
  2465. // [msadek]; MapWindowPoints() is mirroring-aware only if you pass two points
  2466. for (int i = 0; i < *pnViewAreas; i++)
  2467. {
  2468. MapWindowPoints(hwndList, HWND_DESKTOP, (LPPOINT)(&lprcViewAreas[i]), 2);
  2469. }
  2470. }
  2471. }
  2472. }
  2473. break;
  2474. case DTM_MAKEHTMLCHANGES:
  2475. //Make changes to desktop's HTML using Dynamic HTML
  2476. SendMessage(_pbbd->_hwndView, WM_DSV_DESKHTML_CHANGES, wParam, lParam);
  2477. break;
  2478. case DTM_STARTPAGEONOFF:
  2479. SendMessage(_pbbd->_hwndView, WM_DSV_STARTPAGE_TURNONOFF, wParam, lParam);
  2480. break;
  2481. case DTM_REFRESHACTIVEDESKTOP:
  2482. // This message is posted to refresh active desktop in a delayed fashion.
  2483. REFRESHACTIVEDESKTOP();
  2484. break;
  2485. case DTM_SETAPPSTARTCUR:
  2486. {
  2487. INotifyAppStart * pnasTop;
  2488. HRESULT hr = QueryService(SID_STopLevelBrowser, IID_PPV_ARG(INotifyAppStart, &pnasTop));
  2489. if (SUCCEEDED(hr))
  2490. {
  2491. pnasTop->AppStarting();
  2492. pnasTop->Release();
  2493. }
  2494. }
  2495. break;
  2496. // Handle DDE messages for badly written apps (that assume the shell's
  2497. // window is of class Progman and called Program Manager.
  2498. case WM_DDE_INITIATE:
  2499. case WM_DDE_TERMINATE:
  2500. case WM_DDE_ADVISE:
  2501. case WM_DDE_UNADVISE:
  2502. case WM_DDE_ACK:
  2503. case WM_DDE_DATA:
  2504. case WM_DDE_REQUEST:
  2505. case WM_DDE_POKE:
  2506. case WM_DDE_EXECUTE:
  2507. return DDEHandleMsgs(_pbbd->_hwnd, uMsg, wParam, lParam);
  2508. break;
  2509. default:
  2510. if (uMsg == GetDDEExecMsg())
  2511. {
  2512. ASSERT(lParam && 0 == ((LPNMHDR)lParam)->idFrom);
  2513. DDEHandleViewFolderNotify(NULL, _pbbd->_hwnd, (LPNMVIEWFOLDER)lParam);
  2514. LocalFree((LPNMVIEWFOLDER)lParam);
  2515. return TRUE;
  2516. }
  2517. DoDefault:
  2518. return _pbsInner->WndProcBS(hwnd, uMsg, wParam, lParam);
  2519. }
  2520. return 0;
  2521. }
  2522. #ifdef ENABLE_CHANNELS
  2523. // launch the channelbar, this is called when the desktop has finished starting up.
  2524. const WCHAR c_szwChannelBand[] = L"-channelband";
  2525. void CDesktopBrowser::_MaybeLaunchChannelBand()
  2526. {
  2527. DWORD dwType = REG_SZ;
  2528. TCHAR szYesOrNo[20];
  2529. DWORD cbSize = sizeof(szYesOrNo);
  2530. BOOL bLaunchChannelBar = FALSE;
  2531. if(SHRegGetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("Show_ChannelBand"),
  2532. &dwType, (void *)szYesOrNo, &cbSize, FALSE, NULL, 0) == ERROR_SUCCESS)
  2533. {
  2534. bLaunchChannelBar = !lstrcmpi(szYesOrNo, TEXT("yes"));
  2535. }
  2536. // Don't launch by default post IE4
  2537. //else if (IsOS(OS_WINDOWS))
  2538. //{
  2539. // bLaunchChannelBar = TRUE; // launch channel bar by default on Memphis and win95
  2540. //}
  2541. if (bLaunchChannelBar)
  2542. {
  2543. // fake up a WM_COPYDATA struct
  2544. COPYDATASTRUCT cds;
  2545. cds.dwData = SW_NORMAL;
  2546. cds.cbData = sizeof(c_szwChannelBand);
  2547. cds.lpData = (void *) c_szwChannelBand;
  2548. // fake it as if we had launched iexplore.exe, it saves us a whole process doing it this way....
  2549. _OnCopyData(&cds);
  2550. }
  2551. }
  2552. #endif // ENABLE_CHANNELS
  2553. //***
  2554. // NOTES
  2555. // REARCHITECT should this be CBaseBrowser::IInputObject::UIActIO etc.?
  2556. HRESULT CDesktopBrowser::_OnFocusMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  2557. {
  2558. BOOL fActivate = (BOOL) wParam;
  2559. switch (uMsg) {
  2560. case DTM_UIACTIVATEIO:
  2561. fActivate = (BOOL) wParam;
  2562. TraceMsg(DM_FOCUS, "cdtb.oxiois: DTM_UIActIO fAct=%d dtb=%d", fActivate, (int) lParam);
  2563. if (fActivate)
  2564. {
  2565. MSG msg = {_pbbd->_hwnd, WM_KEYDOWN, VK_TAB, 0xf0001};
  2566. BOOL bShift = (GetAsyncKeyState(VK_SHIFT) < 0);
  2567. if (bShift)
  2568. {
  2569. int cToolbars = _pbsInner->_GetToolbarCount();
  2570. while (--cToolbars >= 0)
  2571. {
  2572. // activate last toolbar in tab order
  2573. LPTOOLBARITEM ptbi = _pbsInner->_GetToolbarItem(cToolbars);
  2574. if (ptbi && ptbi->ptbar)
  2575. {
  2576. IInputObject* pio;
  2577. if (SUCCEEDED(ptbi->ptbar->QueryInterface(IID_PPV_ARG(IInputObject, &pio))))
  2578. {
  2579. pio->UIActivateIO(TRUE, &msg);
  2580. pio->Release();
  2581. return S_OK;
  2582. }
  2583. }
  2584. }
  2585. }
  2586. #ifdef KEYBOARDCUES
  2587. // Since we are Tab or Shift Tab we should turn the focus rect on.
  2588. SendMessage(_pbbd->_hwnd, WM_UPDATEUISTATE, MAKEWPARAM(UIS_CLEAR,
  2589. UISF_HIDEFOCUS), 0);
  2590. #endif
  2591. // activate view
  2592. if (bShift && _pbbd->_psv)
  2593. {
  2594. _pbbd->_psv->TranslateAccelerator(&msg);
  2595. }
  2596. else
  2597. {
  2598. _pbsInner->_SetFocus(NULL, _pbbd->_hwndView, NULL);
  2599. }
  2600. }
  2601. else {
  2602. Ldeact:
  2603. // if we don't have focus, we're fine;
  2604. // if we do have focus, there's nothing we can do about it...
  2605. /*NOTHING*/
  2606. ;
  2607. #ifdef DEBUG
  2608. TraceMsg(DM_FOCUS, "cdtb.oxiois: GetFocus()=%x _pbbd->_hwnd=%x _pbbd->_hwndView=%x", GetFocus(), _pbbd->_hwnd, _pbbd->_hwndView);
  2609. #endif
  2610. }
  2611. break;
  2612. case DTM_ONFOCUSCHANGEIS:
  2613. TraceMsg(DM_FOCUS, "cdtb.oxiois: DTM_OnFocChgIS hwnd=%x fAct=%d", (HWND) lParam, fActivate);
  2614. if (fActivate) {
  2615. // someone else is activating, so we need to deactivate
  2616. goto Ldeact;
  2617. }
  2618. break;
  2619. default:
  2620. ASSERT(0);
  2621. break;
  2622. }
  2623. return S_OK;
  2624. }
  2625. LRESULT CALLBACK CDesktopBrowser::DesktopWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2626. {
  2627. CDesktopBrowser *psb = (CDesktopBrowser*)GetWindowLongPtr(hwnd, 0);
  2628. switch(uMsg)
  2629. {
  2630. case WM_CREATE:
  2631. #ifdef KEYBOARDCUES
  2632. // Initialize our keyboard cues bits
  2633. SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0);
  2634. #endif
  2635. // Set the localized name of the Desktop so it can be used in Error messages
  2636. // that have the desktop window as the title.
  2637. if (EVAL(LoadStringW(HINST_THISDLL, IDS_DESKTOP, psb->_wzDesktopTitle, ARRAYSIZE(psb->_wzDesktopTitle))))
  2638. {
  2639. EVAL(SetProp(hwnd, TEXT("pszDesktopTitleW"), (HANDLE)psb->_wzDesktopTitle));
  2640. }
  2641. if (psb)
  2642. return psb->WndProcBS(hwnd, uMsg, wParam, lParam);
  2643. else
  2644. return DefWindowProc(hwnd, uMsg, wParam, lParam); // known charset
  2645. #ifdef KEYBOARDCUES
  2646. case WM_ACTIVATE:
  2647. if (WA_INACTIVE == LOWORD(wParam))
  2648. {
  2649. SendMessage(hwnd, WM_CHANGEUISTATE,
  2650. MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
  2651. }
  2652. goto DoDefault;
  2653. break;
  2654. #endif
  2655. case WM_NCCREATE:
  2656. ASSERT(psb == NULL);
  2657. CDesktopBrowser_CreateInstance(hwnd, (void **)&psb);
  2658. if (psb)
  2659. {
  2660. SetWindowLongPtr(hwnd, 0, (LONG_PTR)psb);
  2661. goto DoDefault;
  2662. }
  2663. else
  2664. {
  2665. return FALSE;
  2666. }
  2667. break;
  2668. case WM_TIMER:
  2669. if (psb)
  2670. {
  2671. switch(wParam)
  2672. {
  2673. case IDT_STARTBACKGROUNDSHELLTASKS:
  2674. KillTimer(hwnd, IDT_STARTBACKGROUNDSHELLTASKS);
  2675. psb->StartBackgroundShellTasks();
  2676. break;
  2677. case IDT_TASKBARWAKEUP:
  2678. KillTimer(hwnd, IDT_TASKBARWAKEUP);
  2679. psb->TaskbarWakeup();
  2680. break;
  2681. default:
  2682. return psb->WndProcBS(hwnd, uMsg, wParam, lParam);
  2683. break;
  2684. }
  2685. }
  2686. break;
  2687. case WM_NCDESTROY:
  2688. if (psb)
  2689. {
  2690. RemoveProp(hwnd, TEXT("pszDesktopTitleW"));
  2691. // In case someone does a get shell window and post a WM_QUIT, we need to
  2692. // make sure that we also close down our other thread.
  2693. TraceMsg(DM_SHUTDOWN, "cdtb.wp(WM_NCDESTROY): ?post WM_QUIT hwndTray=%x(IsWnd=%d)", psb->_hwndTray, IsWindow(psb->_hwndTray));
  2694. if (psb->_hwndTray && IsWindow(psb->_hwndTray))
  2695. PostMessage(psb->_hwndTray, WM_QUIT, 0, 0);
  2696. psb->ReleaseShellView();
  2697. psb->Release();
  2698. }
  2699. PostQuitMessage(0); // exit out message loop
  2700. break;
  2701. default:
  2702. if (psb)
  2703. return psb->WndProcBS(hwnd, uMsg, wParam, lParam);
  2704. else {
  2705. DoDefault:
  2706. return DefWindowProc(hwnd, uMsg, wParam, lParam); // known charset
  2707. }
  2708. }
  2709. return 0;
  2710. }
  2711. void RegisterDesktopClass()
  2712. {
  2713. WNDCLASS wc = {0};
  2714. wc.style = CS_DBLCLKS;
  2715. wc.lpfnWndProc = CDesktopBrowser::DesktopWndProc;
  2716. //wc.cbClsExtra = 0;
  2717. wc.cbWndExtra = sizeof(void *);
  2718. wc.hInstance = HINST_THISDLL;
  2719. //wc.hIcon = NULL;
  2720. wc.hCursor = GetClassCursor(GetDesktopWindow());
  2721. wc.hbrBackground = (HBRUSH)(COLOR_DESKTOP + 1);
  2722. //wc.lpszMenuName = NULL;
  2723. wc.lpszClassName = TEXT(STR_DESKTOPCLASS);
  2724. RegisterClass(&wc);
  2725. }
  2726. #define PEEK_NORMAL 0
  2727. #define PEEK_QUIT 1
  2728. #define PEEK_CONTINUE 2
  2729. #define PEEK_CLOSE 3
  2730. // RETURNS BOOL whehter to continue the search or not.
  2731. // so FALSE means we've found one.
  2732. // TRUE means we haven't.
  2733. BOOL CALLBACK FindBrowserWindow_Callback(HWND hwnd, LPARAM lParam)
  2734. {
  2735. if (IsExplorerWindow(hwnd) || IsFolderWindow(hwnd) || IsTrayWindow(hwnd))
  2736. {
  2737. DWORD dwProcID;
  2738. GetWindowThreadProcessId(hwnd, &dwProcID);
  2739. if (dwProcID == GetCurrentProcessId())
  2740. {
  2741. if (lParam)
  2742. *((BOOL*)lParam) = TRUE; // found one!
  2743. return FALSE; // stop search
  2744. }
  2745. }
  2746. return TRUE; // continue search
  2747. }
  2748. #define IsBrowserWindow(hwnd) !FindBrowserWindow_Callback(hwnd, NULL)
  2749. BOOL CALLBACK CloseWindow_Callback(HWND hwnd, LPARAM lParam)
  2750. {
  2751. if (IsBrowserWindow(hwnd)) {
  2752. TraceMsg(DM_SHUTDOWN, "s.cw_cb: post WM_CLOSE hwnd=%x", hwnd);
  2753. PostMessage(hwnd, WM_CLOSE, 0, 0);
  2754. }
  2755. return TRUE;
  2756. }
  2757. UINT CDesktopBrowser::_PeekForAMessage()
  2758. {
  2759. MSG msg;
  2760. BOOL fPeek;
  2761. fPeek = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  2762. if (fPeek)
  2763. {
  2764. if (msg.message == WM_QUIT)
  2765. {
  2766. TraceMsg(DM_SHUTDOWN, "cdtb.pfam: WM_QUIT wP=%d [lP=%d]", msg.wParam, msg.lParam);
  2767. if (msg.lParam == 1)
  2768. {
  2769. return PEEK_CLOSE;
  2770. }
  2771. TraceMsg(DM_TRACE, "c.ml: Got quit message for %#08x", GetCurrentThreadId());
  2772. return PEEK_QUIT; // break all the way out of the main loop
  2773. }
  2774. if (_pbbd->_hwnd)
  2775. {
  2776. if (S_OK == _pbsInner->v_MayTranslateAccelerator(&msg))
  2777. return PEEK_CONTINUE;
  2778. }
  2779. TranslateMessage(&msg);
  2780. DispatchMessage(&msg);
  2781. return PEEK_CONTINUE; // Go back and get the next message
  2782. }
  2783. return PEEK_NORMAL;
  2784. }
  2785. void CDesktopBrowser::_MessageLoop()
  2786. {
  2787. for (; ;)
  2788. {
  2789. switch (_PeekForAMessage())
  2790. {
  2791. case PEEK_QUIT:
  2792. return;
  2793. case PEEK_NORMAL:
  2794. {
  2795. static BOOL s_fSignaled = FALSE;
  2796. if (!s_fSignaled)
  2797. {
  2798. FireEventSz(TEXT("msgina: ShellReadyEvent"));
  2799. s_fSignaled = TRUE;
  2800. PERFSETMARK("ExplorerDesktopReady");
  2801. }
  2802. WaitMessage();
  2803. break;
  2804. }
  2805. case PEEK_CONTINUE:
  2806. break;
  2807. case PEEK_CLOSE:
  2808. // we need to close all the shell windows too
  2809. TraceMsg(DM_SHUTDOWN, "cdtb._ml: PEEK_CLOSE, close/wait all");
  2810. EnumWindows(CloseWindow_Callback, 0);
  2811. {
  2812. #define MAXIMUM_DESKTOP_WAIT 15000
  2813. DWORD iStartTime = GetTickCount();
  2814. // block until all other browser windows are closed
  2815. for (;;)
  2816. {
  2817. BOOL f = FALSE;
  2818. EnumWindows(FindBrowserWindow_Callback, (LPARAM)&f);
  2819. if (!f || (GetTickCount() - iStartTime > MAXIMUM_DESKTOP_WAIT))
  2820. return;
  2821. switch (_PeekForAMessage())
  2822. {
  2823. case PEEK_NORMAL:
  2824. // don't do a waitmessage because we want to exit when thelast other window is gone
  2825. // and we don't get a message to signal that
  2826. Sleep(100);
  2827. break;
  2828. }
  2829. }
  2830. }
  2831. return;
  2832. }
  2833. }
  2834. }
  2835. HRESULT CDesktopBrowser::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  2836. {
  2837. if (IsEqualGUID(guidService, SID_SShellDesktop))
  2838. return QueryInterface(riid, ppvObj);
  2839. return _pspInner->QueryService(guidService, riid, ppvObj);
  2840. }
  2841. void CDesktopBrowser::StartBackgroundShellTasks(void)
  2842. {
  2843. HKEY hkey = SHGetShellKey(SHELLKEY_HKLM_EXPLORER, TEXT("SharedTaskScheduler"), FALSE);
  2844. if (hkey)
  2845. {
  2846. TCHAR szClass[GUIDSTR_MAX];
  2847. DWORD cchClass, dwType;
  2848. int i = 0;
  2849. while (cchClass = ARRAYSIZE(szClass),
  2850. ERROR_SUCCESS == RegEnumValue(hkey, i++, szClass, &cchClass, NULL, &dwType, NULL, NULL))
  2851. {
  2852. CLSID clsid;
  2853. if (SUCCEEDED(SHCLSIDFromString(szClass, &clsid)))
  2854. {
  2855. IRunnableTask* ptask;
  2856. if (SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC, IID_PPV_ARG(IRunnableTask, &ptask))))
  2857. {
  2858. // Personally I think the start menu should have priority
  2859. // over itbar icon extraction, so set this priority list
  2860. // a tad lower than the default priority (which start menu is at)
  2861. _AddDesktopTask(ptask, ITSAT_DEFAULT_PRIORITY-1);
  2862. ptask->Release();
  2863. }
  2864. }
  2865. }
  2866. RegCloseKey(hkey);
  2867. }
  2868. }
  2869. void CDesktopBrowser::TaskbarWakeup(void)
  2870. {
  2871. if (_dwThreadIdTray)
  2872. {
  2873. HANDLE hThread = OpenThread(THREAD_SET_INFORMATION, FALSE, _dwThreadIdTray);
  2874. SetThreadPriority(hThread, _iTrayPriority);
  2875. CloseHandle(hThread);
  2876. _dwThreadIdTray = 0;
  2877. }
  2878. }
  2879. // create the desktop window and its shell view
  2880. DWORD_PTR DesktopWindowCreate(CDesktopBrowser **ppBrowser)
  2881. {
  2882. *ppBrowser = NULL;
  2883. DWORD dwExStyle = WS_EX_TOOLWINDOW;
  2884. OleInitialize(NULL);
  2885. RegisterDesktopClass();
  2886. _InitDesktopMetrics(0, NULL);
  2887. dwExStyle |= IS_BIDI_LOCALIZED_SYSTEM() ? dwExStyleRTLMirrorWnd : 0L;
  2888. //
  2889. // NB This windows class is Progman and it's title is Program Manager. This makes
  2890. // sure apps (like ATM) think that program is running and don't fail their install.
  2891. //
  2892. HWND hwnd = CreateWindowEx(dwExStyle, TEXT(STR_DESKTOPCLASS), TEXT("Program Manager"),
  2893. WS_POPUP | WS_CLIPCHILDREN,
  2894. g_xVirtualScreen, g_yVirtualScreen,
  2895. g_cxVirtualScreen, g_cyVirtualScreen,
  2896. NULL, NULL, HINST_THISDLL, NULL);
  2897. // The returned hwnd can already be bogus if the system is shutting
  2898. // down and user has somehow already called xxxDestroyWindow on us
  2899. // even though we never even received a WM_NCCREATE!!
  2900. // CreateWindowEx ends up returning a handle to a window that
  2901. // has already been destroyed. So in that case, act as if
  2902. // CreateWindowEx failed (because it did!)
  2903. if (!IsWindow(hwnd)) hwnd = NULL;
  2904. if (hwnd)
  2905. {
  2906. CDesktopBrowser *psb = (CDesktopBrowser*)GetWindowLongPtr(hwnd, 0);
  2907. ASSERT(psb);
  2908. if (!SHRestricted(REST_NODESKTOP))
  2909. {
  2910. // do this here to avoid painting the desktop, then repainting
  2911. // when the tray appears and causes everything to move
  2912. ShowWindow(hwnd, SW_SHOW);
  2913. UpdateWindow(hwnd);
  2914. }
  2915. SetTimer(hwnd, IDT_STARTBACKGROUNDSHELLTASKS, 5 * 1000, NULL);
  2916. *ppBrowser = (CDesktopBrowser*)GetWindowLongPtr(hwnd, 0);
  2917. }
  2918. return (DWORD_PTR)hwnd;
  2919. }
  2920. STDAPI_(HANDLE) SHCreateDesktop(IDeskTray* pdtray)
  2921. {
  2922. if (g_dwProfileCAP & 0x00000010)
  2923. StartCAP();
  2924. ASSERT(pdtray);
  2925. ASSERT(g_pdtray==NULL);
  2926. g_pdtray = pdtray;
  2927. pdtray->AddRef(); // this is no-op, but we want to follow the COM rule.
  2928. // put the desktop on the main thread (this is needed for win95 so that
  2929. // the DDeExecuteHack() in user.exe works, it needs the desktop and the
  2930. // DDE window on the mainthread
  2931. CDesktopBrowser *pBrowser;
  2932. if (DesktopWindowCreate(&pBrowser))
  2933. {
  2934. if (g_dwProfileCAP & 0x00040000)
  2935. StopCAP();
  2936. // hack, cast the object to a handle (otherwise we have to export the class
  2937. // declaration so that explorer.exe can use it)
  2938. return (HANDLE) pBrowser;
  2939. }
  2940. return NULL;
  2941. }
  2942. // nash:49485 (IME focus) and nash:nobug (win95 compat)
  2943. // make sure keyboard input goes to the desktop. this is
  2944. // a) win95 compat: where focus was on win95 and
  2945. // b) nash:49485: focus was in the empty taskband on login so
  2946. // the keys went into the bitbucket
  2947. //
  2948. // If some other process has stolen the foreground window,
  2949. // don't be rude and grab it back.
  2950. void FriendlySetForegroundWindow(HWND hwnd)
  2951. {
  2952. HWND hwndOld = GetForegroundWindow();
  2953. if (hwndOld)
  2954. {
  2955. DWORD dwProcessId;
  2956. GetWindowThreadProcessId(hwndOld, &dwProcessId);
  2957. if (dwProcessId == GetCurrentProcessId())
  2958. hwndOld = NULL;
  2959. }
  2960. if (!hwndOld)
  2961. SetForegroundWindow(hwnd);
  2962. }
  2963. STDAPI_(BOOL) SHDesktopMessageLoop(HANDLE hDesktop)
  2964. {
  2965. CDesktopBrowser *pBrowser = (CDesktopBrowser *) hDesktop;
  2966. if (pBrowser)
  2967. {
  2968. // We must AddRef the pBrowser because _MessageLoop() will
  2969. // Release() it if another app initiated a system shutdown.
  2970. // We will do our own Release() when we don't need the pointer
  2971. // any more.
  2972. pBrowser->AddRef();
  2973. FriendlySetForegroundWindow(pBrowser->GetDesktopWindow());
  2974. pBrowser->_MessageLoop();
  2975. IconCacheSave();
  2976. // In case someone posted us a WM_QUIT message, before terminating
  2977. // the thread, make sure it is properly destroyed so that trident etc
  2978. // gets properly freed up.
  2979. HWND hwnd = pBrowser->GetDesktopWindow();
  2980. if (hwnd)
  2981. {
  2982. DestroyWindow(hwnd);
  2983. }
  2984. pBrowser->Release();
  2985. OleUninitialize();
  2986. }
  2987. return BOOLFROMPTR(pBrowser);
  2988. }
  2989. //
  2990. // Whenever we remove the toolbar from the desktop, we persist it.
  2991. //
  2992. HRESULT CDesktopBrowser::RemoveToolbar(IUnknown* punkSrc, DWORD dwRemoveFlags)
  2993. {
  2994. HRESULT hres = E_FAIL;
  2995. UINT itb = _pbsInner->_FindTBar(punkSrc);
  2996. if (itb==(UINT)-1)
  2997. {
  2998. return E_INVALIDARG;
  2999. }
  3000. LPTOOLBARITEM ptbi = _pbsInner->_GetToolbarItem(itb);
  3001. if (ptbi && ptbi->pwszItem)
  3002. {
  3003. LPCWSTR szItem = ptbi->pwszItem;
  3004. if (dwRemoveFlags & STFRF_DELETECONFIGDATA)
  3005. {
  3006. DeleteDesktopViewStream(szItem);
  3007. }
  3008. else
  3009. {
  3010. IStream* pstm = GetDesktopViewStream(STGM_WRITE, szItem);
  3011. if (pstm)
  3012. {
  3013. IPersistStreamInit* ppstm;
  3014. HRESULT hresT = punkSrc->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &ppstm));
  3015. if (SUCCEEDED(hresT)) {
  3016. ppstm->Save(pstm, TRUE);
  3017. ppstm->Release();
  3018. }
  3019. pstm->Release();
  3020. }
  3021. }
  3022. }
  3023. hres = _pdwfInner->RemoveToolbar(punkSrc, dwRemoveFlags);
  3024. _UpdateViewRectSize();
  3025. return hres;
  3026. }
  3027. HRESULT CDesktopBrowser::GetBorderDW(IUnknown* punkSrc, LPRECT lprectBorder)
  3028. {
  3029. BOOL bUseHmonitor = (GetNumberOfMonitors() > 1);
  3030. return _pbsInner->_GetBorderDWHelper(punkSrc, lprectBorder, bUseHmonitor);
  3031. }
  3032. HRESULT CDesktopBrowser::_ResizeNextBorder(UINT itb)
  3033. {
  3034. _ResizeNextBorderHelper(itb, TRUE);
  3035. return S_OK;
  3036. }
  3037. HRESULT CDesktopBrowser::GetMonitor(IUnknown* punkSrc, HMONITOR * phMon)
  3038. {
  3039. ASSERT(phMon);
  3040. *phMon = NULL; // just in case
  3041. UINT itb = _pbsInner->_FindTBar(punkSrc);
  3042. if (itb==(UINT)-1) {
  3043. return E_INVALIDARG;
  3044. }
  3045. LPTOOLBARITEM ptbi = _pbsInner->_GetToolbarItem(itb);
  3046. if (ptbi) {
  3047. *phMon = ptbi->hMon;
  3048. return S_OK;
  3049. } else {
  3050. return E_FAIL;
  3051. }
  3052. }
  3053. HRESULT CDesktopBrowser::RequestMonitor(IUnknown* punkSrc, HMONITOR * phMonitor)
  3054. {
  3055. UINT itb = _pbsInner->_FindTBar(punkSrc);
  3056. if (itb==(UINT)-1) {
  3057. return E_INVALIDARG;
  3058. }
  3059. ASSERT(phMonitor);
  3060. if (IsMonitorValid(*phMonitor))
  3061. return S_OK;
  3062. else
  3063. {
  3064. *phMonitor = GetPrimaryMonitor();
  3065. return S_FALSE;
  3066. }
  3067. }
  3068. HRESULT CDesktopBrowser::SetMonitor(IUnknown* punkSrc, HMONITOR hMonNew, HMONITOR * phMonOld)
  3069. {
  3070. ASSERT(phMonOld);
  3071. *phMonOld = NULL; // just in case
  3072. UINT itb = _pbsInner->_FindTBar(punkSrc);
  3073. if (itb==(UINT)-1) {
  3074. return E_INVALIDARG;
  3075. }
  3076. LPTOOLBARITEM ptbThis = _pbsInner->_GetToolbarItem(itb);
  3077. if (ptbThis) {
  3078. *phMonOld = ptbThis->hMon;
  3079. ptbThis->hMon = hMonNew;
  3080. return S_OK;
  3081. } else {
  3082. return E_FAIL;
  3083. }
  3084. }
  3085. ///////////////////////////////////////////////////////////////////////
  3086. //
  3087. // CDesktopBrowser FORWARDERS to commonsb
  3088. //
  3089. // {
  3090. #define CALL_INNER(_result, _function, _arglist, _args) \
  3091. _result CDesktopBrowser:: _function _arglist { return _psbInner-> _function _args ; }
  3092. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  3093. // IShellBrowser (same as IOleInPlaceFrame)
  3094. CALL_INNER_HRESULT(GetWindow, (HWND * lphwnd), (lphwnd));
  3095. CALL_INNER_HRESULT(ContextSensitiveHelp, (BOOL fEnterMode), (fEnterMode));
  3096. CALL_INNER_HRESULT(InsertMenusSB, (HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths), (hmenuShared, lpMenuWidths));
  3097. CALL_INNER_HRESULT(SetMenuSB, (HMENU hmenuShared, HOLEMENU holemenu, HWND hwnd), (hmenuShared, holemenu, hwnd));
  3098. CALL_INNER_HRESULT(RemoveMenusSB, (HMENU hmenuShared), (hmenuShared));
  3099. CALL_INNER_HRESULT(SetStatusTextSB, (LPCOLESTR lpszStatusText), (lpszStatusText));
  3100. CALL_INNER_HRESULT(EnableModelessSB, (BOOL fEnable), (fEnable));
  3101. CALL_INNER_HRESULT(TranslateAcceleratorSB, (LPMSG lpmsg, WORD wID), (lpmsg, wID));
  3102. CALL_INNER_HRESULT(GetViewStateStream, (DWORD grfMode, LPSTREAM *ppStrm), (grfMode, ppStrm));
  3103. CALL_INNER_HRESULT(GetControlWindow, (UINT id, HWND * lphwnd), (id, lphwnd));
  3104. CALL_INNER_HRESULT(SendControlMsg, (UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret), (id, uMsg, wParam, lParam, pret));
  3105. CALL_INNER_HRESULT(QueryActiveShellView, (struct IShellView ** ppshv), (ppshv));
  3106. CALL_INNER_HRESULT(OnViewWindowActive, (struct IShellView * ppshv), (ppshv));
  3107. CALL_INNER_HRESULT(SetToolbarItems, (LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags), (lpButtons, nButtons, uFlags));
  3108. #undef CALL_INNER
  3109. #undef CALL_INNER_HRESULT
  3110. // }
  3111. // {
  3112. #define CALL_INNER(_result, _function, _arglist, _args) \
  3113. _result CDesktopBrowser:: _function _arglist { return _pdwsInner-> _function _args ; }
  3114. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  3115. // IDockingWindowSite
  3116. // TODO: move these up from basesb to commonsb - requires toolbars
  3117. CALL_INNER_HRESULT(RequestBorderSpaceDW, (IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths), (punkSrc, pborderwidths));
  3118. CALL_INNER_HRESULT(SetBorderSpaceDW, (IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths), (punkSrc, pborderwidths));
  3119. #undef CALL_INNER
  3120. #undef CALL_INNER_HRESULT
  3121. // }
  3122. // {
  3123. #define CALL_INNER(_result, _function, _arglist, _args) \
  3124. _result CDesktopBrowser:: _function _arglist { return _pdwfInner-> _function _args ; }
  3125. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  3126. // IDockingWindowFrame
  3127. CALL_INNER_HRESULT(AddToolbar, (IUnknown* punkSrc, LPCWSTR pwszItem, DWORD dwReserved), (punkSrc, pwszItem, dwReserved));
  3128. CALL_INNER_HRESULT(FindToolbar, (LPCWSTR pwszItem, REFIID riid, void **ppvObj), (pwszItem, riid, ppvObj));
  3129. #undef CALL_INNER
  3130. #undef CALL_INNER_HRESULT
  3131. // }
  3132. // {
  3133. #define CALL_INNER(_result, _function, _arglist, _args) \
  3134. _result CDesktopBrowser:: _function _arglist { return _piosInner-> _function _args ; }
  3135. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  3136. // IInputObjectSite
  3137. CALL_INNER_HRESULT(OnFocusChangeIS, (IUnknown* punkSrc, BOOL fSetFocus), (punkSrc, fSetFocus));
  3138. #undef CALL_INNER
  3139. #undef CALL_INNER_HRESULT
  3140. // }
  3141. // {
  3142. #define CALL_INNER(_result, _function, _arglist, _args) \
  3143. _result CDesktopBrowser:: _function _arglist { return _pdtInner-> _function _args ; }
  3144. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  3145. // *** IDropTarget ***
  3146. CALL_INNER_HRESULT(DragLeave, (void), ());
  3147. #undef CALL_INNER
  3148. #undef CALL_INNER_HRESULT
  3149. // }
  3150. // {
  3151. #define CALL_INNER(_result, _function, _arglist, _args) \
  3152. _result CDesktopBrowser:: _function _arglist { return _pbsInner-> _function _args ; }
  3153. #define CALL_INNER_HRESULT(_function, _arglist, _args) CALL_INNER(HRESULT, _function, _arglist, _args)
  3154. // *** IBrowserService2 specific methods ***
  3155. CALL_INNER_HRESULT(GetParentSite, ( IOleInPlaceSite** ppipsite), ( ppipsite));
  3156. CALL_INNER_HRESULT(SetTitle, (IShellView* psv, LPCWSTR pszName), (psv, pszName));
  3157. CALL_INNER_HRESULT(GetTitle, (IShellView* psv, LPWSTR pszName, DWORD cchName), (psv, pszName, cchName));
  3158. CALL_INNER_HRESULT(GetOleObject, ( IOleObject** ppobjv), ( ppobjv));
  3159. // think about this one.. I'm not sure we want to expose this -- Chee
  3160. // My impression is that we won't document this whole interface???
  3161. CALL_INNER_HRESULT(GetTravelLog, (ITravelLog** pptl), (pptl));
  3162. CALL_INNER_HRESULT(ShowControlWindow, (UINT id, BOOL fShow), (id, fShow));
  3163. CALL_INNER_HRESULT(IsControlWindowShown, (UINT id, BOOL *pfShown), (id, pfShown));
  3164. CALL_INNER_HRESULT(IEGetDisplayName, (LPCITEMIDLIST pidl, LPWSTR pwszName, UINT uFlags), (pidl, pwszName, uFlags));
  3165. CALL_INNER_HRESULT(IEParseDisplayName, (UINT uiCP, LPCWSTR pwszPath, LPITEMIDLIST * ppidlOut), (uiCP, pwszPath, ppidlOut));
  3166. CALL_INNER_HRESULT(DisplayParseError, (HRESULT hres, LPCWSTR pwszPath), (hres, pwszPath));
  3167. CALL_INNER_HRESULT(NavigateToPidl, (LPCITEMIDLIST pidl, DWORD grfHLNF), (pidl, grfHLNF));
  3168. CALL_INNER_HRESULT(SetNavigateState, (BNSTATE bnstate), (bnstate));
  3169. CALL_INNER_HRESULT(GetNavigateState, (BNSTATE *pbnstate), (pbnstate));
  3170. CALL_INNER_HRESULT(NotifyRedirect, ( IShellView* psv, LPCITEMIDLIST pidl, BOOL *pfDidBrowse), ( psv, pidl, pfDidBrowse));
  3171. CALL_INNER_HRESULT(UpdateWindowList, (), ());
  3172. CALL_INNER_HRESULT(UpdateBackForwardState, (), ());
  3173. CALL_INNER_HRESULT(SetFlags, (DWORD dwFlags, DWORD dwFlagMask), (dwFlags, dwFlagMask));
  3174. CALL_INNER_HRESULT(GetFlags, (DWORD *pdwFlags), (pdwFlags));
  3175. // Tells if it can navigate now or not.
  3176. CALL_INNER_HRESULT(CanNavigateNow, (), ());
  3177. CALL_INNER_HRESULT(GetPidl, (LPITEMIDLIST *ppidl), (ppidl));
  3178. CALL_INNER_HRESULT(SetReferrer, (LPITEMIDLIST pidl), (pidl));
  3179. CALL_INNER(DWORD, GetBrowserIndex ,(), ());
  3180. CALL_INNER_HRESULT(GetBrowserByIndex, (DWORD dwID, IUnknown **ppunk), (dwID, ppunk));
  3181. CALL_INNER_HRESULT(GetHistoryObject, (IOleObject **ppole, IStream **pstm, IBindCtx **ppbc), (ppole, pstm, ppbc));
  3182. CALL_INNER_HRESULT(SetHistoryObject, (IOleObject *pole, BOOL fIsLocalAnchor), (pole, fIsLocalAnchor));
  3183. CALL_INNER_HRESULT(CacheOLEServer, (IOleObject *pole), (pole));
  3184. CALL_INNER_HRESULT(GetSetCodePage, (VARIANT* pvarIn, VARIANT* pvarOut), (pvarIn, pvarOut));
  3185. CALL_INNER_HRESULT(OnHttpEquiv, (IShellView* psv, BOOL fDone, VARIANT* pvarargIn, VARIANT* pvarargOut), (psv, fDone, pvarargIn, pvarargOut));
  3186. CALL_INNER_HRESULT(GetPalette, ( HPALETTE * hpal), ( hpal));
  3187. CALL_INNER_HRESULT(OnSetFocus, (), ());
  3188. CALL_INNER_HRESULT(OnFrameWindowActivateBS, (BOOL fActive), (fActive));
  3189. CALL_INNER_HRESULT(RegisterWindow, (BOOL fUnregister, int swc), (fUnregister, swc));
  3190. CALL_INNER_HRESULT(GetBaseBrowserData,(LPCBASEBROWSERDATA* ppbd), (ppbd));
  3191. CALL_INNER(LPBASEBROWSERDATA, PutBaseBrowserData,(), ());
  3192. CALL_INNER_HRESULT(CreateViewWindow, (IShellView* psvNew, IShellView* psvOld, LPRECT prcView, HWND* phwnd), (psvNew, psvOld, prcView, phwnd));;
  3193. CALL_INNER_HRESULT(SetTopBrowser, (), ());
  3194. CALL_INNER_HRESULT(InitializeDownloadManager, (), ());
  3195. CALL_INNER_HRESULT(InitializeTransitionSite, (), ());
  3196. CALL_INNER_HRESULT(Offline, (int iCmd), (iCmd));
  3197. CALL_INNER_HRESULT(AllowViewResize, (BOOL f), (f));
  3198. CALL_INNER_HRESULT(SetActivateState, (UINT u), (u));
  3199. CALL_INNER_HRESULT(UpdateSecureLockIcon, (int eSecureLock), (eSecureLock));
  3200. CALL_INNER_HRESULT(CreateBrowserPropSheetExt, (REFIID riid, void **ppvObj), (riid, ppvObj));
  3201. CALL_INNER_HRESULT(GetViewWindow,(HWND * phwnd), (phwnd));
  3202. CALL_INNER_HRESULT(InitializeTravelLog,(ITravelLog* ptl, DWORD dw), (ptl, dw));
  3203. CALL_INNER_HRESULT(_UIActivateView, (UINT uState), (uState));
  3204. CALL_INNER_HRESULT(_ResizeView,(), ());
  3205. CALL_INNER_HRESULT(_ExecChildren, (IUnknown *punkBar, BOOL fBroadcast, const GUID *pguidCmdGroup,
  3206. DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut),
  3207. (punkBar, fBroadcast, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut));
  3208. CALL_INNER_HRESULT(_SendChildren,
  3209. (HWND hwndBar, BOOL fBroadcast, UINT uMsg, WPARAM wParam, LPARAM lParam),
  3210. (hwndBar, fBroadcast, uMsg, wParam, lParam));
  3211. CALL_INNER_HRESULT(_OnFocusChange, (UINT itb), (itb));
  3212. CALL_INNER_HRESULT(v_ShowHideChildWindows, (BOOL fChildOnly), (fChildOnly));
  3213. CALL_INNER_HRESULT(_GetViewBorderRect, (RECT* prc), (prc));
  3214. // BEGIN REVIEW: review names and need of each.
  3215. //
  3216. // this first set could be basebrowser only members. no one overrides
  3217. CALL_INNER_HRESULT(_CancelPendingNavigationAsync, (), ());
  3218. CALL_INNER_HRESULT(_MaySaveChanges, (), ());
  3219. CALL_INNER_HRESULT(_PauseOrResumeView, (BOOL fPaused), (fPaused));
  3220. CALL_INNER_HRESULT(_DisableModeless, (), ());
  3221. // rethink these... are all of these necessary?
  3222. CALL_INNER_HRESULT(_NavigateToPidl, (LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags), (pidl, grfHLNF, dwFlags));
  3223. CALL_INNER_HRESULT(_TryShell2Rename, (IShellView* psv, LPCITEMIDLIST pidlNew), (psv, pidlNew));
  3224. CALL_INNER_HRESULT(_SwitchActivationNow, () , ());
  3225. CALL_INNER_HRESULT(_CancelPendingView, (), ());
  3226. //END REVIEW:
  3227. CALL_INNER(UINT, _get_itbLastFocus, (), ());
  3228. CALL_INNER_HRESULT(_put_itbLastFocus, (UINT itbLastFocus), (itbLastFocus));
  3229. CALL_INNER_HRESULT(_ResizeNextBorderHelper, (UINT itb, BOOL bUseHmonitor), (itb, bUseHmonitor));
  3230. #undef CALL_INNER
  3231. #undef CALL_INNER_HRESULT
  3232. // }
  3233. // RunDll32 entry point to create a new local server on the desktop
  3234. // thread. We convert the CLSID to the index into the LocalServer list
  3235. // and then send it to the desktop, which inturn spins the thread off.
  3236. STDAPI_(void) SHCreateLocalServerRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  3237. {
  3238. CLSID clsidLocalServer;
  3239. if (GUIDFromStringA(pszCmdLine, &clsidLocalServer))
  3240. {
  3241. for (int i = 0; i < ARRAYSIZE(c_localServers); i++)
  3242. {
  3243. if (IsEqualCLSID(clsidLocalServer, *c_localServers[i]))
  3244. {
  3245. PostMessage(GetShellWindow(), CWM_CREATELOCALSERVER, (WPARAM)TRUE, (LPARAM)i);
  3246. break;
  3247. }
  3248. }
  3249. }
  3250. }