Source code of Windows XP (NT5)
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.

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