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.

12337 lines
394 KiB

  1. #include "priv.h"
  2. #include "apithk.h"
  3. #include "sccls.h"
  4. #include "shbrows2.h"
  5. #include "commonsb.h"
  6. #include "resource.h"
  7. #include "bindcb.h"
  8. #include "explore2.h"
  9. #include <isguids.h>
  10. #include "desktop.h"
  11. #include <ntverp.h>
  12. #include "bands.h"
  13. #include "browbar.h"
  14. #include "itbdrop.h"
  15. #include "theater.h"
  16. #include "itbar.h"
  17. #include "idispids.h"
  18. #include "bsmenu.h"
  19. #include "legacy.h"
  20. #include "mshtmcid.h"
  21. #include <desktray.h> // IDeskTray
  22. #include "commonsb.h"
  23. #include "onetree.h"
  24. #include "cnctnpt.h"
  25. #include "comcatex.h"
  26. #include "util.h"
  27. #include "uemapp.h"
  28. #include <shobjidlp.h>
  29. #include <subsmgr.h>
  30. #include "trayp.h"
  31. #include "oleacc.h"
  32. // (lamadio): Conflicts with one defined in winuserp.h
  33. #undef WINEVENT_VALID //It's tripping on this...
  34. #include "winable.h"
  35. #include <htmlhelp.h>
  36. #include <varutil.h>
  37. #include "idhidden.h"
  38. #include "mediautil.h"
  39. #ifdef UNIX
  40. #include <mainwin.h>
  41. #include "unixstuff.h"
  42. EXTERN_C void unixGetWininetCacheLockStatus(BOOL *pBool, char **ppsz);
  43. EXTERN_C const GUID CLSID_MsgBand;
  44. #endif /* UNIX */
  45. #include "mluisupp.h"
  46. #define CWM_THEATERMODE (WM_USER + 400)
  47. #define CWM_UPDATEBACKFORWARDSTATE (WM_USER + 401)
  48. #define SUPERCLASS CCommonBrowser
  49. #define PERF_LOGGING 1
  50. HRESULT IUnknown_GetClientDB(IUnknown *punk, IUnknown **ppdbc);
  51. // Timer IDs
  52. #define SHBTIMER_MENUSELECT 100
  53. #define MENUSELECT_TIME 500 // .5 seconds for the menuselect delay
  54. // Command group for private communication with CITBar
  55. // 67077B95-4F9D-11D0-B884-00AA00B60104
  56. const GUID CGID_PrivCITCommands = { 0x67077B95L, 0x4F9D, 0x11D0, 0xB8, 0x84, 0x00, 0xAA, 0x00, 0xB6, 0x01, 0x04 };
  57. // Guid of Office's discussion band
  58. // {BDEADE7F-C265-11d0-BCED-00A0C90AB50F}
  59. EXTERN_C const GUID CLSID_DiscussionBand = { 0xbdeade7fL, 0xc265, 0x11d0, 0xbc, 0xed, 0x00, 0xa0, 0xc9, 0x0a, 0xb5, 0x0f };
  60. // Guid of the Tip of the Day
  61. //{4D5C8C25-D075-11d0-B416-00C04FB90376}
  62. const GUID CLSID_TipOfTheDay = { 0x4d5c8c25L, 0xd075, 0x11d0, 0xb4, 0x16, 0x00, 0xc0, 0x4f, 0xb9, 0x03, 0x76 };
  63. // Used to see if the discussion band is registered for the CATID_CommBand
  64. const LPCTSTR c_szDiscussionBandReg = TEXT("CLSID\\{BDEADE7F-C265-11d0-BCED-00A0C90AB50F}\\Implemented Categories\\{00021494-0000-0000-C000-000000000046}");
  65. // FEATURE: Way back from 1997, ralphw thinks we should remove >iedefault from the following string
  66. const TCHAR c_szHtmlHelpFile[] = TEXT("%SYSTEMROOT%\\Help\\iexplore.chm>iedefault");
  67. // Increment this when the saved structure changes
  68. const WORD c_wVersion = 0x8002;
  69. // This value will be initialized to 0 only when we are under IExplorer.exe
  70. UINT g_tidParking = 0;
  71. #define MAX_NUM_ZONES_ICONS 12
  72. #define MAX_ZONE_DISPLAYNAME 260
  73. UINT_PTR g_sysmenuTimer = 0;
  74. void ITBar_ShowDW(IDockingWindow * pdw, BOOL fTools, BOOL fAddress, BOOL fLinks);
  75. void RestrictItbarViewMenu(HMENU hmenu, IUnknown *punkBar);
  76. BOOL IsExplorerWindow(HWND hwnd);
  77. void _SetWindowIcon(HWND hwnd, HICON hIcon, BOOL bLarge);
  78. //
  79. // A named mutex is being used to determine if a critical operation exist, such as a file download.
  80. // When we detect this we can prevent things like going offline while a download is in progress.
  81. // To start the operation Create the named mutex. When the op is complete, close the handle.
  82. // To see if any pending operations are in progress, Open the named mutex. Success/fail will indicate
  83. // if any pending operations exist. This mechanism is being used to determine if a file download is
  84. // in progress when the user attempts to go offline. If so, we prompt them to let them know that going
  85. // offline will cancel the download(s).
  86. HANDLE g_hCritOpMutex = NULL;
  87. const LPCSTR c_szCritOpMutexName = "CritOpMutex";
  88. #define StartCriticalOperation() ((g_hCritOpMutex = CreateMutexA(NULL, TRUE, c_szCritOpMutexName)) != (HANDLE)NULL)
  89. #define EndCriticalOperation() (CloseHandle(g_hCritOpMutex))
  90. #define IsCriticalOperationPending() (((g_hCritOpMutex = OpenMutexA(MUTEX_ALL_ACCESS, TRUE, c_szCritOpMutexName)) != (HANDLE)NULL) && CloseHandle(g_hCritOpMutex))
  91. #define MAX_FILECONTEXT_STRING (40)
  92. #define VALIDATEPENDINGSTATE() ASSERT((_pbbd->_psvPending && _pbbd->_psfPending) || (!_pbbd->_psvPending && !_pbbd->_psfPending))
  93. #define DM_NAV TF_SHDNAVIGATE
  94. #define DM_ZONE TF_SHDNAVIGATE
  95. #define DM_IEDDE TF_SHDAUTO
  96. #define DM_CANCELMODE 0
  97. #define DM_UIWINDOW 0
  98. #define DM_ENABLEMODELESS 0
  99. #define DM_EXPLORERMENU 0
  100. #define DM_BACKFORWARD 0
  101. #define DM_PROTOCOL 0
  102. #define DM_ITBAR 0
  103. #define DM_STARTUP 0
  104. #define DM_AUTOLIFE 0
  105. #define DM_PALETTE 0
  106. #define DM_SESSIONCOUNT 0
  107. #define DM_FOCUS 0
  108. #define DM_PREMERGEDMENU DM_TRACE
  109. #define DM_ONSIZE DM_TRACE
  110. #define DM_SSL 0
  111. #define DM_SHUTDOWN DM_TRACE
  112. #define DM_MISC 0 // misc/tmp
  113. extern IDeskTray * g_pdtray;
  114. #define ISRECT_EQUAL(rc1, rc2) (((rc1).top == (rc2).top) && ((rc1).bottom == (rc2).bottom) && ((rc1).left == (rc2).left) && ((rc1).right == (rc2).right))
  115. BOOL ViewIDFromViewMode(UINT uViewMode, SHELLVIEWID *pvid);
  116. typedef struct _NAVREQUEST
  117. {
  118. int cbNavData;
  119. BYTE *lpNavData;
  120. struct _NAVREQUEST *pnext;
  121. } NAVREQUEST;
  122. // copied from explore/cabwnd.h
  123. #define MH_POPUP 0x0010
  124. #define MH_TOOLBAR 0x0020
  125. #define TBOFFSET_NONE 50
  126. #define TBOFFSET_STD 0
  127. #define TBOFFSET_HIST 1
  128. #define TBOFFSET_VIEW 2
  129. extern DWORD g_dwStopWatchMode; // Shell performance mode
  130. // Suite Apps Registry keys duplicated from dochost.cpp
  131. #define NEW_MAIL_DEF_KEY TEXT("Mail")
  132. #define NEW_NEWS_DEF_KEY TEXT("News")
  133. #define NEW_CONTACTS_DEF_KEY TEXT("Contacts")
  134. #define NEW_CALL_DEF_KEY TEXT("Internet Call")
  135. #define NEW_APPOINTMENT_DEF_KEY TEXT("Appointment")
  136. #define NEW_MEETING_DEF_KEY TEXT("Meeting")
  137. #define NEW_TASK_DEF_KEY TEXT("Task")
  138. #define NEW_TASKREQUEST_DEF_KEY TEXT("Task Request")
  139. #define NEW_JOURNAL_DEF_KEY TEXT("Journal")
  140. #define NEW_NOTE_DEF_KEY TEXT("Note")
  141. #define SHELLBROWSER_FSNOTIFY_FLAGS (SHCNE_DRIVEADDGUI | SHCNE_SERVERDISCONNECT | \
  142. SHCNE_MEDIAREMOVED | SHCNE_RMDIR | SHCNE_DELETE | \
  143. SHCNE_UPDATEDIR | SHCNE_NETUNSHARE | \
  144. SHCNE_DRIVEREMOVED | SHCNE_UPDATEITEM | \
  145. SHCNE_RENAMEFOLDER | SHCNE_UPDATEIMAGE | \
  146. SHCNE_MEDIAINSERTED | SHCNE_DRIVEADD)
  147. #define FAV_FSNOTIFY_FLAGS (SHCNE_DISKEVENTS | SHCNE_UPDATEIMAGE)
  148. #define GOMENU_RECENT_ITEMS 15
  149. //
  150. // Prototypes for "reset web settings" code
  151. //
  152. extern "C" HRESULT ResetWebSettings(HWND hwnd, BOOL *pfHomePageChanged);
  153. extern "C" BOOL IsResetWebSettingsRequired(void);
  154. const TCHAR c_szMenuItemCust[] = TEXT("Software\\Policies\\Microsoft\\Internet Explorer");
  155. const TCHAR c_szWindowUpdateName[] = TEXT("Windows Update Menu Text");
  156. #pragma warning(disable:4355) // using 'this' in constructor
  157. void CShellBrowser2::_PruneGoSubmenu(HMENU hmenu)
  158. {
  159. // get by position since SHGetMenuFromID does a DFS and we are interested
  160. // in the one that is a direct child of hmenu and not some random menu
  161. // elsewhere in the hierarchy who might happen to have the same ID.
  162. int iPos = SHMenuIndexFromID(hmenu, FCIDM_MENU_EXPLORE);
  163. MENUITEMINFO mii;
  164. mii.cbSize = sizeof(mii);
  165. mii.fMask = MIIM_SUBMENU;
  166. if (iPos >= 0 && GetMenuItemInfo(hmenu, iPos, TRUE, &mii) && mii.hSubMenu) {
  167. HMENU hmenuGo = mii.hSubMenu;
  168. // Remove everything after the first separator
  169. MENUITEMINFO mii;
  170. int iItem = 0;
  171. while (TRUE) {
  172. TCHAR szTmp[100];
  173. mii.cbSize = sizeof(mii);
  174. mii.fMask = MIIM_TYPE;
  175. mii.dwTypeData = szTmp;
  176. mii.cch = ARRAYSIZE(szTmp);
  177. if (!GetMenuItemInfoWrap(hmenuGo, iItem++, TRUE, &mii))
  178. break;
  179. if (mii.fType == MFT_SEPARATOR) {
  180. // we must have hit the first seperator, delete the rest of the menu...
  181. for (int iDel = GetMenuItemCount(hmenuGo) - 1; iDel >= iItem; iDel--)
  182. RemoveMenu(hmenuGo, iDel, MF_BYPOSITION);
  183. break;
  184. }
  185. }
  186. }
  187. }
  188. //
  189. // Okay, menus are weird because of the fifteen bazillion scenarios we
  190. // need to support.
  191. //
  192. // There are several functions involved in menu editing. _MenuTemplate,
  193. // and all the _OnXxxMenuPopup functions.
  194. //
  195. // The job of _MenuTemplate is to do global menu munging. These munges
  196. // once performed are permanent, so don't munge anything that changes
  197. // based on some random ambient condition. The job of the _OnXxxMenuPopup
  198. // functions is to do per-instance last-minute munging.
  199. //
  200. // Also, _MenuTemplate is the only place you can add or remove top-level
  201. // menu items.
  202. //
  203. // fShell = TRUE means that this menu will be used for shell objects.
  204. // fShell = FALSE means that this menu will be used for web objects.
  205. //
  206. // Now the rules...
  207. //
  208. // NT5:
  209. // Tools present.
  210. // Shell: "Folder Options" on Tools (not View).
  211. // Web: "Internet Options" on Tools (not View).
  212. // FTP: "Internet Options" & "Folder Options" on Tools (not View).
  213. // Go under View (not top-level).
  214. //
  215. // Non-NT5, fShell = TRUE, IsCShellBrowser() = TRUE (Single-pane)
  216. // Tools removed.
  217. // Shell: "Folder Options" on View (not Tools).
  218. // Web: "Internet Options" on View (not Tools).
  219. // FTP: "Internet Options" & "Folder Options" on View (not Tools).
  220. // Go on top-level (not under View).
  221. //
  222. // Non-NT5, fShell = TRUE, IsCShellBrowser() = FALSE (Dual-pane)
  223. // Tools present.
  224. // Shell: "Folder Options" on View (not Tools).
  225. // Web: "Internet Options" on View (not Tools).
  226. // FTP: "Internet Options" & "Folder Options" on View (not Tools).
  227. // Go on top-level (not under View).
  228. //
  229. // Non-NT5, fShell = FALSE, viewing web page:
  230. // Tools present.
  231. // Shell: "Folder Options" on Tools (not View).
  232. // Web: "Internet Options" on Tools (not View).
  233. // FTP: "Internet Options" & "Folder Options" on Tools (not View).
  234. // Go under View (not top-level).
  235. //
  236. // Bonus details:
  237. // Restrictions.
  238. // Shell Options disabled if browser-only.
  239. //
  240. HMENU CShellBrowser2::_MenuTemplate(int id, BOOL fShell)
  241. {
  242. HMENU hmenu = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(id));
  243. if (hmenu)
  244. {
  245. //
  246. // According to the chart, there is only one scenario where
  247. // we need to nuke the Tools menu: Non-NT5 shell single-pane
  248. //
  249. if (IsCShellBrowser2() && fShell && GetUIVersion() < 5)
  250. DeleteMenu(hmenu, FCIDM_MENU_TOOLS, MF_BYCOMMAND);
  251. //
  252. // According to the chart, Go vanishes from top-level on NT5
  253. // and on non-shell scenarios. It also vanishes if restricted.
  254. //
  255. if (GetUIVersion() >= 5 || !fShell || SHRestricted(REST_CLASSICSHELL)) {
  256. // get by position since DeleteMenu does a DFS & there are dup FCIDM_MENU_EXPLORE's
  257. int iPos = SHMenuIndexFromID(hmenu, FCIDM_MENU_EXPLORE);
  258. if (iPos >= 0)
  259. DeleteMenu(hmenu, iPos, MF_BYPOSITION);
  260. }
  261. // Nuke file menu if restricted
  262. if (SHRestricted(REST_NOFILEMENU))
  263. DeleteMenu(hmenu, FCIDM_MENU_FILE, MF_BYCOMMAND);
  264. // Nuke favorites menu if a rooted explorer or shell menu and classic shell is set
  265. // or if restricted
  266. if ((fShell && SHRestricted(REST_CLASSICSHELL))
  267. || SHRestricted2(REST_NoFavorites, NULL, 0))
  268. DeleteMenu(hmenu, FCIDM_MENU_FAVORITES, MF_BYCOMMAND);
  269. HMENU hmenuView = SHGetMenuFromID(hmenu, FCIDM_MENU_VIEW);
  270. if (hmenuView) {
  271. // Go appears in only one place, so this test is just
  272. // the reverse of the one that decided if Go stays
  273. // at top-level.
  274. if (fShell && GetUIVersion() < 5) {
  275. DeleteMenu(hmenuView, FCIDM_MENU_EXPLORE, MF_BYCOMMAND);
  276. }
  277. }
  278. // Folder Options requires integrated shell
  279. if (fShell && WhichPlatform() != PLATFORM_INTEGRATED)
  280. {
  281. if (hmenuView)
  282. {
  283. _EnableMenuItem(hmenuView, FCIDM_BROWSEROPTIONS, FALSE);
  284. }
  285. HMENU hmenuTools = SHGetMenuFromID(hmenu, FCIDM_MENU_TOOLS);
  286. if (hmenuTools)
  287. {
  288. _EnableMenuItem(hmenuTools, FCIDM_BROWSEROPTIONS, FALSE);
  289. }
  290. }
  291. }
  292. return hmenu;
  293. }
  294. // Determine if we need to add the Fortezza menu
  295. // For perf reasons, do not call this function unless user is
  296. // browsing outside the local machine--- it will load WININET
  297. bool NeedFortezzaMenu()
  298. {
  299. static bool fChecked = false,
  300. fNeed = false;
  301. // Never show the Fortezza option when offline
  302. if (SHIsGlobalOffline())
  303. return false;
  304. else if (fChecked)
  305. return fNeed;
  306. else
  307. {
  308. fChecked = true;
  309. DWORD fStatus = 0;
  310. BOOL fQuery = InternetQueryFortezzaStatus(&fStatus, 0);
  311. return (fNeed = fQuery && (fStatus&FORTSTAT_INSTALLED));
  312. }
  313. }
  314. // Create and return the Fortezza menu
  315. HMENU FortezzaMenu()
  316. {
  317. HMENU hfm = NULL;
  318. static TCHAR szLogInItem[32] = TEXT(""), // Initialize to empty strings
  319. szLogOutItem[32] = TEXT(""),
  320. szChangeItem[32] = TEXT("");
  321. static bool fInit = false;
  322. if (!fInit) // Load the strings only once
  323. {
  324. MLLoadString(IDS_FORTEZZA_LOGIN, szLogInItem, ARRAYSIZE(szLogInItem)-1);
  325. MLLoadString(IDS_FORTEZZA_LOGOUT, szLogOutItem, ARRAYSIZE(szLogOutItem)-1);
  326. MLLoadString(IDS_FORTEZZA_CHANGE, szChangeItem, ARRAYSIZE(szChangeItem)-1);
  327. fInit = true;
  328. }
  329. if (hfm = CreatePopupMenu())
  330. {
  331. AppendMenu(hfm, MF_STRING, FCIDM_FORTEZZA_LOGIN, szLogInItem);
  332. AppendMenu(hfm, MF_STRING, FCIDM_FORTEZZA_LOGOUT, szLogOutItem);
  333. AppendMenu(hfm, MF_STRING, FCIDM_FORTEZZA_CHANGE, szChangeItem);
  334. }
  335. return hfm;
  336. }
  337. // Configure the menu depending on card state
  338. // This function is called only if Fortezza has been detected
  339. void SetFortezzaMenu(HMENU hfm)
  340. {
  341. if (hfm==NULL)
  342. return;
  343. DWORD fStatus = 0;
  344. if (InternetQueryFortezzaStatus(&fStatus, 0))
  345. {
  346. // If the query succeeds, the items are enabled depending
  347. // on whether the user is logged in to Fortezza.
  348. _EnableMenuItem(hfm, FCIDM_FORTEZZA_CHANGE, (fStatus&FORTSTAT_LOGGEDON) ? TRUE : FALSE);
  349. _EnableMenuItem(hfm, FCIDM_FORTEZZA_LOGIN, (fStatus&FORTSTAT_LOGGEDON) ? FALSE : TRUE);
  350. _EnableMenuItem(hfm, FCIDM_FORTEZZA_LOGOUT, (fStatus&FORTSTAT_LOGGEDON) ? TRUE : FALSE);
  351. }
  352. else
  353. {
  354. // If the query fails, all items are grayed out.
  355. _EnableMenuItem(hfm, FCIDM_FORTEZZA_CHANGE, FALSE);
  356. _EnableMenuItem(hfm, FCIDM_FORTEZZA_LOGIN, FALSE);
  357. _EnableMenuItem(hfm, FCIDM_FORTEZZA_LOGOUT, FALSE);
  358. }
  359. return;
  360. }
  361. DWORD DoNetConnect(HWND hwnd)
  362. {
  363. return (DWORD)SHStartNetConnectionDialog(NULL, NULL, RESOURCETYPE_DISK);
  364. }
  365. DWORD DoNetDisconnect(HWND hwnd)
  366. {
  367. DWORD ret = WNetDisconnectDialog(NULL, RESOURCETYPE_DISK);
  368. SHChangeNotifyHandleEvents(); // flush any drive notifications
  369. TraceMsg(DM_TRACE, "shell:CNet - TRACE: DisconnectDialog returned (%lx)", ret);
  370. if (ret == WN_EXTENDED_ERROR)
  371. {
  372. // FEATURE: is this still needed
  373. // There has been a bug with this returning this but then still
  374. // doing the disconnect. For now lets bring up a message and then
  375. // still do the notify to have the shell attempt to cleanup.
  376. TCHAR szErrorMsg[MAX_PATH]; // should be big enough
  377. TCHAR szName[80]; // The name better not be any bigger.
  378. DWORD dwError;
  379. WNetGetLastError(&dwError, szErrorMsg, ARRAYSIZE(szErrorMsg),
  380. szName, ARRAYSIZE(szName));
  381. MLShellMessageBox(NULL,
  382. MAKEINTRESOURCE(IDS_NETERROR), MAKEINTRESOURCE(IDS_DISCONNECTERROR),
  383. MB_ICONHAND | MB_OK, dwError, szName, szErrorMsg);
  384. }
  385. // FEATURE: deal with error, perhaps open a window on this drive
  386. return ret;
  387. }
  388. CShellBrowser2::CShellBrowser2() :
  389. #ifdef NO_MARSHALLING
  390. _fDelayedClose(FALSE),
  391. _fOnIEThread(TRUE),
  392. #endif
  393. _fStatusBar(TRUE),
  394. _fShowMenu(TRUE),
  395. _fValidComCatCache(FALSE),
  396. _fShowSynchronize(TRUE),
  397. _iSynchronizePos(-1),
  398. CSBSUPERCLASS(NULL)
  399. {
  400. // warning: can't call SUPERCLASS until _Initialize has been called
  401. // (since that's what does the aggregation)
  402. ASSERT(IsEqualCLSID(_clsidThis, CLSID_NULL));
  403. ASSERT(_hwndDummyTB == NULL);
  404. }
  405. #pragma warning(default:4355) // using 'this' in constructor
  406. HRESULT CShellBrowser2::_Initialize(HWND hwnd, IUnknown *pauto)
  407. {
  408. HRESULT hr;
  409. SHELLSTATE ss = {0};
  410. hr = SUPERCLASS::_Initialize(hwnd, pauto);
  411. if (SUCCEEDED(hr)) {
  412. SetTopBrowser();
  413. int i = _AllocToolbarItem();
  414. ASSERT(i == ITB_ITBAR);
  415. _GetToolbarItem(ITB_ITBAR)->fShow = TRUE;
  416. _put_itbLastFocus(ITB_VIEW);
  417. InitializeDownloadManager();
  418. _nTBTextRows = -1;
  419. SHGetSetSettings(&ss, SSF_MAPNETDRVBUTTON, FALSE);
  420. _fShowNetworkButtons = ss.fMapNetDrvBtn;
  421. // Initialize the base class transition site pointer.
  422. InitializeTransitionSite();
  423. // Invalidate icon cache in case non-IE browser took over .htm icons.
  424. IEInvalidateImageList();
  425. _UpdateRegFlags();
  426. _nMBIgnoreNextDeselect = RegisterWindowMessage(TEXT("CMBIgnoreNextDeselect"));
  427. _fShowFortezza = FALSE;
  428. _hfm = NULL;
  429. }
  430. return hr;
  431. }
  432. HRESULT CShellBrowser2_CreateInstance(HWND hwnd, void **ppsb)
  433. {
  434. CShellBrowser2 *psb = new CShellBrowser2();
  435. if (psb)
  436. {
  437. HRESULT hr = psb->_Initialize(hwnd, NULL); // aggregation, etc.
  438. if (FAILED(hr)) {
  439. ASSERT(0); // shouldn't happen
  440. ATOMICRELEASE(psb);
  441. }
  442. *ppsb = (void *)psb;
  443. return hr;
  444. }
  445. return E_OUTOFMEMORY;
  446. }
  447. CShellBrowser2::~CShellBrowser2()
  448. {
  449. _TheaterMode(FALSE, FALSE);
  450. if (IsWindow(_hwndDummyTB))
  451. DestroyWindow(_hwndDummyTB);
  452. // If automation was enabled, kill it now
  453. ATOMICRELEASE(_pbsmInfo);
  454. ATOMICRELEASE(_poctNsc);
  455. ATOMICRELEASE(_pcmNsc);
  456. ATOMICRELEASE(_pism);
  457. ATOMICRELEASE(_pizm);
  458. ATOMICRELEASE(_pcmSearch);
  459. ASSERT(0 == _punkMsgLoop);
  460. ILFree(_pidlLastHist);
  461. if (_hmenuPreMerged)
  462. DestroyMenu(_hmenuPreMerged);
  463. if (_hmenuTemplate)
  464. DestroyMenu(_hmenuTemplate);
  465. if (_hmenuFull)
  466. DestroyMenu(_hmenuFull);
  467. if (_hfm)
  468. DestroyMenu(_hfm);
  469. if (_lpPendingButtons)
  470. LocalFree(_lpPendingButtons);
  471. if (_lpButtons)
  472. LocalFree(_lpButtons);
  473. if (_hZoneIcon)
  474. DestroyIcon(_hZoneIcon);
  475. Str_SetPtr(&_pszSynchronizeText, NULL);
  476. if (_hEventComCat)
  477. CloseHandle(_hEventComCat);
  478. TraceMsg(TF_SHDLIFE, "dtor CShellBrowser2 %x", this);
  479. }
  480. void CShellBrowser2::v_FillCabStateHeader(CABSH* pcabsh, FOLDERSETTINGS* pfs)
  481. {
  482. WINDOWPLACEMENT wp;
  483. OLECMD rgCmds[3] = {0};
  484. LPTOOLBARITEM ptbi = _GetToolbarItem(ITB_ITBAR);
  485. if (ptbi)
  486. {
  487. rgCmds[0].cmdID = CITIDM_VIEWTOOLS;
  488. rgCmds[1].cmdID = CITIDM_VIEWADDRESS;
  489. rgCmds[2].cmdID = CITIDM_VIEWLINKS;
  490. IUnknown_QueryStatus(ptbi->ptbar, &CGID_PrivCITCommands, ARRAYSIZE(rgCmds), rgCmds, NULL);
  491. }
  492. pcabsh->wv.bStdButtons = BOOLIFY(rgCmds[0].cmdf);
  493. pcabsh->wv.bAddress = BOOLIFY(rgCmds[1].cmdf);
  494. pcabsh->wv.bLinks = BOOLIFY(rgCmds[2].cmdf);
  495. pcabsh->wv.bStatusBar = _fStatusBar;
  496. wp.length = sizeof(WINDOWPLACEMENT);
  497. GetWindowPlacement(_pbbd->_hwnd, &wp);
  498. pcabsh->dwHotkey = (UINT)SendMessage(_pbbd->_hwnd, WM_GETHOTKEY, 0, 0);
  499. //
  500. // Now Lets convert all of this common stuff into a
  501. // non 16/32 bit dependant data structure, such that both
  502. // can us it.
  503. //
  504. pcabsh->dwSize = sizeof(*pcabsh);
  505. pcabsh->flags = wp.flags;
  506. // 99/05/26 #345915 vtan: Don't mess with this. It's BY DESIGN.
  507. // #169839 caused #345915. When a window is minimized and closed
  508. // it should NEVER be opened minimized. The code that was here
  509. // has now caused a one month period where persistence of window
  510. // placement can be with SW_SHOWMINIMIZED which will cause the
  511. // window to restore minimized. This will go away when the window
  512. // is next closed.
  513. if ((wp.showCmd == SW_SHOWMINIMIZED) || (wp.showCmd == SW_MINIMIZE))
  514. pcabsh->showCmd = SW_SHOWNORMAL;
  515. else
  516. pcabsh->showCmd = wp.showCmd;
  517. pcabsh->ptMinPosition.x = wp.ptMinPosition.x;
  518. pcabsh->ptMinPosition.y = wp.ptMinPosition.y;
  519. pcabsh->ptMaxPosition.x = wp.ptMaxPosition.x;
  520. pcabsh->ptMaxPosition.y = wp.ptMaxPosition.y;
  521. pcabsh->rcNormalPosition = *((RECTL*)&wp.rcNormalPosition);
  522. // Now the folder settings
  523. pcabsh->ViewMode = pfs->ViewMode;
  524. // NB Don't ever preserve the best-fit flag or the nosubfolders flag.
  525. pcabsh->fFlags = pfs->fFlags & ~FWF_NOSUBFOLDERS & ~FWF_BESTFITWINDOW;
  526. pcabsh->fMask = CABSHM_VERSION;
  527. pcabsh->dwVersionId = CABSH_VER;
  528. }
  529. BOOL CShellBrowser2::_GetVID(SHELLVIEWID *pvid)
  530. {
  531. BOOL bGotVID = FALSE;
  532. if (_pbbd->_psv && pvid)
  533. {
  534. IShellView2 *psv2;
  535. if (SUCCEEDED(_pbbd->_psv->QueryInterface(IID_PPV_ARG(IShellView2, &psv2))))
  536. {
  537. if (S_OK == psv2->GetView(pvid, SV2GV_CURRENTVIEW))
  538. {
  539. bGotVID = TRUE;
  540. }
  541. psv2->Release();
  542. }
  543. }
  544. return bGotVID;
  545. }
  546. HRESULT CShellBrowser2::SetAsDefFolderSettings()
  547. {
  548. HRESULT hres;
  549. if (_pbbd->_psv)
  550. {
  551. SHELLVIEWID vid;
  552. BOOL bGotVID = _GetVID(&vid);
  553. FOLDERSETTINGS fs;
  554. _pbbd->_psv->GetCurrentInfo(&fs);
  555. CABINETSTATE cs;
  556. GetCabState(&cs);
  557. if (cs.fNewWindowMode)
  558. g_dfs.bDefToolBarMulti = FALSE;
  559. else
  560. g_dfs.bDefToolBarSingle = FALSE;
  561. g_dfs.fFlags = fs.fFlags & (FWF_AUTOARRANGE); // choose the ones we case about
  562. g_dfs.uDefViewMode = fs.ViewMode;
  563. g_dfs.bDefStatusBar = _fStatusBar;
  564. g_dfs.bUseVID = bGotVID;
  565. if (bGotVID)
  566. {
  567. g_dfs.vid = vid;
  568. }
  569. else
  570. {
  571. ViewIDFromViewMode(g_dfs.uDefViewMode, &g_dfs.vid);
  572. }
  573. g_dfs.dwViewPriority = VIEW_PRIORITY_USEASDEFAULT;
  574. SaveDefaultFolderSettings(GFSS_SETASDEFAULT);
  575. // 99/02/10 #226140 vtan: Get DefView to set default view
  576. IUnknown_Exec(_pbbd->_psv, &CGID_DefView, DVID_SETASDEFAULT, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  577. hres = S_OK;
  578. } else {
  579. hres = E_FAIL;
  580. }
  581. return hres;
  582. }
  583. //---------------------------------------------------------------------------
  584. // Closing a cabinet window.
  585. //
  586. // save it's local view info in the directory it is looking at
  587. //
  588. // NOTE: this will fail on read only media like net or cdrom
  589. //
  590. // REVIEW: we may not want to save this info on removable media
  591. // (but if we don't allow a switch to force this!)
  592. //
  593. void CShellBrowser2::_SaveState()
  594. {
  595. CABINETSTATE cs;
  596. GetCabState(&cs);
  597. // Don't save any state info if restrictions are in place.
  598. // We are trying to give a way for automation scripts to run that do not
  599. // update the view state. To handle this we say if the window is not visible
  600. // (the script can set or unset visibility) than do not save the state (unless
  601. // falways add...)
  602. // Notwithstanding the above comments, suppress updating view state if UI
  603. // was set by automation
  604. if (_fUISetByAutomation ||
  605. !cs.fSaveLocalView ||
  606. SHRestricted(REST_NOSAVESET) || !IsWindowVisible(_pbbd->_hwnd) || _ptheater)
  607. return;
  608. if (_pbbd->_psv)
  609. {
  610. // Only save state if we close the browser in the same mode (either IE or Explorer)
  611. // that we started in.
  612. if (BOOLIFY(_IsPageInternet(_GetPidl())) == BOOLIFY(_fInternetStart))
  613. {
  614. if (IsOS(OS_WHISTLERORGREATER))
  615. {
  616. _PropertyBagSaveState();
  617. }
  618. else
  619. {
  620. _OldSaveState();
  621. }
  622. }
  623. }
  624. }
  625. void CShellBrowser2::_PropertyBagSaveState()
  626. {
  627. FOLDERSETTINGS fs;
  628. _pbbd->_psv->GetCurrentInfo(&fs);
  629. CABSH cabsh;
  630. v_FillCabStateHeader(&cabsh, &fs);
  631. IPropertyBag* ppb;
  632. if (SUCCEEDED(GetPropertyBag(SHGVSPB_FOLDER, IID_PPV_ARG(IPropertyBag, &ppb))))
  633. {
  634. SHPropertyBag_WritePOINTLScreenRes(ppb, VS_PROPSTR_MINPOS, &cabsh.ptMinPosition);
  635. SHPropertyBag_WritePOINTLScreenRes(ppb, VS_PROPSTR_MAXPOS, &cabsh.ptMaxPosition);
  636. SHPropertyBag_WriteRECTLScreenRes(ppb, VS_PROPSTR_POS, &cabsh.rcNormalPosition);
  637. SHPropertyBag_WriteDWORD(ppb, VS_PROPSTR_REV, _dwRevCount);
  638. SHPropertyBag_WriteDWORD(ppb, VS_PROPSTR_WPFLAGS, cabsh.flags);
  639. SHPropertyBag_WriteDWORD(ppb, VS_PROPSTR_SHOW, cabsh.showCmd);
  640. SHPropertyBag_WriteDWORD(ppb, VS_PROPSTR_FFLAGS, cabsh.fFlags);
  641. SHPropertyBag_WriteDWORD(ppb, VS_PROPSTR_HOTKEY, cabsh.dwHotkey);
  642. SHPropertyBag_WriteBOOL(ppb, VS_PROPSTR_BUTTONS, cabsh.wv.bStdButtons);
  643. SHPropertyBag_WriteBOOL(ppb, VS_PROPSTR_STATUS, cabsh.wv.bStatusBar);
  644. SHPropertyBag_WriteBOOL(ppb, VS_PROPSTR_LINKS, cabsh.wv.bLinks);
  645. SHPropertyBag_WriteBOOL(ppb, VS_PROPSTR_ADDRESS, cabsh.wv.bAddress);
  646. SHELLVIEWID vid;
  647. if (_GetVID(&vid))
  648. {
  649. SHPropertyBag_WriteGUID(ppb, VS_PROPSTR_VID, &vid);
  650. }
  651. else
  652. {
  653. SHPropertyBag_Delete(ppb, VS_PROPSTR_VID);
  654. }
  655. ppb->Release();
  656. }
  657. }
  658. void CShellBrowser2::_OldSaveState()
  659. {
  660. WINDOWPLACEMENT currentWindowPlacement;
  661. WINVIEW winView;
  662. currentWindowPlacement.length = 0;
  663. // if these keys are down, save the current states
  664. if (IsCShellBrowser2() &&
  665. GetAsyncKeyState(VK_CONTROL) < 0)
  666. {
  667. SetAsDefFolderSettings();
  668. }
  669. // Now get the view information
  670. FOLDERSETTINGS fs;
  671. _pbbd->_psv->GetCurrentInfo(&fs);
  672. IStream* pstm = NULL;
  673. // 99/05/07 #291358 vtan: Temporary solution to a problem dating back to IE4 days.
  674. // Here's where the window frame state if saved. This also saves the FOLDERSETTINGS
  675. // view information. Ideally it's best to separate the two but it seems reasonable
  676. // to only save frame state if this is the initial navigation. Once navigated away
  677. // only save view information and preserve the current frame state by reading what's
  678. // there and copying it. If there's no frame state then use what the current frame
  679. // state is. It could be possible to write out an empty frame state but if this
  680. // state is roamed to a down-level platform it may cause unexpected results.
  681. if (_fSBWSaved)
  682. {
  683. IStream *pIStream;
  684. CABSH cabinetStateHeader;
  685. pIStream = v_GetViewStream(_pbbd->_pidlCur, STGM_READ, L"CabView");
  686. if (pIStream != NULL)
  687. {
  688. if (SUCCEEDED(_FillCabinetStateHeader(pIStream, &cabinetStateHeader)))
  689. {
  690. // If an old frame state exists then save it and mark it as valid.
  691. currentWindowPlacement.length = sizeof(currentWindowPlacement);
  692. currentWindowPlacement.flags = cabinetStateHeader.flags;
  693. currentWindowPlacement.showCmd = cabinetStateHeader.showCmd;
  694. currentWindowPlacement.ptMinPosition = *(reinterpret_cast<POINT*>(&cabinetStateHeader.ptMinPosition));
  695. currentWindowPlacement.ptMaxPosition = *(reinterpret_cast<POINT*>(&cabinetStateHeader.ptMaxPosition));
  696. currentWindowPlacement.rcNormalPosition = *(reinterpret_cast<RECT*>(&cabinetStateHeader.rcNormalPosition));
  697. winView = cabinetStateHeader.wv;
  698. }
  699. pIStream->Release();
  700. }
  701. }
  702. if (!(_fSBWSaved && _fWin95ViewState))
  703. {
  704. pstm = v_GetViewStream(_pbbd->_pidlCur, STGM_CREATE | STGM_WRITE, L"CabView");
  705. _fSBWSaved = TRUE;
  706. }
  707. if (pstm)
  708. {
  709. CABSH cabsh;
  710. SHELLVIEWID vid;
  711. BOOL bGotVID = _GetVID(&vid);
  712. v_FillCabStateHeader(&cabsh, &fs);
  713. if (currentWindowPlacement.length == sizeof(currentWindowPlacement))
  714. {
  715. // If an old frame state exists then put it back over the current frame state.
  716. cabsh.flags = currentWindowPlacement.flags;
  717. cabsh.showCmd = currentWindowPlacement.showCmd;
  718. cabsh.ptMinPosition = *(reinterpret_cast<POINTL*>(&currentWindowPlacement.ptMinPosition));
  719. cabsh.ptMaxPosition = *(reinterpret_cast<POINTL*>(&currentWindowPlacement.ptMaxPosition));
  720. cabsh.rcNormalPosition = *(reinterpret_cast<RECTL*>(&currentWindowPlacement.rcNormalPosition));
  721. cabsh.wv = winView;
  722. }
  723. if (bGotVID)
  724. {
  725. cabsh.vid = vid;
  726. cabsh.fMask |= CABSHM_VIEWID;
  727. }
  728. cabsh.fMask |= CABSHM_REVCOUNT;
  729. cabsh.dwRevCount = _dwRevCount; // save out the rev count of when we were opened
  730. //
  731. // First output the common non view specific information
  732. //
  733. pstm->Write(&cabsh, sizeof(cabsh), NULL);
  734. // And release it, which will commit it to disk..
  735. pstm->Release();
  736. // NOTE (toddb): The DefView view state is saved by the base class so we don't need
  737. // to explicitly save it here. If you do it gets called twice which is wasted time.
  738. // Do not call _pbbd->_psv->SaveViewState(); from this function.
  739. }
  740. #ifdef DEBUG
  741. if (g_dwPrototype & 0x00000010) {
  742. //
  743. // Save toolbars
  744. //
  745. pstm = v_GetViewStream(_pbbd->_pidlCur, STGM_CREATE | STGM_WRITE, L"Toolbars");
  746. if (pstm) {
  747. _SaveToolbars(pstm);
  748. pstm->Release();
  749. }
  750. }
  751. #endif
  752. }
  753. STDAPI_(LPITEMIDLIST) IEGetInternetRootID(void);
  754. IStream *CShellBrowser2::v_GetViewStream(LPCITEMIDLIST pidl, DWORD grfMode, LPCWSTR pwszName)
  755. {
  756. IStream *pstm = NULL;
  757. LPITEMIDLIST pidlToFree = NULL;
  758. BOOL bCabView = (0 == StrCmpIW(pwszName, L"CabView"));
  759. if (((NULL == pidl) && IsEqualCLSID(_clsidThis, CLSID_InternetExplorer)) ||
  760. IsBrowserFrameOptionsPidlSet(pidl, BFO_BROWSER_PERSIST_SETTINGS))
  761. {
  762. // If this is a child of the URL or we're looking at an unititialized IE frame,
  763. // then save all in the IE stream
  764. pidlToFree = IEGetInternetRootID();
  765. pidl = pidlToFree;
  766. }
  767. else if (bCabView && _fNilViewStream)
  768. {
  769. // if we loaded cabview settings from the 'unknown pidl' view stream,
  770. // we've got to stick with it, whether or not we now have a pidl.
  771. pidl = NULL;
  772. }
  773. if (pidl)
  774. {
  775. pstm = SHGetViewStream(pidl, grfMode, pwszName, REGSTR_KEY_STREAMMRU, REGVALUE_STREAMS);
  776. }
  777. else if (bCabView)
  778. {
  779. // So we don't have a pidl for which to grab a stream, so we'll just
  780. // make up a stream to cover the situation. A hack no doubt, but before we
  781. // were handling this case by always loading from the IE stream. (doh!)
  782. // Actually, the whole thing is busted because we're
  783. // creating the window (and trying to restore the windowpos) as part of
  784. // CoCreateInstance(), before the client can navigate the browser.
  785. pstm = OpenRegStream(HKEY_CURRENT_USER,
  786. REGSTR_PATH_EXPLORER TEXT("\\Streams\\<nil>"),
  787. TEXT("CabView"),
  788. grfMode);
  789. _fNilViewStream = TRUE; // cabview settings initialized from the 'unknown pidl' view stream.
  790. }
  791. ILFree(pidlToFree);
  792. return pstm;
  793. }
  794. HRESULT CShellBrowser2::_FillCabinetStateHeader (IStream *pIStream, CABSH *cabsh)
  795. {
  796. HRESULT hResult;
  797. // Now read in the state from the stream file.
  798. // read the old header first.
  799. hResult = IStream_Read(pIStream, cabsh, sizeof(CABSHOLD));
  800. // Sanity test to make the structure is sane
  801. if (FAILED(hResult) || (cabsh->dwSize < sizeof(CABSHOLD)))
  802. hResult = E_OUTOFMEMORY; // bogus but good enough
  803. // Read the remainder of the structure if we can. If not, then
  804. // set the mask equal to zero so we don't get confused later.
  805. if (cabsh->dwSize < sizeof(CABSH) ||
  806. FAILED(IStream_Read(pIStream, ((LPBYTE)cabsh) + sizeof(CABSHOLD), sizeof(CABSH) - sizeof(CABSHOLD))))
  807. {
  808. cabsh->fMask = 0;
  809. }
  810. return(hResult);
  811. }
  812. BOOL CShellBrowser2::_ReadSettingsFromPropertyBag(IPropertyBag* ppb, IETHREADPARAM *piei)
  813. {
  814. BOOL fRet;
  815. CABSH cabsh = {0};
  816. cabsh.dwSize = sizeof(cabsh);
  817. cabsh.fMask = CABSHM_VERSION;
  818. cabsh.dwVersionId = CABSH_VER;
  819. if (SUCCEEDED(SHPropertyBag_ReadDWORD(ppb, VS_PROPSTR_WPFLAGS, &cabsh.flags)))
  820. {
  821. if (FAILED(SHPropertyBag_ReadPOINTLScreenRes(ppb, VS_PROPSTR_MINPOS, &cabsh.ptMinPosition)))
  822. {
  823. cabsh.ptMinPosition.x = cabsh.ptMinPosition.y = -1;
  824. }
  825. if (FAILED(SHPropertyBag_ReadPOINTLScreenRes(ppb, VS_PROPSTR_MAXPOS, &cabsh.ptMaxPosition)))
  826. {
  827. cabsh.ptMaxPosition.x = cabsh.ptMaxPosition.y = -1;
  828. }
  829. if (FAILED(SHPropertyBag_ReadRECTLScreenRes(ppb, VS_PROPSTR_POS, &cabsh.rcNormalPosition)))
  830. {
  831. cabsh.rcNormalPosition.left = cabsh.rcNormalPosition.top = cabsh.rcNormalPosition.right = cabsh.rcNormalPosition.bottom = CW_USEDEFAULT;
  832. }
  833. SHPropertyBag_ReadDWORDDef(ppb, VS_PROPSTR_MODE, &cabsh.ViewMode, FVM_TILE);
  834. SHPropertyBag_ReadDWORDDef(ppb, VS_PROPSTR_SHOW, &cabsh.showCmd, 0);
  835. SHPropertyBag_ReadDWORDDef(ppb, VS_PROPSTR_FFLAGS, &cabsh.fFlags, FWF_BESTFITWINDOW | g_dfs.fFlags);
  836. SHPropertyBag_ReadDWORDDef(ppb, VS_PROPSTR_HOTKEY, &cabsh.dwHotkey, 0);
  837. cabsh.wv.bStdButtons = SHPropertyBag_ReadBOOLDefRet(ppb, VS_PROPSTR_BUTTONS, TRUE);
  838. cabsh.wv.bStatusBar = SHPropertyBag_ReadBOOLDefRet(ppb, VS_PROPSTR_STATUS, TRUE);
  839. cabsh.wv.bLinks = SHPropertyBag_ReadBOOLDefRet(ppb, VS_PROPSTR_LINKS, TRUE);
  840. cabsh.wv.bAddress = SHPropertyBag_ReadBOOLDefRet(ppb, VS_PROPSTR_ADDRESS, TRUE);
  841. cabsh.fMask |= CABSHM_REVCOUNT;
  842. SHPropertyBag_ReadDWORDDef(ppb, VS_PROPSTR_REV, &cabsh.dwRevCount, g_dfs.dwDefRevCount);
  843. if (SUCCEEDED(SHPropertyBag_ReadGUID(ppb, VS_PROPSTR_VID, &cabsh.vid)))
  844. {
  845. cabsh.fMask |= CABSHM_VIEWID;
  846. }
  847. fRet = _FillIEThreadParamFromCabsh(&cabsh, piei);
  848. }
  849. else
  850. {
  851. fRet = FALSE;
  852. }
  853. return fRet;
  854. }
  855. BOOL CShellBrowser2::_FillIEThreadParamFromCabsh(CABSH* pcabsh, IETHREADPARAM *piei)
  856. {
  857. BOOL fUpgradeToWebView = FALSE;
  858. bool bInvalidWindowPlacement;
  859. // Now extract the data and put it into appropriate structures
  860. // first the window placement info
  861. piei->wp.length = sizeof(piei->wp);
  862. piei->wp.flags = (UINT)pcabsh->flags;
  863. piei->wp.showCmd = (UINT)pcabsh->showCmd;
  864. ASSERT(sizeof(piei->wp.ptMinPosition) == sizeof(pcabsh->ptMinPosition));
  865. piei->wp.ptMinPosition = *((LPPOINT)&pcabsh->ptMinPosition);
  866. piei->wp.ptMaxPosition = *((LPPOINT)&pcabsh->ptMaxPosition);
  867. ASSERT(sizeof(piei->wp.rcNormalPosition) == sizeof(pcabsh->rcNormalPosition));
  868. piei->wp.rcNormalPosition = *((RECT*)&pcabsh->rcNormalPosition);
  869. // Do some simple sanity checks to make sure that the returned
  870. // information appears to be reasonable and not random garbage
  871. // We want the Show command to be normal or minimize or maximize.
  872. // Only need one test as they are consectutive and start at zero
  873. // DON'T try to validate too much of the WINDOWPLACEMENT--
  874. // SetWindowPlacement does a much better job, especially in
  875. // multiple-monitor scenarios...
  876. // 99/03/09 #303300 vtan: Sanity check for zero/negative width or
  877. // height. SetWindowPlacement doesn't sanity check for this -
  878. // only for whether the rectangle left and top are in the visible
  879. // screen area. If this condition is detected then reset to default
  880. // and force DefView to best fit the window.
  881. {
  882. LONG lWidth, lHeight;
  883. lWidth = piei->wp.rcNormalPosition.right - piei->wp.rcNormalPosition.left;
  884. lHeight = piei->wp.rcNormalPosition.bottom - piei->wp.rcNormalPosition.top;
  885. bInvalidWindowPlacement = ((lWidth <= 0) || (lHeight <= 0));
  886. if (bInvalidWindowPlacement)
  887. piei->wp.length = 0;
  888. }
  889. if (piei->wp.showCmd > SW_MAX)
  890. return FALSE;
  891. piei->fs.ViewMode = (UINT)pcabsh->ViewMode;
  892. piei->fs.fFlags = (UINT)pcabsh->fFlags;
  893. if (pcabsh->fMask & CABSHM_VIEWID)
  894. {
  895. // There was code here to revert to large icon mode if fWin95Classic
  896. // mode was turned on. This is completely busted because fWin95Classic
  897. // just affects the DEFAULT view, not any PERSISTED view.
  898. piei->m_vidRestore = pcabsh->vid;
  899. piei->m_dwViewPriority = VIEW_PRIORITY_CACHEHIT; // we have a cache hit!
  900. }
  901. // If there was a revcount, check if we've been overridden by
  902. // a subsequent "use these settings as the default for all future
  903. // windows".
  904. if (pcabsh->fMask & CABSHM_REVCOUNT)
  905. {
  906. if (g_dfs.dwDefRevCount != pcabsh->dwRevCount)
  907. {
  908. if (g_dfs.bUseVID)
  909. {
  910. piei->m_vidRestore = g_dfs.vid;
  911. }
  912. else
  913. {
  914. ViewIDFromViewMode(g_dfs.uDefViewMode, &(piei->m_vidRestore));
  915. }
  916. piei->fs.ViewMode = g_dfs.uDefViewMode;
  917. piei->fs.fFlags = g_dfs.fFlags;
  918. piei->m_dwViewPriority = g_dfs.dwViewPriority;
  919. }
  920. }
  921. _dwRevCount = g_dfs.dwDefRevCount; // save this with the browser so we can save it out later
  922. if (!(pcabsh->fMask & CABSHM_VERSION) || (pcabsh->dwVersionId < CABSH_VER))
  923. {
  924. SHELLSTATE ss = {0};
  925. // old version of stream....
  926. SHGetSetSettings(&ss, SSF_WIN95CLASSIC, FALSE);
  927. // we have either a cache miss (or an older dwVersionId), or we are restricting to win95 mode,
  928. // so set the priority accordingly.
  929. piei->m_dwViewPriority = ss.fWin95Classic ? VIEW_PRIORITY_RESTRICTED : VIEW_PRIORITY_CACHEMISS;
  930. if (ss.fWin95Classic)
  931. {
  932. // Hey, it's a Win95 CABSH structure and we're in Win95 mode,
  933. // so don't change the defaults!
  934. ViewIDFromViewMode(pcabsh->ViewMode, &(piei->m_vidRestore));
  935. }
  936. else
  937. {
  938. // Upgrade scenario:
  939. // My Computer in List should wind up in Web View/List
  940. // C:\ in List should wind up in List
  941. // If this fails (C:\ winds up in Large Icon), we can try
  942. // to comment out this code altogether. Hopefully defview's
  943. // default view stuff will realize Web View should be
  944. // selected and My Computer will go to Web View instead
  945. // of staying in List.
  946. //
  947. piei->m_vidRestore = DFS_VID_Default;
  948. // Note: if we upgrade to web view, we better let the
  949. // view recalc window space or the window will be TOO SMALL
  950. fUpgradeToWebView = TRUE;
  951. }
  952. if (pcabsh->wv.bStdButtons) // win95 called this bToolbar
  953. {
  954. // Win95 called bStdButtons bToolbar. IE4 separates this
  955. // into bAddress and bStdButtons. Set bAddress for upgrade.
  956. pcabsh->wv.bAddress = TRUE;
  957. #define RECT_YADJUST 18
  958. // bump up the rect slightly to account for new toolbar size....
  959. // 18 is an approximately random number which assumes that the default
  960. // configuration is a single height toolbar which is approx twice as high as the
  961. // old toobar....
  962. //
  963. // NOTE: old browser streams are always for the primary monitor, so we just
  964. // check to see if we are going to fit on the screen. If not, then don't bother.
  965. //
  966. // NOTE: when we rev the version number, we'll want to do this
  967. // rect adjustment for the CABSH_WIN95_VER version...
  968. //
  969. int iMaxYSize = GetSystemMetrics(SM_CYFULLSCREEN);
  970. if (piei->wp.rcNormalPosition.bottom + piei->wp.rcNormalPosition.top + RECT_YADJUST < iMaxYSize)
  971. {
  972. piei->wp.rcNormalPosition.bottom += RECT_YADJUST;
  973. }
  974. #undef RECT_YADJUST
  975. }
  976. }
  977. // After all that upgrade work, check the classic shell restriction
  978. if (SHRestricted(REST_CLASSICSHELL))
  979. {
  980. // It doesn't matter what vid was specified, use the ViewMode
  981. ViewIDFromViewMode(pcabsh->ViewMode, &(piei->m_vidRestore));
  982. piei->m_dwViewPriority = VIEW_PRIORITY_RESTRICTED; // use highest priority because of the restriction.
  983. // Oops, we can't upgrade...
  984. fUpgradeToWebView = FALSE;
  985. }
  986. // And the Hotkey
  987. piei->wHotkey = (UINT)pcabsh->dwHotkey;
  988. piei->wv = pcabsh->wv;
  989. // if we upgraded to web view, then any persisted window sizes will
  990. // probably be too small -- let them get resized by the view...
  991. if (fUpgradeToWebView || bInvalidWindowPlacement)
  992. piei->fs.fFlags |= FWF_BESTFITWINDOW;
  993. else
  994. piei->fs.fFlags &= ~FWF_BESTFITWINDOW;
  995. return TRUE;
  996. }
  997. BOOL CShellBrowser2::_ReadSettingsFromStream(IStream *pstm, IETHREADPARAM *piei)
  998. {
  999. BOOL fRet;
  1000. CABSH cabsh;
  1001. if (SUCCEEDED(_FillCabinetStateHeader(pstm, &cabsh)))
  1002. {
  1003. fRet = _FillIEThreadParamFromCabsh(&cabsh, piei);
  1004. }
  1005. else
  1006. {
  1007. fRet = FALSE;
  1008. }
  1009. return fRet;
  1010. }
  1011. void CShellBrowser2::_FillIEThreadParam(LPCITEMIDLIST pidl, IETHREADPARAM *piei)
  1012. {
  1013. BOOL fSettingsLoaded = FALSE;
  1014. if (0 == GetSystemMetrics(SM_CLEANBOOT))
  1015. {
  1016. if (IsOS(OS_WHISTLERORGREATER))
  1017. {
  1018. IPropertyBag* ppb;
  1019. if (SUCCEEDED(_GetPropertyBag(pidl, SHGVSPB_FOLDER, IID_PPV_ARG(IPropertyBag, &ppb))))
  1020. {
  1021. fSettingsLoaded = _ReadSettingsFromPropertyBag(ppb, piei);
  1022. ppb->Release();
  1023. }
  1024. }
  1025. else
  1026. {
  1027. IStream* pstm = v_GetViewStream(pidl, STGM_READ, L"CabView");
  1028. if (pstm)
  1029. {
  1030. fSettingsLoaded = _ReadSettingsFromStream(pstm, piei);
  1031. pstm->Release();
  1032. }
  1033. }
  1034. }
  1035. if (!fSettingsLoaded)
  1036. v_GetDefaultSettings(piei);
  1037. }
  1038. void CShellBrowser2::_UpdateFolderSettings(LPCITEMIDLIST pidl)
  1039. {
  1040. if (!_fWin95ViewState)
  1041. {
  1042. IETHREADPARAM iei;
  1043. ZeroMemory(&iei, sizeof(iei));
  1044. _FillIEThreadParam(pidl, &iei);
  1045. _fsd._vidRestore = iei.m_vidRestore;
  1046. _fsd._dwViewPriority = iei.m_dwViewPriority;
  1047. _fsd._fs = iei.fs;
  1048. }
  1049. else if (_pbbd->_psv)
  1050. {
  1051. IShellView2 *pISV2;
  1052. // 99/04/16 #323726 vtan: Make sure that both the FOLDERSETTINGS (in _fsd._fs)
  1053. // and the VID (in _fsd.vidRestore) is set up properly for shdocvw to make a
  1054. // decision. This fixes Win95 browse in single window mode inheriting the view
  1055. // from the source of navigation.
  1056. _pbbd->_psv->GetCurrentInfo(&_fsd._fs);
  1057. if (SUCCEEDED(_pbbd->_psv->QueryInterface(IID_PPV_ARG(IShellView2, &pISV2))))
  1058. {
  1059. if (SUCCEEDED(pISV2->GetView(&_fsd._vidRestore, SV2GV_CURRENTVIEW)))
  1060. _fsd._dwViewPriority = VIEW_PRIORITY_INHERIT;
  1061. else
  1062. _fsd._dwViewPriority = VIEW_PRIORITY_DESPERATE;
  1063. pISV2->Release();
  1064. }
  1065. }
  1066. }
  1067. void CShellBrowser2::_LoadBrowserWindowSettings(IETHREADPARAM *piei, LPCITEMIDLIST pidl)
  1068. {
  1069. _FillIEThreadParam(pidl, piei);
  1070. //Copy the two restore settings from piei to ShellBrowser.
  1071. _fsd._vidRestore = piei->m_vidRestore;
  1072. _fsd._dwViewPriority = piei->m_dwViewPriority;
  1073. _fsd._fs = piei->fs;
  1074. // Now that the ITBar has the menu on it, it must always be shown. We turn
  1075. // on/off bands individually now...
  1076. LPTOOLBARITEM ptbi = _GetToolbarItem(ITB_ITBAR);
  1077. ptbi->fShow = TRUE;
  1078. _fStatusBar = piei->wv.bStatusBar;
  1079. // never allow VK_MENU to be our hot key
  1080. if (piei->wHotkey != VK_MENU)
  1081. SendMessage(_pbbd->_hwnd, WM_SETHOTKEY, piei->wHotkey, 0);
  1082. #ifdef DEBUG
  1083. if (g_dwPrototype & 0x00000010) {
  1084. //
  1085. // Load toolbars
  1086. //
  1087. IStream* pstm = v_GetViewStream(pidl, STGM_READ, L"Toolbars");
  1088. if (pstm) {
  1089. _LoadToolbars(pstm);
  1090. pstm->Release();
  1091. }
  1092. }
  1093. #endif
  1094. }
  1095. void CShellBrowser2::_UpdateChildWindowSize(void)
  1096. {
  1097. if (!_fKioskMode) {
  1098. if (_hwndStatus && _fStatusBar) {
  1099. SendMessage(_hwndStatus, WM_SIZE, 0, 0L);
  1100. }
  1101. }
  1102. }
  1103. /*----------------------------------------------------------
  1104. Purpose: Helper function to do ShowDW on the internet toolbar.
  1105. We can show all the bands in the toolbar, but we must
  1106. never accidentally hide the menuband. CShellBrowser2
  1107. should call this function rather than IDockingWindow::ShowDW
  1108. directly if there is any chance fShow would be FALSE.
  1109. */
  1110. void ITBar_ShowDW(IDockingWindow * pdw, BOOL fTools, BOOL fAddress, BOOL fLinks)
  1111. {
  1112. IUnknown_Exec(pdw, &CGID_PrivCITCommands, CITIDM_SHOWTOOLS, fTools, NULL, NULL);
  1113. IUnknown_Exec(pdw, &CGID_PrivCITCommands, CITIDM_SHOWADDRESS, fAddress, NULL, NULL);
  1114. IUnknown_Exec(pdw, &CGID_PrivCITCommands, CITIDM_SHOWLINKS, fLinks, NULL, NULL);
  1115. }
  1116. void CShellBrowser2::_HideToolbar(LPUNKNOWN punk)
  1117. {
  1118. for (UINT itb=0; itb < (UINT)_GetToolbarCount(); itb++) {
  1119. LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  1120. if (ptbi->ptbar && SHIsSameObject(ptbi->ptbar, punk))
  1121. {
  1122. if (ITB_ITBAR == itb)
  1123. ITBar_ShowDW(ptbi->ptbar, FALSE, FALSE, FALSE);
  1124. else
  1125. ptbi->ptbar->ShowDW(FALSE);
  1126. }
  1127. }
  1128. }
  1129. HRESULT CShellBrowser2::v_ShowHideChildWindows(BOOL fChildOnly)
  1130. {
  1131. // (scotth): _hwndStatus is bogus when closing a window
  1132. if (_hwndStatus && IS_VALID_HANDLE(_hwndStatus, WND))
  1133. ShowWindow(_hwndStatus, (!_fKioskMode && _fStatusBar) ? SW_SHOW : SW_HIDE);
  1134. Exec(NULL, OLECMDID_UPDATECOMMANDS, 0, NULL, NULL);
  1135. _UpdateChildWindowSize();
  1136. SUPERCLASS::v_ShowHideChildWindows(fChildOnly);
  1137. // We should call _UpdateBackForwardState after the parent show/hide
  1138. // toolbars.
  1139. UpdateBackForwardState();
  1140. return S_OK;
  1141. }
  1142. #define MAX_BROWSER_WINDOW_TEMPLATE (MAX_BROWSER_WINDOW_TITLE - 20)
  1143. void CShellBrowser2::v_GetAppTitleTemplate(LPTSTR pszBuffer, LPTSTR pszTitle)
  1144. {
  1145. if (_fAppendIEToCaptionBar)
  1146. {
  1147. TCHAR szBuffer[MAX_BROWSER_WINDOW_TEMPLATE];
  1148. _GetAppTitle(szBuffer, ARRAYSIZE(szBuffer));
  1149. wnsprintf(pszBuffer, 80/* Supid params*/, TEXT("%%s - %s"), szBuffer);
  1150. }
  1151. else
  1152. {
  1153. // don't tack on "intenet explorer" if we didn't start there
  1154. StrCpy(pszBuffer, TEXT("%s"));
  1155. }
  1156. }
  1157. /*----------------------------------------------------------
  1158. Purpose: Intercept messages for menuband.
  1159. Menuband messages must be intercepted at two points:
  1160. 1) the main message pump (IsMenuMessage method)
  1161. 2) the wndproc of a window that has a menuband
  1162. (TranslateMenuMessage method)
  1163. The reason is sometimes a message will be received
  1164. by the wndproc which did not pass thru the apps main
  1165. message pump, but must be dealt with. There are other
  1166. messages which must be handled in the main message
  1167. pump, before TranslateMessage or DispatchMessage.
  1168. Returns: TRUE if the message was handled
  1169. */
  1170. HRESULT CShellBrowser2::v_MayTranslateAccelerator(MSG* pmsg)
  1171. {
  1172. HRESULT hres = S_FALSE;
  1173. // (scotth): for some unknown reason (aka ActiveX init), we are
  1174. // receiving a null hwnd with WM_DESTROY when the user scrolls a page
  1175. // that causes the ticker control to appear. Check the pmsg->hwnd here
  1176. // so we don't mistake a rogue WM_DESTROY msg for the real thing.
  1177. IMenuBand* pmb = _GetMenuBand(_pbbd->_hwnd == pmsg->hwnd && WM_DESTROY == pmsg->message);
  1178. if (pmb && _fActivated)
  1179. {
  1180. hres = pmb->IsMenuMessage(pmsg);
  1181. // don't need to release pmb
  1182. }
  1183. if (hres != S_OK)
  1184. {
  1185. // REARCHITECT cleanup -- move menuband stuff & this check to v_MayTranslateAccelerator's caller
  1186. if (WM_KEYFIRST <= pmsg->message && pmsg->message <= WM_KEYLAST)
  1187. {
  1188. hres = SUPERCLASS::v_MayTranslateAccelerator(pmsg);
  1189. if (hres != S_OK)
  1190. {
  1191. //
  1192. // Our SUPERCLASS didn't handle it.
  1193. //
  1194. if (_ShouldTranslateAccelerator(pmsg))
  1195. {
  1196. //
  1197. // Okay, it's one of ours. Let the toolbars have a crack at
  1198. // translating it.
  1199. //
  1200. for (UINT itb=0; (itb < (UINT)_GetToolbarCount()) && (hres != S_OK); itb++)
  1201. {
  1202. LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  1203. if (ptbi->fShow && (NULL != ptbi->ptbar))
  1204. {
  1205. IUnknown *pUnk;
  1206. if (SUCCEEDED(IUnknown_GetClientDB(ptbi->ptbar, &pUnk)))
  1207. {
  1208. ASSERT(NULL != pUnk);
  1209. hres = IUnknown_TranslateAcceleratorIO(pUnk, pmsg);
  1210. pUnk->Release();
  1211. }
  1212. }
  1213. }
  1214. }
  1215. }
  1216. }
  1217. }
  1218. return hres;
  1219. }
  1220. /*----------------------------------------------------------
  1221. Purpose: Take a whack at translating any messages.
  1222. CShellBrowser2 uses this to translate messages needed
  1223. for menu bands.
  1224. Returns: TRUE if we handled it
  1225. */
  1226. BOOL CShellBrowser2::_TranslateMenuMessage(HWND hwnd, UINT uMsg,
  1227. WPARAM * pwParam, LPARAM * plParam, LRESULT * plRet)
  1228. {
  1229. BOOL bRet = FALSE;
  1230. IMenuBand* pmb = _GetMenuBand(WM_DESTROY == uMsg);
  1231. if (pmb)
  1232. {
  1233. MSG msg;
  1234. msg.hwnd = hwnd;
  1235. msg.message = uMsg;
  1236. msg.wParam = *pwParam;
  1237. msg.lParam = *plParam;
  1238. bRet = (S_OK == pmb->TranslateMenuMessage(&msg, plRet));
  1239. *pwParam = msg.wParam;
  1240. *plParam = msg.lParam;
  1241. // don't need to release pmb
  1242. }
  1243. return bRet;
  1244. }
  1245. static TCHAR g_szWorkingOffline[MAX_BROWSER_WINDOW_TEMPLATE]=TEXT("");
  1246. static TCHAR g_szWorkingOfflineTip[MAX_BROWSER_WINDOW_TEMPLATE]=TEXT("");
  1247. static TCHAR g_szAppName[MAX_BROWSER_WINDOW_TEMPLATE]=TEXT("");
  1248. void InitTitleStrings()
  1249. {
  1250. if (!g_szWorkingOffline[0])
  1251. {
  1252. DWORD dwAppNameSize = sizeof(g_szAppName);
  1253. // Load this stuff only once per process for perf.
  1254. if (SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_MAIN, TEXT("Window Title"), NULL,
  1255. g_szAppName, &dwAppNameSize) != ERROR_SUCCESS)
  1256. MLLoadString(IDS_TITLE, g_szAppName, ARRAYSIZE(g_szAppName));
  1257. MLLoadString(IDS_WORKINGOFFLINETIP, g_szWorkingOfflineTip, ARRAYSIZE(g_szWorkingOfflineTip));
  1258. MLLoadString(IDS_WORKINGOFFLINE, g_szWorkingOffline, ARRAYSIZE(g_szWorkingOffline));
  1259. SHTruncateString(g_szWorkingOffline, ARRAYSIZE(g_szWorkingOffline) - (lstrlen(g_szAppName) + 4)); // give room for separator & EOL
  1260. }
  1261. }
  1262. void CShellBrowser2::_ReloadTitle()
  1263. {
  1264. g_szWorkingOffline[0] = 0;
  1265. _fTitleSet = FALSE;
  1266. _SetTitle(NULL);
  1267. }
  1268. HICON OfflineIcon()
  1269. {
  1270. static HICON s_hiconOffline = NULL;
  1271. if (!s_hiconOffline)
  1272. {
  1273. s_hiconOffline = (HICON)LoadImage(HinstShdocvw(), MAKEINTRESOURCE(IDI_OFFLINE), IMAGE_ICON,
  1274. GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0);
  1275. }
  1276. return s_hiconOffline;
  1277. }
  1278. void CShellBrowser2::_ReloadStatusbarIcon()
  1279. {
  1280. BOOL fIsOffline;
  1281. VARIANTARG var = {0};
  1282. var.vt = VT_I4;
  1283. if (_pbbd && SUCCEEDED(IUnknown_Exec(_pbbd->_psv, &CGID_Explorer, SBCMDID_GETPANE, PANE_OFFLINE, NULL, &var)) &&
  1284. (var.lVal != PANE_NONE))
  1285. {
  1286. if (_pbbd->_pidlCur && IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_USE_IE_OFFLINE_SUPPORT))
  1287. fIsOffline = SHIsGlobalOffline();
  1288. else
  1289. fIsOffline = FALSE;
  1290. SendControlMsg(FCW_STATUS, SB_SETICON, var.lVal, fIsOffline ? (LPARAM) OfflineIcon() : NULL, NULL);
  1291. if (fIsOffline)
  1292. {
  1293. InitTitleStrings();
  1294. SendControlMsg(FCW_STATUS, SB_SETTIPTEXT, var.lVal, (LPARAM)g_szWorkingOfflineTip, NULL);
  1295. }
  1296. }
  1297. }
  1298. void CShellBrowser2::_GetAppTitle(LPTSTR pszBuffer, DWORD cchSize)
  1299. {
  1300. BOOL fOffline = SHIsGlobalOffline();
  1301. pszBuffer[0] = 0;
  1302. InitTitleStrings();
  1303. if (fOffline)
  1304. {
  1305. wnsprintf(pszBuffer, cchSize, TEXT("%s - %s"), g_szAppName, g_szWorkingOffline);
  1306. }
  1307. else
  1308. {
  1309. #ifdef DEBUG
  1310. #ifdef UNICODE
  1311. #define DLLNAME TEXT("(BrowseUI UNI)")
  1312. #else
  1313. #define DLLNAME TEXT("(BrowseUI)")
  1314. #endif
  1315. #ifndef UNIX
  1316. wnsprintf(pszBuffer, cchSize, TEXT("%s - %s"), g_szAppName, DLLNAME);
  1317. #else
  1318. wnsprintf(pszBuffer, cchSize, TEXT("%s%s - %s"), g_szAppName, UNIX_TITLE_SUFFIX, DLLNAME);
  1319. #endif
  1320. #else
  1321. #ifndef UNIX
  1322. lstrcpyn(pszBuffer, g_szAppName, cchSize);
  1323. #else
  1324. wnsprintf(pszBuffer, cchSize, TEXT("%s%s"), g_szAppName, UNIX_TITLE_SUFFIX);
  1325. #endif
  1326. #endif
  1327. }
  1328. }
  1329. HWND CShellBrowser2::_GetCaptionWindow()
  1330. {
  1331. return _pbbd->_hwnd;
  1332. }
  1333. /*----------------------------------------------------------
  1334. Purpose: Gets the cached menu band. If the menu band hasn't
  1335. been acquired yet, attempt to get it. If bDestroy
  1336. is TRUE, the menu band will be released.
  1337. This does not AddRef because an AddRef/Release for each
  1338. message is not necessary -- as long as callers beware!
  1339. */
  1340. IMenuBand* CShellBrowser2::_GetMenuBand(BOOL bDestroy)
  1341. {
  1342. // Don't bother to create it if we're about to go away.
  1343. if (_fReceivedDestroy)
  1344. {
  1345. ASSERT(NULL == _pmb);
  1346. }
  1347. else if (bDestroy)
  1348. {
  1349. ATOMICRELEASE(_pmb);
  1350. // Make it so we don't re-create the _pmb after the WM_DESTROY
  1351. _fReceivedDestroy = TRUE;
  1352. }
  1353. // The menuband is created sometime after WM_CREATE is sent. Keep
  1354. // trying to get the menuband interface until we get it.
  1355. else if (!_pmb)
  1356. {
  1357. IBandSite *pbs;
  1358. if (SUCCEEDED(IUnknown_QueryService(_GetITBar(), IID_IBandSite, IID_PPV_ARG(IBandSite, &pbs))))
  1359. {
  1360. IDeskBand *pdbMenu;
  1361. pbs->QueryBand(CBIDX_MENU, &pdbMenu, NULL, NULL, 0);
  1362. if (pdbMenu)
  1363. {
  1364. pdbMenu->QueryInterface(IID_PPV_ARG(IMenuBand, &_pmb));
  1365. // Cache _pmb, so don't release it here
  1366. pdbMenu->Release();
  1367. }
  1368. pbs->Release();
  1369. }
  1370. }
  1371. return _pmb;
  1372. }
  1373. void CShellBrowser2::_SetMenu(HMENU hmenu)
  1374. {
  1375. // Create a top-level menuband given this hmenu. Add it to
  1376. // the bandsite.
  1377. if (!_pmb)
  1378. {
  1379. _GetMenuBand(FALSE); // this does not AddRef
  1380. if (!_pmb)
  1381. return;
  1382. }
  1383. IShellMenu* psm;
  1384. if (SUCCEEDED(_pmb->QueryInterface(IID_PPV_ARG(IShellMenu, &psm))))
  1385. {
  1386. HMENU hCurMenu = NULL;
  1387. psm->GetMenu(&hCurMenu, NULL, NULL);
  1388. // only call setmenu if we know it is not the menu we have currently or it is not one of our precached standards...
  1389. if ((hmenu != hCurMenu) ||
  1390. (hmenu != _hmenuFull && hmenu != _hmenuTemplate && hmenu != _hmenuPreMerged))
  1391. {
  1392. psm->SetMenu(hmenu, NULL, SMSET_DONTOWN | SMSET_MERGE);
  1393. }
  1394. psm->Release();
  1395. }
  1396. }
  1397. STDAPI SHFlushClipboard(void);
  1398. HRESULT CShellBrowser2::OnDestroy()
  1399. {
  1400. SUPERCLASS::OnDestroy();
  1401. SHFlushClipboard();
  1402. if (_uFSNotify)
  1403. SHChangeNotifyDeregister(_uFSNotify);
  1404. if (_fAutomation)
  1405. IECleanUpAutomationObject();
  1406. _DecrNetSessionCount();
  1407. return S_OK;
  1408. }
  1409. BOOL CShellBrowser2::_CreateToolbar()
  1410. {
  1411. return TRUE;
  1412. }
  1413. void CShellBrowser2::v_InitMembers()
  1414. {
  1415. _hmenuTemplate = _MenuTemplate(MENU_TEMPLATE, TRUE);
  1416. _hmenuFull = _MenuTemplate(MENU_FULL, TRUE);
  1417. _hmenuPreMerged = _MenuTemplate(MENU_PREMERGED, FALSE);
  1418. if (_fRunningInIexploreExe)
  1419. _hmenuCur = _hmenuPreMerged;
  1420. else
  1421. _hmenuCur = _hmenuTemplate;
  1422. }
  1423. // REVIEW UNDONE - Stuff in programs defaults to save positions ???
  1424. void CShellBrowser2::v_GetDefaultSettings(IETHREADPARAM *piei)
  1425. {
  1426. // set the flags
  1427. // Best fit window means get the window to size according to the
  1428. // contents of the view so that windows without existing settings
  1429. // come up looking OK.
  1430. piei->fs.fFlags = FWF_BESTFITWINDOW | g_dfs.fFlags;
  1431. if (!_fRunningInIexploreExe)
  1432. {
  1433. piei->wv.bStatusBar = g_dfs.bDefStatusBar;
  1434. }
  1435. else
  1436. {
  1437. piei->wv.bStatusBar = TRUE; //status bar is on by default in IE.
  1438. }
  1439. CABINETSTATE cs;
  1440. GetCabState(&cs);
  1441. if (cs.fSimpleDefault && cs.fNewWindowMode)
  1442. {
  1443. piei->wv.bStdButtons = piei->wv.bAddress = g_dfs.bDefToolBarMulti;
  1444. }
  1445. else
  1446. {
  1447. piei->wv.bStdButtons = piei->wv.bAddress = g_dfs.bDefToolBarSingle;
  1448. }
  1449. // For Win95 classic view, ITBar should be hidden by default.
  1450. SHELLSTATE ss = {0};
  1451. SHGetSetSettings(&ss, SSF_WIN95CLASSIC, FALSE);
  1452. // SHGetSetSettings checks SHRestricted(REST_CLASSICSHELL) for us
  1453. if (ss.fWin95Classic)
  1454. {
  1455. piei->fs.ViewMode = FVM_ICON;
  1456. piei->m_vidRestore = VID_LargeIcons;
  1457. piei->m_dwViewPriority = VIEW_PRIORITY_RESTRICTED; // use highest priority because of the restriction.
  1458. }
  1459. else
  1460. {
  1461. piei->fs.ViewMode = g_dfs.uDefViewMode;
  1462. piei->m_vidRestore = g_dfs.vid;
  1463. piei->m_dwViewPriority = g_dfs.dwViewPriority;
  1464. }
  1465. _dwRevCount = g_dfs.dwDefRevCount; // save this with the browser so we can save it out later
  1466. ASSERT(piei->wp.length == 0);
  1467. }
  1468. void CShellBrowser2::_DecrNetSessionCount()
  1469. {
  1470. TraceMsg(DM_SESSIONCOUNT, "_DecrNetSessionCount");
  1471. if (_fVisitedNet) {
  1472. SetQueryNetSessionCount(SESSION_DECREMENT);
  1473. _fVisitedNet = FALSE;
  1474. }
  1475. }
  1476. void CShellBrowser2::_IncrNetSessionCount()
  1477. {
  1478. TraceMsg(DM_SESSIONCOUNT, "_IncrNetSessionCount");
  1479. if (!_fVisitedNet) {
  1480. BOOL fDontDoDefaultCheck = (BOOLIFY(_fAutomation) || (!(BOOLIFY(_fAddDialUpRef))));
  1481. if (!SetQueryNetSessionCount(fDontDoDefaultCheck ? SESSION_INCREMENT_NODEFAULTBROWSERCHECK : SESSION_INCREMENT)) {
  1482. g_szWorkingOffline[0] = 0;
  1483. #ifdef NO_MARSHALLING
  1484. if (!_fOnIEThread)
  1485. SetQueryNetSessionCount(fDontDoDefaultCheck ? SESSION_INCREMENT_NODEFAULTBROWSERCHECK : SESSION_INCREMENT);
  1486. #endif
  1487. }
  1488. _fVisitedNet = TRUE;
  1489. }
  1490. }
  1491. // Initialize the Internet Toolbar. Create a dummy class to trap all the Messages that
  1492. // are sent to the old toolbar
  1493. BOOL CShellBrowser2::_PrepareInternetToolbar(IETHREADPARAM* piei)
  1494. {
  1495. HRESULT hr = S_OK;
  1496. if (!_GetITBar())
  1497. {
  1498. DWORD dwServerType = CLSCTX_INPROC_SERVER;
  1499. #ifdef FULL_DEBUG
  1500. if (!(g_dwPrototype & PF_NOBROWSEUI))
  1501. /// this will cause us to use OLE's co-create intance and not short circuit it.
  1502. dwServerType = CLSCTX_INPROC;
  1503. #endif
  1504. hr = CoCreateInstance(CLSID_InternetToolbar, NULL,
  1505. dwServerType,
  1506. IID_PPV_ARG(IDockingWindow, &_GetToolbarItem(ITB_ITBAR)->ptbar));
  1507. TraceMsg(DM_ITBAR|DM_STARTUP, "CSB::_PrepareInternetToolbar CoCreate(CLS_ITBAR) returned %x", hr);
  1508. if (SUCCEEDED(hr))
  1509. {
  1510. IUnknown_SetSite(_GetITBar(), SAFECAST(this, IShellBrowser*));
  1511. // Look at the type of folder using "pidlInitial" and
  1512. // see if we have a stream for this type.
  1513. // If so, open it and call IPersistStreamInit::Load(pstm);
  1514. // else, call IPersistStreamInit::InitNew(void);
  1515. IPersistStreamInit *pITbarPSI;
  1516. //Get the pointer to
  1517. if (SUCCEEDED(_GetITBar()->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &pITbarPSI))))
  1518. {
  1519. // The initial toolbar needs to be the Web toolbar
  1520. IUnknown_Exec(pITbarPSI, &CGID_PrivCITCommands, CITIDM_ONINTERNET, (_fUseIEToolbar ? CITE_INTERNET : CITE_SHELL), NULL, NULL);
  1521. IStream *pstm = _GetITBarStream(_fUseIEToolbar, STGM_READ);
  1522. if (pstm)
  1523. {
  1524. //Stream exists. Let's load it from there.
  1525. hr = pITbarPSI->Load(pstm);
  1526. pstm->Release();
  1527. }
  1528. else
  1529. {
  1530. //No stream already exists. Initialize from the old location!
  1531. pITbarPSI->InitNew();
  1532. }
  1533. pITbarPSI->Release();
  1534. }
  1535. SUPERCLASS::v_ShowHideChildWindows(TRUE);
  1536. if (!_hwndDummyTB)
  1537. {
  1538. _hwndDummyTB = SHCreateWorkerWindow(DummyTBWndProc, _pbbd->_hwnd, 0, WS_CHILD, (HMENU)9999, this);
  1539. }
  1540. }
  1541. }
  1542. if (SUCCEEDED(hr) && !_pxtb)
  1543. hr = QueryService(SID_SExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &_pxtb));
  1544. return SUCCEEDED(hr);
  1545. }
  1546. BOOL LoadWindowPlacement(WINDOWPLACEMENT * pwndpl)
  1547. {
  1548. BOOL fRetVal = FALSE;
  1549. if (pwndpl)
  1550. {
  1551. DWORD dwSize = sizeof(WINDOWPLACEMENT);
  1552. if (SHGetValueGoodBoot(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  1553. TEXT("Window_Placement"), NULL, (PBYTE)pwndpl, &dwSize) == ERROR_SUCCESS)
  1554. {
  1555. fRetVal = TRUE;
  1556. // Is the default value invalid?
  1557. if ((pwndpl->rcNormalPosition.left >= pwndpl->rcNormalPosition.right) ||
  1558. (pwndpl->rcNormalPosition.top >= pwndpl->rcNormalPosition.bottom))
  1559. {
  1560. // Yes, so fix it. We worry about the normal size being zero or negative.
  1561. // This fixes the munged case.
  1562. ASSERT(0); // the stream is corrupted.
  1563. fRetVal = FALSE;
  1564. }
  1565. }
  1566. }
  1567. return fRetVal;
  1568. }
  1569. BOOL StoreWindowPlacement(WINDOWPLACEMENT *pwndpl)
  1570. {
  1571. if (pwndpl)
  1572. {
  1573. // Don't store us as minimized - that isn't what the user intended.
  1574. // I.E. right click on minimized IE 3.0 in tray, pick close. Since
  1575. // we are minmized in that scenario we want to force normal
  1576. // instead so we at least show up.
  1577. if (pwndpl->showCmd == SW_SHOWMINIMIZED ||
  1578. pwndpl->showCmd == SW_MINIMIZE)
  1579. pwndpl->showCmd = SW_SHOWNORMAL;
  1580. // Are about to save a corrupted window size?
  1581. if ((pwndpl->rcNormalPosition.left >= pwndpl->rcNormalPosition.right) ||
  1582. (pwndpl->rcNormalPosition.top >= pwndpl->rcNormalPosition.bottom))
  1583. {
  1584. // Yes, so fix it.
  1585. ASSERT(0); // the size is invalid or corrupted.
  1586. }
  1587. else
  1588. {
  1589. return SHSetValue(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  1590. TEXT("Window_Placement"), REG_BINARY, (const BYTE *)pwndpl, sizeof(WINDOWPLACEMENT)) == ERROR_SUCCESS;
  1591. }
  1592. }
  1593. return FALSE;
  1594. }
  1595. BOOL StorePlacementOfWindow(HWND hwnd)
  1596. {
  1597. WINDOWPLACEMENT wndpl;
  1598. wndpl.length = sizeof(WINDOWPLACEMENT);
  1599. if (GetWindowPlacement(hwnd, &wndpl))
  1600. {
  1601. return StoreWindowPlacement(&wndpl);
  1602. }
  1603. return FALSE;
  1604. }
  1605. // forward declaration
  1606. void EnsureWindowIsCompletelyOnScreen (RECT *prc);
  1607. // The rect will be offset slightly below and to the right of its current position.
  1608. // If this would cause it to move partly off the nearest monitor, then it is
  1609. // instead placed at the top left of the same monitor.
  1610. void CascadeWindowRect(RECT *pRect)
  1611. {
  1612. int delta = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYSIZEFRAME) - 1;
  1613. OffsetRect(pRect, delta, delta);
  1614. // test if the new rect will end up getting moved later on
  1615. RECT rc = *pRect;
  1616. EnsureWindowIsCompletelyOnScreen(&rc);
  1617. if (!EqualRect(pRect, &rc))
  1618. {
  1619. // rc had to be moved, so we'll restart the cascade using the best monitor
  1620. MONITORINFO minfo;
  1621. minfo.cbSize = sizeof(minfo);
  1622. if (GetMonitorInfo(MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST), &minfo))
  1623. {
  1624. // And we do mean rcMonitor, not rcWork. For example, if the taskbar is
  1625. // at the top, then using rcMonitor with top-left = (0,0) will place it on
  1626. // the edge of the taskbar. Using rcWork with top-left = (0,y) will put
  1627. // it y pixels below the taskbar's bottom edge, which is wrong.
  1628. if (rc.bottom < pRect->bottom && rc.left == pRect->left)
  1629. {
  1630. // Too tall to cascade further down, but we can keep the X and just
  1631. // reset the Y. This fixes the bug of having a tall windows piling up
  1632. // on the top left corner -- instead they will be offset to the right
  1633. OffsetRect(pRect, 0, minfo.rcMonitor.top - pRect->top);
  1634. }
  1635. else
  1636. {
  1637. // we've really run out of room, so restart cascade at top left
  1638. OffsetRect(pRect,
  1639. minfo.rcMonitor.left - pRect->left,
  1640. minfo.rcMonitor.top - pRect->top);
  1641. }
  1642. }
  1643. }
  1644. }
  1645. void CalcWindowPlacement(BOOL fInternetStart, HWND hwnd, IETHREADPARAM *piei, WINDOWPLACEMENT *pwndpl)
  1646. {
  1647. static RECT s_rcExplorer = {-1, -1, -1, -1};
  1648. // We don't load the window placement for shell windows
  1649. if (!fInternetStart || LoadWindowPlacement(pwndpl))
  1650. {
  1651. // If the show command specifies a normal show or default (i.e., our initial
  1652. // display setting is not being overridden by the command line or
  1653. // CreateProcess setting) then use the saved window state show command.
  1654. // Otherwise, use the show command passed in to us.
  1655. if (fInternetStart && ((piei->nCmdShow == SW_SHOWNORMAL) || (piei->nCmdShow == SW_SHOWDEFAULT)))
  1656. piei->nCmdShow = pwndpl->showCmd;
  1657. // Cascade if there is window of the same kind directly under us.
  1658. HWND hwndT = NULL;
  1659. ATOM atomClass = (ATOM) GetClassWord(hwnd, GCW_ATOM);
  1660. while (hwndT = FindWindowEx(NULL, hwndT, (LPCTSTR) atomClass, NULL))
  1661. {
  1662. // Don't use GetWindowRect here because we load window placements
  1663. // from the registry and they use the workspace coordinate system
  1664. WINDOWPLACEMENT wp;
  1665. wp.length = sizeof(wp);
  1666. GetWindowPlacement(hwndT, &wp);
  1667. if (wp.rcNormalPosition.left == pwndpl->rcNormalPosition.left &&
  1668. wp.rcNormalPosition.top == pwndpl->rcNormalPosition.top)
  1669. {
  1670. if ((piei->uFlags & COF_EXPLORE) &&
  1671. (s_rcExplorer.left != -1) && (s_rcExplorer.top != -1))
  1672. {
  1673. // An explorer window is trying to appear on top of
  1674. // another one. We'll use our stored rect's top-left
  1675. // to make it cascade like IE windows.
  1676. OffsetRect(&pwndpl->rcNormalPosition,
  1677. s_rcExplorer.left - pwndpl->rcNormalPosition.left,
  1678. s_rcExplorer.top - pwndpl->rcNormalPosition.top);
  1679. }
  1680. // do the cascade for all windows
  1681. CascadeWindowRect(&pwndpl->rcNormalPosition);
  1682. }
  1683. }
  1684. // for IE and explorer, save the current location
  1685. if (piei->uFlags & COF_EXPLORE)
  1686. s_rcExplorer = pwndpl->rcNormalPosition;
  1687. else if (fInternetStart)
  1688. StoreWindowPlacement(pwndpl);
  1689. }
  1690. else
  1691. {
  1692. pwndpl->length = 0;
  1693. }
  1694. }
  1695. class CRGN
  1696. {
  1697. public:
  1698. CRGN (void) { mRgn = CreateRectRgn(0, 0, 0, 0); }
  1699. CRGN (const RECT& rc) { mRgn = CreateRectRgnIndirect(&rc); }
  1700. ~CRGN (void) { if (mRgn) TBOOL(DeleteObject(mRgn)); }
  1701. operator HRGN (void) const { return(mRgn); }
  1702. void SetRegion (const RECT& rc) { TBOOL(SetRectRgn(mRgn, rc.left, rc.top, rc.right, rc.bottom)); }
  1703. private:
  1704. HRGN mRgn;
  1705. };
  1706. BOOL CALLBACK GetDesktopRegionEnumProc (HMONITOR hMonitor, HDC hdcMonitor, RECT* prc, LPARAM lpUserData)
  1707. {
  1708. MONITORINFO monitorInfo;
  1709. monitorInfo.cbSize = sizeof(monitorInfo);
  1710. if (GetMonitorInfo(hMonitor, &monitorInfo) != 0)
  1711. {
  1712. HRGN hRgnDesktop;
  1713. CRGN rgnMonitorWork(monitorInfo.rcWork);
  1714. hRgnDesktop = *reinterpret_cast<CRGN*>(lpUserData);
  1715. if ((HRGN)rgnMonitorWork)
  1716. TINT(CombineRgn(hRgnDesktop, hRgnDesktop, rgnMonitorWork, RGN_OR));
  1717. }
  1718. return(TRUE);
  1719. }
  1720. void EnsureWindowIsCompletelyOnScreen (RECT *prc)
  1721. // 99/04/13 #321962 vtan: This function exists because user32 only determines
  1722. // whether ANY part of the window is visible on the screen. It's possible to
  1723. // place a window without an accessible title. Pretty useless when using the
  1724. // mouse and forces the user to use the VERY un-intuitive alt-space.
  1725. {
  1726. HMONITOR hMonitor;
  1727. MONITORINFO monitorInfo;
  1728. // First find the monitor that the window resides on using GDI.
  1729. hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
  1730. ASSERT(hMonitor); // get vtan - GDI should always return a result
  1731. monitorInfo.cbSize = sizeof(monitorInfo);
  1732. if (GetMonitorInfo(hMonitor, &monitorInfo) != 0)
  1733. {
  1734. LONG lOffsetX, lOffsetY;
  1735. RECT *prcWorkArea, rcIntersect;
  1736. CRGN rgnDesktop, rgnIntersect, rgnWindow;
  1737. // Because the WINDOWPLACEMENT rcNormalPosition field is in WORKAREA
  1738. // co-ordinates this causes a displacement problem. If the taskbar is
  1739. // at the left or top of the primary monitor the RECT passed even though
  1740. // at (0, 0) may be at (100, 0) on the primary monitor in GDI co-ordinates
  1741. // and GetMonitorInfo() will return a MONITORINFO in GDI co-ordinates.
  1742. // The safest generic algorithm is to offset the WORKAREA RECT into GDI
  1743. // co-ordinates and apply the algorithm in that system. Then offset the
  1744. // WORKAREA RECT back into WORKAREA co-ordinates.
  1745. prcWorkArea = &monitorInfo.rcWork;
  1746. if (EqualRect(&monitorInfo.rcMonitor, &monitorInfo.rcWork) == 0)
  1747. {
  1748. // Taskbar is on this monitor - offset required.
  1749. lOffsetX = prcWorkArea->left - monitorInfo.rcMonitor.left;
  1750. lOffsetY = prcWorkArea->top - monitorInfo.rcMonitor.top;
  1751. }
  1752. else
  1753. {
  1754. // Taskbar is NOT on this monitor - no offset required.
  1755. lOffsetX = lOffsetY = 0;
  1756. }
  1757. TBOOL(OffsetRect(prc, lOffsetX, lOffsetY));
  1758. // WORKAREA RECT is in GDI co-ordinates. Apply the algorithm.
  1759. // Check to see if this window already fits the current visible screen
  1760. // area. This is a direct region comparison.
  1761. // This enumeration may cause a performance problem. In the event that
  1762. // a cheap and simple solution is required it would be best to do a
  1763. // RECT intersection with the monitor and the window before resorting
  1764. // to the more expensive region comparison. Get vtan if necessary.
  1765. TBOOL(EnumDisplayMonitors(NULL, NULL, GetDesktopRegionEnumProc, reinterpret_cast<LPARAM>(&rgnDesktop)));
  1766. rgnWindow.SetRegion(*prc);
  1767. TINT(CombineRgn(rgnIntersect, rgnDesktop, rgnWindow, RGN_AND));
  1768. if (EqualRgn(rgnIntersect, rgnWindow) == 0)
  1769. {
  1770. LONG lDeltaX, lDeltaY;
  1771. // Some part of the window is not within the visible desktop region
  1772. // Move it until it all fits. Size it if it's too big.
  1773. lDeltaX = lDeltaY = 0;
  1774. if (prc->left < prcWorkArea->left)
  1775. lDeltaX = prcWorkArea->left - prc->left;
  1776. if (prc->top < prcWorkArea->top)
  1777. lDeltaY = prcWorkArea->top - prc->top;
  1778. if (prc->right > prcWorkArea->right)
  1779. lDeltaX = prcWorkArea->right - prc->right;
  1780. if (prc->bottom > prcWorkArea->bottom)
  1781. lDeltaY = prcWorkArea->bottom - prc->bottom;
  1782. TBOOL(OffsetRect(prc, lDeltaX, lDeltaY));
  1783. TBOOL(IntersectRect(&rcIntersect, prc, prcWorkArea));
  1784. TBOOL(CopyRect(prc, &rcIntersect));
  1785. }
  1786. // Put WORKAREA RECT back into WORKAREA co-ordinates.
  1787. TBOOL(OffsetRect(prc, -lOffsetX, -lOffsetY));
  1788. }
  1789. }
  1790. LPITEMIDLIST MyDocsIDList(void);
  1791. #define FRAME_OPTIONS_TO_TEST (BFO_ADD_IE_TOCAPTIONBAR | BFO_USE_DIALUP_REF | BFO_USE_IE_TOOLBAR | \
  1792. BFO_BROWSER_PERSIST_SETTINGS | BFO_USE_IE_OFFLINE_SUPPORT)
  1793. HRESULT CShellBrowser2::_SetBrowserFrameOptions(LPCITEMIDLIST pidl)
  1794. {
  1795. BROWSERFRAMEOPTIONS dwOptions = FRAME_OPTIONS_TO_TEST;
  1796. if (FAILED(GetBrowserFrameOptionsPidl(pidl, dwOptions, &dwOptions)))
  1797. {
  1798. // GetBrowserFrameOptionsPidl() will fail if pidl is NULL.
  1799. // in that case we want to use _fInternetStart to determine
  1800. // if we want these bits set or not.
  1801. if (_fInternetStart)
  1802. dwOptions = FRAME_OPTIONS_TO_TEST; // Assume None.
  1803. else
  1804. dwOptions = BFO_NONE; // Assume None.
  1805. }
  1806. _fAppendIEToCaptionBar = BOOLIFY(dwOptions & BFO_ADD_IE_TOCAPTIONBAR);
  1807. _fAddDialUpRef = BOOLIFY(dwOptions & BFO_USE_DIALUP_REF);
  1808. _fUseIEToolbar = BOOLIFY(dwOptions & BFO_USE_IE_TOOLBAR);
  1809. _fEnableOfflineFeature = BOOLIFY(dwOptions & BFO_USE_IE_OFFLINE_SUPPORT);
  1810. _fUseIEPersistence = BOOLIFY(dwOptions & BFO_BROWSER_PERSIST_SETTINGS);
  1811. return S_OK;
  1812. }
  1813. HRESULT CShellBrowser2::_ReplaceCmdLine(LPTSTR pszCmdLine, DWORD cchCmdLine)
  1814. {
  1815. TCHAR szVeryFirstPage[MAX_URL_STRING];
  1816. HRESULT hr = _GetStdLocation(szVeryFirstPage, ARRAYSIZE(szVeryFirstPage), DVIDM_GOFIRSTHOME);
  1817. TraceMsg(DM_NAV, "CSB::_ReplaceCmdLine _GetStdLocation(DVIDM_GOFIRSTHOME) returned %x", hr);
  1818. if (SUCCEEDED(hr))
  1819. {
  1820. StrCpyN(pszCmdLine, szVeryFirstPage, cchCmdLine);
  1821. TraceMsg(DM_NAV, "CSB::_ReplaceCmdLine _GetStdLocation(DVIDM_GOFIRSTHOME) returned %s", pszCmdLine);
  1822. }
  1823. return hr;
  1824. }
  1825. HRESULT CShellBrowser2::OnCreate(LPCREATESTRUCT pcs)
  1826. {
  1827. HRESULT hres = S_OK;
  1828. IETHREADPARAM* piei = (IETHREADPARAM*)pcs->lpCreateParams;
  1829. BOOL fUseHomePage = (piei->piehs ? FALSE : TRUE); // intentionally reversered
  1830. DWORD dwExStyle = IS_BIDI_LOCALIZED_SYSTEM() ? dwExStyleRTLMirrorWnd : 0L;
  1831. _clsidThis = (piei->uFlags & COF_IEXPLORE) ?
  1832. CLSID_InternetExplorer : CLSID_ShellBrowserWindow;
  1833. #ifdef NO_MARSHALLING
  1834. if (!piei->fOnIEThread)
  1835. _fOnIEThread = FALSE;
  1836. #endif
  1837. //
  1838. // Make this thread foreground here so that any UI from
  1839. // USERCLASS::OnCreate will be on the top of other windows.
  1840. // We used to call this in _AfterWindowCreate, but it is
  1841. // too late for dialog boxes we popup while processing WM_CREATE
  1842. // message.
  1843. //
  1844. // Note that we do call SetForegroundWindow even if this window
  1845. // is not created as a result of CoCreateInstance. The automation
  1846. // client is supposed to make it visible and bring it to the
  1847. // foreground if it needs to.
  1848. //
  1849. if (!piei->piehs)
  1850. {
  1851. // On UNIX it is not common to force the window to the top of Z-order.
  1852. #ifndef UNIX
  1853. SetForegroundWindow(_pbbd->_hwnd);
  1854. #endif
  1855. }
  1856. SUPERCLASS::OnCreate(pcs);
  1857. EnsureWebViewRegSettings();
  1858. ASSERT(piei);
  1859. _fRunningInIexploreExe = BOOLIFY(piei->uFlags & COF_IEXPLORE);
  1860. v_InitMembers();
  1861. CString strCmdLine;
  1862. if (piei->pszCmdLine)
  1863. {
  1864. strCmdLine = piei->pszCmdLine;
  1865. }
  1866. else
  1867. {
  1868. strCmdLine.Empty();
  1869. }
  1870. if (piei->fCheckFirstOpen)
  1871. {
  1872. ASSERT(!ILIsRooted(piei->pidl));
  1873. //
  1874. // We don't want to go to the very first page, if this window
  1875. // is created as the result of CoCreateInstnace.
  1876. //
  1877. if (!piei->piehs && (piei->uFlags & COF_IEXPLORE))
  1878. {
  1879. LPTSTR pstrCmdLine = strCmdLine.GetBuffer( MAX_URL_STRING );
  1880. if ( strCmdLine.GetAllocLength() < MAX_URL_STRING )
  1881. {
  1882. TraceMsg( TF_WARNING, "CShellBrowser2::OnCreate() - strCmdLine Allocation Failed!" );
  1883. hres = E_OUTOFMEMORY;
  1884. }
  1885. else
  1886. {
  1887. if (SUCCEEDED(_ReplaceCmdLine( pstrCmdLine, MAX_URL_STRING )))
  1888. {
  1889. _fInternetStart = TRUE;
  1890. }
  1891. // Let CString class own the buffer again.
  1892. strCmdLine.ReleaseBuffer();
  1893. }
  1894. }
  1895. piei->fCheckFirstOpen = FALSE;
  1896. }
  1897. // NOTE: These flags and corresponding ones in IETHREADPARAM are set to FALSE at creation,
  1898. // ParseCommandLine() is the only place where they are set. -- dli
  1899. _fNoLocalFileWarning = piei->fNoLocalFileWarning;
  1900. _fKioskMode = piei->fFullScreen;
  1901. if (piei->fNoDragDrop)
  1902. SetFlags(0, BSF_REGISTERASDROPTARGET);
  1903. _fAutomation = piei->fAutomation;
  1904. // If someone deliberately tell us not to use home page.
  1905. if (piei->fDontUseHomePage)
  1906. {
  1907. fUseHomePage = 0;
  1908. // only the IE path sets this flag.
  1909. // this is used by iexplorer.exe -nohome
  1910. // and by ie dde to start out blank then navigate next
  1911. _fInternetStart = TRUE;
  1912. }
  1913. if (piei->ptl)
  1914. InitializeTravelLog(piei->ptl, piei->dwBrowserIndex);
  1915. LPITEMIDLIST pidl = NULL;
  1916. BOOL fCloning = FALSE;
  1917. if ((( ! strCmdLine.IsEmpty() ) || piei->pidl) && !_fAutomation)
  1918. {
  1919. if (piei->pidl)
  1920. {
  1921. pidl = ILClone(piei->pidl);
  1922. }
  1923. else
  1924. {
  1925. int cchCmdLine = strCmdLine.GetLength();
  1926. LPTSTR pstrCmdLine = strCmdLine.GetBuffer( MAX_URL_STRING );
  1927. HRESULT hresWrap;
  1928. if ( strCmdLine.GetAllocLength() < MAX_URL_STRING )
  1929. {
  1930. TraceMsg( TF_WARNING, "CShellBrowser2::OnCreate() - strCmdLine Allocation Failed!" );
  1931. hresWrap = E_OUTOFMEMORY;
  1932. }
  1933. else
  1934. {
  1935. hresWrap = WrapSpecialUrlFlat( pstrCmdLine, cchCmdLine + 1 );
  1936. // Let CString class own the buffer again.
  1937. strCmdLine.ReleaseBuffer();
  1938. }
  1939. if ( SUCCEEDED( hresWrap ) )
  1940. {
  1941. HRESULT hresT = _ConvertPathToPidl(this, _pbbd->_hwnd, strCmdLine, &pidl);
  1942. TraceMsg(DM_STARTUP, "CSB::OnCreate ConvertPathToPidl(strCmdLine) returns %x", hresT);
  1943. }
  1944. }
  1945. }
  1946. if (pidl)
  1947. {
  1948. fUseHomePage = FALSE;
  1949. }
  1950. else if (_pbbd->_ptl && SUCCEEDED(_pbbd->_ptl->GetTravelEntry((IShellBrowser *)this, 0, NULL)))
  1951. {
  1952. pidl = ILClone(&s_idlNULL);
  1953. fCloning = TRUE;
  1954. fUseHomePage = FALSE;
  1955. // NOTE: if we ever hit this code when opening a window at non-web address
  1956. // we'll need to be more selective about setting this flag
  1957. _fInternetStart = TRUE;
  1958. }
  1959. else if (fUseHomePage)
  1960. {
  1961. // if we're not top level, assume we're going to be told
  1962. // where to browse
  1963. CString strPath;
  1964. LPTSTR pstrPath = strPath.GetBuffer( MAX_URL_STRING );
  1965. if ( strPath.GetAllocLength() < MAX_URL_STRING )
  1966. {
  1967. TraceMsg( TF_WARNING, "CShellBrowser2::OnCreate() - strPath Allocation Failed!" );
  1968. hres = E_OUTOFMEMORY;
  1969. }
  1970. else
  1971. {
  1972. if (piei->uFlags & COF_IEXPLORE)
  1973. {
  1974. hres = _GetStdLocation( pstrPath, MAX_URL_STRING, DVIDM_GOHOME );
  1975. }
  1976. else
  1977. {
  1978. // we need to get the default location for an explorer window
  1979. // which classically has been the root drive of the windows install
  1980. GetModuleFileName( GetModuleHandle(NULL), pstrPath, MAX_URL_STRING );
  1981. PathStripToRoot(pstrPath);
  1982. }
  1983. // Let CString class own the buffer again.
  1984. strPath.ReleaseBuffer();
  1985. }
  1986. if (SUCCEEDED(hres))
  1987. {
  1988. IECreateFromPath( strPath, &pidl );
  1989. }
  1990. }
  1991. // do this here after we've found what pidl we're looking at
  1992. // but do it before the CalcWindowPlacement because
  1993. // it might need to override
  1994. _LoadBrowserWindowSettings(piei, pidl);
  1995. // call this before PrepareInternetToolbar because it needs to know
  1996. // _fInternetStart to know which toolbar config to use
  1997. if (!_fInternetStart)
  1998. {
  1999. if (pidl)
  2000. {
  2001. if (fUseHomePage || IsURLChild(pidl, TRUE))
  2002. {
  2003. _fInternetStart = TRUE;
  2004. }
  2005. else
  2006. {
  2007. DWORD dwAttrib = SFGAO_FOLDER | SFGAO_BROWSABLE;
  2008. // if it's on the file system, we'll still consider it to be an
  2009. // internet folder if it's a docobj (including .htm file)
  2010. IEGetAttributesOf(pidl, &dwAttrib);
  2011. if ((dwAttrib & (SFGAO_FOLDER | SFGAO_BROWSABLE)) == SFGAO_BROWSABLE)
  2012. _fInternetStart = TRUE;
  2013. }
  2014. }
  2015. else if (!(piei->uFlags & COF_SHELLFOLDERWINDOW))
  2016. {
  2017. _fInternetStart = TRUE;
  2018. }
  2019. }
  2020. _SetBrowserFrameOptions(pidl);
  2021. CalcWindowPlacement(_fUseIEPersistence, _pbbd->_hwnd, piei, &piei->wp);
  2022. if (!_PrepareInternetToolbar(piei))
  2023. return E_FAIL;
  2024. _CreateToolbar();
  2025. // We must create _hwndStatus before navigating, because the
  2026. // first navigate will go synchronous and the shell sends
  2027. // status messages during that time. If the status window hasn't
  2028. // been created, they drop on the floor.
  2029. //
  2030. _hwndStatus = CreateWindowEx(dwExStyle, STATUSCLASSNAME, NULL,
  2031. WS_CHILD | SBARS_SIZEGRIP | WS_CLIPSIBLINGS | WS_VISIBLE | SBT_TOOLTIPS
  2032. & ~(WS_BORDER | CCS_NODIVIDER),
  2033. -100, -100, 10, 10, _pbbd->_hwnd, (HMENU)FCIDM_STATUS, HINST_THISDLL, NULL);
  2034. #ifdef DEBUG
  2035. if (g_dwPrototype & 0x00000004)
  2036. {
  2037. HRESULT hres = E_FAIL;
  2038. if (_SaveToolbars(NULL) == S_OK)
  2039. {
  2040. // _LoadBrowserWindowSettings did a v_GetViewStream/ _LoadToolbars
  2041. // if it succeeded (i.e. if we have > 0 toolbars), we're done
  2042. // actually, even 0 toolbars could mean success, oh well...
  2043. hres = S_OK;
  2044. }
  2045. ASSERT(SUCCEEDED(hres));
  2046. }
  2047. #endif
  2048. // REARCHITECT: do this early to let these objects see the first
  2049. // navigate. but this causes a deadlock if the objects require
  2050. // marshalling back to the main thread.
  2051. _LoadBrowserHelperObjects();
  2052. #ifdef UNIX
  2053. {
  2054. BOOL bReadOnly = FALSE;
  2055. static s_bMsgShown = FALSE;
  2056. if (!s_bMsgShown)
  2057. {
  2058. s_bMsgShown = TRUE;
  2059. unixGetWininetCacheLockStatus (&bReadOnly, NULL);
  2060. if (bReadOnly)
  2061. {
  2062. _SetBrowserBarState(-1, &CLSID_MsgBand, 1);
  2063. }
  2064. }
  2065. }
  2066. #endif
  2067. BOOL fDontIncrementSessionCounter = FALSE;
  2068. if (pidl) // paranoia
  2069. {
  2070. if (fCloning)
  2071. {
  2072. ASSERT(_pbbd->_ptl);
  2073. hres = _pbbd->_ptl->Travel((IShellBrowser*)this, 0);
  2074. }
  2075. else
  2076. #ifndef UNIX
  2077. {
  2078. if (!_fAddDialUpRef)
  2079. fDontIncrementSessionCounter = TRUE;
  2080. hres = _NavigateToPidl(pidl, 0, 0);
  2081. if (FAILED(hres))
  2082. {
  2083. fDontIncrementSessionCounter = TRUE; // We're going to windows\blank.htm or fail ...
  2084. if (_fAddDialUpRef)
  2085. {
  2086. // if we failed, but this was a URL child,
  2087. // we should still activate and go to blank.htm
  2088. hres = S_FALSE;
  2089. }
  2090. else if (piei->uFlags & COF_EXPLORE)
  2091. {
  2092. // If an explorer browser, fall back to the desktop.
  2093. //
  2094. // The reason is that we want Start->Windows Explorer to
  2095. // bring up a browser even if MyDocs is inaccessible;
  2096. // however we don't want Start->Run "<path>" to bring up
  2097. // a browser if <path> is inaccessible.
  2098. //
  2099. BOOL fNavDesktop = (hres != HRESULT_FROM_WIN32(ERROR_CANCELLED));
  2100. if (!fNavDesktop)
  2101. {
  2102. LPITEMIDLIST pidlDocs = MyDocsIDList();
  2103. if (pidlDocs)
  2104. {
  2105. fNavDesktop = ILIsEqual(pidl, pidlDocs);
  2106. ILFree(pidlDocs);
  2107. }
  2108. }
  2109. if (fNavDesktop)
  2110. hres = _NavigateToPidl(&s_idlNULL, 0, 0);
  2111. }
  2112. }
  2113. }
  2114. #else
  2115. {
  2116. hres = S_FALSE;
  2117. if (pidl)
  2118. {
  2119. LPITEMIDLIST pidlCopy = ILClone(pidl);
  2120. PostMessage(_pbbd->_hwnd, WM_COMMAND, FCIDM_STARTPAGE, (LPARAM)pidlCopy);
  2121. }
  2122. }
  2123. #endif
  2124. ILFree(pidl);
  2125. }
  2126. if (_fAddDialUpRef && !fDontIncrementSessionCounter)
  2127. _IncrNetSessionCount();
  2128. if (IsOS(OS_WHISTLERORGREATER))
  2129. {
  2130. if (piei->wp.length == 0)
  2131. {
  2132. HMONITOR hmon = (piei->uFlags & COF_HASHMONITOR) ? reinterpret_cast<HMONITOR>(piei->pidlRoot) : NULL;
  2133. _GetDefaultWindowPlacement(_pbbd->_hwnd, hmon, &piei->wp);
  2134. }
  2135. }
  2136. else
  2137. {
  2138. // 99/04/07 #141049 vtan: If hMonitor was given then use this as the basis
  2139. // for placement of a new window. Move the window position from the primary
  2140. // monitor (where user32 placed it) to the specified HMONITOR. If this
  2141. // results in a placement off screen then SetWindowPlacement() will fix
  2142. // this up for us.
  2143. if ((piei->wp.length == 0) && ((piei->uFlags & COF_HASHMONITOR) != 0) && (piei->pidlRoot != NULL))
  2144. {
  2145. MONITORINFO monitorInfo;
  2146. piei->wp.length = sizeof(piei->wp);
  2147. TBOOL(GetWindowPlacement(_pbbd->_hwnd, &piei->wp));
  2148. monitorInfo.cbSize = sizeof(monitorInfo);
  2149. TBOOL(GetMonitorInfo(reinterpret_cast<HMONITOR>(piei->pidlRoot), &monitorInfo));
  2150. TBOOL(OffsetRect(&piei->wp.rcNormalPosition, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top));
  2151. }
  2152. }
  2153. if (piei->wp.length == sizeof(piei->wp))
  2154. {
  2155. BOOL fSetWindowPosition = TRUE;
  2156. // we do a SetWindowPlacement first with SW_HIDE
  2157. // to get the size right firsth
  2158. // then we really show it.
  2159. if ((piei->nCmdShow == SW_SHOWNORMAL) ||
  2160. (piei->nCmdShow == SW_SHOWDEFAULT))
  2161. piei->nCmdShow = piei->wp.showCmd;
  2162. piei->wp.showCmd = SW_HIDE;
  2163. HWND hwndTray = GetTrayWindow();
  2164. if (hwndTray)
  2165. {
  2166. RECT rc;
  2167. if (GetWindowRect(hwndTray, &rc) && ISRECT_EQUAL(rc, piei->wp.rcNormalPosition))
  2168. {
  2169. // In this case, we want to ignore the position because
  2170. // it's equal to the tray. (Came from Win95/OSR2 days)
  2171. fSetWindowPosition = FALSE;
  2172. }
  2173. }
  2174. if (fSetWindowPosition)
  2175. {
  2176. EnsureWindowIsCompletelyOnScreen(&piei->wp.rcNormalPosition);
  2177. SetWindowPlacement(_pbbd->_hwnd, &piei->wp);
  2178. }
  2179. }
  2180. v_ShowHideChildWindows(TRUE);
  2181. if (piei->piehs)
  2182. {
  2183. // this thread was created to be the browser automation object
  2184. // turn this on to prove CoCreateInstance does not cause a dead lock.
  2185. #ifdef MAX_DEBUG
  2186. SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
  2187. Sleep(5);
  2188. SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, 0);
  2189. #endif
  2190. //
  2191. // WARNING: Note that we must SetEvent even though we can't return
  2192. // the marshalled automation object for some reason. Not signaling
  2193. // the event will block the caller thread for a long time.
  2194. //
  2195. if (SUCCEEDED(hres))
  2196. {
  2197. hres = CoMarshalInterface(piei->piehs->GetStream(), IID_IUnknown, _pbbd->_pautoWB2,
  2198. MSHCTX_INPROC, 0, MSHLFLAGS_NORMAL);
  2199. }
  2200. piei->piehs->PutHresult(hres);
  2201. SetEvent(piei->piehs->GetHevent());
  2202. }
  2203. if (g_tidParking == GetCurrentThreadId())
  2204. {
  2205. IEOnFirstBrowserCreation(_fAutomation ? _pbbd->_pautoWB2 : NULL);
  2206. }
  2207. SHGetThreadRef(&_punkMsgLoop); // pick up the ref to this thread
  2208. TraceMsg(DM_STARTUP, "CSB::OnCreate returning hres=%x", hres);
  2209. if (FAILED(hres))
  2210. {
  2211. _SetMenu(NULL);
  2212. return E_FAIL;
  2213. }
  2214. return S_OK;
  2215. }
  2216. void CShellBrowser2::_GetDefaultWindowPlacement(HWND hwnd, HMONITOR hmon, WINDOWPLACEMENT* pwp)
  2217. {
  2218. ASSERT(IsOS(OS_WHISTLERORGREATER)); // don't use on legacy systems.
  2219. // We tailor our Web View content for 800x600
  2220. int cxView = 800;
  2221. int cyView = 600;
  2222. int x;
  2223. int y;
  2224. // Make sure we fit on the monitor...
  2225. //
  2226. if (NULL == hmon)
  2227. hmon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
  2228. if (hmon)
  2229. {
  2230. MONITORINFO monInfo = {sizeof(monInfo), 0};
  2231. if (GetMonitorInfo(hmon, &monInfo))
  2232. {
  2233. pwp->length = sizeof(WINDOWPLACEMENT);
  2234. if (GetWindowPlacement(hwnd, pwp))
  2235. {
  2236. // Move the window to the specified monitor.
  2237. OffsetRect(&pwp->rcNormalPosition, monInfo.rcMonitor.left, monInfo.rcMonitor.top);
  2238. // Reposition this window to fit on this monitor
  2239. x = pwp->rcNormalPosition.left;
  2240. y = pwp->rcNormalPosition.top;
  2241. if (monInfo.rcWork.left <= pwp->rcNormalPosition.left &&
  2242. pwp->rcNormalPosition.left <= monInfo.rcWork.right &&
  2243. pwp->rcNormalPosition.left + cxView > monInfo.rcWork.right)
  2244. {
  2245. x = max(monInfo.rcWork.left, monInfo.rcWork.right - cxView);
  2246. }
  2247. if (monInfo.rcWork.top <= pwp->rcNormalPosition.top &&
  2248. pwp->rcNormalPosition.top <= monInfo.rcWork.bottom &&
  2249. pwp->rcNormalPosition.top + cyView > monInfo.rcWork.bottom)
  2250. {
  2251. y = max(monInfo.rcWork.top, monInfo.rcWork.bottom - cyView);
  2252. }
  2253. // Even with the above positioning, we don't want to be bigger than the monitor
  2254. cxView = min(cxView, RECTWIDTH(monInfo.rcWork));
  2255. cyView = min(cyView, RECTHEIGHT(monInfo.rcWork));
  2256. // We're not using the whole screen so use the calculated position, else maximize.
  2257. if (cxView != RECTWIDTH(monInfo.rcWork) || cyView != RECTHEIGHT(monInfo.rcWork))
  2258. {
  2259. pwp->rcNormalPosition.left = x;
  2260. pwp->rcNormalPosition.top = y;
  2261. pwp->rcNormalPosition.right = x + cxView;
  2262. pwp->rcNormalPosition.bottom = y + cyView;
  2263. }
  2264. else
  2265. {
  2266. pwp->showCmd = SW_MAXIMIZE;
  2267. }
  2268. }
  2269. else
  2270. {
  2271. pwp->length = 0;
  2272. }
  2273. }
  2274. }
  2275. }
  2276. //*** InfoIdmToTBIdm -- convert btwn browserbar IDM and TBIDM
  2277. //
  2278. int InfoIdmToTBIdm(int val, BOOL fToTB)
  2279. {
  2280. static const int menutab[] = {
  2281. FCIDM_VBBSEARCHBAND,
  2282. FCIDM_VBBFAVORITESBAND,
  2283. FCIDM_VBBHISTORYBAND,
  2284. FCIDM_VBBEXPLORERBAND,
  2285. };
  2286. static const int tbtab[] = {
  2287. TBIDM_SEARCH,
  2288. TBIDM_FAVORITES,
  2289. TBIDM_HISTORY,
  2290. TBIDM_ALLFOLDERS,
  2291. };
  2292. return SHSearchMapInt(fToTB ? menutab : tbtab, fToTB ? tbtab : menutab,
  2293. ARRAYSIZE(menutab), val);
  2294. }
  2295. void _CheckSearch(UINT idmInfo, BOOL fCheck, IExplorerToolbar* _pxtb)
  2296. {
  2297. idmInfo = InfoIdmToTBIdm(idmInfo, TRUE);
  2298. if (idmInfo == -1)
  2299. return;
  2300. if (_pxtb)
  2301. {
  2302. UINT uiState;
  2303. if (SUCCEEDED(_pxtb->GetState(&CLSID_CommonButtons, idmInfo, &uiState)))
  2304. {
  2305. if (fCheck)
  2306. uiState |= TBSTATE_CHECKED;
  2307. else
  2308. uiState &= ~TBSTATE_CHECKED;
  2309. _pxtb->SetState(&CLSID_CommonButtons, idmInfo, uiState);
  2310. }
  2311. }
  2312. }
  2313. //
  2314. // Implementation of CShellBrowser2::ShowToolbar
  2315. //
  2316. // Make toolbar visible or not and update our conception of whether it
  2317. // should be shown. The toolbar by definition is strictly the toolbar.
  2318. // The caller has no idea that part of our internet toolbar also has
  2319. // the menu. We must make sure we don't hide the menuband -- only the
  2320. // other bands on the internet toolbar.
  2321. //
  2322. // Returns: S_OK, if successfully done.
  2323. // E_INVALIDARG, duh.
  2324. //
  2325. HRESULT CShellBrowser2::ShowToolbar(IUnknown* punkSrc, BOOL fShow)
  2326. {
  2327. HRESULT hres;
  2328. UINT itb = _FindTBar(punkSrc);
  2329. if (ITB_ITBAR == itb)
  2330. {
  2331. LPTOOLBARITEM ptbi = _GetToolbarItem(itb);
  2332. ITBar_ShowDW(ptbi->ptbar, fShow, fShow, fShow);
  2333. ptbi->fShow = fShow;
  2334. hres = S_OK;
  2335. }
  2336. else
  2337. hres = SUPERCLASS::ShowToolbar(punkSrc, fShow);
  2338. return S_OK;
  2339. }
  2340. extern IDeskBand * _GetInfoBandBS(IBandSite *pbs, REFCLSID clsid);
  2341. #ifdef DEBUG // {
  2342. //***
  2343. // NOTES
  2344. // WARNING: dtor frees up CBandSiteMenu on exit!
  2345. // should we make sure some minimum set is created?
  2346. HRESULT CShellBrowser2::_AddInfoBands(IBandSite *pbs)
  2347. {
  2348. if (!_pbsmInfo)
  2349. return E_FAIL;
  2350. BANDCLASSINFO *pbci;
  2351. for (int i = 0; (pbci = _pbsmInfo->GetBandClassDataStruct(i)) != NULL; i++)
  2352. {
  2353. IDeskBand *pband = _GetInfoBandBS(pbs, pbci->clsid);
  2354. if (pband != NULL)
  2355. pband->Release();
  2356. }
  2357. {
  2358. // Exec -> Select or SetBandState ??? What do this mean ???
  2359. // REARCHITECT chrisfra 5/23/97 - ever heard of variants? this should set
  2360. // vt = VT_I4 and lVal = 1. this is horrible, I assume this is being ripped
  2361. // out when Select funcs added, if not, it should be recoded.
  2362. VARIANTARG vaIn = { 0 };
  2363. //VariantInit();
  2364. vaIn.vt = VT_UNKNOWN;
  2365. vaIn.punkVal = (IUnknown *)1; // show all
  2366. IUnknown_Exec(pbs, &CGID_DeskBand, DBID_SHOWONLY, OLECMDEXECOPT_PROMPTUSER, &vaIn, NULL);
  2367. //VariantClear();
  2368. }
  2369. return S_OK;
  2370. }
  2371. #endif // }
  2372. // REARCHITECT: [justmann 2000-01-27 this seems so ancient that it can be ignored]
  2373. // this is for ie4 shell compat - the ie4 shell menus have a Explorer bar popup
  2374. // need to make a pass through & fix all _GetBrowserBarMenu ref's,
  2375. // since we're back to having view->explorer bars-> on all platforms
  2376. HMENU CShellBrowser2::_GetBrowserBarMenu()
  2377. {
  2378. HMENU hmenu = _GetMenuFromID(FCIDM_VIEWBROWSERBARS);
  2379. if (hmenu == NULL)
  2380. {
  2381. hmenu = _GetMenuFromID(FCIDM_MENU_VIEW);
  2382. if (hmenu == NULL)
  2383. {
  2384. //if we're here, someone has taken our view menu (docobj)
  2385. hmenu = SHGetMenuFromID(_hmenuPreMerged, FCIDM_VIEWBROWSERBARS);
  2386. ASSERT(hmenu);
  2387. }
  2388. }
  2389. ASSERT(IsMenu(hmenu));
  2390. return hmenu;
  2391. }
  2392. void CShellBrowser2::_AddBrowserBarMenuItems(HMENU hmenu)
  2393. {
  2394. // Find the placeholder item, so we can add items before it
  2395. int iPos = SHMenuIndexFromID(hmenu, FCIDM_VBBPLACEHOLDER);
  2396. if (iPos < 0)
  2397. {
  2398. // we've already had our way with this menu
  2399. ASSERT(_pbsmInfo);
  2400. return;
  2401. }
  2402. //_pbsmInfo is shared across all views in the view menu
  2403. BOOL fCreatedNewBSMenu = FALSE;
  2404. if (!_pbsmInfo)
  2405. {
  2406. IUnknown *punk;
  2407. if (SUCCEEDED(CBandSiteMenu_CreateInstance(NULL, &punk, NULL)))
  2408. {
  2409. punk->QueryInterface(CLSID_BandSiteMenu, (void **)&_pbsmInfo);
  2410. punk->Release();
  2411. fCreatedNewBSMenu = TRUE;
  2412. }
  2413. }
  2414. if (!_pbsmInfo)
  2415. return;
  2416. int idCmdNext;
  2417. UINT cBands = 0;
  2418. if (fCreatedNewBSMenu)
  2419. {
  2420. // Load up infobands
  2421. cBands = _pbsmInfo->LoadFromComCat(&CATID_InfoBand);
  2422. // nuke any infoband entries that are already in the fixed list
  2423. for (int i = FCIDM_VBBFIXFIRST; i < FCIDM_VBBFIXLAST; i++)
  2424. {
  2425. const CLSID *pclsid = _InfoIdmToCLSID(i);
  2426. if (pclsid)
  2427. {
  2428. if (_pbsmInfo->DeleteBandClass(*pclsid))
  2429. cBands--;
  2430. }
  2431. }
  2432. // merge the additional infobands contiguously
  2433. idCmdNext = _pbsmInfo->CreateMergeMenu(hmenu, VBBDYN_MAXBAND, iPos - 1, FCIDM_VBBDYNFIRST,0);
  2434. // Load up commbands
  2435. _iCommOffset = cBands;
  2436. cBands = _pbsmInfo->LoadFromComCat(&CATID_CommBand);
  2437. }
  2438. else
  2439. {
  2440. // Add the additional infobands contiguously
  2441. int cMergedInfoBands = _pbsmInfo->GetBandClassCount(&CATID_InfoBand, TRUE /*merged*/);
  2442. idCmdNext = _pbsmInfo->CreateMergeMenu(hmenu, cMergedInfoBands, iPos - 1, FCIDM_VBBDYNFIRST,0);
  2443. cBands = _pbsmInfo->LoadFromComCat(NULL);
  2444. }
  2445. // placeholder position may have changed at this point
  2446. iPos = SHMenuIndexFromID(hmenu, FCIDM_VBBPLACEHOLDER);
  2447. // Add comm bands.
  2448. if (_iCommOffset != cBands)
  2449. {
  2450. // Insert a separator if there are comm bands
  2451. InsertMenu(hmenu, iPos + _iCommOffset + 1, MF_BYPOSITION | MF_SEPARATOR, -1, NULL);
  2452. // Now merge the comm bands
  2453. _pbsmInfo->CreateMergeMenu(hmenu, VBBDYN_MAXBAND, iPos + _iCommOffset + 2, idCmdNext, _iCommOffset);
  2454. }
  2455. DeleteMenu(hmenu, FCIDM_VBBPLACEHOLDER, MF_BYCOMMAND);
  2456. if (!CMediaBarUtil::IsWMP7OrGreaterCapable())
  2457. {
  2458. DeleteMenu(hmenu, FCIDM_VBBMEDIABAND, MF_BYCOMMAND);
  2459. }
  2460. }
  2461. int CShellBrowser2::_IdBarFromCmdID(UINT idCmd)
  2462. {
  2463. const CATID* pcatid = _InfoIdmToCATID(idCmd);
  2464. if (pcatid)
  2465. {
  2466. if (IsEqualCATID(*pcatid, CATID_InfoBand))
  2467. {
  2468. // It's a vertical bar
  2469. return IDBAR_VERTICAL;
  2470. }
  2471. else
  2472. {
  2473. // It's a horizontal bar
  2474. ASSERT(IsEqualCATID(*pcatid, CATID_CommBand));
  2475. return IDBAR_HORIZONTAL;
  2476. }
  2477. }
  2478. // Command doesn't correspond to any bar
  2479. return IDBAR_INVALID;
  2480. }
  2481. int CShellBrowser2::_eOnOffNotMunge(int eOnOffNot, UINT idCmd, UINT idBar)
  2482. {
  2483. // FEATURE: todo -- drive an ashen stake through the foul heart of this function
  2484. if (eOnOffNot == -1)
  2485. {
  2486. // toggle
  2487. // 'special' guys are set; 'real' guys are toggled
  2488. ASSERT(idCmd != FCIDM_VBBNOVERTICALBAR && idCmd != FCIDM_VBBNOHORIZONTALBAR);
  2489. if (idCmd == FCIDM_VBBNOVERTICALBAR || idCmd == FCIDM_VBBNOHORIZONTALBAR)
  2490. eOnOffNot = 0;
  2491. else if ((idCmd >= FCIDM_VBBDYNFIRST) && (idCmd <= FCIDM_VBBDYNLAST))
  2492. eOnOffNot = (idBar == IDBAR_VERTICAL) ? (idCmd != _idmInfo) : (idCmd != _idmComm);
  2493. else
  2494. eOnOffNot = (idCmd != _idmInfo);
  2495. }
  2496. return eOnOffNot;
  2497. }
  2498. #define MIIM_FTYPE 0x00000100
  2499. //*** csb::_SetBrowserBarState -- handle menu/toolbar/exec command, *and* update UI
  2500. // ENTRY/EXIT
  2501. // idCmd FCIDM_VBB* or -1 (if want to use pclsid instead)
  2502. // pclsid clsid or NULL (if want to use idCmd instead)
  2503. // eOnOffToggle 1=on, 0=off, -1=not (off/not only for fixed bands for now)
  2504. // NOTES
  2505. // menu code calls w/ idCmd, Exec code calls w/ pclsid
  2506. //
  2507. void CShellBrowser2::_SetBrowserBarState(UINT idCmd, const CLSID *pclsid, int eOnOffNot, LPCITEMIDLIST pidl)
  2508. {
  2509. if (idCmd == -1)
  2510. idCmd = _InfoCLSIDToIdm(pclsid);
  2511. if (pclsid == NULL)
  2512. pclsid = _InfoIdmToCLSID(idCmd);
  2513. ASSERT(_InfoCLSIDToIdm(pclsid) == idCmd);
  2514. int idBar = _IdBarFromCmdID(idCmd);
  2515. if (idBar == IDBAR_INVALID)
  2516. {
  2517. // We don't recognize this bubby, bail
  2518. return;
  2519. }
  2520. ASSERT(IDBAR_VERTICAL == idBar || IDBAR_HORIZONTAL == idBar);
  2521. // Munge the unholy eOnOffNot
  2522. eOnOffNot = _eOnOffNotMunge(eOnOffNot, idCmd, idBar);
  2523. if (eOnOffNot == 0 && (idCmd != _idmInfo) && (idCmd != _idmComm))
  2524. {
  2525. // already off
  2526. return;
  2527. }
  2528. // _ShowHideBrowserBar can affect the size of the view window, but the on/off state of
  2529. // the bar isn't actually updated until we update _idmInfo below. But we want the
  2530. // view to be able to query the accurate on/off state of the bar during the resize.
  2531. // So postpone resize of the actual hwnd until after the on/off state is set correctly.
  2532. //
  2533. _fHaveDelayedSize = FALSE;
  2534. _hwndDelayedSize = _pbbd->_hwndView;
  2535. // Reduce flicker: turn off window painting while we resize several windows
  2536. BOOL fLock = LockWindowUpdate(_pbbd->_hwnd);
  2537. ASSERT(0 == eOnOffNot || 1 == eOnOffNot);
  2538. pclsid = _ShowHideBrowserBar(idBar, pclsid, eOnOffNot, pidl);
  2539. if (IDBAR_VERTICAL == idBar)
  2540. v_SetIcon();
  2541. if (IDBAR_VERTICAL == idBar)
  2542. {
  2543. // Vertical bar
  2544. // since we support multiple searches in the same band
  2545. // it is possible to have search band open when we clicked on
  2546. // a different search so to avoid flicker we don't "unpress" the button
  2547. if (_idmInfo != idCmd)
  2548. _CheckSearch(_idmInfo, FALSE, _pxtb);
  2549. _idmInfo = eOnOffNot ? idCmd : FCIDM_VBBNOVERTICALBAR;
  2550. _CheckSearch(_idmInfo, TRUE, _pxtb);
  2551. }
  2552. else
  2553. {
  2554. // Horizontal bar
  2555. _idmComm = eOnOffNot ? idCmd : FCIDM_VBBNOHORIZONTALBAR;
  2556. }
  2557. // Make sure that the toolbar is updated
  2558. Exec(NULL, OLECMDID_UPDATECOMMANDS, 0, NULL, NULL);
  2559. //set the dirty bit on itbar and save
  2560. Exec(&CGID_PrivCITCommands, CITIDM_SET_DIRTYBIT, TRUE, NULL, NULL);
  2561. Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
  2562. // If we delayed a resize of the view window, update it now
  2563. if (_fHaveDelayedSize)
  2564. {
  2565. HWND hwnd = _hwndDelayedSize;
  2566. _hwndDelayedSize = NULL;
  2567. _PositionViewWindow(hwnd, &_rcDelayedSize);
  2568. }
  2569. else
  2570. {
  2571. _hwndDelayedSize = NULL;
  2572. }
  2573. if (fLock)
  2574. LockWindowUpdate(NULL);
  2575. }
  2576. //*** do the op, but do *not* update the UI
  2577. // ENTRY/EXIT
  2578. // return guy who's now visible (pclsid, 0 [VBBNONE], or 1 [VBBALL])
  2579. // NOTES
  2580. // don't call this directly, it's just a helper.
  2581. // don't reference UI stuff (_idmInfo etc.) (except for ASSERTs).
  2582. const CLSID * CShellBrowser2::_ShowHideBrowserBar(int idBar, const CLSID *pclsid, int eOnOff, LPCITEMIDLIST pidl /*= NULL*/)
  2583. {
  2584. ASSERT(IDBAR_VERTICAL == idBar || IDBAR_HORIZONTAL == idBar);
  2585. IBandSite* pbsSite = NULL;
  2586. HRESULT hr = E_FAIL;
  2587. if (_fUISetByAutomation)
  2588. {
  2589. if (0 == eOnOff || NULL == pclsid)
  2590. {
  2591. // if pclsid -- hide that bar, else -- hide everyone
  2592. ASSERT(NULL == pclsid || _InfoCLSIDToIdm(pclsid) == ((IDBAR_VERTICAL == idBar) ? _idmInfo : _idmComm));
  2593. _GetBrowserBar(idBar, FALSE, NULL, NULL);
  2594. return NULL;
  2595. }
  2596. }
  2597. if (0 == eOnOff || NULL == pclsid)
  2598. {
  2599. // if pclsid -- hide that bar, else -- hide everyone
  2600. ASSERT(NULL == pclsid || _InfoCLSIDToIdm(pclsid) == ((IDBAR_VERTICAL == idBar) ? _idmInfo : _idmComm));
  2601. _GetBrowserBar(idBar, FALSE, NULL, NULL);
  2602. return NULL;
  2603. }
  2604. hr = _GetBandSite(idBar, &pbsSite, pclsid, eOnOff);
  2605. if (SUCCEEDED(hr))
  2606. {
  2607. hr = _EnsureAndNavigateBand(pbsSite, pclsid, pidl);
  2608. ASSERT(pbsSite); // _GetBandSite() or _GetBrowserBand() flunked with its return code ?
  2609. pbsSite->Release();
  2610. }
  2611. return SUCCEEDED(hr) ? pclsid : NULL;
  2612. }
  2613. HRESULT CShellBrowser2::_GetBandSite(int idBar, IBandSite** ppbsSite, const CLSID *pclsid, int eOnOff)
  2614. {
  2615. *ppbsSite = NULL;
  2616. LPCWSTR pwszItem = (IDBAR_VERTICAL == idBar) ? INFOBAR_TBNAME : COMMBAR_TBNAME;
  2617. //----- Persist current DeskBar (if it exists) -----
  2618. IDeskBar* pdbBar;
  2619. HRESULT hr = FindToolbar(pwszItem, IID_PPV_ARG(IDeskBar, &pdbBar));
  2620. if (S_OK == hr)
  2621. {
  2622. VARIANT varClsid;
  2623. // if a bar is being shown, tell CBrowserBar which clsid it is
  2624. SA_BSTRGUID strClsid;
  2625. InitFakeBSTR(&strClsid, *pclsid);
  2626. varClsid.vt = VT_BSTR;
  2627. varClsid.bstrVal = strClsid.wsz;
  2628. IUnknown_Exec(pdbBar, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, eOnOff, &varClsid, NULL);
  2629. }
  2630. ATOMICRELEASE(pdbBar);
  2631. // get bar (create/cache or retrieve from cache)
  2632. return _GetBrowserBar(idBar, TRUE, ppbsSite, pclsid);
  2633. }
  2634. HRESULT CShellBrowser2::_EnsureAndNavigateBand(IBandSite* pbsSite, const CLSID* pclsid, LPCITEMIDLIST pidl /*= NULL*/)
  2635. {
  2636. ASSERT(NULL != pbsSite);
  2637. ASSERT(NULL != pclsid);
  2638. IDeskBand* pdbBand = NULL;
  2639. HRESULT hr = E_FAIL;
  2640. if (NULL != _pbbd->_pautoWB2)
  2641. {
  2642. // check if this band can be found through automation
  2643. SA_BSTRGUID strClsid;
  2644. InitFakeBSTR(&strClsid, *pclsid);
  2645. VARIANT varProp;
  2646. hr = _pbbd->_pautoWB2->GetProperty(strClsid.wsz, &varProp);
  2647. if (SUCCEEDED(hr))
  2648. {
  2649. if (VT_UNKNOWN == varProp.vt && NULL != varProp.punkVal)
  2650. {
  2651. hr = varProp.punkVal->QueryInterface(IID_PPV_ARG(IDeskBand, &pdbBand));
  2652. }
  2653. else
  2654. {
  2655. hr = E_FAIL;
  2656. }
  2657. VariantClear(&varProp);
  2658. }
  2659. // this property doesn't exist yet, so create a new band
  2660. if (FAILED(hr))
  2661. {
  2662. pdbBand = _GetInfoBandBS(pbsSite, *pclsid);
  2663. if (pdbBand)
  2664. {
  2665. // add to the property so that it can be found later
  2666. VARIANT var;
  2667. var.vt = VT_UNKNOWN;
  2668. var.punkVal = pdbBand;
  2669. _pbbd->_pautoWB2->PutProperty(strClsid.wsz, var);
  2670. }
  2671. }
  2672. }
  2673. // automation object is not there, try to succeed anyway
  2674. if (NULL == pdbBand)
  2675. {
  2676. ASSERTMSG(FALSE, "IWebBrowser2 is not available");
  2677. pdbBand = _GetInfoBandBS(pbsSite, *pclsid);
  2678. }
  2679. if (pdbBand)
  2680. {
  2681. IBandNavigate* pbn;
  2682. if (pidl && SUCCEEDED(pdbBand->QueryInterface(IID_PPV_ARG(IBandNavigate, &pbn))))
  2683. {
  2684. pbn->Select(pidl);
  2685. pbn->Release();
  2686. }
  2687. // show me, hide everyone else
  2688. VARIANT var;
  2689. var.vt = VT_UNKNOWN;
  2690. var.punkVal = pdbBand;
  2691. // Exec -> Select or SetBandState
  2692. IUnknown_Exec(pbsSite, &CGID_DeskBand, DBID_SHOWONLY, OLECMDEXECOPT_PROMPTUSER, &var, NULL);
  2693. pdbBand->Release();
  2694. hr = S_OK;
  2695. }
  2696. return hr;
  2697. }
  2698. BANDCLASSINFO* CShellBrowser2::_BandClassInfoFromCmdID(UINT idCmd)
  2699. {
  2700. if (IsInRange(idCmd, FCIDM_VBBDYNFIRST, FCIDM_VBBDYNLAST))
  2701. {
  2702. if (_pbsmInfo)
  2703. {
  2704. int i, cnt = _pbsmInfo->GetBandClassCount(NULL, FALSE);
  2705. for (i = 0; i < cnt; i++)
  2706. {
  2707. BANDCLASSINFO *pbci = _pbsmInfo->GetBandClassDataStruct(i);
  2708. if (pbci && idCmd == pbci->idCmd)
  2709. return pbci;
  2710. }
  2711. }
  2712. }
  2713. return NULL;
  2714. }
  2715. // map menu ID valued (FCIDM_VBB*'s) to corresponding CLSID
  2716. // handles both 'fixed' and dynamic guys
  2717. const CLSID *CShellBrowser2::_InfoIdmToCLSID(UINT idCmd)
  2718. {
  2719. const CLSID *pclsid = NULL;
  2720. if (IsInRange(idCmd, FCIDM_VBBFIXFIRST, FCIDM_VBBFIXLAST))
  2721. {
  2722. switch (idCmd) {
  2723. case FCIDM_VBBSEARCHBAND: pclsid = &CLSID_SearchBand; break;
  2724. case FCIDM_VBBFAVORITESBAND: pclsid = &CLSID_FavBand; break;
  2725. case FCIDM_VBBHISTORYBAND: pclsid = &CLSID_HistBand; break;
  2726. case FCIDM_VBBEXPLORERBAND: pclsid = &CLSID_ExplorerBand; break;
  2727. case FCIDM_VBBMEDIABAND: pclsid = &CLSID_MediaBand; break;
  2728. }
  2729. }
  2730. else
  2731. {
  2732. BANDCLASSINFO* pbci = _BandClassInfoFromCmdID(idCmd);
  2733. if (pbci)
  2734. pclsid = &pbci->clsid;
  2735. }
  2736. return pclsid;
  2737. }
  2738. const CATID *CShellBrowser2::_InfoIdmToCATID(UINT idCmd)
  2739. {
  2740. const CATID* pcatid = NULL;
  2741. if (IsInRange(idCmd, FCIDM_VBBFIXFIRST, FCIDM_VBBFIXLAST))
  2742. {
  2743. // The fixed bars are all in the vertical comcat
  2744. pcatid = &CATID_InfoBand;
  2745. }
  2746. else
  2747. {
  2748. // Dynamic bar, have to look up the catid
  2749. BANDCLASSINFO* pbci = _BandClassInfoFromCmdID(idCmd);
  2750. if (pbci)
  2751. pcatid = &pbci->catid;
  2752. }
  2753. return pcatid;
  2754. }
  2755. UINT CShellBrowser2::_InfoCLSIDToIdm(const CLSID *pguid)
  2756. {
  2757. if (pguid == NULL)
  2758. return 0;
  2759. else if (IsEqualIID(*pguid, CLSID_ExplorerBand))
  2760. return FCIDM_VBBEXPLORERBAND;
  2761. else if (IsEqualIID(*pguid, CLSID_SearchBand))
  2762. return FCIDM_VBBSEARCHBAND;
  2763. else if (IsEqualIID(*pguid, CLSID_FileSearchBand))
  2764. return FCIDM_VBBSEARCHBAND;
  2765. else if (IsEqualIID(*pguid, CLSID_FavBand))
  2766. return FCIDM_VBBFAVORITESBAND;
  2767. else if (IsEqualIID(*pguid, CLSID_HistBand))
  2768. return FCIDM_VBBHISTORYBAND;
  2769. else if (IsEqualIID(*pguid, CLSID_MediaBand))
  2770. return FCIDM_VBBMEDIABAND;
  2771. #ifdef UNIX
  2772. else if (IsEqualIID(*pguid, CLSID_MsgBand))
  2773. return FCIDM_VBBMSGBAND;
  2774. #endif
  2775. else
  2776. {
  2777. if (!_pbsmInfo)
  2778. {
  2779. // Load the Browser Bar Menu to load the class ids of all Component Categories dynamic Browser bars
  2780. _AddBrowserBarMenuItems(_GetBrowserBarMenu());
  2781. // Unable to load the clsids from dynamic bars.
  2782. if (!_pbsmInfo)
  2783. return -1;
  2784. }
  2785. BANDCLASSINFO *pbci;
  2786. for (int i = 0; NULL != (pbci = _pbsmInfo->GetBandClassDataStruct(i)); i++)
  2787. if (IsEqualIID(*pguid, pbci->clsid))
  2788. return (pbci->idCmd);
  2789. // FEATURE: look up in _pbsmInfo->LoadFromComCat's HDPA
  2790. // ASSERT(0);
  2791. }
  2792. return -1;
  2793. }
  2794. HBITMAP CreateColorBitmap(int cx, int cy)
  2795. {
  2796. HBITMAP hbm = NULL;
  2797. HDC hdc = GetDC(NULL);
  2798. if (hdc)
  2799. {
  2800. hbm = CreateCompatibleBitmap(hdc, cx, cy);
  2801. ReleaseDC(NULL, hdc);
  2802. }
  2803. return hbm;
  2804. }
  2805. HRESULT CShellBrowser2::_GetBSForBar(LPCWSTR pwszItem, IBandSite **ppbs)
  2806. {
  2807. *ppbs = NULL;
  2808. IDeskBar *pdbBar;
  2809. HRESULT hr = FindToolbar(pwszItem, IID_PPV_ARG(IDeskBar, &pdbBar));
  2810. if (hr == S_OK)
  2811. {
  2812. IUnknown *punkBS;
  2813. hr = pdbBar->GetClient(&punkBS);
  2814. if (SUCCEEDED(hr))
  2815. {
  2816. hr = punkBS->QueryInterface(IID_PPV_ARG(IBandSite, ppbs));
  2817. ASSERT(SUCCEEDED(hr));
  2818. punkBS->Release();
  2819. }
  2820. pdbBar->Release();
  2821. }
  2822. return hr;
  2823. }
  2824. void CShellBrowser2::_ExecAllBands(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  2825. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  2826. {
  2827. IBandSite *pbsBS;
  2828. HRESULT hres = _GetBSForBar(INFOBAR_TBNAME, &pbsBS);
  2829. if (hres == S_OK)
  2830. {
  2831. DWORD dwBandID;
  2832. for (int i = 0; SUCCEEDED(pbsBS->EnumBands(i, &dwBandID)); i++)
  2833. {
  2834. IDeskBand *pstb;
  2835. hres = pbsBS->QueryBand(dwBandID, &pstb, NULL, NULL, 0);
  2836. if (SUCCEEDED(hres))
  2837. {
  2838. IUnknown_Exec(pstb, pguidCmdGroup, nCmdID, nCmdexecopt,
  2839. pvarargIn, pvarargOut);
  2840. pstb->Release();
  2841. }
  2842. }
  2843. pbsBS->Release();
  2844. }
  2845. }
  2846. HRESULT CShellBrowser2::_GetBrowserBar(int idBar, BOOL fShow, IBandSite** ppbs, const CLSID* pclsid)
  2847. {
  2848. HRESULT hres;
  2849. IUnknown *punkBar;
  2850. IDeskBar *pdbBar = NULL;
  2851. IUnknown *punkBS = NULL;
  2852. if (ppbs)
  2853. *ppbs = NULL;
  2854. if (IDBAR_VERTICAL == idBar)
  2855. {
  2856. hres = FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdbBar));
  2857. }
  2858. else
  2859. {
  2860. ASSERT(IDBAR_HORIZONTAL == idBar); // No other bars right now.
  2861. hres = FindToolbar(COMMBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdbBar));
  2862. }
  2863. TraceMsg(DM_MISC, "CSB::_GetBrowserBar FindToolbar returned %x", hres);
  2864. BOOL fTurnOffAutoHide = FALSE;
  2865. if (hres == S_OK)
  2866. {
  2867. // already have one
  2868. hres = pdbBar->GetClient((IUnknown**) &punkBS);
  2869. ASSERT(SUCCEEDED(hres));
  2870. punkBar = pdbBar;
  2871. // punkBar->Release() down below
  2872. }
  2873. else
  2874. {
  2875. //if there's not a bar, don't bother creating one so it can be hidden
  2876. if (!fShow)
  2877. return S_OK;
  2878. // 1st time, create a new one
  2879. CBrowserBar* pdb = new CBrowserBar();
  2880. if (NULL == pdb)
  2881. {
  2882. return E_OUTOFMEMORY;
  2883. }
  2884. else
  2885. {
  2886. // add it
  2887. pdb->QueryInterface(IID_PPV_ARG(IUnknown, &punkBar));
  2888. //if a bar is being shown, tell CBrowserBar which clsid it is
  2889. SA_BSTRGUID strClsid;
  2890. InitFakeBSTR(&strClsid, *pclsid);
  2891. VARIANT varClsid;
  2892. varClsid.vt = VT_BSTR;
  2893. varClsid.bstrVal = strClsid.wsz;
  2894. IUnknown_Exec(punkBar, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, fShow, &varClsid, NULL);
  2895. UINT uiWidthOrHeight = pdb->_PersistState(NULL, FALSE);
  2896. //don't let anyone be 0 width
  2897. if (uiWidthOrHeight == 0)
  2898. uiWidthOrHeight = (IDBAR_VERTICAL == idBar) ? INFOBAR_WIDTH : COMMBAR_HEIGHT;
  2899. fTurnOffAutoHide = !(GetSystemMetrics(SM_CXSCREEN) <= 800);
  2900. CBrowserBarPropertyBag* ppb;
  2901. // FEATURE - this needs to be persisted and restored
  2902. // when % widths are implemented, should use that
  2903. ppb = new CBrowserBarPropertyBag();
  2904. if (ppb)
  2905. {
  2906. if (IDBAR_VERTICAL == idBar)
  2907. {
  2908. ppb->SetDataDWORD(PROPDATA_SIDE, ABE_LEFT); // LEFT
  2909. ppb->SetDataDWORD(PROPDATA_LEFT, uiWidthOrHeight);
  2910. ppb->SetDataDWORD(PROPDATA_RIGHT, uiWidthOrHeight);
  2911. }
  2912. else
  2913. {
  2914. ppb->SetDataDWORD(PROPDATA_SIDE, ABE_BOTTOM); // BOTTOM
  2915. ppb->SetDataDWORD(PROPDATA_TOP, uiWidthOrHeight);
  2916. ppb->SetDataDWORD(PROPDATA_BOTTOM, uiWidthOrHeight);
  2917. }
  2918. ppb->SetDataDWORD(PROPDATA_MODE, WBM_BBOTTOMMOST);
  2919. SHLoadFromPropertyBag(punkBar, ppb);
  2920. ppb->Release();
  2921. }
  2922. hres = AddToolbar(punkBar, (IDBAR_VERTICAL == idBar) ? INFOBAR_TBNAME : COMMBAR_TBNAME, DWFAF_HIDDEN);
  2923. if (SUCCEEDED(hres))
  2924. {
  2925. hres = BrowserBar_Init(pdb, &punkBS, idBar);
  2926. }
  2927. pdb->Release();
  2928. }
  2929. }
  2930. // need to set band info here each time since deskbar/bandsite get reused
  2931. if (fShow && punkBS)
  2932. {
  2933. BANDSITEINFO bsinfo;
  2934. bsinfo.dwMask = BSIM_STYLE;
  2935. bsinfo.dwStyle = BSIS_NOGRIPPER | BSIS_LEFTALIGN;
  2936. IBandSite* pSite;
  2937. HRESULT hr = punkBS->QueryInterface(IID_PPV_ARG(IBandSite, &pSite));
  2938. if (SUCCEEDED(hr))
  2939. {
  2940. pSite->SetBandSiteInfo(&bsinfo);
  2941. pSite->Release();
  2942. }
  2943. }
  2944. // note: must call _SetTheaterBrowserBar BEFORE ShowToolbar when showing bar
  2945. if (IDBAR_VERTICAL == idBar && fShow)
  2946. _SetTheaterBrowserBar();
  2947. ShowToolbar(punkBar, fShow);
  2948. // note: must call _SetTheaterBrowserBar AFTER ShowToolbar when hiding bar
  2949. if (IDBAR_VERTICAL == idBar && !fShow)
  2950. _SetTheaterBrowserBar();
  2951. //tell CBrowserBar about the new bar, must be AFTER it is shown (to get the size right)
  2952. if (SUCCEEDED(hres) && fShow)
  2953. {
  2954. //if a bar is being shown, tell CBrowserBar which clsid it is
  2955. SA_BSTRGUID strClsid;
  2956. InitFakeBSTR(&strClsid, *pclsid);
  2957. VARIANT varClsid;
  2958. varClsid.vt = VT_BSTR;
  2959. varClsid.bstrVal = strClsid.wsz;
  2960. IUnknown_Exec(punkBar, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, fShow, &varClsid, NULL);
  2961. }
  2962. else
  2963. {
  2964. IUnknown_Exec(punkBar, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, 0, NULL, NULL);
  2965. }
  2966. // note: must have called ShowToolbar BEFORE setting pin button state
  2967. if (fTurnOffAutoHide)
  2968. {
  2969. VARIANT v = { VT_I4 };
  2970. v.lVal = FALSE;
  2971. IUnknown_Exec(punkBar, &CGID_Theater, THID_SETBROWSERBARAUTOHIDE, 0, &v, &v);
  2972. }
  2973. punkBar->Release();
  2974. //FEATURE: What should we do for CommBar in Theatre Mode?
  2975. if (punkBS)
  2976. {
  2977. HRESULT hr = S_OK;
  2978. if (ppbs)
  2979. {
  2980. hr = punkBS->QueryInterface(IID_PPV_ARG(IBandSite, ppbs));
  2981. }
  2982. punkBS->Release();
  2983. return hr; // there are callers to _GetBrowserBar which need to know if QI for IBandSite succeeded
  2984. }
  2985. return E_FAIL;
  2986. }
  2987. #ifdef DEBUG
  2988. //*** DBCheckCLSID -- make sure class tells truth about its CLSID
  2989. //
  2990. BOOL DBCheckCLSID(IUnknown *punk, const CLSID *pclsid)
  2991. {
  2992. CLSID clsid;
  2993. HRESULT hr = IUnknown_GetClassID(punk, &clsid);
  2994. if (SUCCEEDED(hr) && IsEqualGUID(*pclsid, clsid))
  2995. return TRUE;
  2996. TraceMsg(DM_ERROR, "dbcc: CLSID mismatch! &exp=%x &act=%x", pclsid, clsid);
  2997. return FALSE;
  2998. }
  2999. #endif
  3000. IDeskBand * _GetInfoBandBS(IBandSite *pbs, REFCLSID clsid)
  3001. {
  3002. IDeskBand *pstb = FindBandByClsidBS(pbs, clsid);
  3003. if (pstb == NULL)
  3004. {
  3005. TraceMsg(DM_MISC, "_gib: create band");
  3006. if (SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IDeskBand, &pstb))))
  3007. {
  3008. // hide all bands before adding new band
  3009. VARIANTARG vaIn = { 0 };
  3010. vaIn.vt = VT_UNKNOWN;
  3011. vaIn.punkVal = 0;
  3012. IUnknown_Exec(pbs, &CGID_DeskBand, DBID_SHOWONLY, OLECMDEXECOPT_PROMPTUSER, &vaIn, NULL);
  3013. pbs->AddBand(pstb);
  3014. }
  3015. }
  3016. return pstb;
  3017. }
  3018. void CShellBrowser2::_OrganizeFavorites()
  3019. {
  3020. TCHAR szPath[MAX_PATH];
  3021. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE))
  3022. {
  3023. #ifndef UNIX
  3024. if (GetKeyState(VK_SHIFT) < 0)
  3025. {
  3026. OpenFolderPath(szPath);
  3027. }
  3028. else
  3029. #endif
  3030. DoOrganizeFavDlgW(_pbbd->_hwnd, NULL);
  3031. }
  3032. }
  3033. /*----------------------------------------------------------
  3034. Purpose: Handle WM_COMMAND for favorites menu
  3035. */
  3036. void CShellBrowser2::_FavoriteOnCommand(HMENU hmenu, UINT idCmd)
  3037. {
  3038. switch (idCmd)
  3039. {
  3040. case FCIDM_ORGANIZEFAVORITES:
  3041. _OrganizeFavorites();
  3042. break;
  3043. case FCIDM_ADDTOFAVORITES:
  3044. Exec(&CGID_Explorer, SBCMDID_ADDTOFAVORITES, OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  3045. // Instrument add to favorites from menu
  3046. UEMFireEvent(&UEMIID_BROWSER, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_ADDTOFAV, UIBL_MENU);
  3047. break;
  3048. case FCIDM_UPDATESUBSCRIPTIONS:
  3049. UpdateSubscriptions();
  3050. break;
  3051. }
  3052. }
  3053. HRESULT CShellBrowser2::CreateBrowserPropSheetExt(REFIID riid, void **ppvObj)
  3054. {
  3055. *ppvObj = NULL;
  3056. IUnknown *punk;
  3057. HRESULT hr = CoCreateInstance(CLSID_ShellFldSetExt, NULL, CLSCTX_INPROC_SERVER, riid, (void **)&punk);
  3058. if (SUCCEEDED(hr))
  3059. {
  3060. IShellExtInit *psxi;
  3061. hr = punk->QueryInterface(IID_PPV_ARG(IShellExtInit, &psxi));
  3062. if (SUCCEEDED(hr))
  3063. {
  3064. hr = psxi->Initialize(NULL, NULL, 0);
  3065. if (SUCCEEDED(hr))
  3066. {
  3067. IUnknown_SetSite(punk, SAFECAST(this, IShellBrowser*));
  3068. IUnknown_Set((IUnknown **)ppvObj, punk);
  3069. hr = S_OK; // All happy
  3070. }
  3071. psxi->Release();
  3072. }
  3073. punk->Release();
  3074. }
  3075. return hr;
  3076. }
  3077. LPITEMIDLIST CShellBrowser2::_GetSubscriptionPidl()
  3078. {
  3079. LPITEMIDLIST pidlSubscribe = NULL;
  3080. IDispatch * pDispatch = NULL;
  3081. IHTMLDocument2 * pHTMLDocument = NULL;
  3082. // Search HTML for <LINK REL="Subscription" HREF="{URL}">
  3083. if (
  3084. SUCCEEDED(_pbbd->_pautoWB2->get_Document(&pDispatch))
  3085. &&
  3086. SUCCEEDED(pDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pHTMLDocument)))
  3087. )
  3088. {
  3089. IHTMLElementCollection * pLinksCollection;
  3090. if (SUCCEEDED(GetDocumentTags(pHTMLDocument, OLESTR("LINK"), &pLinksCollection)))
  3091. {
  3092. long lItemCnt;
  3093. // Step through each of the LINKs in the
  3094. // collection looking for REL="Subscription".
  3095. EVAL(SUCCEEDED(pLinksCollection->get_length(&lItemCnt)));
  3096. for (long lItem = 0; lItem < lItemCnt; lItem++)
  3097. {
  3098. IDispatch * pDispItem = NULL;
  3099. IHTMLLinkElement * pLinkElement = NULL;
  3100. VARIANT vEmpty = { 0 };
  3101. VARIANT vIndex; V_VT(&vIndex) = VT_I4; V_I4(&vIndex) = lItem;
  3102. if (
  3103. SUCCEEDED(pLinksCollection->item(vIndex, vEmpty, &pDispItem))
  3104. &&
  3105. SUCCEEDED(pDispItem->QueryInterface(IID_IHTMLLinkElement,
  3106. (void **)&pLinkElement))
  3107. )
  3108. {
  3109. BSTR bstrREL = NULL;
  3110. BSTR bstrHREF = NULL;
  3111. // Finally! We have a LINK element, check its REL type.
  3112. if (
  3113. SUCCEEDED(pLinkElement->get_rel(&bstrREL))
  3114. &&
  3115. (bstrREL != NULL)
  3116. &&
  3117. SUCCEEDED(pLinkElement->get_href(&bstrHREF))
  3118. &&
  3119. (bstrHREF != NULL)
  3120. )
  3121. {
  3122. // Check for REL="Subscription"
  3123. if (StrCmpIW(bstrREL, OLESTR("Subscription")) == 0)
  3124. {
  3125. TCHAR szName[MAX_URL_STRING];
  3126. SHUnicodeToTChar(bstrHREF, szName, ARRAYSIZE(szName));
  3127. EVAL(SUCCEEDED(IECreateFromPath(szName, &pidlSubscribe)));
  3128. }
  3129. }
  3130. if (bstrHREF != NULL)
  3131. SysFreeString(bstrHREF);
  3132. if (bstrREL != NULL)
  3133. SysFreeString(bstrREL);
  3134. }
  3135. VariantClear(&vIndex);
  3136. VariantClear(&vEmpty);
  3137. SAFERELEASE(pLinkElement);
  3138. SAFERELEASE(pDispItem);
  3139. // If we found a correctl REL type, quit searching.
  3140. if (pidlSubscribe != NULL)
  3141. break;
  3142. }
  3143. pLinksCollection->Release();
  3144. }
  3145. }
  3146. SAFERELEASE(pHTMLDocument);
  3147. SAFERELEASE(pDispatch);
  3148. return pidlSubscribe;
  3149. }
  3150. LPITEMIDLIST CShellBrowser2::_TranslateRoot(LPCITEMIDLIST pidl)
  3151. {
  3152. LPCITEMIDLIST pidlChild = ILFindChild(ILRootedFindIDList(_pbbd->_pidlCur), pidl);
  3153. ASSERT(pidlChild);
  3154. LPITEMIDLIST pidlRoot = ILCloneFirst(_pbbd->_pidlCur);
  3155. if (pidlRoot)
  3156. {
  3157. LPITEMIDLIST pidlRet = ILCombine(pidlRoot, pidlChild);
  3158. ILFree(pidlRoot);
  3159. return pidlRet;
  3160. }
  3161. return NULL;
  3162. }
  3163. BOOL CShellBrowser2::_ValidTargetPidl(LPCITEMIDLIST pidl, BOOL *pfTranslateRoot)
  3164. {
  3165. // validate that this is an allowable target to browse to.
  3166. // check that it is a child of our root.
  3167. if (pfTranslateRoot)
  3168. *pfTranslateRoot = FALSE;
  3169. if (ILIsRooted(_pbbd->_pidlCur))
  3170. {
  3171. BOOL fRet = ILIsEqualRoot(_pbbd->_pidlCur, pidl);
  3172. if (!fRet && pfTranslateRoot
  3173. && ILIsParent(ILRootedFindIDList(_pbbd->_pidlCur), pidl, FALSE))
  3174. {
  3175. fRet = TRUE;
  3176. *pfTranslateRoot = TRUE;
  3177. }
  3178. return fRet;
  3179. }
  3180. return TRUE;
  3181. }
  3182. IStream* CShellBrowser2::_GetITBarStream(BOOL fWebBrowser, DWORD grfMode)
  3183. {
  3184. return GetITBarStream(fWebBrowser ? ITBS_WEB : ITBS_SHELL, grfMode);
  3185. }
  3186. HRESULT CShellBrowser2::_SaveITbarLayout(void)
  3187. {
  3188. HRESULT hres = E_FAIL;
  3189. #ifdef NO_MARSHALLING
  3190. if (!_fOnIEThread)
  3191. return S_OK;
  3192. #endif
  3193. if (_fUISetByAutomation || _ptheater)
  3194. {
  3195. return S_OK;
  3196. }
  3197. if (_GetITBar())
  3198. {
  3199. IPersistStreamInit *pITbarPSI;
  3200. //Yes! It's a different type. We may need to save the stream
  3201. if (SUCCEEDED(_GetITBar()->QueryInterface(IID_PPV_ARG(IPersistStreamInit, &pITbarPSI))))
  3202. {
  3203. //Do we need to save the stream?
  3204. if (pITbarPSI->IsDirty() == S_OK)
  3205. {
  3206. BOOL fInternet = (CITE_INTERNET ==
  3207. GetScode(IUnknown_Exec(pITbarPSI, &CGID_PrivCITCommands, CITIDM_ONINTERNET, CITE_QUERY, NULL, NULL)));
  3208. IStream *pstm = _GetITBarStream(fInternet, STGM_WRITE);
  3209. if (pstm)
  3210. {
  3211. //Stream exists. Save it there!.
  3212. hres = pITbarPSI->Save(pstm, TRUE);
  3213. pstm->Release();
  3214. }
  3215. else
  3216. {
  3217. //Stream creation failed! Why?
  3218. TraceMsg(DM_ITBAR, "CSB::_SaveITbarLayout ITBar Stream creation failed");
  3219. ASSERT(0);
  3220. }
  3221. }
  3222. else
  3223. hres = S_OK; // No need to save. Return success!
  3224. pITbarPSI->Release();
  3225. }
  3226. else
  3227. {
  3228. //ITBar doesn't support IPersistStreamInit?
  3229. AssertMsg(0, TEXT("CSB::_NavigateToPidl ITBar doesn't support IPersistStreamInit"));
  3230. }
  3231. }
  3232. return hres;
  3233. }
  3234. // Returns TRUE if we are supposed to fail the navigate, FALSE otherwise
  3235. BOOL MaybeRunICW(LPCITEMIDLIST pidl, IShellBrowser *psb, HWND hwndUI)
  3236. {
  3237. TCHAR szURL[MAX_URL_STRING];
  3238. EVAL(SUCCEEDED(IEGetNameAndFlags(pidl, SHGDN_FORPARSING, szURL, SIZECHARS(szURL), NULL)));
  3239. if (UrlHitsNetW(szURL) && !UrlIsInstalledEntry(szURL))
  3240. {
  3241. if ((CheckRunICW(szURL)) || CheckSoftwareUpdateUI(hwndUI, psb)) // see if ICW needs to run
  3242. return TRUE;
  3243. }
  3244. return FALSE;
  3245. }
  3246. HRESULT CShellBrowser2::_NavigateToPidl(LPCITEMIDLIST pidl, DWORD grfHLNF, DWORD dwFlags)
  3247. {
  3248. if (pidl)
  3249. {
  3250. ASSERT(_ValidTargetPidl(pidl, NULL));
  3251. if (!g_fICWCheckComplete && IsBrowserFrameOptionsPidlSet(pidl, BFO_USE_DIALUP_REF))
  3252. {
  3253. if (MaybeRunICW(pidl, SAFECAST(this, IShellBrowser *), _pbbd->_hwnd))
  3254. {
  3255. // ICW ran and this was first navigate, shut down now.
  3256. // Or the user wants a software update, so we're launching a new browser
  3257. // to the update page
  3258. _pbbd->_pautoWB2->put_Visible(FALSE);
  3259. _pbbd->_pautoWB2->Quit();
  3260. return E_FAIL;
  3261. }
  3262. }
  3263. if (!_fVisitedNet && IsBrowserFrameOptionsPidlSet(pidl, BFO_USE_DIALUP_REF))
  3264. _IncrNetSessionCount();
  3265. }
  3266. // See if we are about to navigate to a pidl of a different type. If so,
  3267. // open the stream and call the ITBar's IPersistStreamInit::save to save.
  3268. // If we don't have a _pidlCur, then we're opening for the first time, so don't need to save
  3269. if (_pbbd->_pidlCur && _GetITBar())
  3270. {
  3271. //Check if we are about to navigate to a different "type" of folder
  3272. if (((INT_PTR)_pbbd->_pidlCur && !IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_BROWSER_PERSIST_SETTINGS)) !=
  3273. ((INT_PTR)pidl && !IsBrowserFrameOptionsPidlSet(pidl, BFO_BROWSER_PERSIST_SETTINGS)))
  3274. {
  3275. _SaveITbarLayout();
  3276. }
  3277. }
  3278. return SUPERCLASS::_NavigateToPidl(pidl, grfHLNF, dwFlags);
  3279. }
  3280. HRESULT CShellBrowser2::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
  3281. {
  3282. HRESULT hr;
  3283. LPITEMIDLIST pidlFree = NULL;
  3284. // if we're about to go to a new browser, save the layout so that they'll pick it up
  3285. if (wFlags & SBSP_NEWBROWSER)
  3286. _SaveITbarLayout();
  3287. // 99/03/30 vtan: part of #254171 addition
  3288. // explore with explorer band visible = same window
  3289. // explore with explorer band NOT visible = new window
  3290. if (wFlags & SBSP_EXPLOREMODE)
  3291. {
  3292. BOOL fExplorerBandVisible;
  3293. if (SUCCEEDED(IsControlWindowShown(FCW_TREE, &fExplorerBandVisible)) && fExplorerBandVisible)
  3294. {
  3295. wFlags &= ~SBSP_NEWBROWSER;
  3296. wFlags |= SBSP_SAMEBROWSER;
  3297. }
  3298. else
  3299. {
  3300. wFlags &= ~SBSP_SAMEBROWSER;
  3301. wFlags |= SBSP_NEWBROWSER;
  3302. }
  3303. }
  3304. // if the caller did not specify explictly "new window" or "same window"
  3305. // we compute that here for them. note, CBaseBrowser assumes SBSP_SAMEBROWSER
  3306. // if SBSP_NEWBROWSER is not specified
  3307. if ((wFlags & (SBSP_NEWBROWSER | SBSP_SAMEBROWSER)) == 0)
  3308. {
  3309. CABINETSTATE cs;
  3310. GetCabState(&cs);
  3311. if (GetAsyncKeyState(VK_CONTROL) < 0)
  3312. cs.fNewWindowMode = !cs.fNewWindowMode;
  3313. if (cs.fNewWindowMode)
  3314. wFlags |= SBSP_NEWBROWSER | SBSP_NOTRANSFERHIST;
  3315. }
  3316. BOOL fTranslate = FALSE;
  3317. // REVIEW: do this only if NEWBROWSER is not set?
  3318. if (pidl && pidl != (LPCITEMIDLIST)-1 && !_ValidTargetPidl(pidl, &fTranslate))
  3319. {
  3320. OpenFolderPidl(pidl); // we can't navigate to it... create a new top level dude
  3321. return E_FAIL;
  3322. }
  3323. if (fTranslate)
  3324. {
  3325. pidl = pidlFree = _TranslateRoot(pidl);
  3326. }
  3327. if ((wFlags & SBSP_PARENT) && !_ShouldAllowNavigateParent())
  3328. {
  3329. hr = E_FAIL;
  3330. goto exit;
  3331. }
  3332. #ifdef BROWSENEWPROCESS_STRICT // "Nav in new process" has become "Launch in new process", so this is no longer needed
  3333. // If we want to be strict about BrowseNewProcess (apparently not,
  3334. // given recent email discussions), we'd have to try this one in
  3335. // a new process. However, don't do that if the window would wind up
  3336. // completely blank.
  3337. //
  3338. if ((_pbbd->_pidlCur || _pbbd->_pidlPending) && TryNewProcessIfNeeded(pidl))
  3339. {
  3340. hr = S_OK;
  3341. goto exit;
  3342. }
  3343. #endif
  3344. hr = SUPERCLASS::BrowseObject(pidl, wFlags);
  3345. exit:
  3346. ILFree(pidlFree);
  3347. return hr;
  3348. }
  3349. void CShellBrowser2::_ToolTipFromCmd(LPTOOLTIPTEXT pnm)
  3350. {
  3351. UINT idCommand = (UINT)pnm->hdr.idFrom;
  3352. LPTSTR pszText = pnm->szText;
  3353. int cchText = ARRAYSIZE(pnm->szText);
  3354. DWORD dwStyle;
  3355. ITravelLog *ptl;
  3356. if (pnm->hdr.hwndFrom)
  3357. dwStyle = GetWindowLong(pnm->hdr.hwndFrom, GWL_STYLE);
  3358. switch (idCommand) {
  3359. case FCIDM_NAVIGATEBACK:
  3360. case FCIDM_NAVIGATEFORWARD:
  3361. if (SUCCEEDED(GetTravelLog(&ptl)))
  3362. {
  3363. WCHAR wzText[MAX_PATH];
  3364. ASSERT(ptl);
  3365. if (S_OK == ptl->GetToolTipText(SAFECAST(this, IShellBrowser *), idCommand == FCIDM_NAVIGATEBACK ? TLOG_BACK : TLOG_FORE, 0, wzText, ARRAYSIZE(wzText)))
  3366. {
  3367. SHUnicodeToTChar(wzText, pszText, cchText);
  3368. if (pnm->hdr.hwndFrom)
  3369. SetWindowLong(pnm->hdr.hwndFrom, GWL_STYLE, dwStyle | TTS_NOPREFIX);
  3370. }
  3371. ptl->Release();
  3372. return;
  3373. }
  3374. break;
  3375. }
  3376. if (pnm->hdr.hwndFrom)
  3377. SetWindowLong(pnm->hdr.hwndFrom, GWL_STYLE, dwStyle & ~(TTS_NOPREFIX));
  3378. if (!MLLoadString(idCommand + MH_TTBASE, pszText, cchText))
  3379. *pszText = 0;
  3380. }
  3381. void CShellBrowser2::v_ParentFolder()
  3382. {
  3383. if (_ShouldAllowNavigateParent())
  3384. {
  3385. IETHREADPARAM* piei = SHCreateIETHREADPARAM(NULL, 0, NULL, NULL);
  3386. if (piei)
  3387. {
  3388. piei->hwndCaller = _pbbd->_hwnd;
  3389. piei->pidl = ILClone(_pbbd->_pidlCur);
  3390. if (!ILRemoveHiddenID(piei->pidl, IDLHID_NAVIGATEMARKER))
  3391. {
  3392. ILRemoveLastID(piei->pidl);
  3393. }
  3394. piei->uFlags = COF_NORMAL;
  3395. piei->nCmdShow = SW_SHOW;
  3396. piei->psbCaller = this;
  3397. AddRef();
  3398. SHOpenFolderWindow(piei);
  3399. }
  3400. }
  3401. }
  3402. LRESULT CShellBrowser2::v_ForwardMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
  3403. {
  3404. return ForwardViewMsg(uMsg, wParam, lParam);
  3405. }
  3406. HRESULT CShellBrowser2::_GetCodePage(UINT *puiCodePage, DWORD dwCharSet)
  3407. {
  3408. HRESULT hres = E_FAIL;
  3409. VARIANT varIn = { 0 };
  3410. VARIANT varResult = { 0 };
  3411. VARIANT *pvarIn;
  3412. if (_pbbd->_pctView)
  3413. {
  3414. if (dwCharSet == SHDVID_DOCFAMILYCHARSET)
  3415. {
  3416. // need varIn
  3417. varIn.vt = VT_I4;
  3418. // varIn.lVal is already inited to zero which is what we want
  3419. pvarIn = &varIn;
  3420. }
  3421. else
  3422. {
  3423. pvarIn = NULL;
  3424. }
  3425. _pbbd->_pctView->Exec(&CGID_ShellDocView, dwCharSet, 0, pvarIn, &varResult);
  3426. *puiCodePage = (UINT)varResult.lVal;
  3427. }
  3428. return hres;
  3429. }
  3430. #if defined(UNIX)
  3431. HRESULT _UnixSendDocToOE(LPCITEMIDLIST, UINT, DWORD);
  3432. #endif
  3433. void CShellBrowser2::_SendCurrentPage(DWORD dwSendAs)
  3434. {
  3435. if (_pbbd->_pidlCur && !ILIsEmpty(_pbbd->_pidlCur))
  3436. {
  3437. UINT uiCodePage;
  3438. _GetCodePage(&uiCodePage, SHDVID_DOCCHARSET);
  3439. #ifdef UNIX
  3440. if (OEHandlesMail())
  3441. _UnixSendDocToOE(_pbbd->_pidlCur, uiCodePage, dwSendAs);
  3442. else
  3443. #endif
  3444. {
  3445. IOleCommandTarget *pcmdt = NULL;
  3446. if (_pbbd->_pautoWB2)
  3447. {
  3448. (_pbbd->_pautoWB2)->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  3449. ASSERT(pcmdt);
  3450. }
  3451. SendDocToMailRecipient(_pbbd->_pidlCur, uiCodePage, dwSendAs, pcmdt);
  3452. if (pcmdt)
  3453. pcmdt->Release();
  3454. }
  3455. }
  3456. }
  3457. typedef void (* PFNSHOWJAVACONSOLE)(void);
  3458. // We need a LoadLibrary/GetProcAddress stub here since msjava.lib improperly
  3459. // exports ShowJavaConsole as undecorated (ShowJavaConsole vs. _ShowJavaConsole@0).
  3460. STDAPI_(void) DL_ShowJavaConsole()
  3461. {
  3462. static PFNSHOWJAVACONSOLE s_pfn = (PFNSHOWJAVACONSOLE)-1;
  3463. if (s_pfn == (PFNSHOWJAVACONSOLE)-1)
  3464. {
  3465. HMODULE hmodMSJAVA = LoadLibraryA("MSJAVA.DLL");
  3466. if (hmodMSJAVA)
  3467. {
  3468. s_pfn = (PFNSHOWJAVACONSOLE)GetProcAddress(hmodMSJAVA, "ShowJavaConsole");
  3469. }
  3470. else
  3471. {
  3472. s_pfn = NULL;
  3473. }
  3474. }
  3475. if (s_pfn)
  3476. {
  3477. s_pfn();
  3478. }
  3479. }
  3480. LRESULT CShellBrowser2::OnCommand(WPARAM wParam, LPARAM lParam)
  3481. {
  3482. int id;
  3483. DWORD dwError;
  3484. if (_ShouldForwardMenu(WM_COMMAND, wParam, lParam)) {
  3485. ForwardViewMsg(WM_COMMAND, wParam, lParam);
  3486. return S_OK;
  3487. }
  3488. UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
  3489. switch(idCmd)
  3490. {
  3491. case FCIDM_MOVE:
  3492. case FCIDM_COPY:
  3493. case FCIDM_PASTE:
  3494. case FCIDM_SELECTALL:
  3495. {
  3496. IOleCommandTarget* pcmdt;
  3497. HRESULT hres = _FindActiveTarget(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  3498. if (SUCCEEDED(hres)) {
  3499. const static UINT c_mapEdit[] = {
  3500. OLECMDID_CUT, OLECMDID_COPY, OLECMDID_PASTE, OLECMDID_SELECTALL };
  3501. pcmdt->Exec(NULL, c_mapEdit[idCmd-FCIDM_MOVE], OLECMDEXECOPT_PROMPTUSER, NULL, NULL);
  3502. pcmdt->Release();
  3503. }
  3504. }
  3505. return S_OK;
  3506. case FCIDM_DELETE:
  3507. case FCIDM_PROPERTIES:
  3508. case FCIDM_RENAME:
  3509. if (_HasToolbarFocus())
  3510. {
  3511. static const int tbtab[] = {
  3512. FCIDM_DELETE, FCIDM_PROPERTIES, FCIDM_RENAME };
  3513. static const int cttab[] = {
  3514. SBCMDID_FILEDELETE, SBCMDID_FILEPROPERTIES, SBCMDID_FILERENAME };
  3515. DWORD nCmdID = SHSearchMapInt(tbtab, cttab, ARRAYSIZE(tbtab), idCmd);
  3516. IDockingWindow* ptbar = _GetToolbarItem(_itbLastFocus)->ptbar;
  3517. if (SUCCEEDED(IUnknown_Exec(ptbar, &CGID_Explorer, nCmdID, 0, NULL, NULL)))
  3518. return S_OK;
  3519. }
  3520. SUPERCLASS::OnCommand(wParam, lParam);
  3521. break;
  3522. case FCIDM_VIEWAUTOHIDE:
  3523. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_VIEWAUTOHIDE, 0, NULL, NULL);
  3524. break;
  3525. case FCIDM_VIEWTOOLBARCUSTOMIZE:
  3526. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_VIEWTOOLBARCUSTOMIZE, 0, NULL, NULL);
  3527. break;
  3528. case FCIDM_VIEWLOCKTOOLBAR:
  3529. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_VIEWLOCKTOOLBAR, 0, NULL, NULL);
  3530. break;
  3531. case FCIDM_VIEWTEXTLABELS:
  3532. if (!SHIsRestricted2W(_pbbd->_hwnd, REST_NoToolbarOptions, NULL, 0))
  3533. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_TEXTLABELS, 0, NULL, NULL);
  3534. break;
  3535. case FCIDM_EDITPAGE:
  3536. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_EDITPAGE, 0, NULL, NULL);
  3537. break;
  3538. case FCIDM_FINDFILES:
  3539. // Call Exec on ourselfes -- it's handled there
  3540. if (!SHIsRestricted2W(_pbbd->_hwnd, REST_NoFindFiles, NULL, 0))
  3541. {
  3542. IDockingWindow* ptbar = _GetToolbarItem(ITB_ITBAR)->ptbar;
  3543. VARIANT var = {0};
  3544. VARIANT *pvar = NULL;
  3545. if (ptbar)
  3546. {
  3547. pvar = &var;
  3548. var.vt = VT_UNKNOWN;
  3549. var.punkVal = ptbar;
  3550. ptbar->AddRef();
  3551. }
  3552. Exec(NULL, OLECMDID_FIND, OLECMDEXECOPT_PROMPTUSER, pvar, NULL);
  3553. if (ptbar)
  3554. ptbar->Release();
  3555. }
  3556. break;
  3557. case FCIDM_CONNECT:
  3558. DoNetConnect(_pbbd->_hwnd);
  3559. break;
  3560. case FCIDM_DISCONNECT:
  3561. DoNetDisconnect(_pbbd->_hwnd);
  3562. break;
  3563. case FCIDM_FORTEZZA_LOGIN:
  3564. dwError = InternetFortezzaCommand(FORTCMD_LOGON, _pbbd->_hwnd, 0);
  3565. break;
  3566. case FCIDM_FORTEZZA_LOGOUT:
  3567. dwError = InternetFortezzaCommand(FORTCMD_LOGOFF, _pbbd->_hwnd, 0);
  3568. break;
  3569. case FCIDM_FORTEZZA_CHANGE:
  3570. dwError = InternetFortezzaCommand(FORTCMD_CHG_PERSONALITY, _pbbd->_hwnd, 0);
  3571. break;
  3572. case FCIDM_BACKSPACE:
  3573. // NT #216896: We want to use FCIDM_PREVIOUSFOLDER even for URL PIDLs if they
  3574. // have the folder attribute set because they could be using delegate
  3575. // pidls thru DefView. (FTP & Web Folders) -BryanSt
  3576. if (_pbbd->_pidlCur && IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_NO_PARENT_FOLDER_SUPPORT))
  3577. {
  3578. ITravelLog *ptl;
  3579. if (SUCCEEDED(GetTravelLog(&ptl)))
  3580. {
  3581. ASSERT(ptl);
  3582. if (S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_FORE, NULL))
  3583. {
  3584. OnCommand(GET_WM_COMMAND_MPS(FCIDM_NAVIGATEBACK,
  3585. GET_WM_COMMAND_HWND(wParam, lParam),
  3586. GET_WM_COMMAND_CMD(wParam, lParam)));
  3587. }
  3588. ptl->Release();
  3589. }
  3590. } else {
  3591. OnCommand(GET_WM_COMMAND_MPS(FCIDM_PREVIOUSFOLDER,
  3592. GET_WM_COMMAND_HWND(wParam, lParam),
  3593. GET_WM_COMMAND_CMD(wParam, lParam)));
  3594. }
  3595. break;
  3596. case FCIDM_PREVIOUSFOLDER:
  3597. // missnamed... is really parent folder
  3598. v_ParentFolder();
  3599. break;
  3600. case FCIDM_FILECLOSE:
  3601. PostMessage(_pbbd->_hwnd, WM_CLOSE, 0, 0);
  3602. break;
  3603. case FCIDM_FTPOPTIONS:
  3604. {
  3605. VARIANT varArgs = {0};
  3606. varArgs.vt = VT_I4;
  3607. varArgs.lVal = SBO_NOBROWSERPAGES;
  3608. Exec(&CGID_Explorer, SBCMDID_OPTIONS, 0, &varArgs, NULL);
  3609. }
  3610. break;
  3611. case FCIDM_BROWSEROPTIONS:
  3612. if (!IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_RENAME_FOLDER_OPTIONS_TOINTERNET) ||
  3613. !SHIsRestricted2W(_pbbd->_hwnd, REST_NoBrowserOptions, NULL, 0))
  3614. Exec(&CGID_Explorer, SBCMDID_OPTIONS, 0, NULL, NULL);
  3615. break;
  3616. case FCIDM_RESETWEBSETTINGS:
  3617. ResetWebSettings(_pbbd->_hwnd, NULL);
  3618. break;
  3619. case FCIDM_MAIL:
  3620. #ifdef UNIX
  3621. if (!OEHandlesMail())
  3622. {
  3623. SendDocToMailRecipient(NULL, 0, MAIL_ACTION_READ, NULL);
  3624. }
  3625. else
  3626. #endif
  3627. SHRunIndirectRegClientCommand(_pbbd->_hwnd, MAIL_DEF_KEY);
  3628. break;
  3629. case FCIDM_MYCOMPUTER:
  3630. {
  3631. LPITEMIDLIST pidlMyComputer;
  3632. SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer);
  3633. if (pidlMyComputer)
  3634. {
  3635. BrowseObject(pidlMyComputer, SBSP_SAMEBROWSER);
  3636. ILFree(pidlMyComputer);
  3637. }
  3638. }
  3639. break;
  3640. case FCIDM_CONTACTS:
  3641. SHRunIndirectRegClientCommand(_pbbd->_hwnd, CONTACTS_DEF_KEY);
  3642. break;
  3643. case FCIDM_NEWS:
  3644. #ifdef UNIX
  3645. if (!CheckAndExecNewsScript(_pbbd->_hwnd))
  3646. #endif
  3647. SHRunIndirectRegClientCommand(_pbbd->_hwnd, NEWS_DEF_KEY);
  3648. break;
  3649. case FCIDM_CALENDAR:
  3650. SHRunIndirectRegClientCommand(_pbbd->_hwnd, CALENDAR_DEF_KEY);
  3651. break;
  3652. case FCIDM_TASKS:
  3653. SHRunIndirectRegClientCommand(_pbbd->_hwnd, TASKS_DEF_KEY);
  3654. break;
  3655. case FCIDM_JOURNAL:
  3656. SHRunIndirectRegClientCommand(_pbbd->_hwnd, JOURNAL_DEF_KEY);
  3657. break;
  3658. case FCIDM_NOTES:
  3659. SHRunIndirectRegClientCommand(_pbbd->_hwnd, NOTES_DEF_KEY);
  3660. break;
  3661. case FCIDM_CALL:
  3662. SHRunIndirectRegClientCommand(_pbbd->_hwnd, CALL_DEF_KEY);
  3663. break;
  3664. case FCIDM_NEWMESSAGE:
  3665. #ifdef UNIX
  3666. if (OEHandlesMail())
  3667. {
  3668. // PORT QSY should be SendDocToMailRecipient()
  3669. // But the function is now used to invoke native unix
  3670. // mailers such as emacs script
  3671. _UnixSendDocToOE(NULL, 0, MAIL_ACTION_SEND);
  3672. }
  3673. else
  3674. {
  3675. SendDocToMailRecipient(NULL, 0, MAIL_ACTION_SEND, NULL);
  3676. }
  3677. #else
  3678. DropOnMailRecipient(NULL, 0);
  3679. #endif
  3680. break;
  3681. case FCIDM_SENDLINK:
  3682. case FCIDM_SENDDOCUMENT:
  3683. _SendCurrentPage(idCmd == FCIDM_SENDDOCUMENT ? FORCE_COPY : FORCE_LINK);
  3684. break;
  3685. case FCIDM_STARTPAGE:
  3686. case FCIDM_UPDATEPAGE:
  3687. case FCIDM_CHANNELGUIDE:
  3688. {
  3689. LPITEMIDLIST pidl = NULL;
  3690. #ifdef UNIX
  3691. if (idCmd == FCIDM_STARTPAGE && lParam != 0)
  3692. {
  3693. pidl = (LPITEMIDLIST)lParam;
  3694. BrowseObject(pidl, SBSP_SAMEBROWSER);
  3695. ILFree(pidl);
  3696. break;
  3697. }
  3698. #endif
  3699. ASSERT(IDP_START == 0);
  3700. ASSERT(FCIDM_STARTPAGE+IDP_START == FCIDM_STARTPAGE);
  3701. ASSERT(FCIDM_STARTPAGE+IDP_UPDATE == FCIDM_UPDATEPAGE);
  3702. ASSERT(FCIDM_STARTPAGE+IDP_CHANNELGUIDE == FCIDM_CHANNELGUIDE);
  3703. HRESULT hres = SHDGetPageLocation(_pbbd->_hwnd, idCmd-FCIDM_STARTPAGE, NULL, 0, &pidl);
  3704. if (SUCCEEDED(hres)) {
  3705. hres = BrowseObject(pidl, SBSP_SAMEBROWSER);
  3706. ILFree(pidl);
  3707. }
  3708. }
  3709. break;
  3710. case FCIDM_SEARCHPAGE:
  3711. {
  3712. // This command from the Windows Explorer's Go menu used to be handled by navigating to
  3713. // a search page on MSN. We now maintain consistency with the shell's handling of
  3714. // Start->Find->On the Internet, by invoking the extension directly.
  3715. ASSERT(FCIDM_STARTPAGE+IDP_SEARCH == FCIDM_SEARCHPAGE);
  3716. IContextMenu *pcm;
  3717. HRESULT hres = CoCreateInstance(CLSID_WebSearchExt, NULL,
  3718. CLSCTX_INPROC_SERVER, IID_IContextMenu, (void **) &pcm);
  3719. if (SUCCEEDED(hres))
  3720. {
  3721. CMINVOKECOMMANDINFO ici = {0};
  3722. ici.cbSize = sizeof(ici);
  3723. ici.nShow = SW_NORMAL;
  3724. pcm->InvokeCommand(&ici);
  3725. pcm->Release();
  3726. }
  3727. }
  3728. break;
  3729. case FCIDM_HELPABOUT:
  3730. #ifdef UNIX
  3731. IEAboutBox(_pbbd->_hwnd);
  3732. break;
  3733. #else
  3734. {
  3735. TCHAR szWindows[64];
  3736. MLLoadString(IDS_WINDOWSNT, szWindows, ARRAYSIZE(szWindows));
  3737. ShellAbout(_pbbd->_hwnd, szWindows, NULL, NULL);
  3738. break;
  3739. }
  3740. #endif
  3741. case FCIDM_HELPTIPOFTHEDAY:
  3742. _SetBrowserBarState(-1, &CLSID_TipOfTheDay, -1);
  3743. break;
  3744. case FCIDM_HELPISLEGAL:
  3745. {
  3746. TCHAR szFWLinkPathTemplate[MAX_PATH];
  3747. TCHAR szFWLinkPath[MAX_PATH];
  3748. LPITEMIDLIST pidl;
  3749. LoadString(HINST_THISDLL, IDS_FWLINK_HELPISLEGAL, szFWLinkPathTemplate, ARRAYSIZE(szFWLinkPathTemplate));
  3750. if (SUCCEEDED(URLSubstitution(szFWLinkPathTemplate, szFWLinkPath, ARRAYSIZE(szFWLinkPath), URLSUB_CLCID)))
  3751. {
  3752. if (SUCCEEDED(IEParseDisplayName(CP_ACP, szFWLinkPath, &pidl)))
  3753. {
  3754. BrowseObject(pidl, SBSP_SAMEBROWSER);
  3755. ILFree(pidl);
  3756. }
  3757. }
  3758. break;
  3759. }
  3760. case FCIDM_NAVIGATEBACK:
  3761. if (_pbbd->_psvPending)
  3762. {
  3763. _CancelPendingView();
  3764. }
  3765. else
  3766. {
  3767. if (g_dwStopWatchMode & (SPMODE_BROWSER | SPMODE_JAVA))
  3768. {
  3769. DWORD dwTime = GetPerfTime();
  3770. if (g_dwStopWatchMode & SPMODE_BROWSER) // Used to get browser total download time
  3771. StopWatch_StartTimed(SWID_BROWSER_FRAME, TEXT("Browser Frame Back"), SPMODE_BROWSER | SPMODE_DEBUGOUT, dwTime);
  3772. if (g_dwStopWatchMode & SPMODE_JAVA) // Used to get java applet load time
  3773. StopWatch_StartTimed(SWID_JAVA_APP, TEXT("Java Applet Back"), SPMODE_JAVA | SPMODE_DEBUGOUT, dwTime);
  3774. }
  3775. NavigateToPidl(NULL, HLNF_NAVIGATINGBACK);
  3776. }
  3777. break;
  3778. case FCIDM_NAVIGATEFORWARD:
  3779. NavigateToPidl(NULL, HLNF_NAVIGATINGFORWARD);
  3780. break;
  3781. case FCIDM_ADDTOFAVNOUI:
  3782. Exec(&CGID_Explorer, SBCMDID_ADDTOFAVORITES, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  3783. // Instrument this, add to favorites called by keyboard
  3784. UEMFireEvent(&UEMIID_BROWSER, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_ADDTOFAV, UIBL_KEYBOARD);
  3785. break;
  3786. // Some tools relied on the old Command ID...
  3787. case FCIDM_W95REFRESH:
  3788. idCmd = FCIDM_REFRESH;
  3789. // Fall through...
  3790. case FCIDM_REFRESH:
  3791. if (TRUE == _fInRefresh)
  3792. {
  3793. // We are already doing a refresh. If we keep doing refreshes,
  3794. // then we can enter into infinite recursion. If the refresh
  3795. // cause a dialog to be displayed and refresh messages keep coming
  3796. // in, then the messagebox call will be called over and over.
  3797. // Besides multiple dialog boxes, this grows the stack until
  3798. // we run out of space and crash.
  3799. break;
  3800. }
  3801. _fInRefresh = TRUE;
  3802. // fall thru...
  3803. case FCIDM_STOP:
  3804. {
  3805. SHELLSTATE ss = {0};
  3806. SHGetSetSettings(&ss, SSF_MAPNETDRVBUTTON, FALSE);
  3807. if ((!_fShowNetworkButtons && ss.fMapNetDrvBtn) ||
  3808. (_fShowNetworkButtons && !ss.fMapNetDrvBtn))
  3809. {
  3810. UINT uiBtnState = 0;
  3811. _fShowNetworkButtons = ss.fMapNetDrvBtn;
  3812. _pxtb->GetState(&CLSID_CommonButtons, TBIDM_CONNECT, &uiBtnState);
  3813. if (ss.fMapNetDrvBtn)
  3814. uiBtnState &= ~TBSTATE_HIDDEN;
  3815. else
  3816. uiBtnState |= TBSTATE_HIDDEN;
  3817. _pxtb->SetState(&CLSID_CommonButtons, TBIDM_CONNECT, uiBtnState);
  3818. _pxtb->SetState(&CLSID_CommonButtons, TBIDM_DISCONNECT, uiBtnState);
  3819. }
  3820. if (idCmd == FCIDM_REFRESH)
  3821. {
  3822. VARIANT v = {0};
  3823. v.vt = VT_I4;
  3824. v.lVal = OLECMDIDF_REFRESH_NO_CACHE|OLECMDIDF_REFRESH_PROMPTIFOFFLINE;
  3825. Exec(NULL, OLECMDID_REFRESH, OLECMDEXECOPT_DONTPROMPTUSER, &v, NULL);
  3826. // Refresh the toolbar
  3827. if (_pxtb)
  3828. {
  3829. IServiceProvider* psp;
  3830. if (SUCCEEDED(_pxtb->QueryInterface(IID_PPV_ARG(IServiceProvider, &psp))))
  3831. {
  3832. IAddressBand *pab = NULL;
  3833. if (SUCCEEDED(psp->QueryService(IID_IAddressBand, IID_IAddressBand, (void**)&pab)))
  3834. {
  3835. VARIANTARG varType = {0};
  3836. varType.vt = VT_I4;
  3837. varType.lVal = OLECMD_REFRESH_TOPMOST;
  3838. pab->Refresh(&varType);
  3839. pab->Release();
  3840. }
  3841. psp->Release();
  3842. }
  3843. }
  3844. }
  3845. else
  3846. {
  3847. if (g_dwStopWatchMode & SPMODE_BROWSER)
  3848. StopWatch_Lap(SWID_BROWSER_FRAME | SWID_MASK_BROWSER_STOPBTN, TEXT("Browser Frame Esc"), SPMODE_BROWSER | SPMODE_DEBUGOUT);
  3849. Exec(NULL, OLECMDID_STOP, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
  3850. }
  3851. if (FCIDM_REFRESH == idCmd)
  3852. {
  3853. _fInRefresh = FALSE;
  3854. }
  3855. break;
  3856. }
  3857. #ifndef DISABLE_FULLSCREEN
  3858. case FCIDM_THEATER:
  3859. if (!SHRestricted2(REST_NoTheaterMode, NULL, 0))
  3860. {
  3861. // Toggle theater mode. Don't allow theater mode if we're in kiosk mode.
  3862. if (_ptheater || _fKioskMode) {
  3863. _TheaterMode(FALSE, TRUE);
  3864. } else {
  3865. _TheaterMode(TRUE, FALSE);
  3866. }
  3867. }
  3868. break;
  3869. #endif
  3870. case FCIDM_NEXTCTL:
  3871. _CycleFocus(NULL);
  3872. break;
  3873. case FCIDM_VIEWOFFLINE:
  3874. if ((!SHIsGlobalOffline()) && (IsCriticalOperationPending()))
  3875. {
  3876. if (MLShellMessageBox(_pbbd->_hwnd,
  3877. MAKEINTRESOURCE(IDS_CANCELFILEDOWNLOAD),
  3878. MAKEINTRESOURCE(IDS_FILEDOWNLOADCAPTION),
  3879. MB_YESNO | MB_ICONSTOP) == IDNO)
  3880. break;
  3881. }
  3882. Offline(SBSC_TOGGLE);
  3883. if (_pbbd->_pszTitleCur)
  3884. _SetTitle(_pbbd->_pszTitleCur);
  3885. break;
  3886. #ifdef TEST_AMBIENTS
  3887. case FCIDM_VIEWLOCALOFFLINE:
  3888. _LocalOffline(SBSC_TOGGLE);
  3889. break;
  3890. case FCIDM_VIEWLOCALSILENT:
  3891. _LocalSilent(SBSC_TOGGLE);
  3892. break;
  3893. #endif // TEST_AMBIENTS
  3894. case FCIDM_VIEWTOOLBAR:
  3895. v_ShowControl(FCW_INTERNETBAR, SBSC_TOGGLE);
  3896. break;
  3897. case FCIDM_VIEWMENU:
  3898. id = CITIDM_VIEWMENU;
  3899. goto ITBarShowBand;
  3900. case FCIDM_VIEWTOOLS:
  3901. id = CITIDM_VIEWTOOLS;
  3902. goto ITBarShowBand;
  3903. case FCIDM_VIEWADDRESS:
  3904. id = CITIDM_VIEWADDRESS;
  3905. goto ITBarShowBand;
  3906. case FCIDM_VIEWLINKS:
  3907. id = CITIDM_VIEWLINKS;
  3908. goto ITBarShowBand;
  3909. ITBarShowBand:
  3910. if (!SHIsRestricted2W(_pbbd->_hwnd, REST_NoToolbarOptions, NULL, 0))
  3911. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, id, 0, NULL, NULL);
  3912. break;
  3913. case FCIDM_VIEWSTATUSBAR:
  3914. v_ShowControl(FCW_STATUS, SBSC_TOGGLE);
  3915. break;
  3916. case FCIDM_VBBSEARCHBAND:
  3917. {
  3918. IDockingWindow* ptbar = _GetToolbarItem(ITB_ITBAR)->ptbar;
  3919. VARIANT var = {0};
  3920. var.vt = VT_I4;
  3921. var.lVal = -1;
  3922. IUnknown_Exec(ptbar, &CLSID_CommonButtons, TBIDM_SEARCH, 0, NULL, &var);
  3923. }
  3924. break;
  3925. case FCIDM_VIEW_PRIVACY_POLICIES:
  3926. {
  3927. if ( _pbbd != NULL && _pbbd->_pctView != NULL)
  3928. {
  3929. HRESULT hr = _pbbd->_pctView->Exec(&CGID_ShellDocView,
  3930. SHDVID_PRIVACYSTATUS, TRUE, NULL, NULL);
  3931. }
  3932. }
  3933. break;
  3934. case FCIDM_VBBEXPLORERBAND:
  3935. case FCIDM_VBBFAVORITESBAND:
  3936. case FCIDM_VBBHISTORYBAND:
  3937. case FCIDM_VBBMEDIABAND:
  3938. if (g_dwStopWatchMode)
  3939. {
  3940. StopWatch_Start(SWID_EXPLBAR, TEXT("Shell bar Start"), SPMODE_SHELL | SPMODE_DEBUGOUT);
  3941. }
  3942. switch (idCmd)
  3943. {
  3944. case FCIDM_VBBFAVORITESBAND:
  3945. if (SHIsRestricted2W(_pbbd->_hwnd, REST_NoFavorites, NULL, 0))
  3946. break;
  3947. default:
  3948. _SetBrowserBarState(idCmd, NULL, -1);
  3949. break;
  3950. }
  3951. if (g_dwStopWatchMode)
  3952. {
  3953. TCHAR szText[100];
  3954. TCHAR szMenu[32];
  3955. DWORD dwTime = GetPerfTime();
  3956. GetMenuString(_GetMenuFromID(FCIDM_MENU_VIEW), idCmd, szMenu, ARRAYSIZE(szMenu) - 1, MF_BYCOMMAND);
  3957. wnsprintf(szText, ARRAYSIZE(szText) - 1, TEXT("Shell %s bar Stop"), szMenu);
  3958. StopWatch_StopTimed(SWID_EXPLBAR, (LPCTSTR)szText, SPMODE_SHELL | SPMODE_DEBUGOUT, dwTime);
  3959. }
  3960. break;
  3961. case FCIDM_JAVACONSOLE:
  3962. DL_ShowJavaConsole();
  3963. break;
  3964. case FCIDM_SHOWSCRIPTERRDLG:
  3965. {
  3966. HRESULT hr;
  3967. hr = Exec(&CGID_ShellDocView,
  3968. SHDVID_DISPLAYSCRIPTERRORS,
  3969. 0,
  3970. NULL,
  3971. NULL);
  3972. return hr;
  3973. }
  3974. break;
  3975. default:
  3976. if (IsInRange(idCmd, FCIDM_FAVORITECMDFIRST, FCIDM_FAVORITECMDLAST)
  3977. && !SHIsRestricted2W(_pbbd->_hwnd, REST_NoFavorites, NULL, 0)) {
  3978. _FavoriteOnCommand(NULL, idCmd);
  3979. } else if (IsInRange(idCmd, FCIDM_RECENTFIRST, FCIDM_RECENTLAST)) {
  3980. ITravelLog *ptl;
  3981. GetTravelLog(&ptl);
  3982. if (ptl)
  3983. {
  3984. ptl->Travel(SAFECAST(this, IShellBrowser *), idCmd - (FCIDM_RECENTFIRST + GOMENU_RECENT_ITEMS) + GOMENU_RECENT_ITEMS / 2);
  3985. ptl->Release();
  3986. UpdateBackForwardState();
  3987. }
  3988. } else if (IsInRange(idCmd, FCIDM_SEARCHFIRST, FCIDM_SEARCHLAST)) {
  3989. if (_pcmSearch)
  3990. {
  3991. CMINVOKECOMMANDINFO ici = {0};
  3992. ici.cbSize = sizeof(ici);
  3993. //ici.hwnd = NULL; // no need for hwnd for search cm InvokeCommand
  3994. ici.lpVerb = (LPSTR)MAKEINTRESOURCE(idCmd - FCIDM_SEARCHFIRST);
  3995. ici.nShow = SW_NORMAL;
  3996. _pcmSearch->InvokeCommand(&ici);
  3997. }
  3998. else
  3999. {
  4000. TraceMsg(DM_TRACE, "CSB::OnCommand() - find cmd with NULL pcmFind");
  4001. }
  4002. } else if (IsInRange(idCmd, FCIDM_MENU_TOOLS_FINDFIRST, FCIDM_MENU_TOOLS_FINDLAST)) {
  4003. if (GetUIVersion() < 5 && _pcmFind)
  4004. {
  4005. LPITEMIDLIST pidl = (_pbbd->_pidlPending) ? _pbbd->_pidlPending : _pbbd->_pidlCur;
  4006. TCHAR szPath[MAX_PATH];
  4007. SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szPath, SIZECHARS(szPath), NULL);
  4008. // Handle cases like "desktop" (make it default to My Computer)
  4009. if (!PathIsDirectory(szPath))
  4010. {
  4011. szPath[0] = TEXT('\0');
  4012. }
  4013. CMINVOKECOMMANDINFO ici = {0};
  4014. ici.cbSize = sizeof(ici);
  4015. //ici.hwnd = NULL; // no need for hwnd for search cm InvokeCommand
  4016. ici.lpVerb = (LPSTR)MAKEINTRESOURCE(idCmd - FCIDM_MENU_TOOLS_FINDFIRST);
  4017. ici.nShow = SW_NORMAL;
  4018. // Set the root of the search
  4019. char szAnsiPath[MAX_PATH];
  4020. szAnsiPath[0] = '\0';
  4021. SHTCharToAnsi(szPath, szAnsiPath, ARRAYSIZE(szAnsiPath));
  4022. ici.lpDirectory = szAnsiPath;
  4023. _pcmFind->InvokeCommand(&ici);
  4024. }
  4025. } else if (IsInRange(idCmd, FCIDM_VBBDYNFIRST, FCIDM_VBBDYNLAST)) {
  4026. _SetBrowserBarState(idCmd, NULL, -1);
  4027. } else if (IsInRange(idCmd, FCIDM_FILECTX_FIRST, FCIDM_FILECTX_LAST)) {
  4028. _ExecFileContext(idCmd);
  4029. } else if (IsInRange(idCmd, FCIDM_EXTERNALBANDS_FIRST, FCIDM_EXTERNALBANDS_LAST)) {
  4030. id = idCmd - FCIDM_EXTERNALBANDS_FIRST + CITIDM_VIEWEXTERNALBAND_FIRST;
  4031. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, id, 0, NULL, NULL);
  4032. } else {
  4033. SUPERCLASS::OnCommand(wParam, lParam);
  4034. }
  4035. break;
  4036. }
  4037. return S_OK;
  4038. }
  4039. HMENU CShellBrowser2::_GetMenuFromID(UINT uID)
  4040. {
  4041. return SHGetMenuFromID(_hmenuCur, uID);
  4042. }
  4043. void CShellBrowser2::_PruneMailNewsItems(HMENU hmenu)
  4044. {
  4045. //
  4046. // REARCHITECT: this logic is duplicated in _OnFileMenuPopup,
  4047. // _OnMailMenuPopup, CDocObjectHost::_OnInitMenuPopup
  4048. //
  4049. // Iterate through the mail, news, contacts, etc. menu items,
  4050. // and for each item, remove the item if either
  4051. //
  4052. // (a) REST_GoMenu is set, or
  4053. // (b) the item has no registered client
  4054. //
  4055. // If all items are removed, remember to remove the separator too.
  4056. //
  4057. static const struct
  4058. {
  4059. DWORD dwCmd;
  4060. LPCTSTR pszClient;
  4061. }
  4062. c_mailnewsitems[] =
  4063. {
  4064. { FCIDM_MAIL, MAIL_DEF_KEY },
  4065. { FCIDM_NEWS, NEWS_DEF_KEY },
  4066. { FCIDM_CONTACTS, CONTACTS_DEF_KEY },
  4067. { FCIDM_CALENDAR, CALENDAR_DEF_KEY },
  4068. { FCIDM_TASKS, TASKS_DEF_KEY },
  4069. { FCIDM_JOURNAL, JOURNAL_DEF_KEY },
  4070. { FCIDM_NOTES, NOTES_DEF_KEY },
  4071. { FCIDM_CALL, CALL_DEF_KEY },
  4072. };
  4073. BOOL fGoRestricted = SHRestricted2(REST_GoMenu, NULL, 0);
  4074. for (int i = 0; i < ARRAYSIZE(c_mailnewsitems); i++)
  4075. {
  4076. if (fGoRestricted || !SHIsRegisteredClient(c_mailnewsitems[i].pszClient))
  4077. {
  4078. DeleteMenu(hmenu, c_mailnewsitems[i].dwCmd, MF_BYCOMMAND);
  4079. }
  4080. }
  4081. _SHPrettyMenu(hmenu); // to ensure separator is removed if necessary
  4082. }
  4083. void CShellBrowser2::_ExecFileContext(UINT idCmd)
  4084. {
  4085. if (_pcmNsc)
  4086. {
  4087. CMINVOKECOMMANDINFO ici = {
  4088. sizeof(CMINVOKECOMMANDINFO),
  4089. 0L,
  4090. _pbbd->_hwnd,
  4091. MAKEINTRESOURCEA(idCmd-FCIDM_FILECTX_FIRST),
  4092. NULL,
  4093. NULL,
  4094. SW_NORMAL,
  4095. };
  4096. _pcmNsc->InvokeCommand(&ici);
  4097. // It's no good after an invoke...
  4098. IUnknown_SetSite(_pcmNsc, NULL);
  4099. ATOMICRELEASE(_pcmNsc);
  4100. }
  4101. }
  4102. void CShellBrowser2::_EnableFileContext(HMENU hmenuPopup)
  4103. {
  4104. IContextMenu2 *pcm = NULL;
  4105. OLECMDTEXTV<MAX_FILECONTEXT_STRING> cmdtv;
  4106. OLECMDTEXT *pcmdText = &cmdtv;
  4107. // First clean up any previous merge we may have done
  4108. DeleteMenu(hmenuPopup, FCIDM_FILENSCBANDSEP, MF_BYCOMMAND);
  4109. DeleteMenu(hmenuPopup, FCIDM_FILENSCBANDPOPUP, MF_BYCOMMAND);
  4110. IUnknown_SetSite(_pcmNsc, NULL);
  4111. ATOMICRELEASE(_pcmNsc);
  4112. // Second, get the name and pcm for the NSC selection, if available
  4113. if (_poctNsc)
  4114. {
  4115. OLECMD rgcmd = { SBCMDID_INITFILECTXMENU, 0 };
  4116. pcmdText->cwBuf = MAX_FILECONTEXT_STRING;
  4117. pcmdText->cmdtextf = OLECMDTEXTF_NAME;
  4118. pcmdText->rgwz[0] = 0;
  4119. _poctNsc->QueryStatus(&CGID_Explorer, 1, &rgcmd, pcmdText);
  4120. if (rgcmd.cmdf & OLECMDF_ENABLED)
  4121. {
  4122. VARIANT var = {0};
  4123. HRESULT hr = _poctNsc->Exec(&CGID_Explorer, SBCMDID_INITFILECTXMENU, OLECMDEXECOPT_PROMPTUSER, NULL, &var);
  4124. if (SUCCEEDED(hr) && VT_UNKNOWN == var.vt && NULL != var.punkVal)
  4125. {
  4126. var.punkVal->QueryInterface(IID_PPV_ARG(IContextMenu2, &pcm));
  4127. }
  4128. VariantClearLazy(&var);
  4129. }
  4130. }
  4131. // Third, merge the menu in if we got it
  4132. if (pcm)
  4133. {
  4134. HMENU hmenu = CreatePopupMenu();
  4135. if (hmenu)
  4136. {
  4137. IUnknown_SetSite(pcm, _poctNsc);
  4138. HRESULT hr = pcm->QueryContextMenu(hmenu, 0, FCIDM_FILECTX_FIRST, FCIDM_FILECTX_LAST, CMF_EXPLORE);
  4139. if (SUCCEEDED(hr))
  4140. {
  4141. UINT nInsert = SHMenuIndexFromID(hmenuPopup, FCIDM_VIEWOFFLINE);
  4142. if (-1 == nInsert)
  4143. nInsert = SHMenuIndexFromID(hmenuPopup, FCIDM_FILECLOSE);
  4144. if (-1 == nInsert)
  4145. nInsert = GetMenuItemCount(hmenuPopup);
  4146. MENUITEMINFO mii = {0};
  4147. mii.cbSize = sizeof(mii);
  4148. mii.fMask = MIIM_ID | MIIM_TYPE;
  4149. mii.fType = MFT_SEPARATOR;
  4150. mii.wID = FCIDM_FILENSCBANDSEP;
  4151. InsertMenuItem(hmenuPopup, nInsert, MF_BYPOSITION, &mii);
  4152. // BUGBUG: "&" is a legal UI name, we need to map this to "&&" or whatever the menu escape sequence is...
  4153. mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU;
  4154. mii.fType = MFT_STRING;
  4155. mii.hSubMenu = hmenu;
  4156. mii.dwTypeData = pcmdText->rgwz;
  4157. mii.wID = FCIDM_FILENSCBANDPOPUP;
  4158. InsertMenuItem(hmenuPopup, nInsert, MF_BYPOSITION, &mii);
  4159. _pcmNsc = pcm;
  4160. _pcmNsc->AddRef();
  4161. }
  4162. else
  4163. {
  4164. IUnknown_SetSite(pcm, NULL);
  4165. }
  4166. if (FAILED(hr))
  4167. DestroyMenu(hmenu);
  4168. }
  4169. pcm->Release();
  4170. }
  4171. }
  4172. void CShellBrowser2::_MungeGoMyComputer(HMENU hmenuPopup)
  4173. {
  4174. //need to have a menu item My Computer but a user might have changed
  4175. //it to something else so go get the new name
  4176. LPITEMIDLIST pidlMyComputer;
  4177. TCHAR szBuffer[MAX_PATH]; //buffer to hold menu item string
  4178. TCHAR szMenuText[MAX_PATH+1+6];
  4179. SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer);
  4180. if (pidlMyComputer)
  4181. {
  4182. if (SUCCEEDED(SHGetNameAndFlags(pidlMyComputer, SHGDN_NORMAL, szMenuText, SIZECHARS(szMenuText), NULL)))
  4183. {
  4184. MENUITEMINFO mii;
  4185. mii.cbSize = sizeof(MENUITEMINFO);
  4186. mii.fMask = MIIM_TYPE;
  4187. mii.fType = MFT_STRING;
  4188. mii.dwTypeData = szBuffer;
  4189. mii.cch = ARRAYSIZE(szBuffer);
  4190. if (GetMenuItemInfoWrap(hmenuPopup, FCIDM_MYCOMPUTER, FALSE, &mii))
  4191. {
  4192. LPTSTR pszHot;
  4193. LPTSTR pszMenuItem = (LPTSTR) mii.dwTypeData;
  4194. //before we get rid of the old name, need to get
  4195. //the hot key for it
  4196. //check if the old name had a hot key
  4197. //StrChr is defined in shlwapi (strings.c) and accepts word even in ascii version
  4198. if (NULL != (pszHot = StrChr(pszMenuItem, (WORD)TEXT('&'))))
  4199. { //yes
  4200. LPTSTR psz;
  4201. DWORD cch;
  4202. pszHot++; //make it point to the hot key, not &
  4203. //try to find the key in the new string
  4204. if (NULL == (psz = StrChr(szMenuText, (WORD)*pszHot)))
  4205. { //not found, then we'll insert & at the beginning of the new string
  4206. psz = szMenuText;
  4207. }
  4208. // can't put hotkey to full width characters
  4209. // and some of japanese specific half width chars.
  4210. // the comparison
  4211. BOOL fFEmnemonic = FALSE;
  4212. if (g_fRunOnFE)
  4213. {
  4214. WORD wCharType[2];
  4215. // if built Ansi it takes max. 2 bytes to determine if
  4216. // the given character is full width.
  4217. // DEFAULT_SYSTEM_LOCALE has to change when we have a way
  4218. // to get current UI locale.
  4219. //
  4220. GetStringTypeEx(LOCALE_SYSTEM_DEFAULT, CT_CTYPE3, psz,
  4221. sizeof(WCHAR)/sizeof(TCHAR), wCharType);
  4222. if ((wCharType[0] & C3_FULLWIDTH)
  4223. ||(wCharType[0] & C3_KATAKANA)
  4224. ||(wCharType[0] & C3_IDEOGRAPH)
  4225. ||((wCharType[0] & C3_ALPHA) && !(wCharType[0] & C3_HALFWIDTH)))
  4226. {
  4227. fFEmnemonic = TRUE;
  4228. }
  4229. }
  4230. if (fFEmnemonic)
  4231. {
  4232. // assume we have room for hotkey...
  4233. ASSERT(lstrlen(szMenuText) < ARRAYSIZE(szMenuText));
  4234. StrCat(szMenuText, TEXT("(&"));
  4235. cch = lstrlen(szMenuText);
  4236. szMenuText[cch] = *pszHot;
  4237. StrCpy(&szMenuText[cch+1], TEXT(")"));
  4238. }
  4239. else
  4240. {
  4241. cch = lstrlen(psz) + 1;
  4242. //make space for & to be inserted
  4243. memmove(psz+1, psz, cch * sizeof(TCHAR));
  4244. psz[0] = TEXT('&');
  4245. }
  4246. }
  4247. mii.dwTypeData = szMenuText;
  4248. SetMenuItemInfo(hmenuPopup, FCIDM_MYCOMPUTER, FALSE, &mii);
  4249. }
  4250. }
  4251. ILFree(pidlMyComputer);
  4252. }
  4253. }
  4254. inline BOOL IsWebPidl(LPCITEMIDLIST pidl)
  4255. {
  4256. return (!pidl || ILIsWeb(pidl));
  4257. }
  4258. void CShellBrowser2::_InsertTravelLogItems(HMENU hmenu, int nPos)
  4259. {
  4260. ITravelLog *ptl;
  4261. GetTravelLog(&ptl);
  4262. if (!ptl)
  4263. return;
  4264. //add the back items to the menu
  4265. MENUITEMINFO mii = {0};
  4266. mii.cbSize = sizeof(MENUITEMINFO);
  4267. mii.fMask = MIIM_ID | MIIM_TYPE;
  4268. //delete all back menu items after the separator
  4269. for (int i=GetMenuItemCount(hmenu); i >=0; i--)
  4270. {
  4271. mii.cch = 0;
  4272. if (GetMenuItemInfoWrap(hmenu, i, TRUE, &mii) &&
  4273. IsInRange(mii.wID, FCIDM_RECENTMENU, FCIDM_RECENTLAST))
  4274. {
  4275. DeleteMenu(hmenu, i, MF_BYPOSITION);
  4276. if (i < nPos)
  4277. nPos--;
  4278. }
  4279. }
  4280. //add the items
  4281. if (S_OK == ptl->InsertMenuEntries(SAFECAST(this, IShellBrowser*), hmenu, nPos, FCIDM_RECENTFIRST,
  4282. FCIDM_RECENTFIRST + GOMENU_RECENT_ITEMS, TLMENUF_CHECKCURRENT | TLMENUF_BACKANDFORTH))
  4283. {
  4284. //if something was added, insert a separator
  4285. MENUITEMINFO mii = {0};
  4286. mii.cbSize = sizeof(MENUITEMINFO);
  4287. mii.fMask = MIIM_ID | MIIM_TYPE;
  4288. mii.fType = MFT_SEPARATOR;
  4289. mii.wID = FCIDM_RECENTMENU;
  4290. InsertMenuItem(hmenu, nPos, TRUE, &mii);
  4291. }
  4292. ptl->Release();
  4293. }
  4294. void CShellBrowser2::_OnGoMenuPopup(HMENU hmenuPopup)
  4295. {
  4296. ITravelLog *ptl;
  4297. GetTravelLog(&ptl);
  4298. // if we've got a site or if we're trying to get to a site,
  4299. // enable the back button
  4300. BOOL fBackward = (ptl ? S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_BACK, NULL) : FALSE);
  4301. _EnableMenuItem(hmenuPopup, FCIDM_NAVIGATEBACK, fBackward);
  4302. BOOL fForeward = (ptl ? S_OK == ptl->GetTravelEntry(SAFECAST(this, IShellBrowser *), TLOG_FORE, NULL) : FALSE);
  4303. _EnableMenuItem(hmenuPopup, FCIDM_NAVIGATEFORWARD, fForeward);
  4304. if (IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_NO_PARENT_FOLDER_SUPPORT) ||
  4305. SHRestricted2W(REST_GoMenu, NULL, 0))
  4306. {
  4307. DeleteMenu(hmenuPopup, FCIDM_PREVIOUSFOLDER, MF_BYCOMMAND);
  4308. }
  4309. else
  4310. _EnableMenuItem(hmenuPopup, FCIDM_PREVIOUSFOLDER, _ShouldAllowNavigateParent());
  4311. ATOMICRELEASE(ptl);
  4312. if (SHRestricted2(REST_NoChannelUI, NULL, 0))
  4313. DeleteMenu(hmenuPopup, FCIDM_CHANNELGUIDE, MF_BYCOMMAND);
  4314. _MungeGoMyComputer(hmenuPopup);
  4315. _PruneMailNewsItems(hmenuPopup);
  4316. // if in ie4 shell browser we leave travel log in the file menu
  4317. if ((GetUIVersion() >= 5 || !_pbbd->_psf || IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_GO_HOME_PAGE)))
  4318. {
  4319. // The travel log goes after "Home Page".
  4320. int nPos = GetMenuPosFromID(hmenuPopup, FCIDM_STARTPAGE) + 1;
  4321. // If "Home Page" isn't there, then just append to the end.
  4322. if (nPos <= 0)
  4323. {
  4324. nPos = GetMenuItemCount(hmenuPopup);
  4325. }
  4326. _InsertTravelLogItems(hmenuPopup, nPos);
  4327. }
  4328. }
  4329. HRESULT AssureFtpOptionsMenuItem(HMENU hmenuPopup)
  4330. {
  4331. HRESULT hr = S_OK;
  4332. // Append the item if it is missing. It can be missing because
  4333. // sometimes the menu will be displayed before the shell merges it's
  4334. // menus, so we are modifying the template that will be used for other
  4335. // pages.
  4336. if (GetMenuPosFromID(hmenuPopup, FCIDM_FTPOPTIONS) == 0xFFFFFFFF)
  4337. {
  4338. // Yes, it's missing so we need to add it.
  4339. int nToInsert = GetMenuPosFromID(hmenuPopup, FCIDM_BROWSEROPTIONS);
  4340. if (EVAL(0xFFFFFFFF != nToInsert))
  4341. {
  4342. TCHAR szInternetOptions[64];
  4343. MLLoadString(IDS_INTERNETOPTIONS, szInternetOptions, ARRAYSIZE(szInternetOptions));
  4344. MENUITEMINFO mii = {0};
  4345. mii.cbSize = sizeof(mii);
  4346. mii.fMask = (MIIM_TYPE | MIIM_STATE | MIIM_ID);
  4347. mii.fType = MFT_STRING;
  4348. mii.fState = MFS_ENABLED | MFS_UNCHECKED;
  4349. mii.wID = FCIDM_FTPOPTIONS;
  4350. mii.dwTypeData = szInternetOptions;
  4351. mii.cch = lstrlen(szInternetOptions);
  4352. // We want to go right after "Folder Options" so we found
  4353. // the spot.
  4354. TBOOL(InsertMenuItem(hmenuPopup, (nToInsert + 1), TRUE, &mii));
  4355. // REARCHITECT: The PMs finally decided that
  4356. // it would be good to always have "Inet Options" & "Folder Options"
  4357. // in all views. (FTP, Shell, & Web) However doing it now
  4358. // is too late so we want to do this later. When that is done
  4359. // we can get ride of all this stuff.
  4360. // Now we just want to make sure FCIDM_BROWSEROPTIONS is "Folder Options"
  4361. // because some users over load it to say "Internet Options" which
  4362. // just added above. So we want to force it back to "Folder Options".
  4363. if (GetMenuItemInfo(hmenuPopup, FCIDM_BROWSEROPTIONS, FALSE, &mii))
  4364. {
  4365. TCHAR szFolderOptions[MAX_PATH];
  4366. MLLoadString(IDS_FOLDEROPTIONS, szFolderOptions, ARRAYSIZE(szFolderOptions));
  4367. mii.dwTypeData = szFolderOptions;
  4368. mii.cch = lstrlen(szFolderOptions);
  4369. SetMenuItemInfo(hmenuPopup, FCIDM_BROWSEROPTIONS, FALSE, &mii);
  4370. }
  4371. }
  4372. else
  4373. {
  4374. hr = E_FAIL;
  4375. }
  4376. }
  4377. return hr;
  4378. }
  4379. HRESULT UpdateOptionsMenuItem(IShellFolder * psf, HMENU hmenuPopup, BOOL fForNT5)
  4380. {
  4381. BOOL fCorrectVersion;
  4382. if (fForNT5)
  4383. fCorrectVersion = (GetUIVersion() >= 5);
  4384. else
  4385. fCorrectVersion = (GetUIVersion() < 5);
  4386. // We want "Internet Options" in addition to "Folder Options" on
  4387. // NT5's Tools menu for FTP Folders. Is this the case?
  4388. if (fCorrectVersion &&
  4389. IsBrowserFrameOptionsSet(psf, BFO_BOTH_OPTIONS))
  4390. {
  4391. EVAL(SUCCEEDED(AssureFtpOptionsMenuItem(hmenuPopup)));
  4392. }
  4393. else
  4394. {
  4395. // No, so delete the item.
  4396. DeleteMenu(hmenuPopup, FCIDM_FTPOPTIONS, MF_BYCOMMAND);
  4397. }
  4398. return S_OK;
  4399. }
  4400. void CShellBrowser2::_OnViewMenuPopup(HMENU hmenuPopup)
  4401. {
  4402. OLECMD rgcmd[] = {
  4403. { CITIDM_VIEWTOOLS, 0 },
  4404. { CITIDM_VIEWADDRESS, 0 },
  4405. { CITIDM_VIEWLINKS, 0 },
  4406. { CITIDM_VIEWTOOLBARCUSTOMIZE, 0 },
  4407. { CITIDM_VIEWMENU, 0 },
  4408. { CITIDM_VIEWAUTOHIDE, 0 },
  4409. { CITIDM_TEXTLABELS, 0 },
  4410. { CITIDM_VIEWLOCKTOOLBAR, 0 },
  4411. };
  4412. UpdateOptionsMenuItem(_pbbd->_psf, hmenuPopup, FALSE);
  4413. // See _MenuTemplate for the kooky enable/disable scenarios.
  4414. // Today's kookiness: The ever-changing "Options" menuitem.
  4415. // According to the table, we want Options under View on
  4416. // Non-NT5, in the shell or FTP scenarios. Therefore, we want
  4417. // options deleted in the opposite scenario. And for good measure,
  4418. // we also delete it if we don't know who we are yet, or if we
  4419. // are restricted.
  4420. if (SHRestricted(REST_NOFOLDEROPTIONS) ||
  4421. (GetUIVersion() >= 5) || !_pbbd->_pidlCur ||
  4422. IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_RENAME_FOLDER_OPTIONS_TOINTERNET))
  4423. {
  4424. DeleteMenu(hmenuPopup, FCIDM_BROWSEROPTIONS, MF_BYCOMMAND);
  4425. }
  4426. if (SHRestricted2(REST_NoViewSource, NULL, 0))
  4427. _EnableMenuItem(hmenuPopup, DVIDM_MSHTML_FIRST+IDM_VIEWSOURCE, FALSE);
  4428. if (_GetToolbarItem(ITB_ITBAR)->fShow) {
  4429. IUnknown_QueryStatus(_GetITBar(), &CGID_PrivCITCommands, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4430. }
  4431. HMENU hmenuToolbar = LoadMenuPopup(MENU_ITOOLBAR);
  4432. MENUITEMINFO mii;
  4433. mii.cbSize = sizeof(mii);
  4434. mii.fMask = MIIM_SUBMENU;
  4435. mii.hSubMenu = hmenuToolbar;
  4436. // why _hmenuCur? why not hmenuPopup?
  4437. SetMenuItemInfo(_hmenuCur, FCIDM_VIEWTOOLBAR, FALSE, &mii);
  4438. _CheckMenuItem(hmenuToolbar, FCIDM_VIEWADDRESS, rgcmd[1].cmdf & OLECMDF_ENABLED);
  4439. _CheckMenuItem(hmenuToolbar, FCIDM_VIEWLINKS, rgcmd[2].cmdf & OLECMDF_ENABLED);
  4440. int cItemsBelowSep = 3;
  4441. BOOL fCustomizeAvailable = TRUE;
  4442. if (!(rgcmd[3].cmdf & OLECMDF_ENABLED)) {
  4443. DeleteMenu(hmenuToolbar, FCIDM_VIEWTOOLBARCUSTOMIZE, MF_BYCOMMAND);
  4444. fCustomizeAvailable = FALSE;
  4445. cItemsBelowSep--;
  4446. }
  4447. DeleteMenu(hmenuToolbar, FCIDM_VIEWGOBUTTON, MF_BYCOMMAND);
  4448. if (fCustomizeAvailable || _ptheater ||
  4449. SHRestricted2(REST_LOCKICONSIZE, NULL, 0)) {
  4450. DeleteMenu(hmenuToolbar, FCIDM_VIEWTEXTLABELS, MF_BYCOMMAND);
  4451. cItemsBelowSep--;
  4452. } else {
  4453. _CheckMenuItem (hmenuToolbar, FCIDM_VIEWTEXTLABELS, rgcmd[6].cmdf);
  4454. }
  4455. if (_ptheater) {
  4456. _CheckMenuItem (hmenuToolbar, FCIDM_VIEWMENU, rgcmd[4].cmdf);
  4457. _CheckMenuItem (hmenuToolbar, FCIDM_VIEWAUTOHIDE, rgcmd[5].cmdf);
  4458. DeleteMenu(hmenuToolbar, FCIDM_VIEWTOOLS, MF_BYCOMMAND);
  4459. } else {
  4460. _CheckMenuItem(hmenuToolbar, FCIDM_VIEWTOOLS, rgcmd[0].cmdf & OLECMDF_ENABLED);
  4461. DeleteMenu(hmenuToolbar, FCIDM_VIEWMENU, MF_BYCOMMAND);
  4462. DeleteMenu(hmenuToolbar, FCIDM_VIEWAUTOHIDE, MF_BYCOMMAND);
  4463. cItemsBelowSep--;
  4464. }
  4465. if (_ptheater || SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0))
  4466. {
  4467. // No lock in theater mode or Windows Explorer
  4468. DeleteMenu(hmenuToolbar, FCIDM_VIEWLOCKTOOLBAR, MF_BYCOMMAND);
  4469. }
  4470. else
  4471. {
  4472. _CheckMenuItem(hmenuToolbar, FCIDM_VIEWLOCKTOOLBAR, rgcmd[7].cmdf & OLECMDF_ENABLED);
  4473. }
  4474. _CheckMenuItem(hmenuPopup, FCIDM_VIEWSTATUSBAR,
  4475. v_ShowControl(FCW_STATUS, SBSC_QUERY) == SBSC_SHOW);
  4476. #ifndef DISABLE_FULLSCREEN
  4477. if (SHRestricted2(REST_NoTheaterMode, NULL, 0))
  4478. _EnableMenuItem(hmenuPopup, FCIDM_THEATER, FALSE);
  4479. else
  4480. _CheckMenuItem(hmenuPopup, FCIDM_THEATER, (_ptheater ? TRUE : FALSE));
  4481. #endif
  4482. // if we're on nt5 OR we're not integrated and we're not in explorer
  4483. // add browser bars to the view menu
  4484. if (_GetBrowserBarMenu() == hmenuPopup)
  4485. {
  4486. _AddBrowserBarMenuItems(hmenuPopup);
  4487. }
  4488. // else it gets added only on view/explorer bars
  4489. RestrictItbarViewMenu(hmenuPopup, _GetITBar());
  4490. if (!cItemsBelowSep)
  4491. DeleteMenu(hmenuToolbar, FCIDM_VIEWCONTEXTMENUSEP, MF_BYCOMMAND);
  4492. DWORD dwValue;
  4493. DWORD dwSize = sizeof(dwValue);
  4494. BOOL fDefault = FALSE;
  4495. // Check the registry to see if we need to show the "Java Console" menu item.
  4496. //
  4497. SHRegGetUSValue(TEXT("Software\\Microsoft\\Java VM"),
  4498. TEXT("EnableJavaConsole"), NULL, (LPBYTE)&dwValue, &dwSize, FALSE,
  4499. (void *) &fDefault, sizeof(fDefault));
  4500. // If the value is false or absent, remove the menu item.
  4501. //
  4502. if (!dwValue)
  4503. {
  4504. RemoveMenu(hmenuPopup, FCIDM_JAVACONSOLE, MF_BYCOMMAND);
  4505. }
  4506. // Component categories cache can be passively (and efficiently) kept consistent through
  4507. // a registry change notification in integrated platforms on NT and Win=>98.
  4508. // both of these do an async update as necessary.
  4509. if (g_fRunningOnNT && GetUIVersion() >= 5)
  4510. {
  4511. _QueryHKCRChanged();
  4512. }
  4513. else if (!_fValidComCatCache)
  4514. {
  4515. // With browser-only, we'll refresh only if we haven't done so already.
  4516. _fValidComCatCache =
  4517. S_OK == _FreshenComponentCategoriesCache(TRUE /* unconditional update */) ;
  4518. }
  4519. IDispatch * pDispatch = NULL;
  4520. IHTMLDocument2* pHTMLDocument = NULL;
  4521. BSTR bstrUrl = NULL;
  4522. if( SUCCEEDED(_pbbd->_pautoWB2->get_Document(&pDispatch))
  4523. && SUCCEEDED(pDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, &pHTMLDocument)))
  4524. && pHTMLDocument != NULL
  4525. && SUCCEEDED(pHTMLDocument->get_URL( &bstrUrl)))
  4526. {
  4527. bool fEnableViewPrivacyPolicies = (0 == StrNCmpI( bstrUrl, L"http", ARRAYSIZE(L"http")-1));
  4528. _EnableMenuItem( hmenuPopup, FCIDM_VIEW_PRIVACY_POLICIES, fEnableViewPrivacyPolicies);
  4529. // if( !fEnableViewPrivacyPolicies)
  4530. // DeleteMenu( hmenuPopup, FCIDM_VIEW_PRIVACY_POLICIES, MF_BYCOMMAND);
  4531. }
  4532. SAFERELEASE( pDispatch);
  4533. SAFERELEASE( pHTMLDocument);
  4534. SysFreeString( bstrUrl);
  4535. bstrUrl = NULL;
  4536. // prettify the menu (make sure first and last items aren't
  4537. // separators and that there are no runs of >1 separator)
  4538. _SHPrettyMenu(hmenuPopup);
  4539. }
  4540. void CShellBrowser2::_OnToolsMenuPopup(HMENU hmenuPopup)
  4541. {
  4542. // Party on tools->options
  4543. //
  4544. // Again _MenuTemplate has the gory details. We want to lose
  4545. // "Options" in the non-NT5, shell or FTP scenarios, so we want
  4546. // to keep it in the opposite case. (FTP is a freebie since FTP
  4547. // doesn't have a Tools menu to begin with.)
  4548. //
  4549. // And don't forget restrictions.
  4550. // And as a bonus, we have to change the name of the menuitem
  4551. // in the web scenario to "Internet &Options".
  4552. BOOL fWeb = IsWebPidl(_pbbd->_pidlCur);
  4553. UpdateOptionsMenuItem(_pbbd->_psf, hmenuPopup, TRUE);
  4554. //
  4555. // Figure out whether or not "reset web settings" is needed
  4556. //
  4557. if (!fWeb || // only visible in web mode
  4558. !IsResetWebSettingsEnabled() || // only if not disabled by the ieak
  4559. !IsResetWebSettingsRequired()) // and only needed if someone clobbered our reg keys
  4560. {
  4561. DeleteMenu(hmenuPopup, FCIDM_RESETWEBSETTINGS, MF_BYCOMMAND);
  4562. }
  4563. DWORD dwOptions;
  4564. GetBrowserFrameOptions(_pbbd->_psf, (BFO_RENAME_FOLDER_OPTIONS_TOINTERNET | BFO_BOTH_OPTIONS), &dwOptions);
  4565. DWORD rgfAttrib = SFGAO_FOLDER;
  4566. if (SHRestricted(REST_NOFOLDEROPTIONS) &&
  4567. SUCCEEDED(IEGetAttributesOf(_pbbd->_pidlCur, &rgfAttrib)) && (rgfAttrib & SFGAO_FOLDER))
  4568. {
  4569. DeleteMenu(hmenuPopup, FCIDM_BROWSEROPTIONS, MF_BYCOMMAND);
  4570. }
  4571. else
  4572. {
  4573. // Only do this if the NSE wants it named "Internet Options" but doesn't want "Folder Options"
  4574. // also.
  4575. if (IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_RENAME_FOLDER_OPTIONS_TOINTERNET))
  4576. {
  4577. TCHAR szInternetOptions[64];
  4578. MLLoadString(IDS_INTERNETOPTIONS, szInternetOptions, ARRAYSIZE(szInternetOptions));
  4579. MENUITEMINFO mii;
  4580. mii.cbSize = sizeof(mii);
  4581. mii.fMask = MIIM_TYPE | MIIM_STATE | MIIM_ID;
  4582. mii.fType = MFT_STRING;
  4583. mii.fState = MFS_ENABLED | MFS_UNCHECKED;
  4584. mii.dwTypeData = szInternetOptions;
  4585. mii.cch = lstrlen(szInternetOptions);
  4586. mii.wID = FCIDM_BROWSEROPTIONS;
  4587. // Append the item if it is missing, else just set it
  4588. if (GetMenuState(hmenuPopup, FCIDM_BROWSEROPTIONS, MF_BYCOMMAND) == 0xFFFFFFFF)
  4589. {
  4590. AppendMenu(hmenuPopup, MF_SEPARATOR, -1, NULL);
  4591. InsertMenuItem(hmenuPopup, 0xFFFFFFFF, TRUE, &mii);
  4592. }
  4593. else
  4594. {
  4595. SetMenuItemInfo(hmenuPopup, FCIDM_BROWSEROPTIONS, FALSE, &mii);
  4596. }
  4597. }
  4598. }
  4599. // Nuke tools->connect through tools->disconnect if restricted or if no net
  4600. if ((!(GetSystemMetrics(SM_NETWORK) & RNC_NETWORKS)) ||
  4601. SHRestricted(REST_NONETCONNECTDISCONNECT))
  4602. {
  4603. for (int i = FCIDM_CONNECT; i <= FCIDM_CONNECT_SEP; i++)
  4604. DeleteMenu(hmenuPopup, i, MF_BYCOMMAND);
  4605. }
  4606. // Nuke tools->find + sep if restricted or if UI version >= 5
  4607. // or if running rooted explorer (since the Find extensions assume
  4608. // unrooted)
  4609. if (SHRestricted(REST_NOFIND) || (GetUIVersion() >= 5)) {
  4610. DeleteMenu(hmenuPopup, FCIDM_TOOLSSEPARATOR, MF_BYCOMMAND);
  4611. DeleteMenu(hmenuPopup, FCIDM_MENU_FIND, MF_BYCOMMAND);
  4612. }
  4613. BOOL fAvailable;
  4614. uCLSSPEC ucs;
  4615. QUERYCONTEXT qc = { 0 };
  4616. MENUITEMINFO mii;
  4617. ucs.tyspec = TYSPEC_CLSID;
  4618. ucs.tagged_union.clsid = CLSID_SubscriptionMgr;
  4619. // see if this option is available
  4620. fAvailable = (SUCCEEDED(FaultInIEFeature(NULL, &ucs, &qc, FIEF_FLAG_PEEK)));
  4621. if (fAvailable && !_fShowSynchronize)
  4622. {
  4623. // Turn it back on
  4624. if (NULL != _pszSynchronizeText)
  4625. {
  4626. _fShowSynchronize = TRUE;
  4627. mii.cbSize = sizeof(mii);
  4628. mii.fMask = MIIM_TYPE | MIIM_ID;
  4629. mii.fType = MFT_STRING;
  4630. mii.wID = FCIDM_UPDATESUBSCRIPTIONS;
  4631. mii.dwTypeData = _pszSynchronizeText;
  4632. InsertMenuItem(hmenuPopup, _iSynchronizePos, MF_BYPOSITION, &mii);
  4633. }
  4634. }
  4635. else if (!fAvailable && _fShowSynchronize)
  4636. {
  4637. // Turn it off
  4638. int iSyncPos = GetMenuPosFromID(hmenuPopup, FCIDM_UPDATESUBSCRIPTIONS);
  4639. if (NULL == _pszSynchronizeText)
  4640. {
  4641. _iSynchronizePos = iSyncPos;
  4642. MENUITEMINFO mii;
  4643. TCHAR szBuf[MAX_PATH];
  4644. mii.cbSize = sizeof(mii);
  4645. mii.fMask = MIIM_TYPE | MIIM_ID;
  4646. mii.dwTypeData = szBuf;
  4647. mii.cch = ARRAYSIZE(szBuf);
  4648. if (GetMenuItemInfo(hmenuPopup, FCIDM_UPDATESUBSCRIPTIONS, MF_BYCOMMAND, &mii))
  4649. {
  4650. Str_SetPtr(&_pszSynchronizeText, (LPTSTR)mii.dwTypeData);
  4651. }
  4652. }
  4653. DeleteMenu(hmenuPopup, FCIDM_UPDATESUBSCRIPTIONS, MF_BYCOMMAND);
  4654. _fShowSynchronize = FALSE;
  4655. }
  4656. ASSERT((fAvailable && _fShowSynchronize) || (!fAvailable && !_fShowSynchronize));
  4657. if (SHRestricted2(REST_NoWindowsUpdate, NULL, 0))
  4658. {
  4659. DeleteMenu(hmenuPopup, (DVIDM_HELPMSWEB+2), MF_BYCOMMAND);
  4660. }
  4661. else
  4662. {
  4663. DWORD dwRet;
  4664. DWORD dwType;
  4665. DWORD dwSize;
  4666. TCHAR szNewUpdateName[MAX_PATH];
  4667. // check to see if "Windows Update" should be called
  4668. // something different in the menu
  4669. dwSize = sizeof(szNewUpdateName);
  4670. dwRet = SHRegGetUSValue(c_szMenuItemCust,
  4671. c_szWindowUpdateName,
  4672. &dwType,
  4673. (LPVOID)szNewUpdateName,
  4674. &dwSize,
  4675. FALSE,
  4676. NULL,
  4677. 0);
  4678. if (dwRet == ERROR_SUCCESS)
  4679. {
  4680. ASSERT(dwSize <= sizeof(szNewUpdateName));
  4681. ASSERT(szNewUpdateName[(dwSize/sizeof(TCHAR))-1] == TEXT('\0'));
  4682. // if we got anything, replace the menu item's text, or delete
  4683. // the item if the text was NULL. we can tell if the text was
  4684. // an empty string by seeing whether we got back more
  4685. // bytes than just a null terminator
  4686. if (dwSize > sizeof(TCHAR))
  4687. {
  4688. MENUITEMINFO mii;
  4689. mii.cbSize = sizeof(mii);
  4690. mii.fMask = MIIM_TYPE;
  4691. mii.fType = MFT_STRING;
  4692. mii.dwTypeData = szNewUpdateName;
  4693. SetMenuItemInfo(hmenuPopup, FCIDM_PRODUCTUPDATES, FALSE, &mii);
  4694. }
  4695. else
  4696. {
  4697. ASSERT(dwSize == 0);
  4698. DeleteMenu(hmenuPopup, FCIDM_PRODUCTUPDATES, MF_BYCOMMAND);
  4699. }
  4700. }
  4701. }
  4702. // Disable Mail and News submenu if we don't support it
  4703. OLECMD rgcmd[] = {
  4704. { SBCMDID_DOMAILMENU, 0 },
  4705. };
  4706. HRESULT hr = QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4707. _EnableMenuItem(hmenuPopup, FCIDM_MAILANDNEWS, SUCCEEDED(hr) && (rgcmd[0].cmdf & OLECMDF_ENABLED));
  4708. // prettify the menu (make sure first and last items aren't
  4709. // separators and that there are no runs of >1 separator)
  4710. _SHPrettyMenu(hmenuPopup);
  4711. }
  4712. void CShellBrowser2::_OnFileMenuPopup(HMENU hmenuPopup)
  4713. {
  4714. // disable create shortcut, rename, delete, and properties
  4715. // we'll enable them bellow if they are available
  4716. _EnableMenuItem(hmenuPopup, FCIDM_DELETE, FALSE);
  4717. _EnableMenuItem(hmenuPopup, FCIDM_PROPERTIES, FALSE);
  4718. _EnableMenuItem(hmenuPopup, FCIDM_RENAME, FALSE);
  4719. _EnableMenuItem(hmenuPopup, FCIDM_LINK, FALSE);
  4720. if (SHRestricted2(REST_NoExpandedNewMenu, NULL, 0)
  4721. && (GetMenuState(hmenuPopup, DVIDM_NEW, MF_BYCOMMAND) != 0xFFFFFFFF))
  4722. {
  4723. TCHAR szNewWindow[64];
  4724. MLLoadString(IDS_NEW_WINDOW, szNewWindow, ARRAYSIZE(szNewWindow));
  4725. MENUITEMINFO mii;
  4726. mii.cbSize = sizeof(MENUITEMINFO);
  4727. mii.fMask = MIIM_ID | MIIM_TYPE;
  4728. mii.fType = MFT_STRING;
  4729. mii.fState = MFS_ENABLED;
  4730. mii.wID = DVIDM_NEWWINDOW;
  4731. mii.dwTypeData = szNewWindow;
  4732. mii.cch = lstrlen(szNewWindow);
  4733. InsertMenuItem(hmenuPopup, DVIDM_NEW, FALSE, &mii);
  4734. DeleteMenu(hmenuPopup, DVIDM_NEW, MF_BYCOMMAND);
  4735. }
  4736. if (_HasToolbarFocus())
  4737. {
  4738. OLECMD rgcmd[] = {
  4739. { SBCMDID_FILEDELETE, 0 },
  4740. { SBCMDID_FILEPROPERTIES, 0 },
  4741. { SBCMDID_FILERENAME, 0},
  4742. { SBCMDID_CREATESHORTCUT, 0},
  4743. };
  4744. IDockingWindow* ptbar = _GetToolbarItem(_itbLastFocus)->ptbar;
  4745. if (SUCCEEDED(IUnknown_QueryStatus(ptbar, &CGID_Explorer, ARRAYSIZE(rgcmd), rgcmd, NULL)))
  4746. {
  4747. _EnableMenuItem(hmenuPopup, FCIDM_DELETE, rgcmd[0].cmdf & OLECMDF_ENABLED);
  4748. _EnableMenuItem(hmenuPopup, FCIDM_PROPERTIES, rgcmd[1].cmdf & OLECMDF_ENABLED);
  4749. _EnableMenuItem(hmenuPopup, FCIDM_RENAME, rgcmd[2].cmdf & OLECMDF_ENABLED);
  4750. _EnableMenuItem(hmenuPopup, FCIDM_LINK, rgcmd[3].cmdf & OLECMDF_ENABLED);
  4751. }
  4752. }
  4753. _EnableMenuItem(hmenuPopup, FCIDM_FILECLOSE, S_FALSE == _DisableModeless());
  4754. _EnableFileContext(hmenuPopup);
  4755. if (_fEnableOfflineFeature || (GetUIVersion() < 5))
  4756. {
  4757. _CheckMenuItem(hmenuPopup, FCIDM_VIEWOFFLINE, (Offline(SBSC_QUERY) == S_OK));
  4758. }
  4759. else
  4760. RemoveMenu(hmenuPopup, FCIDM_VIEWOFFLINE, MF_BYCOMMAND);
  4761. if (_fVisitedNet && NeedFortezzaMenu()) // Do not load WININET.DLL in explorer mode
  4762. {
  4763. // The logic here ensures that the menu is created once per instance
  4764. // and only if there is a need to display a Fortezza menu.
  4765. if (!_fShowFortezza)
  4766. {
  4767. static TCHAR szItemText[16] = TEXT("");
  4768. if (!szItemText[0]) // The string will be loaded only once
  4769. MLLoadString(IDS_FORTEZZA_MENU, szItemText, ARRAYSIZE(szItemText));
  4770. if (_hfm==NULL)
  4771. _hfm = FortezzaMenu();
  4772. InsertMenu(hmenuPopup, FCIDM_FILECLOSE, MF_POPUP, (UINT_PTR) _hfm, szItemText);
  4773. _fShowFortezza = TRUE;
  4774. }
  4775. SetFortezzaMenu(hmenuPopup);
  4776. }
  4777. else if (_fShowFortezza) // Don't need the menu but already displayed?
  4778. { // Remove without destroying the handle
  4779. int cbItems = GetMenuItemCount(hmenuPopup);
  4780. RemoveMenu(hmenuPopup, cbItems-2, MF_BYPOSITION);
  4781. _fShowFortezza = FALSE;
  4782. }
  4783. // See if we can edit the page
  4784. OLECMD rgcmd[] = {
  4785. { CITIDM_EDITPAGE, 0 },
  4786. };
  4787. struct {
  4788. OLECMDTEXT ct;
  4789. wchar_t rgwz[128];
  4790. } cmdText = {0};
  4791. cmdText.ct.cwBuf = ARRAYSIZE(cmdText.rgwz) + ARRAYSIZE(cmdText.ct.rgwz);
  4792. cmdText.ct.cmdtextf = OLECMDTEXTF_NAME;
  4793. IDockingWindow* ptbar = _GetITBar();
  4794. IUnknown_QueryStatus(ptbar, &CGID_PrivCITCommands, ARRAYSIZE(rgcmd), rgcmd, &cmdText.ct);
  4795. _EnableMenuItem(hmenuPopup, FCIDM_EDITPAGE, rgcmd[0].cmdf & OLECMDF_ENABLED);
  4796. // Update the name of the edit menu item
  4797. TCHAR szText[80];
  4798. MENUITEMINFO mii = {0};
  4799. mii.cbSize = sizeof(MENUITEMINFO);
  4800. mii.fMask = MIIM_TYPE;
  4801. mii.dwTypeData = szText;
  4802. if (cmdText.ct.cwActual > 1)
  4803. {
  4804. SHUnicodeToTChar(cmdText.ct.rgwz, szText, ARRAYSIZE(szText));
  4805. }
  4806. else
  4807. {
  4808. // Use default edit text
  4809. MLLoadString(IDS_EDITPAGE, szText, ARRAYSIZE(szText));
  4810. }
  4811. SetMenuItemInfo(hmenuPopup, FCIDM_EDITPAGE, FALSE, &mii);
  4812. #ifdef TEST_AMBIENTS
  4813. _CheckMenuItem(hmenuPopup, FCIDM_VIEWLOCALOFFLINE,
  4814. _LocalOffline(SBSC_QUERY) == TRUE);
  4815. _CheckMenuItem(hmenuPopup, FCIDM_VIEWLOCALSILENT,
  4816. _LocalSilent(SBSC_QUERY) == TRUE);
  4817. #endif // TEST_AMBIENTS
  4818. // must not change ie4 shell experience
  4819. // so travel log still goes to the file menu
  4820. if ((GetUIVersion() < 5) && !IsWebPidl(_pbbd->_pidlCur))
  4821. {
  4822. int nPos = GetMenuItemCount(hmenuPopup) - 1; // Start with the last item
  4823. MENUITEMINFO mii = {0};
  4824. BOOL fFound = FALSE;
  4825. mii.cbSize = sizeof(MENUITEMINFO);
  4826. mii.fMask = MIIM_ID | MIIM_TYPE;
  4827. // Find the last separator separator
  4828. while (!fFound && nPos > 0)
  4829. {
  4830. mii.cch = 0;
  4831. GetMenuItemInfo(hmenuPopup, nPos, TRUE, &mii);
  4832. if (mii.fType & MFT_SEPARATOR)
  4833. fFound = TRUE;
  4834. else
  4835. nPos --;
  4836. }
  4837. if (fFound)
  4838. {
  4839. _InsertTravelLogItems(hmenuPopup, nPos);
  4840. }
  4841. }
  4842. HMENU hmFileNew = SHGetMenuFromID(hmenuPopup, DVIDM_NEW);
  4843. if (hmFileNew)
  4844. {
  4845. // remove menu items for unregistered components
  4846. // this code is duplicated in shdocvw\dochost.cpp and is necessary here
  4847. // so that unwanted items are not present before dochost has fully loaded
  4848. const static struct {
  4849. LPCTSTR pszClient;
  4850. UINT idCmd;
  4851. } s_Clients[] = {
  4852. { NEW_MAIL_DEF_KEY, DVIDM_NEWMESSAGE },
  4853. { NEW_CONTACTS_DEF_KEY, DVIDM_NEWCONTACT },
  4854. { NEW_NEWS_DEF_KEY, DVIDM_NEWPOST },
  4855. { NEW_APPOINTMENT_DEF_KEY, DVIDM_NEWAPPOINTMENT },
  4856. { NEW_MEETING_DEF_KEY, DVIDM_NEWMEETING },
  4857. { NEW_TASK_DEF_KEY, DVIDM_NEWTASK },
  4858. { NEW_TASKREQUEST_DEF_KEY, DVIDM_NEWTASKREQUEST },
  4859. { NEW_JOURNAL_DEF_KEY, DVIDM_NEWJOURNAL },
  4860. { NEW_NOTE_DEF_KEY, DVIDM_NEWNOTE },
  4861. { NEW_CALL_DEF_KEY, DVIDM_CALL }
  4862. };
  4863. BOOL bItemRemoved = FALSE;
  4864. for (int i = 0; i < ARRAYSIZE(s_Clients); i++)
  4865. {
  4866. if (!SHIsRegisteredClient(s_Clients[i].pszClient))
  4867. {
  4868. if (RemoveMenu(hmFileNew, s_Clients[i].idCmd, MF_BYCOMMAND))
  4869. bItemRemoved = TRUE;
  4870. }
  4871. }
  4872. if (bItemRemoved) // ensure the last item is not a separator
  4873. _SHPrettyMenu(hmFileNew);
  4874. }
  4875. if (!SHIsRegisteredClient(MAIL_DEF_KEY))
  4876. {
  4877. // disable Send Page by Email, Send Link by Email
  4878. HMENU hmFileSend = SHGetMenuFromID(hmenuPopup, DVIDM_SEND);
  4879. if (hmFileSend)
  4880. {
  4881. EnableMenuItem(hmFileSend, DVIDM_SENDPAGE, MF_BYCOMMAND | MF_GRAYED);
  4882. EnableMenuItem(hmFileSend, DVIDM_SENDSHORTCUT, MF_BYCOMMAND | MF_GRAYED);
  4883. }
  4884. }
  4885. }
  4886. void CShellBrowser2::_OnSearchMenuPopup(HMENU hmenuPopup)
  4887. {
  4888. if (!_pcmSearch)
  4889. _pxtb->QueryInterface(IID_PPV_ARG(IContextMenu3, &_pcmSearch));
  4890. if (_pcmSearch)
  4891. _pcmSearch->QueryContextMenu(hmenuPopup, 0, FCIDM_SEARCHFIRST, FCIDM_SEARCHLAST, 0);
  4892. }
  4893. void CShellBrowser2::_OnHelpMenuPopup(HMENU hmenuPopup)
  4894. {
  4895. RIP(IS_VALID_HANDLE(hmenuPopup, MENU));
  4896. // Do nothing if this is the DocHost version of the Help menu,
  4897. // which always says "About Internet Explorer", and bring up
  4898. // IE about dlg.
  4899. // If we're running in native browser mode,
  4900. // it says "About Windows" and bring up shell about dlg.
  4901. // Change the "About Windows" to "About Windows NT" if running on NT.
  4902. // Not sure what to do for Memphis yet.
  4903. //
  4904. // remove menu items which have been marked for removal
  4905. // via the IEAK restrictions
  4906. //
  4907. if (SHRestricted2(REST_NoHelpItem_TipOfTheDay, NULL, 0))
  4908. {
  4909. DeleteMenu(hmenuPopup, FCIDM_HELPTIPOFTHEDAY, MF_BYCOMMAND);
  4910. }
  4911. if (SHRestricted2(REST_NoHelpItem_NetscapeHelp, NULL, 0))
  4912. {
  4913. DeleteMenu(hmenuPopup, FCIDM_HELPNETSCAPEUSERS, MF_BYCOMMAND);
  4914. }
  4915. if (SHRestricted2(REST_NoHelpItem_Tutorial, NULL, 0))
  4916. {
  4917. DeleteMenu(hmenuPopup, DVIDM_HELPTUTORIAL, MF_BYCOMMAND);
  4918. }
  4919. if (SHRestricted2(REST_NoHelpItem_SendFeedback, NULL, 0))
  4920. {
  4921. DeleteMenu(hmenuPopup, FCIDM_HELPSENDFEEDBACK, MF_BYCOMMAND);
  4922. }
  4923. // "Is this copy of Windows legal?" only supported on Whistler and greater.
  4924. if (!IsOS(OS_WHISTLERORGREATER))
  4925. {
  4926. DeleteMenu(hmenuPopup, FCIDM_HELPISLEGAL, MF_BYCOMMAND);
  4927. }
  4928. UINT ids = IDS_ABOUTWINDOWS;
  4929. if (IsOS(OS_NT4ORGREATER) && !IsOS(OS_WIN2000ORGREATER))
  4930. {
  4931. ids = IDS_ABOUTWINDOWSNT;
  4932. }
  4933. else if (IsOS(OS_WIN98ORGREATER))
  4934. {
  4935. ids = IDS_ABOUTWINDOWS9X;
  4936. }
  4937. if (ids)
  4938. {
  4939. MENUITEMINFO mii;
  4940. TCHAR szName[80]; // The name better not be any bigger.
  4941. memset(&mii, 0, sizeof(MENUITEMINFO));
  4942. mii.cbSize = sizeof(MENUITEMINFO);
  4943. mii.fMask = MIIM_TYPE;
  4944. // We only try to get FCIDM_HELPABOUT, which will fail if this
  4945. // is the DocHost version of help menu (who has DVIDM_HELPABOUT.)
  4946. if (GetMenuItemInfoWrap(hmenuPopup, FCIDM_HELPABOUT, FALSE, &mii) &&
  4947. MLLoadString(ids, szName, ARRAYSIZE(szName)))
  4948. {
  4949. mii.dwTypeData = szName;
  4950. SetMenuItemInfo(hmenuPopup, FCIDM_HELPABOUT, FALSE, &mii);
  4951. }
  4952. }
  4953. SHCheckMenuItem(hmenuPopup, FCIDM_HELPTIPOFTHEDAY, (_idmComm == _InfoCLSIDToIdm(&CLSID_TipOfTheDay)));
  4954. }
  4955. void CShellBrowser2::_OnMailMenuPopup(HMENU hmenuPopup)
  4956. {
  4957. if (!SHIsRegisteredClient(MAIL_DEF_KEY))
  4958. {
  4959. DeleteMenu(hmenuPopup, FCIDM_MAIL, MF_BYCOMMAND);
  4960. DeleteMenu(hmenuPopup, FCIDM_NEWMESSAGE, MF_BYCOMMAND);
  4961. DeleteMenu(hmenuPopup, FCIDM_SENDLINK, MF_BYCOMMAND);
  4962. DeleteMenu(hmenuPopup, FCIDM_SENDDOCUMENT, MF_BYCOMMAND);
  4963. DeleteMenu(hmenuPopup, FCIDM_MAILNEWSSEPARATOR, MF_BYCOMMAND);
  4964. }
  4965. if (!SHIsRegisteredClient(NEWS_DEF_KEY))
  4966. {
  4967. DeleteMenu(hmenuPopup, FCIDM_MAILNEWSSEPARATOR, MF_BYCOMMAND);
  4968. DeleteMenu(hmenuPopup, FCIDM_NEWS, MF_BYCOMMAND);
  4969. }
  4970. }
  4971. void CShellBrowser2::_OnEditMenuPopup(HMENU hmenuPopup)
  4972. {
  4973. OLECMD rgcmdEdit[] = {{CITIDM_EDITPAGE, 0 }};
  4974. OLECMD rgcmd[] = {
  4975. { OLECMDID_CUT, 0 },
  4976. { OLECMDID_COPY, 0 },
  4977. { OLECMDID_PASTE, 0 },
  4978. { OLECMDID_SELECTALL, 0 }
  4979. };
  4980. ASSERT(FCIDM_COPY==FCIDM_MOVE+1);
  4981. ASSERT(FCIDM_PASTE==FCIDM_MOVE+2);
  4982. ASSERT(FCIDM_SELECTALL==FCIDM_MOVE+3);
  4983. TraceMsg(DM_PREMERGEDMENU, "CSB::_OnEditMenuPopup got FCIDM_MENU_EDIT");
  4984. IOleCommandTarget* pcmdt;
  4985. HRESULT hres = _FindActiveTarget(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  4986. if (SUCCEEDED(hres)) {
  4987. pcmdt->QueryStatus(NULL, ARRAYSIZE(rgcmd), rgcmd, NULL);
  4988. pcmdt->Release();
  4989. }
  4990. for (int i=0; i<ARRAYSIZE(rgcmd); i++) {
  4991. _EnableMenuItem(hmenuPopup, FCIDM_MOVE+i, rgcmd[i].cmdf & OLECMDF_ENABLED);
  4992. }
  4993. if (SUCCEEDED(_GetITBar()->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pcmdt))))
  4994. {
  4995. pcmdt->QueryStatus(&CGID_PrivCITCommands, ARRAYSIZE(rgcmdEdit), rgcmdEdit, NULL);
  4996. pcmdt->Release();
  4997. }
  4998. _EnableMenuItem(hmenuPopup, FCIDM_EDITPAGE, rgcmdEdit[0].cmdf & OLECMDF_ENABLED);
  4999. // prettify the menu (make sure first and last items aren't
  5000. // separators and that there are no runs of >1 separator)
  5001. _SHPrettyMenu(hmenuPopup);
  5002. }
  5003. void CShellBrowser2::_OnFindMenuPopup(HMENU hmenuPopup)
  5004. {
  5005. TraceMsg(DM_TRACE, "CSB::_OnFindMenuPopup cabinet InitMenuPopup of Find commands");
  5006. ASSERT(GetUIVersion() < 5); // otherwise the menu is deleted when we load it from resources
  5007. ASSERT(!SHRestricted(REST_NOFIND)); // otherwise the menu is deleted when we load it from resources
  5008. ATOMICRELEASE(_pcmFind);
  5009. _pcmFind = SHFind_InitMenuPopup(hmenuPopup, _pbbd->_hwnd, FCIDM_MENU_TOOLS_FINDFIRST, FCIDM_MENU_TOOLS_FINDLAST);
  5010. }
  5011. void CShellBrowser2::_OnExplorerBarMenuPopup(HMENU hmenuPopup)
  5012. {
  5013. if (_hEventComCat)
  5014. {
  5015. // Wait a bit for the comcat cache enumeration to finish
  5016. WaitForSingleObject(_hEventComCat, 1500);
  5017. CloseHandle(_hEventComCat);
  5018. _hEventComCat = NULL;
  5019. }
  5020. _AddBrowserBarMenuItems(hmenuPopup);
  5021. if (SHRestricted2(REST_NoFavorites, NULL, 0))
  5022. _EnableMenuItem(hmenuPopup, FCIDM_VBBFAVORITESBAND, FALSE);
  5023. if (SHRestricted2(REST_No_LaunchMediaBar, NULL, 0))
  5024. _EnableMenuItem(hmenuPopup, FCIDM_VBBMEDIABAND, FALSE);
  5025. for (int idCmd = FCIDM_VBBFIXFIRST; idCmd <= FCIDM_VBBDYNLAST; idCmd++)
  5026. SHCheckMenuItem(hmenuPopup, idCmd, FALSE);
  5027. MENUITEMINFO mii;
  5028. mii.cbSize = sizeof(mii);
  5029. mii.fState = MFS_CHECKED;
  5030. mii.fMask = MIIM_STATE;
  5031. SetMenuItemInfo(hmenuPopup, _idmInfo, FALSE, &mii);
  5032. SetMenuItemInfo(hmenuPopup, _idmComm, FALSE, &mii);
  5033. // if we have pre-ie4 shell32, remove the folders bar option
  5034. if (GetUIVersion() < 4)
  5035. DeleteMenu(hmenuPopup, FCIDM_VBBEXPLORERBAND, MF_BYCOMMAND);
  5036. }
  5037. LRESULT CShellBrowser2::v_OnInitMenuPopup(HMENU hmenuPopup, int nIndex, BOOL fSystemMenu)
  5038. {
  5039. if (hmenuPopup == _GetMenuFromID(FCIDM_MENU_EXPLORE)) {
  5040. _OnGoMenuPopup(hmenuPopup);
  5041. }
  5042. else if (hmenuPopup == _GetMenuFromID(FCIDM_MENU_VIEW)) {
  5043. _OnViewMenuPopup(hmenuPopup);
  5044. }
  5045. else if (hmenuPopup == _GetMenuFromID(FCIDM_MENU_TOOLS)) {
  5046. _OnToolsMenuPopup(hmenuPopup);
  5047. }
  5048. else if (hmenuPopup == _GetMenuFromID(FCIDM_MENU_FILE)) {
  5049. _OnFileMenuPopup(hmenuPopup);
  5050. }
  5051. else if (hmenuPopup == _GetMenuFromID(FCIDM_SEARCHMENU)) {
  5052. _OnSearchMenuPopup(hmenuPopup);
  5053. }
  5054. else if ((hmenuPopup == _GetMenuFromID(FCIDM_MENU_HELP)) ||
  5055. (hmenuPopup == SHGetMenuFromID(_hmenuFull, FCIDM_MENU_HELP))) {
  5056. // For the help menu we try both the current menu and by chance the FullSB menu
  5057. // as if we get here before the menu merge we will not have set the current menu
  5058. // and that would leave Help about windows95 for all platforms.
  5059. _OnHelpMenuPopup(hmenuPopup);
  5060. }
  5061. else if (hmenuPopup == _GetMenuFromID(FCIDM_MENU_EDIT)) {
  5062. _OnEditMenuPopup(hmenuPopup);
  5063. }
  5064. else if (hmenuPopup == _GetMenuFromID(FCIDM_MENU_FIND)) {
  5065. _OnFindMenuPopup(hmenuPopup);
  5066. }
  5067. else if (hmenuPopup == _GetMenuFromID(FCIDM_VIEWBROWSERBARS)) {
  5068. _OnExplorerBarMenuPopup(hmenuPopup);
  5069. }
  5070. else {
  5071. UINT wID = GetMenuItemID(hmenuPopup, 0); // assume the first item on the popup identifies the menu
  5072. if (wID == FCIDM_MAIL) {
  5073. _OnMailMenuPopup(hmenuPopup);
  5074. }
  5075. else if (_pcmNsc && IsInRange(wID, FCIDM_FILECTX_FIRST, FCIDM_FILECTX_LAST)) {
  5076. _pcmNsc->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)hmenuPopup, (LPARAM)MAKELONG(nIndex, fSystemMenu));
  5077. }
  5078. else if (_pcm) {
  5079. _pcm->HandleMenuMsg(WM_INITMENUPOPUP, (WPARAM)hmenuPopup, (LPARAM)MAKELONG(nIndex, fSystemMenu));
  5080. }
  5081. }
  5082. return S_OK;
  5083. }
  5084. #pragma warning (disable:4200)
  5085. typedef struct {
  5086. int nItemOffset;
  5087. int nPopupOffset;
  5088. struct {
  5089. UINT uID;
  5090. HMENU hPopup;
  5091. #ifndef UNIX
  5092. } sPopupIDs[];
  5093. #else
  5094. } sPopupIDs[2];
  5095. #endif
  5096. } MENUHELPIDS;
  5097. #pragma warning (default:4200)
  5098. void CShellBrowser2::_SetMenuHelp(HMENU hmenu, UINT wID, LPCTSTR pszHelp)
  5099. {
  5100. if (pszHelp && pszHelp[0])
  5101. {
  5102. UINT flags = SBT_NOBORDERS | 255;
  5103. // If the menu text is RTL, then so too will the status text be
  5104. MENUITEMINFO mii = { sizeof(mii) };
  5105. mii.fMask = MIIM_TYPE;
  5106. if (GetMenuItemInfo(hmenu, wID, FALSE, &mii) &&
  5107. (mii.fType & MFT_RIGHTORDER))
  5108. flags |= SBT_RTLREADING;
  5109. SendMessage(_hwndStatus, SB_SETTEXT, flags, (LPARAM)pszHelp);
  5110. SendMessage(_hwndStatus, SB_SIMPLE, 1, 0);
  5111. }
  5112. }
  5113. void CShellBrowser2::_SetExternalBandMenuHelp(HMENU hmenu, UINT wID)
  5114. {
  5115. USES_CONVERSION;
  5116. OLECMD cmd = { CITIDM_VIEWEXTERNALBAND_FIRST + (wID - FCIDM_EXTERNALBANDS_FIRST), 0 };
  5117. OLECMDTEXTV<MAX_PATH> cmdtv;
  5118. cmdtv.cwBuf = MAX_PATH;
  5119. cmdtv.cmdtextf = OLECMDTEXTF_STATUS;
  5120. cmdtv.rgwz[0] = 0;
  5121. IUnknown_QueryStatus(_GetITBar(), &CGID_PrivCITCommands, 1, &cmd, &cmdtv);
  5122. _SetMenuHelp(hmenu, wID, W2CT(cmdtv.rgwz));
  5123. }
  5124. void CShellBrowser2::_SetBrowserBarMenuHelp(HMENU hmenu, UINT wID)
  5125. {
  5126. if (_pbsmInfo)
  5127. {
  5128. BANDCLASSINFO *pbci = _BandClassInfoFromCmdID(wID);
  5129. if (pbci)
  5130. {
  5131. LPCTSTR pszHelp = pbci->pszHelpPUI ? pbci->pszHelpPUI : pbci->pszHelp;
  5132. _SetMenuHelp(hmenu, wID, pszHelp);
  5133. }
  5134. }
  5135. }
  5136. // Handles WM_MENUSELECT. Returns FALSE if this menu item isn't handled by
  5137. // the frame.
  5138. LRESULT CShellBrowser2::_OnMenuSelect(WPARAM wParam, LPARAM lParam, UINT uHelpFlags)
  5139. {
  5140. MENUHELPIDS sMenuHelpIDs = {
  5141. MH_ITEMS, MH_POPUPS,
  5142. 0, NULL, // Placeholder for specific menu
  5143. 0, NULL // This list must be NULL terminated
  5144. };
  5145. TCHAR szHint[MAX_PATH]; // OK with MAX_PATH
  5146. UINT uMenuFlags = GET_WM_MENUSELECT_FLAGS(wParam, lParam);
  5147. WORD wID = GET_WM_MENUSELECT_CMD(wParam, lParam);
  5148. HMENU hMenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  5149. /*
  5150. HACKHACK
  5151. USER32 TrackPopup menus send a menu deselect message which clears our
  5152. status text at inopportune times. We work around this with a private
  5153. MBIgnoreNextDeselect message.
  5154. */
  5155. // Did someone ask us to clear the status text?
  5156. if (!hMenu && LOWORD(uMenuFlags)==0xffff)
  5157. {
  5158. // Yes
  5159. // Should we honour that request?
  5160. if (!_fIgnoreNextMenuDeselect)
  5161. // Yes
  5162. SendMessage(_hwndStatus, SB_SIMPLE, 0, 0L);
  5163. else
  5164. // No
  5165. _fIgnoreNextMenuDeselect = FALSE;
  5166. return 1L;
  5167. }
  5168. // Clear this out just in case, but don't update yet
  5169. SendMessage(_hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)(LPTSTR)c_szNULL);
  5170. SendMessage(_hwndStatus, SB_SIMPLE, 1, 0L);
  5171. if (uMenuFlags & MF_SYSMENU)
  5172. {
  5173. // We don't put special items on the system menu any more, so go
  5174. // straight to the MenuHelp
  5175. goto DoMenuHelp;
  5176. }
  5177. if (uMenuFlags & MH_POPUP)
  5178. {
  5179. MENUITEMINFO miiSubMenu;
  5180. if (!_hmenuCur)
  5181. {
  5182. return(0L);
  5183. }
  5184. miiSubMenu.cbSize = sizeof(MENUITEMINFO);
  5185. miiSubMenu.fMask = MIIM_SUBMENU|MIIM_ID;
  5186. if (!GetMenuItemInfoWrap(GET_WM_MENUSELECT_HMENU(wParam, lParam), wID, TRUE, &miiSubMenu))
  5187. {
  5188. // Check if this was a top level menu
  5189. return(0L);
  5190. }
  5191. // Change the parameters to simulate a "normal" menu item
  5192. wParam = miiSubMenu.wID;
  5193. wID = (WORD)miiSubMenu.wID;
  5194. //
  5195. // NOTES: We are eliminating this range check so that we can display
  5196. // help-text on sub-menus. I'm not sure why explorer.exe has this check.
  5197. //
  5198. #if 0
  5199. if (!IsInRange(wID, FCIDM_GLOBALFIRST, FCIDM_GLOBALLAST))
  5200. return 0L;
  5201. #endif
  5202. uMenuFlags = 0;
  5203. }
  5204. // FEATURE: chrisfra 9/2/97
  5205. // No menu help for context menu stuck in File Menu or menus that aren't ours
  5206. // in IE 5.0, might want to write code to use context
  5207. // menu to get help to work
  5208. if (IsInRange(wID, FCIDM_FILECTX_FIRST, FCIDM_FILECTX_LAST) ||
  5209. !IsInRange(wID, FCIDM_FIRST, FCIDM_LAST))
  5210. return 0L;
  5211. if (_pcmSearch && IsInRange(wID, FCIDM_SEARCHFIRST, FCIDM_SEARCHLAST))
  5212. {
  5213. _pcmSearch->HandleMenuMsg(WM_MENUSELECT, wParam, lParam);
  5214. return 0L;
  5215. }
  5216. #if 0
  5217. if (IsInRange(wID, FCIDM_RECENTFIRST, FCIDM_RECENTLAST)) {
  5218. wID = FCIDM_RECENTFIRST;
  5219. }
  5220. #endif
  5221. // Menu help for plug-in explorer bars.
  5222. if (IsInRange(wID, FCIDM_VBBDYNFIRST, FCIDM_VBBDYNLAST))
  5223. {
  5224. _SetBrowserBarMenuHelp(hMenu, wID);
  5225. return 0L;
  5226. }
  5227. // Menu help for plug-in itbar bands
  5228. if (IsInRange(wID, FCIDM_EXTERNALBANDS_FIRST, FCIDM_EXTERNALBANDS_LAST))
  5229. {
  5230. _SetExternalBandMenuHelp(hMenu, wID);
  5231. return 0L;
  5232. }
  5233. szHint[0] = 0;
  5234. sMenuHelpIDs.sPopupIDs[0].uID = 0;
  5235. sMenuHelpIDs.sPopupIDs[0].hPopup = NULL;
  5236. DoMenuHelp:
  5237. MenuHelp(WM_MENUSELECT, wParam, lParam, _hmenuCur, MLGetHinst(),
  5238. _hwndStatus, (UINT *)&sMenuHelpIDs);
  5239. return 1L;
  5240. }
  5241. void CShellBrowser2::_DisplayFavoriteStatus(LPCITEMIDLIST pidl)
  5242. {
  5243. LPTSTR pszURL = NULL;
  5244. IUniformResourceLocator * pURL;
  5245. if (SUCCEEDED(CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_INPROC_SERVER,
  5246. IID_IUniformResourceLocator, (void **)&pURL)))
  5247. {
  5248. IPersistFile *ppf;
  5249. if (SUCCEEDED(pURL->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf))))
  5250. {
  5251. WCHAR wszPath[MAX_PATH];
  5252. // Get the full path to the .lnk
  5253. SHGetPathFromIDListW(pidl, wszPath);
  5254. // Attempt to connect the storage of the IURL to the pidl
  5255. if (SUCCEEDED(ppf->Load(wszPath, STGM_READ)))
  5256. {
  5257. pURL->GetURL(&pszURL);
  5258. }
  5259. ppf->Release();
  5260. }
  5261. pURL->Release();
  5262. }
  5263. SendMessage(_hwndStatus, SB_SIMPLE, 1, 0L);
  5264. SendMessage(_hwndStatus, SB_SETTEXT, SBT_NOBORDERS|255, (LPARAM)pszURL);
  5265. if (pszURL)
  5266. SHFree(pszURL);
  5267. }
  5268. LRESULT CShellBrowser2::_ThunkTTNotify(LPTOOLTIPTEXTA pnmTTTA)
  5269. {
  5270. TOOLTIPTEXTW tttw = {0};
  5271. tttw.hdr = pnmTTTA->hdr;
  5272. tttw.hdr.code = TTN_NEEDTEXTW;
  5273. tttw.lpszText = tttw.szText;
  5274. tttw.hinst = pnmTTTA->hinst;
  5275. tttw.uFlags = pnmTTTA->uFlags;
  5276. tttw.lParam = pnmTTTA->lParam;
  5277. LRESULT lRes = SUPERCLASS::OnNotify(&tttw.hdr);
  5278. pnmTTTA->hdr = tttw.hdr;
  5279. pnmTTTA->hdr.code = TTN_NEEDTEXTA;
  5280. pnmTTTA->hinst = tttw.hinst;
  5281. pnmTTTA->uFlags = tttw.uFlags;
  5282. pnmTTTA->lParam = tttw.lParam;
  5283. if (tttw.lpszText == LPSTR_TEXTCALLBACKW)
  5284. pnmTTTA->lpszText = LPSTR_TEXTCALLBACKA;
  5285. else if (!tttw.lpszText)
  5286. pnmTTTA->lpszText = NULL;
  5287. else if (!HIWORD(tttw.lpszText))
  5288. pnmTTTA->lpszText = (LPSTR)tttw.lpszText;
  5289. else {
  5290. WideCharToMultiByte(CP_ACP, 0, tttw.lpszText, -1,
  5291. pnmTTTA->szText, ARRAYSIZE(pnmTTTA->szText), NULL, NULL);
  5292. }
  5293. return lRes;
  5294. }
  5295. UINT GetDDEExecMsg()
  5296. {
  5297. static UINT uDDEExec = 0;
  5298. if (!uDDEExec)
  5299. uDDEExec = RegisterWindowMessage(TEXT("DDEEXECUTESHORTCIRCUIT"));
  5300. return uDDEExec;
  5301. }
  5302. LRESULT CShellBrowser2::OnNotify(LPNMHDR pnm)
  5303. {
  5304. switch (pnm->code)
  5305. {
  5306. case NM_DBLCLK:
  5307. {
  5308. int idCmd = -1;
  5309. LPNMCLICK pnmc = (LPNMCLICK)pnm;
  5310. switch(pnmc->dwItemSpec)
  5311. {
  5312. case STATUS_PANE_NAVIGATION:
  5313. idCmd = SHDVID_NAVIGATIONSTATUS;
  5314. break;
  5315. case STATUS_PANE_PROGRESS:
  5316. idCmd = SHDVID_PROGRESSSTATUS;
  5317. break;
  5318. case STATUS_PANE_OFFLINE:
  5319. idCmd = SHDVID_ONLINESTATUS;
  5320. break;
  5321. case STATUS_PANE_PRIVACY:
  5322. idCmd = SHDVID_PRIVACYSTATUS;
  5323. break;
  5324. //case STATUS_PANE_PRINTER:
  5325. // idCmd = SHDVID_PRINTSTATUS;
  5326. // break;
  5327. case STATUS_PANE_ZONE:
  5328. idCmd = SHDVID_ZONESTATUS;
  5329. break;
  5330. case STATUS_PANE_SSL:
  5331. idCmd = SHDVID_SSLSTATUS;
  5332. break;
  5333. default:
  5334. break;
  5335. }
  5336. if (_pbbd->_pctView && (idCmd != -1))
  5337. {
  5338. HRESULT hr = _pbbd->_pctView->Exec(&CGID_ShellDocView, idCmd, NULL, NULL, NULL);
  5339. // If the parent couldn't handle it, maybe we can.
  5340. if (FAILED(hr)) {
  5341. if (pnmc->dwItemSpec == _uiZonePane &&
  5342. _pbbd->_pidlCur)
  5343. {
  5344. WCHAR wszUrl[MAX_URL_STRING];
  5345. if (SUCCEEDED(::IEGetDisplayName(_pbbd->_pidlCur, wszUrl, SHGDN_FORPARSING)))
  5346. {
  5347. ULONG_PTR uCookie = 0;
  5348. SHActivateContext(&uCookie);
  5349. ZoneConfigureW(_pbbd->_hwnd, wszUrl);
  5350. if (uCookie)
  5351. {
  5352. SHDeactivateContext(uCookie);
  5353. }
  5354. }
  5355. }
  5356. }
  5357. }
  5358. break;
  5359. }
  5360. case TTN_NEEDTEXTA:
  5361. case TTN_NEEDTEXTW:
  5362. if (IsInRange(pnm->idFrom, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST)) {
  5363. if (pnm->code == TTN_NEEDTEXTA && _fUnicode)
  5364. return _ThunkTTNotify((LPTOOLTIPTEXTA)pnm);
  5365. else
  5366. return SUPERCLASS::OnNotify(pnm);
  5367. }
  5368. return 0;
  5369. case SEN_DDEEXECUTE:
  5370. // 381213 - webfolders needs dde shortcircuit in IE to work - ZekeL - 30-APR-2001
  5371. // on NT4SUR (non-integrated) we have to make sure that webfolders
  5372. // continues to be able to get folder window reuse for navigation.
  5373. //
  5374. // this was:
  5375. // if (pnm->idFrom == 0 && GetUIVersion() >= 4)
  5376. // and i am pretty sure some thing will break, since we once again
  5377. // allow the shortcircuit code to run on pre-shell integrated.
  5378. // but maybe not since we no longer use the bogus folder navigation
  5379. // in order to implement OpenNew window for HTMLFile
  5380. if (pnm->idFrom == 0)
  5381. {
  5382. LPNMVIEWFOLDER pnmPost = DDECreatePostNotify((LPNMVIEWFOLDER)pnm) ;
  5383. if (pnmPost)
  5384. {
  5385. PostMessage(_pbbd->_hwnd, GetDDEExecMsg(), 0, (LPARAM)pnmPost);
  5386. return TRUE;
  5387. }
  5388. }
  5389. break;
  5390. case SBN_SIMPLEMODECHANGE:
  5391. if ((pnm->idFrom == FCIDM_STATUS) && _hwndProgress)
  5392. _ShowHideProgress();
  5393. break;
  5394. default:
  5395. break;
  5396. }
  5397. return 0;
  5398. }
  5399. DWORD CShellBrowser2::_GetTempZone()
  5400. {
  5401. LPCITEMIDLIST pidlChild;
  5402. IShellFolder* psfParent;
  5403. WCHAR szURL[MAX_URL_STRING];
  5404. szURL[0] = 0; // parse name for zone goes here
  5405. if (SUCCEEDED(IEBindToParentFolder(_pbbd->_pidlCur, &psfParent, &pidlChild)))
  5406. {
  5407. // see if this is a folder shortcut, if so we use it's path for the zone
  5408. IShellLink *psl;
  5409. if (SUCCEEDED(psfParent->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidlChild, IID_IShellLink, NULL, (void **)&psl)))
  5410. {
  5411. LPITEMIDLIST pidlTarget;
  5412. if (S_OK == psl->GetIDList(&pidlTarget))
  5413. {
  5414. ::IEGetDisplayName(pidlTarget, szURL, SHGDN_FORPARSING);
  5415. ILFree(pidlTarget);
  5416. }
  5417. psl->Release();
  5418. }
  5419. psfParent->Release();
  5420. }
  5421. if (NULL == _pism)
  5422. CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetSecurityManager, &_pism));
  5423. DWORD nZone = ZONE_UNKNOWN;
  5424. if (_pism && (szURL[0] || SUCCEEDED(::IEGetDisplayName(_pbbd->_pidlCur, szURL, SHGDN_FORPARSING))))
  5425. {
  5426. _pism->MapUrlToZone(szURL, &nZone, 0);
  5427. }
  5428. return nZone;
  5429. }
  5430. void Exec_GetZone(IUnknown * punk, VARIANTARG *pvar)
  5431. {
  5432. IUnknown_Exec(punk, &CGID_Explorer, SBCMDID_MIXEDZONE, 0, NULL, pvar);
  5433. if (pvar->vt == VT_UI4) // MSHTML was able to figure out what zone we are in
  5434. pvar->ulVal = MAKELONG(STATUS_PANE_ZONE, pvar->ulVal);
  5435. else if (pvar->vt == VT_NULL) // MSHTML has figured us to be in a mixed zone
  5436. pvar->ulVal = MAKELONG(STATUS_PANE_ZONE, ZONE_MIXED);
  5437. else // We don't have zone info
  5438. pvar->ulVal = MAKELONG(STATUS_PANE_ZONE, ZONE_UNKNOWN);
  5439. pvar->vt = VT_UI4;
  5440. }
  5441. //
  5442. // in:
  5443. // pvar if NULL, we query the view for the zone
  5444. // non NULL, contains a VT_UI4 that encodes the zone pane and the zone value
  5445. void CShellBrowser2::_UpdateZonesPane(VARIANT *pvar)
  5446. {
  5447. LONG lZone = ZONE_UNKNOWN;
  5448. BOOL fMixed = FALSE;
  5449. TCHAR szDisplayName[MAX_ZONE_DISPLAYNAME];
  5450. VARIANTARG var = {0};
  5451. if (NULL == pvar)
  5452. {
  5453. pvar = &var;
  5454. Exec_GetZone(_pbbd->_pctView, &var);
  5455. }
  5456. // Do we already have the zone and fMixed info?
  5457. if (pvar->vt == VT_UI4)
  5458. {
  5459. lZone = (signed short)HIWORD(pvar->lVal);
  5460. _uiZonePane = (int)(signed short)LOWORD(pvar->lVal);
  5461. if (lZone == ZONE_MIXED)
  5462. {
  5463. lZone = ZONE_UNKNOWN;
  5464. fMixed = TRUE;
  5465. }
  5466. if (lZone < 0 && !IS_SPECIAL_ZONE(lZone))
  5467. {
  5468. // sometimes we're getting back an invalid zone index from urlmon,
  5469. // and if we don't bound the index, we'll crash later
  5470. lZone = ZONE_UNKNOWN;
  5471. }
  5472. }
  5473. var.vt = VT_EMPTY;
  5474. if (_pbbd->_pctView && SUCCEEDED(_pbbd->_pctView->Exec(&CGID_Explorer, SBCMDID_GETPANE, PANE_ZONE, NULL, &var)))
  5475. _uiZonePane = var.ulVal;
  5476. else
  5477. _uiZonePane = STATUS_PANE_ZONE;
  5478. // Sanity Check the zone
  5479. if (_pbbd->_pidlCur)
  5480. {
  5481. DWORD nTempZone = _GetTempZone();
  5482. if (nTempZone != ZONE_UNKNOWN)
  5483. if (nTempZone > (DWORD)lZone)
  5484. lZone = nTempZone;
  5485. }
  5486. szDisplayName[0] = 0;
  5487. if (ZONE_UNKNOWN == lZone)
  5488. MLLoadStringW(IDS_UNKNOWNZONE, szDisplayName, ARRAYSIZE(szDisplayName));
  5489. else
  5490. {
  5491. if (_hZoneIcon)
  5492. {
  5493. // Before we can delete it, make comctl32's statusbar code stop using it.
  5494. // Or else we rip.
  5495. SendControlMsg(FCW_STATUS, SB_SETICON, _uiZonePane, (LPARAM)NULL, NULL);
  5496. DestroyIcon(_hZoneIcon);
  5497. }
  5498. // This will zero the icon & name on failure
  5499. _GetCachedZoneIconAndName(lZone, &_hZoneIcon, szDisplayName, ARRAYSIZE(szDisplayName));
  5500. }
  5501. if (fMixed)
  5502. {
  5503. TCHAR szMixed[32];
  5504. MLLoadString(IDS_MIXEDZONE, szMixed, ARRAYSIZE(szMixed));
  5505. StrCatBuff(szDisplayName, szMixed, ARRAYSIZE(szDisplayName));
  5506. }
  5507. SendControlMsg(FCW_STATUS, SB_SETTEXTW, _uiZonePane, (LPARAM)szDisplayName, NULL);
  5508. SendControlMsg(FCW_STATUS, SB_SETICON, _uiZonePane, (LPARAM)_hZoneIcon, NULL);
  5509. }
  5510. HRESULT CShellBrowser2::ReleaseShellView()
  5511. {
  5512. // Give the current view a chance to save before we navigate away
  5513. if (!_fClosingWindow)
  5514. {
  5515. // only try to save if we actually have a current view (this gets
  5516. // called multiple times in a row on destruction, and it gets called
  5517. // before the first view is created)
  5518. //
  5519. if (_pbbd->_psv)
  5520. _SaveState();
  5521. }
  5522. return SUPERCLASS::ReleaseShellView();
  5523. }
  5524. bool IsWin95ClassicViewState (void)
  5525. {
  5526. DWORD dwValue;
  5527. DWORD cbSize = sizeof(dwValue);
  5528. return ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER,
  5529. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
  5530. TEXT("ClassicViewState"), NULL, &dwValue, &cbSize) && dwValue;
  5531. }
  5532. BOOL _PersistOpenBrowsers()
  5533. {
  5534. return SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
  5535. TEXT("PersistBrowsers"), FALSE, FALSE);
  5536. }
  5537. // For Folder Advanced Options flags that we check often, it's better
  5538. // to cache the values as flags in CBaseBrowser2. Update them here.
  5539. void CShellBrowser2::_UpdateRegFlags()
  5540. {
  5541. _fWin95ViewState = IsWin95ClassicViewState();
  5542. }
  5543. HRESULT CShellBrowser2::CreateViewWindow(IShellView* psvNew, IShellView* psvOld, LPRECT prcView, HWND* phwnd)
  5544. {
  5545. if (_pbbd->_psv)
  5546. {
  5547. // snag the current view's setting so we can pass it along
  5548. _UpdateFolderSettings(_pbbd->_pidlPending);
  5549. // this is not a valid flag to pass along after the first one
  5550. _fsd._fs.fFlags &= ~FWF_BESTFITWINDOW;
  5551. }
  5552. return SUPERCLASS::CreateViewWindow(psvNew, psvOld, prcView, phwnd);
  5553. }
  5554. HRESULT CShellBrowser2::ActivatePendingView(void)
  5555. {
  5556. _fTitleSet = FALSE;
  5557. // NOTES: (SatoNa)
  5558. //
  5559. // Notice that we no longer call SetRect(&_rcBorderDoc, 0, 0, 0, 0)
  5560. // here. We call it in CShellBrowser2::ReleaseShellView instead.
  5561. // See my comment over there for detail.
  5562. //
  5563. HRESULT hres = SUPERCLASS::ActivatePendingView();
  5564. if (FAILED(hres))
  5565. return hres;
  5566. _ReloadStatusbarIcon();
  5567. _SetTitle(NULL);
  5568. v_SetIcon();
  5569. VALIDATEPENDINGSTATE();
  5570. if (_pxtb)
  5571. _pxtb->SendToolbarMsg(&CLSID_CommonButtons, TB_ENABLEBUTTON, TBIDM_PREVIOUSFOLDER, _ShouldAllowNavigateParent(), NULL);
  5572. UpdateWindowList();
  5573. if (!_HasToolbarFocus())
  5574. {
  5575. HWND hwndFocus = GetFocus();
  5576. //
  5577. // Trident may take the input focus when they are being UIActivated.
  5578. // In that case, don't mess with the focus.
  5579. //
  5580. if (_pbbd->_hwndView && (hwndFocus==NULL || !IsChild(_pbbd->_hwndView, hwndFocus)))
  5581. SetFocus(_pbbd->_hwndView);
  5582. }
  5583. // Let's profile opening time
  5584. if (g_dwProfileCAP & 0x00010000)
  5585. StopCAP();
  5586. // Let's profile opening time
  5587. if (g_dwProfileCAP & 0x00000020)
  5588. StartCAP();
  5589. return S_OK;
  5590. }
  5591. void CShellBrowser2::_UpdateBackForwardStateNow()
  5592. {
  5593. _fUpdateBackForwardPosted = FALSE;
  5594. SUPERCLASS::UpdateBackForwardState();
  5595. }
  5596. HRESULT CShellBrowser2::UpdateBackForwardState()
  5597. {
  5598. if (!_fUpdateBackForwardPosted)
  5599. {
  5600. PostMessage(_pbbd->_hwnd, CWM_UPDATEBACKFORWARDSTATE, 0, 0);
  5601. _fUpdateBackForwardPosted = TRUE;
  5602. }
  5603. return S_OK;
  5604. }
  5605. HRESULT CShellBrowser2::_TryShell2Rename(IShellView* psv, LPCITEMIDLIST pidlNew)
  5606. {
  5607. HRESULT hres = SUPERCLASS::_TryShell2Rename(psv, pidlNew);
  5608. if (SUCCEEDED(hres))
  5609. {
  5610. _SetTitle(NULL);
  5611. }
  5612. return hres;
  5613. }
  5614. /*----------------------------------------------------------
  5615. Purpose: Determines if this message should be forwarded onto
  5616. the dochost frame.
  5617. Returns: TRUE if the message needs to be forwarded
  5618. */
  5619. BOOL CShellBrowser2::_ShouldForwardMenu(UINT uMsg, WPARAM wParam, LPARAM lParam)
  5620. {
  5621. if (!_fDispatchMenuMsgs)
  5622. return FALSE;
  5623. switch (uMsg)
  5624. {
  5625. case WM_MENUSELECT:
  5626. {
  5627. // See CDocObjectHost::_ShouldForwardMenu for more details
  5628. // about how this works.
  5629. HMENU hmenu = GET_WM_MENUSELECT_HMENU(wParam, lParam);
  5630. if (hmenu && (MF_POPUP & GET_WM_MENUSELECT_FLAGS(wParam, lParam)))
  5631. {
  5632. HMENU hmenuSub = GetSubMenu(hmenu, GET_WM_MENUSELECT_CMD(wParam, lParam));
  5633. if (hmenu == _hmenuCur)
  5634. {
  5635. // Normal case, where we just look at the topmost popdown menus
  5636. _fForwardMenu = _menulist.IsObjectMenu(hmenuSub);
  5637. }
  5638. else if (_menulist.IsObjectMenu(hmenuSub))
  5639. {
  5640. // This happens if the cascading submenu (micro-merged help menu for
  5641. // example) should be forwarded on, but the parent menu should
  5642. // not.
  5643. _fForwardMenu = TRUE;
  5644. }
  5645. }
  5646. break;
  5647. }
  5648. case WM_COMMAND:
  5649. if (_fForwardMenu)
  5650. {
  5651. // Stop forwarding menu messages after WM_COMMAND
  5652. _fForwardMenu = FALSE;
  5653. // If it wasn't from an accelerator, forward it
  5654. if (0 == GET_WM_COMMAND_CMD(wParam, lParam))
  5655. return TRUE;
  5656. }
  5657. break;
  5658. }
  5659. return _fForwardMenu;
  5660. }
  5661. DWORD CShellBrowser2::v_RestartFlags()
  5662. {
  5663. return COF_CREATENEWWINDOW;
  5664. }
  5665. void CShellBrowser2::_CloseAllParents()
  5666. {
  5667. LPITEMIDLIST pidl = ILClone(_pbbd->_pidlCur);
  5668. if (pidl)
  5669. {
  5670. for (ILRemoveLastID(pidl); !ILIsEmpty(pidl); ILRemoveLastID(pidl))
  5671. {
  5672. HWND hwnd;
  5673. if (WinList_FindFolderWindow(pidl, NULL, &hwnd, NULL) == S_OK)
  5674. {
  5675. TraceMsg(DM_SHUTDOWN, "csb.cap: post WM_CLOSE hwnd=%x", hwnd);
  5676. PostMessage(hwnd, WM_CLOSE, 0, 0);
  5677. }
  5678. }
  5679. ILFree(pidl);
  5680. }
  5681. }
  5682. BOOL CShellBrowser2::_ShouldSaveWindowPlacement()
  5683. {
  5684. // If this is done by automation, maybe we should not update the defaults, so
  5685. // to detect this we say if the window is not visible, don't save away the defaults
  5686. // For the internet, save one setting for all, otherwise use the win95
  5687. // view stream mru
  5688. return (IsWindowVisible(_pbbd->_hwnd) && _fUseIEPersistence && !_fUISetByAutomation &&
  5689. _pbbd->_pidlCur && IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_BROWSER_PERSIST_SETTINGS));
  5690. }
  5691. void CShellBrowser2::_OnConfirmedClose()
  5692. {
  5693. if (_pbbd->_pidlCur && IsCShellBrowser2() && (GetKeyState(VK_SHIFT) < 0)) {
  5694. _CloseAllParents();
  5695. }
  5696. if (_fUseIEPersistence && IsCShellBrowser2())
  5697. {
  5698. // save off whether we should launch in fullscreen or not
  5699. SHRegSetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  5700. TEXT("FullScreen"), REG_SZ,
  5701. _ptheater ? TEXT("yes") : TEXT("no"),
  5702. _ptheater ? sizeof(TEXT("yes")) : sizeof(TEXT("no")),
  5703. SHREGSET_DEFAULT);
  5704. }
  5705. if (_ptheater)
  5706. {
  5707. ShowWindow(_pbbd->_hwnd, SW_HIDE);
  5708. _TheaterMode(FALSE, FALSE);
  5709. _fDontSaveViewOptions = TRUE;
  5710. }
  5711. else
  5712. {
  5713. if (_ShouldSaveWindowPlacement())
  5714. {
  5715. StorePlacementOfWindow(_pbbd->_hwnd);
  5716. }
  5717. else
  5718. _fDontSaveViewOptions = TRUE;
  5719. }
  5720. // for now we use the same 12-hour (SessionTime) rule
  5721. // possibly we should just do it always?
  5722. UEMFireEvent(&UEMIID_BROWSER, UEME_CTLSESSION, UEMF_XEVENT, FALSE, -1);
  5723. if (!g_bRunOnNT5) {
  5724. // for down-level guys (old explorer), fake a shell end session too
  5725. UEMFireEvent(&UEMIID_SHELL, UEME_CTLSESSION, UEMF_XEVENT, FALSE, -1);
  5726. }
  5727. // Save view states before closing all toolbars
  5728. // Remember that we saved so we don't do it again
  5729. // during _ReleaseShellView
  5730. _SaveState();
  5731. _fClosingWindow = TRUE;
  5732. // To prevent flashing, we move the window off the screen, unfortunately
  5733. // we can't hide it as shockwave briefly puts up dialog which causes
  5734. // an ugly blank taskbar icon to appear.
  5735. // do this after _SaveState() because that saves window pos info
  5736. // NTRAID 455003: this won't look too good with multi monitors...
  5737. SetWindowPos(_pbbd->_hwnd, NULL, 10000, 10000, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
  5738. // Save the Internet toolbar before we close it!
  5739. if (!_fDontSaveViewOptions)
  5740. _SaveITbarLayout();
  5741. _CloseAndReleaseToolbars(TRUE);
  5742. ATOMICRELEASE(_pxtb);
  5743. // If you wait until WM_DESTROY (DestroyWindow below) to do this, under some
  5744. // circumstances (eg an html page with an iframe whose src is an UNC based directory)
  5745. // Ole will not Release the CShellBrowser2 that it addref'ed on RegisterDragDrop
  5746. // (chrisfra 7/22/97)
  5747. SetFlags(0, BSF_REGISTERASDROPTARGET);
  5748. // If you wait until WM_DESTROY to do this, some OCs (like shockwave)
  5749. // will hang (probably posting themselves a message)
  5750. _CancelPendingView();
  5751. ReleaseShellView();
  5752. ATOMICRELEASE(_pmb);
  5753. // Destroy the icons we created while we still can
  5754. _SetWindowIcon(_pbbd->_hwnd, NULL, ICON_SMALL);
  5755. _SetWindowIcon(_pbbd->_hwnd, NULL, ICON_BIG);
  5756. // getting a random fault on rooted explorer on shutdown on this Destroy, maybe
  5757. // somehow getting reentered. So atomic destroy it...
  5758. // NOTE: chrisg removed this at one point - is it dead?
  5759. HWND hwndT = _pbbd->_hwnd;
  5760. PutBaseBrowserData()->_hwnd = NULL;
  5761. DestroyWindow(hwndT);
  5762. }
  5763. // these three functions, CommonHandleFielSysChange,
  5764. // v_HandleFileSysChange and this one
  5765. // may seem strange, but the idea is that the notify may come in from
  5766. // different sources (OneTree vs, win95 style fsnotify vs nt style)
  5767. // _OnFSNotify cracks the input, unifies it and calls CommonHnaldeFileSysChange
  5768. // that calls to v_HandleFIleSysChange. The Common...() is for stuff both needs
  5769. // the v_Handle...() is for overridden ones
  5770. void CShellBrowser2::_OnFSNotify(WPARAM wParam, LPARAM lParam)
  5771. {
  5772. LPSHChangeNotificationLock pshcnl = NULL;
  5773. LONG lEvent;
  5774. LPITEMIDLIST *ppidl = NULL; // on error, SHChangeNotification_Lock doesn't zero this out!
  5775. IShellChangeNotify * pIFSN;
  5776. if (g_fNewNotify && (wParam || lParam))
  5777. {
  5778. // New style of notifications need to lock and unlock in order to free the memory...
  5779. pshcnl = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent);
  5780. } else {
  5781. lEvent = (LONG)lParam;
  5782. ppidl = (LPITEMIDLIST*)wParam;
  5783. }
  5784. if (ppidl)
  5785. {
  5786. //
  5787. // If we haven't initialized "this" yet, we should ignore all the
  5788. // notification.
  5789. //
  5790. if (_pbbd->_pidlCur)
  5791. {
  5792. _CommonHandleFileSysChange(lEvent, ppidl[0], ppidl[1]);
  5793. //
  5794. // Forward to ITBar too...
  5795. //
  5796. if (_GetITBar() && SUCCEEDED(_GetITBar()->QueryInterface(IID_PPV_ARG(IShellChangeNotify, &pIFSN))))
  5797. {
  5798. pIFSN->OnChange(lEvent, ppidl[0], ppidl[1]);
  5799. pIFSN->Release();
  5800. }
  5801. }
  5802. }
  5803. if (pshcnl)
  5804. {
  5805. SHChangeNotification_Unlock(pshcnl);
  5806. }
  5807. }
  5808. LPITEMIDLIST BurnDrivePidl()
  5809. {
  5810. LPITEMIDLIST pidl = NULL;
  5811. ICDBurn *pcdb;
  5812. if (SUCCEEDED(CoCreateInstance(CLSID_CDBurn, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICDBurn, &pcdb))))
  5813. {
  5814. WCHAR szDrive[4];
  5815. if (SUCCEEDED(pcdb->GetRecorderDriveLetter(szDrive, ARRAYSIZE(szDrive))))
  5816. {
  5817. pidl = ILCreateFromPath(szDrive);
  5818. }
  5819. pcdb->Release();
  5820. }
  5821. return pidl;
  5822. }
  5823. BOOL IsCurrentBurnDrive(LPCITEMIDLIST pidl)
  5824. {
  5825. BOOL fRet = FALSE;
  5826. LPITEMIDLIST pidlBurn = BurnDrivePidl();
  5827. if (pidlBurn)
  5828. {
  5829. fRet = ILIsEqual(pidlBurn, pidl) || ILIsParent(pidlBurn, pidl, FALSE);
  5830. ILFree(pidlBurn);
  5831. }
  5832. return fRet;
  5833. }
  5834. // fDisconnectAlways means we shouldn't try to re-open the folder (like when
  5835. // someone logs off of a share, reconnecting would ask them for
  5836. // a password again when they just specified that they want to log off)
  5837. void CShellBrowser2::_FSChangeCheckClose(LPCITEMIDLIST pidl, BOOL fDisconnect)
  5838. {
  5839. if (ILIsParent(pidl, _pbbd->_pidlCur, FALSE) ||
  5840. (ILIsRooted(_pbbd->_pidlCur) && (ILIsParent(pidl, ILRootedFindIDList(_pbbd->_pidlCur), FALSE))))
  5841. {
  5842. if (!fDisconnect)
  5843. {
  5844. // APPCOMPAT: FileNet IDMDS (Panagon)'s shell folder extension
  5845. // incorrectly reports itself as a file system folder, so sniff the
  5846. // pidl to see if we should ignore the bit. (B#359464: tracysh)
  5847. // (tybeam) argh put the burndrive check back in again.
  5848. // this app compat hack brings me no joy, its false positive city and basically all it is is the
  5849. // PathFileExistsAndAttributes check. if you ever have an issue where you have a namespace
  5850. // extension that reports that it's on the filesystem and could possibly fail a PathFileExists
  5851. // on a parsing name (which happens in the burning folder if theres no cd in the drive and it
  5852. // checks the parsing name of the root) and it closes the window randomly, this is the problem
  5853. // right here.
  5854. TCHAR szPath[MAX_PATH];
  5855. DWORD dwAttrib = SFGAO_FILESYSTEM | SFGAO_BROWSABLE;
  5856. if (SUCCEEDED(SHGetNameAndFlags(_pbbd->_pidlCur, SHGDN_FORPARSING, szPath, SIZECHARS(szPath), &dwAttrib))
  5857. && (dwAttrib & SFGAO_FILESYSTEM)
  5858. && !(dwAttrib & SFGAO_BROWSABLE)
  5859. && IsFlagClear(SHGetObjectCompatFlagsFromIDList(_pbbd->_pidlCur), OBJCOMPATF_NOTAFILESYSTEM)
  5860. && !PathFileExistsAndAttributes(szPath, NULL)
  5861. && !IsCurrentBurnDrive(_pbbd->_pidlCur))
  5862. {
  5863. fDisconnect = TRUE;
  5864. }
  5865. }
  5866. if (fDisconnect)
  5867. _pbbd->_pautoWB2->Quit();
  5868. }
  5869. }
  5870. void CShellBrowser2::v_HandleFileSysChange(LONG lEvent, LPITEMIDLIST pidl1, LPITEMIDLIST pidl2)
  5871. {
  5872. BOOL fDisconnectAlways = FALSE;
  5873. //
  5874. // If we are in the middle of changing folders,
  5875. // ignore this event.
  5876. //
  5877. if (_pbbd->_psvPending) {
  5878. return;
  5879. }
  5880. // README:
  5881. // If you need to add events here, then you must change SHELLBROWSER_FSNOTIFY_FLAGS in
  5882. // order to get the notifications
  5883. switch(lEvent)
  5884. {
  5885. case SHCNE_DRIVEADDGUI:
  5886. if (ILIsParent(pidl1, _pbbd->_pidlCur, FALSE)) {
  5887. PostMessage(_pbbd->_hwnd, WM_COMMAND, FCIDM_REFRESH, 0L);
  5888. }
  5889. break;
  5890. case SHCNE_DELETE:
  5891. case SHCNE_RMDIR:
  5892. case SHCNE_MEDIAREMOVED:
  5893. case SHCNE_SERVERDISCONNECT:
  5894. case SHCNE_DRIVEREMOVED:
  5895. if (g_fRunningOnNT || (lEvent == SHCNE_MEDIAREMOVED) || (lEvent == SHCNE_SERVERDISCONNECT))
  5896. fDisconnectAlways = TRUE;
  5897. // the cd burning case can get a removal event when we lock the
  5898. // drive to commence burning or when the user ejects.
  5899. // since we have an open browser on the drive we could get closed and thats bad,
  5900. // so we prevent that here.
  5901. if ((lEvent == SHCNE_MEDIAREMOVED) && IsCurrentBurnDrive(_pbbd->_pidlCur))
  5902. {
  5903. // jump out, we don't want to close.
  5904. break;
  5905. }
  5906. // fall through
  5907. case SHCNE_UPDATEDIR:
  5908. case SHCNE_NETUNSHARE:
  5909. // preserve old behavior of when the explorer (all folders) bar is up,
  5910. // go to nearest parent folder
  5911. if (_idmInfo == FCIDM_VBBEXPLORERBAND)
  5912. break;
  5913. _FSChangeCheckClose(pidl1, fDisconnectAlways);
  5914. break;
  5915. }
  5916. }
  5917. // converts a simple pidl to a full pidl
  5918. LPITEMIDLIST _SimpleToReal(LPCITEMIDLIST pidl)
  5919. {
  5920. LPITEMIDLIST pidlReturn = NULL;
  5921. IShellFolder *psf;
  5922. LPCITEMIDLIST pidlChild;
  5923. if (SUCCEEDED(IEBindToParentFolder(pidl, &psf, &pidlChild)))
  5924. {
  5925. LPITEMIDLIST pidlRealChild;
  5926. if (SUCCEEDED(SHGetRealIDL(psf, pidlChild, &pidlRealChild)))
  5927. {
  5928. LPITEMIDLIST pidlParent = ILCloneParent(pidl);
  5929. if (pidlParent)
  5930. {
  5931. pidlReturn = ILCombine(pidlParent, pidlRealChild);
  5932. ILFree(pidlParent);
  5933. }
  5934. ILFree(pidlRealChild);
  5935. }
  5936. psf->Release();
  5937. }
  5938. return pidlReturn;
  5939. }
  5940. void CShellBrowser2::_CommonHandleFileSysChange(LONG lEvent, LPITEMIDLIST pidl1, LPITEMIDLIST pidl2)
  5941. {
  5942. v_HandleFileSysChange(lEvent, pidl1, pidl2);
  5943. // WARNING: In all cases _pbbd will have NULL contents before first navigate.
  5944. if (_pbbd->_psvPending) {
  5945. return;
  5946. }
  5947. // stuff that needs to be done tree or no tree
  5948. switch (lEvent) {
  5949. // README:
  5950. // If you need to add events here, then you must change SHELLBROWSER_FSNOTIFY_FLAGS in
  5951. // order to get the notifications
  5952. case SHCNE_RENAMEFOLDER:
  5953. {
  5954. // the rename might be ourselfs or our parent... if it's
  5955. // our parent, we want to tack on the child idl's from the renamed
  5956. // parent to us onto the new pidl (pidlExtra).
  5957. // then show that result.
  5958. LPCITEMIDLIST pidlChild = ILFindChild(pidl1, _pbbd->_pidlCur);
  5959. if (pidlChild)
  5960. {
  5961. LPITEMIDLIST pidlTarget = ILCombine(pidl2, pidlChild);
  5962. if (pidlTarget)
  5963. {
  5964. LPITEMIDLIST pidlReal = _SimpleToReal(pidlTarget);
  5965. if (pidlReal)
  5966. {
  5967. if (!ILIsEqual(pidlReal, _pbbd->_pidlCur))
  5968. {
  5969. BrowseObject(pidlReal, SBSP_REDIRECT | SBSP_SAMEBROWSER);
  5970. }
  5971. ILFree(pidlReal);
  5972. }
  5973. ILFree(pidlTarget);
  5974. }
  5975. }
  5976. }
  5977. // fall through
  5978. case SHCNE_UPDATEITEM:
  5979. // the name could have changed
  5980. if (ILIsEqual(_pbbd->_pidlCur, pidl1))
  5981. _SetTitle(NULL);
  5982. break;
  5983. case SHCNE_UPDATEIMAGE:
  5984. IUnknown_CPContainerInvokeParam(_pbbd->_pautoEDS,
  5985. DIID_DWebBrowserEvents2, DISPID_TITLEICONCHANGE, NULL, 0);
  5986. #ifdef DEBUG
  5987. if (_pbbd->_pautoEDS)
  5988. {
  5989. // Verify that every IExpDispSupport also supports IConnectionPointContainer
  5990. IConnectionPointContainer *pcpc;
  5991. IExpDispSupport* peds;
  5992. if (SUCCEEDED(_pbbd->_pautoEDS->QueryInterface(IID_IConnectionPointContainer, (void **)&pcpc)))
  5993. {
  5994. pcpc->Release();
  5995. }
  5996. else if (SUCCEEDED(_pbbd->_pautoEDS->QueryInterface(IID_IExpDispSupport, (void **)&peds)))
  5997. {
  5998. peds->Release();
  5999. AssertMsg(0, TEXT("IExpDispSupport without IConnectionPointContainer for %08x"), _pbbd->_pautoEDS);
  6000. }
  6001. }
  6002. #endif
  6003. v_SetIcon();
  6004. break;
  6005. }
  6006. }
  6007. //---------------------------------------------------------------------------
  6008. // Helper Function to see if a pidl is on a network drive which is not
  6009. // persistent. This is useful if we are shuting down and saving a list
  6010. // of the open windows to restore as we won't be able to restore these.
  6011. BOOL FPidlOnNonPersistentDrive(LPCITEMIDLIST pidl)
  6012. {
  6013. TCHAR szPath[MAX_PATH];
  6014. HANDLE hEnum;
  6015. BOOL fRet = TRUE;
  6016. TraceMsg(DM_SHUTDOWN, "csb.wp: FPidlOnNonPersistentDrive(pidl=%x)", pidl);
  6017. if (!SHGetPathFromIDList(pidl, szPath) || (szPath[0] == TEXT('\0')))
  6018. return(FALSE); // not file system pidl assume ok.
  6019. TraceMsg(DM_SHUTDOWN, "csb.wp: FPidlOnNonPersistentDrive - After GetPath=%s)", szPath);
  6020. if (PathIsUNC(szPath) || !IsNetDrive(DRIVEID(szPath)))
  6021. {
  6022. fRet = FALSE;
  6023. goto End;
  6024. }
  6025. // Ok we got here so now we have a network drive ...
  6026. // we will have to enumerate over
  6027. //
  6028. if (WNetOpenEnum(RESOURCE_REMEMBERED, RESOURCETYPE_DISK,
  6029. RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED,
  6030. NULL, &hEnum) == WN_SUCCESS)
  6031. {
  6032. DWORD dwCount=1;
  6033. union
  6034. {
  6035. NETRESOURCE nr; // Large stack usage but I
  6036. TCHAR buf[1024]; // Dont think it is thunk to 16 bits...
  6037. }nrb;
  6038. DWORD dwBufSize = sizeof(nrb);
  6039. while (WNetEnumResource(hEnum, &dwCount, &nrb.buf,
  6040. &dwBufSize) == WN_SUCCESS)
  6041. {
  6042. // We only want to add items if they do not have a local
  6043. // name. If they had a local name we would have already
  6044. // added them!
  6045. if ((nrb.nr.lpLocalName != NULL) &&
  6046. (CharUpperChar(*(nrb.nr.lpLocalName)) == CharUpperChar(szPath[0])))
  6047. {
  6048. fRet = FALSE;
  6049. break;
  6050. }
  6051. }
  6052. WNetCloseEnum(hEnum);
  6053. }
  6054. End:
  6055. TraceMsg(DM_TRACE, "c.c_arl: %s, is Persistent? %d", szPath, fRet);
  6056. return(fRet);
  6057. }
  6058. void HackToPrepareForEndSession(LPCITEMIDLIST pidl)
  6059. {
  6060. TCHAR szPath[MAX_PATH];
  6061. TraceMsg(DM_SHUTDOWN, "csb.wp: HackToPrepareForEndSession(pidl=%x)", pidl);
  6062. SHGetPathFromIDList(pidl, szPath);
  6063. }
  6064. //---------------------------------------------------------------------------
  6065. // returns:
  6066. // TRUE if the user wants to abort the startup sequence
  6067. // FALSE keep going
  6068. //
  6069. // note: this is a switch, once on it will return TRUE to all
  6070. // calls so these keys don't need to be pressed the whole time
  6071. BOOL AbortStartup()
  6072. {
  6073. static BOOL bAborted = FALSE; // static so it sticks!
  6074. // TraceMsg(DM_TRACE, "Abort Startup?");
  6075. if (bAborted)
  6076. return TRUE; // don't do funky startup stuff
  6077. else {
  6078. bAborted = (GetSystemMetrics(SM_CLEANBOOT) || ((GetAsyncKeyState(VK_CONTROL) < 0) || (GetAsyncKeyState(VK_SHIFT) < 0)));
  6079. return bAborted;
  6080. }
  6081. }
  6082. //---------------------------------------------------------------------------
  6083. // Restore all of the window that asked to save a command line to be
  6084. // restarted when windows was exited.
  6085. //
  6086. BOOL AddToRestartList(DWORD dwFlags, LPCITEMIDLIST pidl)
  6087. {
  6088. int cItems = 0;
  6089. DWORD cbData = sizeof(cItems);
  6090. TCHAR szSubKey[80];
  6091. BOOL fRet = FALSE;
  6092. IStream *pstm;
  6093. // cases that we don't want to save window state for...
  6094. if (SHRestricted(REST_NOSAVESET) || FPidlOnNonPersistentDrive(pidl) || !_PersistOpenBrowsers())
  6095. return FALSE;
  6096. HKEY hkRestart = SHGetShellKey(SHELLKEY_HKCU_EXPLORER, TEXT("RestartCommands"), TRUE);
  6097. if (hkRestart)
  6098. {
  6099. if (ERROR_SUCCESS != (SHGetValueGoodBoot(hkRestart, NULL, TEXT("Count"), NULL, (BYTE *)&cItems, &cbData)))
  6100. cItems = 0;
  6101. // Now Lets Create a registry Stream for this guy...
  6102. wnsprintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), cItems);
  6103. pstm = OpenRegStream(hkRestart, NULL, szSubKey, STGM_WRITE);
  6104. TraceMsg(DM_SHUTDOWN, "csb.wp: AddToRestartList(pstm=%x)", pstm);
  6105. if (pstm)
  6106. {
  6107. WORD wType = (WORD)-1; // sizeof of cmd line == -1 implies pidl...
  6108. // Now Write a preamble to the start of the line that
  6109. // tells wType that this is an explorer
  6110. pstm->Write(&wType, sizeof(wType), NULL);
  6111. // Now Write out the version number of this stream
  6112. // Make sure to inc the version number if the structure changes
  6113. pstm->Write(&c_wVersion, sizeof(c_wVersion), NULL);
  6114. // Now Write out the dwFlags
  6115. pstm->Write(&dwFlags, sizeof(dwFlags), NULL);
  6116. // And the pidl;
  6117. ILSaveToStream(pstm, pidl);
  6118. // And Release the stream;
  6119. pstm->Release();
  6120. cItems++; // Say that there are twice as many items...
  6121. fRet = (ERROR_SUCCESS == SHSetValue(hkRestart, NULL, TEXT("Count"), REG_BINARY, &cItems, sizeof(cItems)));
  6122. }
  6123. RegCloseKey(hkRestart);
  6124. }
  6125. return fRet;
  6126. }
  6127. //---------------------------------------------------------------------------
  6128. void SHCreateSavedWindows(void)
  6129. {
  6130. HKEY hkRestart = SHGetShellKey(SHELLKEY_HKCU_EXPLORER, TEXT("RestartCommands"), FALSE);
  6131. if (_PersistOpenBrowsers() && hkRestart)
  6132. {
  6133. int cItems = 0;
  6134. DWORD cbData = sizeof(cItems);
  6135. SHGetValueGoodBoot(hkRestart, NULL, TEXT("Count"), NULL, (PBYTE)&cItems, &cbData);
  6136. // walk in the reverse order that they were added.
  6137. for (cItems--; cItems >= 0; cItems--)
  6138. {
  6139. TCHAR szName[80];
  6140. IStream *pstm;
  6141. if (AbortStartup())
  6142. break;
  6143. wnsprintf(szName, ARRAYSIZE(szName), TEXT("%d"), cItems);
  6144. pstm = OpenRegStream(hkRestart, NULL, szName, STGM_READ);
  6145. if (pstm)
  6146. {
  6147. WORD wType;
  6148. if (SUCCEEDED(pstm->Read(&wType, sizeof(wType), NULL)))
  6149. {
  6150. if (wType == (WORD)-1)
  6151. {
  6152. WORD wVersion;
  6153. DWORD dwFlags;
  6154. LPITEMIDLIST pidl = NULL; // need to be inited for ILLoadFromStream()
  6155. // We have a folder serialized so get:
  6156. // WORD:wVersion, DWORD:dwFlags, PIDL:pidlRoot, PIDL:pidl
  6157. if (SUCCEEDED(pstm->Read(&wVersion, sizeof(wVersion), NULL)) &&
  6158. (wVersion == c_wVersion) &&
  6159. SUCCEEDED(pstm->Read(&dwFlags, sizeof(dwFlags), NULL)) &&
  6160. SUCCEEDED(ILLoadFromStream(pstm, &pidl)) && pidl)
  6161. {
  6162. // this call does window instance management
  6163. IETHREADPARAM* piei = SHCreateIETHREADPARAM(NULL, 0, NULL, NULL);
  6164. if (piei)
  6165. {
  6166. piei->pidl = pidl;
  6167. pidl = NULL; // so this is not freed below
  6168. piei->uFlags = dwFlags;
  6169. piei->nCmdShow = SW_SHOWDEFAULT;
  6170. SHOpenFolderWindow(piei);
  6171. }
  6172. ILFree(pidl);
  6173. }
  6174. }
  6175. else if (wType < MAX_PATH)
  6176. {
  6177. // I don't think this is ever used.
  6178. CHAR aszScratch[MAX_PATH];
  6179. pstm->Read(aszScratch, wType, NULL);
  6180. WinExec(aszScratch, SW_SHOWNORMAL); // the show cmd will be ignored
  6181. }
  6182. }
  6183. pstm->Release();
  6184. }
  6185. }
  6186. }
  6187. if (hkRestart)
  6188. {
  6189. SHDeleteKeyA(hkRestart, NULL);
  6190. RegCloseKey(hkRestart);
  6191. }
  6192. }
  6193. //
  6194. // This code intercept the WM_CONTEXTMENU message from USER and popups
  6195. // up the context menu of the folder itself when the user clicks the icon
  6196. // at the left-top corner of the frame (only when it is in the folder mode).
  6197. //
  6198. BOOL CShellBrowser2::v_OnContextMenu(WPARAM wParam, LPARAM lParam)
  6199. {
  6200. BOOL fProcessed = FALSE;
  6201. TraceMsg(DM_TRACE, "csb.ocm Got WM_CONTEXTMENU");
  6202. if (_pbbd->_pidlCur && !ILIsEmpty(_pbbd->_pidlCur) && SendMessage(_pbbd->_hwnd, WM_NCHITTEST, 0, lParam) == HTSYSMENU)
  6203. {
  6204. IShellFolder *psfParent;
  6205. LPCITEMIDLIST pidlChild;
  6206. if (SUCCEEDED(IEBindToParentFolder(_pbbd->_pidlCur, &psfParent, &pidlChild)))
  6207. {
  6208. IContextMenu * pcm;
  6209. HRESULT hres = psfParent->GetUIObjectOf(_pbbd->_hwnd, 1, (LPCITEMIDLIST*)&pidlChild, IID_IContextMenu, NULL, (void **)&pcm);
  6210. if (SUCCEEDED(hres))
  6211. {
  6212. HMENU hpopup = LoadMenuPopup(MENU_SYSPOPUP);
  6213. if (hpopup)
  6214. {
  6215. pcm->QueryContextMenu(hpopup, GetMenuItemCount(hpopup), IDSYSPOPUP_FIRST, IDSYSPOPUP_LAST, 0);
  6216. // Open doesn't make sense, since you're already looking at the folder
  6217. ContextMenu_DeleteCommandByName(pcm, hpopup, IDSYSPOPUP_FIRST, L"open");
  6218. // These are just confusing
  6219. ContextMenu_DeleteCommandByName(pcm, hpopup, IDSYSPOPUP_FIRST, L"delete");
  6220. ContextMenu_DeleteCommandByName(pcm, hpopup, IDSYSPOPUP_FIRST, L"link");
  6221. // The above may have allowed two separators to now be adjascent
  6222. _SHPrettyMenu(hpopup);
  6223. // For sendto menu, we go on even if this fails
  6224. pcm->QueryInterface(IID_PPV_ARG(IContextMenu3, &_pcm));
  6225. if (GetMenuItemCount(hpopup) > 1)
  6226. {
  6227. // only do this if the context menu added something...
  6228. // otherwise we end up with nothing but a "close" menu
  6229. fProcessed=TRUE;
  6230. UINT idCmd = TrackPopupMenu(hpopup,
  6231. TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_LEFTALIGN,
  6232. GET_X_LPARAM(lParam),
  6233. GET_Y_LPARAM(lParam),
  6234. 0, _pbbd->_hwnd, NULL);
  6235. switch(idCmd)
  6236. {
  6237. case 0:
  6238. break; // canceled
  6239. case IDSYSPOPUP_CLOSE:
  6240. _pbbd->_pautoWB2->Quit();
  6241. break;
  6242. default:
  6243. {
  6244. TCHAR szPath[MAX_PATH];
  6245. // unless we KNOW that our target can handle CommandInfoEx, we cannot send it to them
  6246. CMINVOKECOMMANDINFO ici = {
  6247. sizeof(ici),
  6248. 0L,
  6249. _pbbd->_hwnd,
  6250. (LPSTR)MAKEINTRESOURCE(idCmd - IDSYSPOPUP_FIRST),
  6251. NULL, NULL,
  6252. SW_NORMAL
  6253. };
  6254. #ifdef UNICODE
  6255. CHAR szPathAnsi[MAX_PATH];
  6256. SHGetPathFromIDListA(_pbbd->_pidlCur, szPathAnsi);
  6257. SHGetPathFromIDList(_pbbd->_pidlCur, szPath);
  6258. ici.lpDirectory = szPathAnsi;
  6259. // ici.lpDirectoryW = szPath;
  6260. ici.fMask |= CMIC_MASK_UNICODE;
  6261. #else
  6262. SHGetPathFromIDList(_pbbd->_pidlCur, szPath);
  6263. ici.lpDirectory = szPath;
  6264. #endif
  6265. pcm->InvokeCommand(&ici);
  6266. break;
  6267. }
  6268. }
  6269. }
  6270. ATOMICRELEASE(_pcm);
  6271. DestroyMenu(hpopup);
  6272. }
  6273. pcm->Release();
  6274. }
  6275. psfParent->Release();
  6276. }
  6277. }
  6278. return fProcessed;
  6279. }
  6280. void CShellBrowser2::_OnClose(BOOL fPushed)
  6281. {
  6282. // We can't close if it's nested.
  6283. if (fPushed)
  6284. {
  6285. #ifdef NO_MARSHALLING
  6286. // IEUNIX : Mark this window for delayed deletion from the main message
  6287. // pump. The problem is , if scripting closes a window and immediately
  6288. // opens a modal dialog. The WM_CLOSE message for the browser window is
  6289. // dispatched from the modal loop and we end up being called from the
  6290. // window proc. This happens a lot on UNIX because we have multiple
  6291. // browser windows on the same thread.
  6292. if (!_fDelayedClose)
  6293. _fDelayedClose = TRUE;
  6294. else
  6295. #endif
  6296. MessageBeep(0);
  6297. return;
  6298. }
  6299. if (SHIsRestricted2W(_pbbd->_hwnd, REST_NoBrowserClose, NULL, 0))
  6300. return;
  6301. // We are not supposed to process WM_CLOSE if modeless operation is
  6302. // disabled.
  6303. if (S_OK == _DisableModeless())
  6304. {
  6305. TraceMsg(DM_ERROR, "CShellBrowser2::_OnClose called when _DisableModeless() is TRUE. Ignored.");
  6306. MessageBeep(0);
  6307. UINT id = MLShellMessageBox(_pbbd->_hwnd,
  6308. MAKEINTRESOURCE(IDS_CLOSEANYWAY),
  6309. MAKEINTRESOURCE(IDS_TITLE),
  6310. MB_OKCANCEL | MB_SETFOREGROUND | MB_ICONSTOP);
  6311. if (id == IDCANCEL)
  6312. {
  6313. #ifdef NO_MARSHALLING
  6314. _fReallyClosed = FALSE;
  6315. #endif
  6316. return;
  6317. }
  6318. }
  6319. #ifdef NO_MARSHALLING
  6320. _fReallyClosed = TRUE;
  6321. #endif
  6322. // we cannot close in the middle of creating view window.
  6323. // someone dispatched messages and it wasn't us...
  6324. // we WILL fault.
  6325. // FEATURE: after ie3, we can flag this and close when we're done tryingto create the
  6326. // viewwindow
  6327. if (_pbbd->_fCreatingViewWindow)
  6328. return;
  6329. // The dochost needs to know that we are shutting
  6330. // down so that it do such things send an Exec to
  6331. // Trident to tell it we are unloading.
  6332. //
  6333. Exec(&CGID_Explorer, SBCMDID_ONCLOSE, 0, NULL, NULL);
  6334. if (_MaySaveChanges() != S_FALSE)
  6335. {
  6336. // Close the browse context and release it.
  6337. IHlinkBrowseContext * phlbc = NULL;
  6338. if (_pbbd->_phlf)
  6339. _pbbd->_phlf->GetBrowseContext(&phlbc);
  6340. if (phlbc)
  6341. {
  6342. _pbbd->_phlf->SetBrowseContext(NULL);
  6343. phlbc->Close(0);
  6344. phlbc->Release();
  6345. }
  6346. FireEvent_Quit(_pbbd->_pautoEDS);
  6347. // this is once we KNOW that we're going to close down
  6348. // give subclasses a chance to clean up
  6349. #ifdef NO_MARSHALLING
  6350. RemoveBrowserFromList(this);
  6351. #endif
  6352. _OnConfirmedClose();
  6353. }
  6354. //
  6355. // NOTES: Originally, this call was made only for RISC platform.
  6356. // We, however, got a request from ISVs that their OCs should be
  6357. // unloaded when the user closes the window.
  6358. //
  6359. // On risc NT we need to call CoFreeUnusedLibraries in case any x86 dlls
  6360. // were loaded by Ole32. We call this after calling _OnClose so that
  6361. // we can even unload the OC on the current page. (SatoNa)
  6362. //
  6363. CoFreeUnusedLibraries();
  6364. }
  6365. //
  6366. // stolen from comctl32
  6367. //
  6368. // in:
  6369. // hwnd to do check on
  6370. // x, y in client coordinates
  6371. //
  6372. // returns:
  6373. // TRUE the user began to drag (moved mouse outside double click rect)
  6374. // FALSE mouse came up inside click rect
  6375. //
  6376. // FEATURE, should support VK_ESCAPE to cancel
  6377. BOOL CheckForDragBegin(HWND hwnd, int x, int y)
  6378. {
  6379. RECT rc;
  6380. int dxClickRect = GetSystemMetrics(SM_CXDRAG);
  6381. int dyClickRect = GetSystemMetrics(SM_CYDRAG);
  6382. ASSERT((dxClickRect > 1) && (dyClickRect > 1));
  6383. // See if the user moves a certain number of pixels in any direction
  6384. SetRect(&rc, x - dxClickRect, y - dyClickRect, x + dxClickRect, y + dyClickRect);
  6385. MapWindowRect(hwnd, NULL, &rc);
  6386. SetCapture(hwnd);
  6387. do
  6388. {
  6389. MSG msg;
  6390. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  6391. {
  6392. // See if the application wants to process the message...
  6393. if (CallMsgFilter(&msg, MSGF_COMMCTRL_BEGINDRAG) != 0)
  6394. continue;
  6395. switch (msg.message) {
  6396. case WM_LBUTTONUP:
  6397. case WM_RBUTTONUP:
  6398. case WM_LBUTTONDOWN:
  6399. case WM_RBUTTONDOWN:
  6400. ReleaseCapture();
  6401. return FALSE;
  6402. case WM_MOUSEMOVE:
  6403. if (!PtInRect(&rc, msg.pt))
  6404. {
  6405. ReleaseCapture();
  6406. return TRUE;
  6407. }
  6408. break;
  6409. default:
  6410. TranslateMessage(&msg);
  6411. DispatchMessage(&msg);
  6412. break;
  6413. }
  6414. }
  6415. // WM_CANCELMODE messages will unset the capture, in that
  6416. // case I want to exit this loop
  6417. } while (GetCapture() == hwnd);
  6418. return FALSE;
  6419. }
  6420. void CShellBrowser2::_SetTheaterBrowserBar()
  6421. {
  6422. #ifndef DISABLE_FULLSCREEN
  6423. if (_ptheater) {
  6424. IDeskBar *pdbBar = NULL;
  6425. FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdbBar));
  6426. _ptheater->SetBrowserBar(pdbBar, 120, 200);
  6427. if (pdbBar)
  6428. pdbBar->Release();
  6429. }
  6430. #endif
  6431. }
  6432. void CShellBrowser2::_TheaterMode(BOOL fShow, BOOL fRestorePrevious)
  6433. {
  6434. #ifndef DISABLE_FULLSCREEN
  6435. if (BOOLIFY(fShow) == BOOLIFY(_ptheater))
  6436. return;
  6437. WINDOWPLACEMENT wp;
  6438. RECT rc;
  6439. if (fRestorePrevious && !fShow) {
  6440. _ptheater->GetPreviousWindowPlacement(&wp, &rc);
  6441. } else
  6442. fRestorePrevious = FALSE;
  6443. HRESULT hresResize = _pbsInner->AllowViewResize(FALSE);
  6444. if (!fShow)
  6445. {
  6446. if (_ptheater) {
  6447. if (fRestorePrevious) {
  6448. PutBaseBrowserData()->_hwnd = _ptheater->GetMasterWindow();
  6449. #ifndef UNIX
  6450. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_DLGFRAME | WS_THICKFRAME | WS_BORDER, WS_DLGFRAME | WS_THICKFRAME | WS_BORDER);
  6451. #else
  6452. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_DLGFRAME | WS_THICKFRAME | WS_BORDER, 0);
  6453. #endif
  6454. SetWindowPos(_pbbd->_hwnd, NULL, 0, 0,0,0,SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
  6455. }
  6456. delete _ptheater;
  6457. _ptheater = NULL;
  6458. }
  6459. }
  6460. else
  6461. {
  6462. _SaveITbarLayout();
  6463. _SaveState();
  6464. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_DLGFRAME | WS_THICKFRAME, 0);
  6465. // if we're going to theater mode, don't allow best fit stuff
  6466. _fsd._fs.fFlags &= ~FWF_BESTFITWINDOW;
  6467. HWND hwndToolbar = NULL;
  6468. if (_GetITBar())
  6469. _GetITBar()->GetWindow(&hwndToolbar);
  6470. _ptheater = new CTheater(_pbbd->_hwnd, hwndToolbar, (IOleCommandTarget*)this);
  6471. if (_ptheater)
  6472. {
  6473. _SetTheaterBrowserBar();
  6474. // the progress control is a bit special in this mode. we pull this out and make it topmost.
  6475. _ShowHideProgress();
  6476. }
  6477. }
  6478. // the itbar is special in that it stays with the auto-hide window.
  6479. // it needs to know about theater mode specially
  6480. // Also, set _ptheater->_fAutoHideToolbar to _pitbar->_fAutoHide
  6481. VARIANT vOut = { VT_I4 };
  6482. vOut.lVal = FALSE; // default: no auto hide explorer toolbar
  6483. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_THEATER, fShow ? THF_ON : THF_OFF, &vOut, &vOut);
  6484. if (_ptheater)
  6485. {
  6486. _ptheater->SetAutoHideToolbar(vOut.lVal);
  6487. }
  6488. _pbsInner->AllowViewResize(hresResize == S_OK);
  6489. SUPERCLASS::OnSize(SIZE_RESTORED);
  6490. if (_ptheater)
  6491. _ptheater->Begin(); // kick start!
  6492. // notify trident that it's ambients are invalid to force
  6493. // it to re-query us for the flat property
  6494. if (_pbbd->_pctView)
  6495. {
  6496. VARIANTARG vaIn;
  6497. vaIn.vt = VT_I4;
  6498. vaIn.lVal = DISPID_UNKNOWN;
  6499. _pbbd->_pctView->Exec(&CGID_ShellDocView, SHDVID_AMBIENTPROPCHANGE, NULL, &vaIn, NULL);
  6500. }
  6501. if (_pxtb)
  6502. {
  6503. UINT uiState;
  6504. if (SUCCEEDED(_pxtb->GetState(&CLSID_CommonButtons, TBIDM_THEATER, &uiState)))
  6505. {
  6506. if (_ptheater)
  6507. uiState |= TBSTATE_CHECKED;
  6508. else
  6509. uiState &= ~TBSTATE_CHECKED;
  6510. _pxtb->SetState(&CLSID_CommonButtons, TBIDM_THEATER, uiState);
  6511. }
  6512. }
  6513. if (!_ptheater && !_fShowMenu)
  6514. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_SHOWMENU, FALSE, NULL, NULL);
  6515. if (fRestorePrevious)
  6516. {
  6517. SetWindowPos(_pbbd->_hwnd, NULL, rc.left, rc.top, RECTWIDTH(rc), RECTHEIGHT(rc), 0);
  6518. if (IsWindowVisible(_pbbd->_hwnd))
  6519. {
  6520. ShowWindow(_pbbd->_hwnd, wp.showCmd);
  6521. SetWindowPlacement(_pbbd->_hwnd, &wp);
  6522. }
  6523. }
  6524. #endif /* !DISABLE_FULLSCREEN */
  6525. }
  6526. BOOL CShellBrowser2::_OnSysMenuClick(BOOL bLeftClick, WPARAM wParam, LPARAM lParam)
  6527. {
  6528. POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
  6529. DWORD dwStart = GetTickCount();
  6530. MapWindowPoints(NULL, _pbbd->_hwnd, &pt, 1);
  6531. if (!CheckForDragBegin(_pbbd->_hwnd, pt.x, pt.y))
  6532. {
  6533. if (bLeftClick)
  6534. {
  6535. DWORD dwDelta = (GetTickCount() - dwStart);
  6536. DWORD dwDblClick = GetDoubleClickTime();
  6537. if (dwDelta < dwDblClick)
  6538. {
  6539. // HACK: use the lParam (coords) as the timer ID to communicate
  6540. // that to the WM_TIMER handler
  6541. //
  6542. // HACK: store the timer id in a global. Since there's only one
  6543. // double-click on a sysmenu at a time, this should be fine.
  6544. if (g_sysmenuTimer)
  6545. KillTimer(_GetCaptionWindow(), g_sysmenuTimer);
  6546. // We are special casing 0 as meaning there is no timer, so if the coords come in at
  6547. // 0 then cheat them to 1.
  6548. if (lParam == 0)
  6549. lParam++;
  6550. g_sysmenuTimer = SetTimer(_GetCaptionWindow(), lParam, dwDblClick - dwDelta, NULL);
  6551. }
  6552. else
  6553. DefWindowProcWrap(_pbbd->_hwnd, WM_CONTEXTMENU, (WPARAM)_pbbd->_hwnd, lParam);
  6554. }
  6555. else
  6556. SendMessage(_pbbd->_hwnd, WM_CONTEXTMENU, (WPARAM)_pbbd->_hwnd, lParam);
  6557. return FALSE;
  6558. }
  6559. IOleCommandTarget *pcmdt = NULL;
  6560. if (_pbbd->_pautoWB2)
  6561. {
  6562. (_pbbd->_pautoWB2)->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  6563. ASSERT(pcmdt);
  6564. }
  6565. BOOL fRet = DoDragDropWithInternetShortcut(pcmdt, _pbbd->_pidlCur, _pbbd->_hwnd);
  6566. if (pcmdt)
  6567. pcmdt->Release();
  6568. return fRet;
  6569. }
  6570. void _SetWindowsListMarshalled(IWebBrowser2 *pautoWB2)
  6571. {
  6572. IEFrameAuto* pief;
  6573. if (SUCCEEDED(pautoWB2->QueryInterface(IID_IEFrameAuto, (void **)&pief)))
  6574. {
  6575. pief->OnWindowsListMarshalled();
  6576. pief->Release();
  6577. }
  6578. }
  6579. BOOL CShellBrowser2::_OnTimer(UINT_PTR idTimer)
  6580. {
  6581. BOOL fResult = FALSE;
  6582. // HACK: _OnSysMenuClick uses the cursor coords as the timer ID.
  6583. // So first check if g_sysmenuTimer is set before checking for
  6584. // standard timer IDs.
  6585. if (g_sysmenuTimer == idTimer)
  6586. {
  6587. KillTimer(_GetCaptionWindow(), g_sysmenuTimer);
  6588. g_sysmenuTimer = 0;
  6589. // the timer ID is the lParam from the left click!
  6590. SendMessage(_GetCaptionWindow(), WM_SYSMENU, 0, idTimer);
  6591. fResult = TRUE;
  6592. }
  6593. else
  6594. {
  6595. switch (idTimer)
  6596. {
  6597. case SHBTIMER_MENUSELECT:
  6598. KillTimer(_pbbd->_hwnd, SHBTIMER_MENUSELECT);
  6599. fResult = TRUE;
  6600. if (_pidlMenuSelect)
  6601. {
  6602. _DisplayFavoriteStatus(_pidlMenuSelect);
  6603. Pidl_Set(&_pidlMenuSelect, NULL);
  6604. }
  6605. break;
  6606. }
  6607. }
  6608. return fResult;
  6609. }
  6610. void CShellBrowser2::_OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam)
  6611. {
  6612. if (LOWORD(wParam) == WA_INACTIVE)
  6613. _fActivated = FALSE;
  6614. else
  6615. _fActivated = TRUE;
  6616. if (_pbbd->_hwndView)
  6617. SendMessage(_pbbd->_hwndView, uMsg, wParam, lParam);
  6618. if (LOWORD(wParam) != WA_INACTIVE)
  6619. {
  6620. // remember who had focus last, since trident will
  6621. // grab focus on an OnFrameWindowActivate(TRUE)
  6622. int itbLast = _pbsOuter->_get_itbLastFocus();
  6623. _pbsOuter->OnFrameWindowActivateBS(TRUE);
  6624. if (itbLast != ITB_VIEW)
  6625. {
  6626. // restore focus to its rightful owner
  6627. LPTOOLBARITEM ptbi = _GetToolbarItem(itbLast);
  6628. if (ptbi)
  6629. IUnknown_UIActivateIO(ptbi->ptbar, TRUE, NULL);
  6630. }
  6631. }
  6632. else
  6633. {
  6634. #ifdef KEYBOARDCUES
  6635. if (_pbbd->_hwnd)
  6636. {
  6637. SendMessage(_pbbd->_hwnd, WM_CHANGEUISTATE,
  6638. MAKEWPARAM(UIS_SET, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
  6639. }
  6640. #endif
  6641. _pbsOuter->OnFrameWindowActivateBS(FALSE);
  6642. }
  6643. }
  6644. // Main window proc for CShellBrowser2
  6645. LRESULT CShellBrowser2::WndProcBS(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  6646. {
  6647. LRESULT lRet = 0;
  6648. if (_TranslateMenuMessage(hwnd, uMsg, &wParam, &lParam, &lRet))
  6649. return lRet;
  6650. switch(uMsg)
  6651. {
  6652. case WMC_DISPATCH:
  6653. BSTR Url;
  6654. {
  6655. HRESULT hres;
  6656. switch(wParam) {
  6657. case DSID_NOACTION:
  6658. return S_OK;
  6659. case DSID_NAVIGATEIEBROWSER:
  6660. //
  6661. // APPCOMPAT: To be fully compatible with IE 2.0, we don't want to use
  6662. // the window that has a navigation in progress. Enabling this code,
  6663. // however, causes some problem with the very first DDE. I need to
  6664. // investigate more, IF we need that level of compatibility. (SatoNa)
  6665. //
  6666. // this is only used for IE Browser.
  6667. // if this is not in iemode, then fail.
  6668. // this prevents us from reusing C:\ to navigate to www
  6669. if (!v_IsIEModeBrowser())
  6670. return E_FAIL;
  6671. ASSERT(lParam);
  6672. if (!lParam)
  6673. break;
  6674. Url = ((DDENAVIGATESTRUCT*)lParam)->wszUrl;
  6675. hres = _pbbd->_pautoWB2->Navigate(Url, NULL, NULL, NULL, NULL);
  6676. return hres;
  6677. break;
  6678. case DSID_GETLOCATIONURL:
  6679. return _pbbd->_pautoWB2->get_LocationURL((BSTR*)lParam);
  6680. case DSID_GETLOCATIONTITLE:
  6681. return _pbbd->_pautoWB2->get_LocationName((BSTR*)lParam);
  6682. case DSID_GETHWND:
  6683. *(HWND*)lParam = hwnd;
  6684. return S_OK;
  6685. #if 0
  6686. case DSID_CANCEL:
  6687. return _pbbd->_pautoWB2->Stop();
  6688. #endif
  6689. case DSID_EXIT:
  6690. return _pbbd->_pautoWB2->Quit();
  6691. }
  6692. }
  6693. return (LRESULT)HRESULT_FROM_WIN32(ERROR_BUSY);
  6694. case CWM_CLONEPIDL:
  6695. if (_pbbd->_pidlCur)
  6696. {
  6697. return (LRESULT)SHAllocShared(_pbbd->_pidlCur, ILGetSize(_pbbd->_pidlCur), (DWORD)wParam);
  6698. }
  6699. break;
  6700. case CWM_SELECTITEM:
  6701. {
  6702. LPITEMIDLIST pidl = (LPITEMIDLIST)SHLockShared((HANDLE)lParam, GetCurrentProcessId());
  6703. if (pidl)
  6704. {
  6705. if (_pbbd->_psv)
  6706. _pbbd->_psv->SelectItem(pidl, (UINT)wParam);
  6707. SHUnlockShared(pidl);
  6708. }
  6709. SHFreeShared((HANDLE)lParam, GetCurrentProcessId()); // Receiver responsible for freeing
  6710. break;
  6711. }
  6712. case CWM_THEATERMODE:
  6713. _TheaterMode(BOOLFROMPTR(wParam), !wParam);
  6714. break;
  6715. case CWM_GLOBALSTATECHANGE:
  6716. // need to update the title
  6717. if (wParam == CWMF_GLOBALSTATE)
  6718. _SetTitle(NULL);
  6719. else if (wParam == CWMF_SECURITY)
  6720. {
  6721. _UpdateZonesPane(NULL);
  6722. }
  6723. break;
  6724. case CWM_FSNOTIFY:
  6725. _OnFSNotify(wParam, lParam);
  6726. break;
  6727. case CWM_UPDATEBACKFORWARDSTATE:
  6728. _UpdateBackForwardStateNow();
  6729. break;
  6730. case CWM_SHOWDRAGIMAGE:
  6731. return DAD_ShowDragImage((BOOL)lParam);
  6732. case WM_ENDSESSION:
  6733. TraceMsg(DM_SHUTDOWN, "csb.wp: WM_ENDSESSION wP=%d lP=%d", wParam, lParam);
  6734. if (wParam && IsWindowVisible(_pbbd->_hwnd) && _pbbd->_pidlCur && !_fUISetByAutomation)
  6735. {
  6736. TraceMsg(DM_SHUTDOWN, "csb.wp: call AddToRestartList");
  6737. if (!IsBrowserFrameOptionsSet(_pbbd->_psf, BFO_NO_REOPEN_NEXT_RESTART))
  6738. AddToRestartList(v_RestartFlags(), _pbbd->_pidlCur);
  6739. // for now we use the same 12-hour (SessionTime) rule
  6740. // possibly we should just do it always?
  6741. UEMFireEvent(&UEMIID_BROWSER, UEME_CTLSESSION, UEMF_XEVENT, FALSE, -1);
  6742. if (!g_bRunOnNT5) {
  6743. // for down-level guys (old explorer), fake a shell end session too
  6744. UEMFireEvent(&UEMIID_SHELL, UEME_CTLSESSION, UEMF_XEVENT, FALSE, -1);
  6745. }
  6746. // And make sure we have saved it's state out
  6747. TraceMsg(DM_SHUTDOWN, "csb.wp: call _SaveState");
  6748. _SaveState();
  6749. }
  6750. TraceMsg(DM_SHUTDOWN, "csb.wp: WM_ENDSESSION return 0");
  6751. break;
  6752. case WM_TIMER:
  6753. if (!_OnTimer(wParam))
  6754. goto DoDefault;
  6755. break;
  6756. case WM_NCLBUTTONDOWN:
  6757. case WM_NCRBUTTONDOWN:
  6758. if (wParam != HTSYSMENU)
  6759. goto DoDefault;
  6760. _OnSysMenuClick(uMsg == WM_NCLBUTTONDOWN, wParam, lParam);
  6761. break;
  6762. case WM_NCLBUTTONDBLCLK:
  6763. // We fault while shutting down the window if the timing is bad.
  6764. // We're not sure why, but USER get's mightily confused. The only
  6765. // difference between this scheme and a normal double-click-on-sysmenu
  6766. // is the timer we have hanging around. Kill the timer before
  6767. // processing this message. Hopefully that will work [mikesh/cheechew]
  6768. //
  6769. // HACK: remember this timer id is stored in a global variable
  6770. //
  6771. if (g_sysmenuTimer)
  6772. {
  6773. KillTimer(_GetCaptionWindow(), g_sysmenuTimer);
  6774. g_sysmenuTimer = 0;
  6775. }
  6776. // We still want to process this DBLCLK
  6777. goto DoDefault;
  6778. case WM_CONTEXTMENU:
  6779. if (!v_OnContextMenu(wParam, lParam))
  6780. goto DoDefault;
  6781. break;
  6782. case WM_WININICHANGE:
  6783. {
  6784. DWORD dwSection = SHIsExplorerIniChange(wParam, lParam);
  6785. // Hack for NT4 and Win95, where there is no SPI_GETMENUSHOWDELAY
  6786. // Don't need to check wParam == SPI_SETMENUSHOWDELAY since we
  6787. // always query afresh on NT5/Win98.
  6788. if (dwSection & EICH_SWINDOWS)
  6789. g_lMenuPopupTimeout = -1; /* in case MenuShowDelay changed */
  6790. // Transitioning to/from "Working Offline" just broadcasts (0,0)
  6791. // so that's all we listen for
  6792. if (dwSection == EICH_UNKNOWN)
  6793. {
  6794. _ReloadTitle();
  6795. _ReloadStatusbarIcon();
  6796. }
  6797. }
  6798. goto DoDefault;
  6799. case WM_INITMENUPOPUP:
  6800. v_OnInitMenuPopup((HMENU)wParam, LOWORD(lParam), HIWORD(lParam));
  6801. v_ForwardMenuMsg(uMsg, wParam, lParam);
  6802. break;
  6803. case WM_MENUSELECT:
  6804. #ifdef UNIX
  6805. /* IEUNIX: Avoid getting delayed timer messages, which screws up
  6806. statusbar. */
  6807. if (_pidlMenuSelect) {
  6808. KillTimer(_pbbd->_hwnd, SHBTIMER_MENUSELECT);
  6809. Pidl_Set(&_pidlMenuSelect, NULL);
  6810. }
  6811. #endif
  6812. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  6813. {
  6814. ForwardViewMsg(uMsg, wParam, lParam);
  6815. }
  6816. else
  6817. {
  6818. BOOL fIsPopup = GET_WM_MENUSELECT_FLAGS(wParam, lParam) & MF_POPUP;
  6819. if ((!_OnMenuSelect(wParam, lParam, 0) &&
  6820. (fIsPopup || IsInRange(LOWORD(wParam), FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST)))
  6821. || (_fDispatchMenuMsgs && fIsPopup))
  6822. {
  6823. ForwardViewMsg(uMsg, wParam, lParam);
  6824. }
  6825. }
  6826. break;
  6827. case WM_EXITSIZEMOVE:
  6828. _fDisallowSizing = FALSE;
  6829. break;
  6830. case WM_WINDOWPOSCHANGING:
  6831. if (_fDisallowSizing)
  6832. {
  6833. LPWINDOWPOS pwp = (LPWINDOWPOS)lParam;
  6834. pwp->flags |= SWP_NOMOVE | SWP_NOSIZE;
  6835. }
  6836. break;
  6837. case WM_ENTERSIZEMOVE:
  6838. if (_ptheater)
  6839. _fDisallowSizing = TRUE;
  6840. break;
  6841. case WM_EXITMENULOOP:
  6842. case WM_ENTERMENULOOP:
  6843. ForwardViewMsg(uMsg, wParam, lParam);
  6844. break;
  6845. case WM_DRAWITEM:
  6846. case WM_MEASUREITEM:
  6847. if (_ShouldForwardMenu(uMsg, wParam, lParam))
  6848. ForwardViewMsg(uMsg, wParam, lParam);
  6849. else
  6850. {
  6851. UINT idCmd;
  6852. switch (uMsg)
  6853. {
  6854. case WM_MEASUREITEM:
  6855. idCmd = GET_WM_COMMAND_ID(((MEASUREITEMSTRUCT *)lParam)->itemID, 0);
  6856. break;
  6857. case WM_DRAWITEM:
  6858. idCmd = GET_WM_COMMAND_ID(((LPDRAWITEMSTRUCT)lParam)->itemID, 0);
  6859. break;
  6860. }
  6861. if (InRange(idCmd, FCIDM_SEARCHFIRST, FCIDM_SEARCHLAST) && _pcmSearch)
  6862. _pcmSearch->HandleMenuMsg(uMsg, wParam, lParam);
  6863. else if (_pcmNsc && IsInRange(idCmd, FCIDM_FILECTX_FIRST, FCIDM_FILECTX_LAST))
  6864. _pcmNsc->HandleMenuMsg(uMsg, wParam, lParam);
  6865. else if (_pcm && (_pcm->HandleMenuMsg(uMsg, wParam, lParam) == S_OK))
  6866. {
  6867. // the context menu ate it
  6868. }
  6869. else
  6870. {
  6871. v_ForwardMenuMsg(uMsg, wParam, lParam);
  6872. }
  6873. }
  6874. break;
  6875. case WM_QUERYENDSESSION:
  6876. TraceMsg(DM_SHUTDOWN, "csb.wp: WM_QUERYENDSESSION");
  6877. #ifdef DEBUG
  6878. if (S_OK == _DisableModeless())
  6879. {
  6880. TraceMsg(DM_WARNING, "CSB::WndProc got WM_QUERYENDSESSION when disabled");
  6881. MessageBeep(0);
  6882. UINT id = MLShellMessageBox(_pbbd->_hwnd,
  6883. MAKEINTRESOURCE(IDS_CLOSEANYWAY),
  6884. MAKEINTRESOURCE(IDS_TITLE),
  6885. MB_OKCANCEL | MB_SETFOREGROUND | MB_ICONSTOP);
  6886. if (id==IDCANCEL) {
  6887. return FALSE;
  6888. }
  6889. }
  6890. #endif
  6891. // Try calling something that will call SHGetPathFromIDList to make sure we won't
  6892. // call GetProcAddress while processing the WM_ENDSESSION...
  6893. if (_pbbd->_pidlCur)
  6894. HackToPrepareForEndSession(_pbbd->_pidlCur);
  6895. return TRUE; // OK to close
  6896. case WM_CLOSE:
  6897. #ifdef NO_MARSHALLING
  6898. _OnClose(_fOnIEThread);
  6899. #else
  6900. _OnClose(TRUE);
  6901. #endif
  6902. break;
  6903. case PUI_OFFICE_COMMAND:
  6904. {
  6905. switch (wParam)
  6906. {
  6907. case PLUGUI_CMD_SHUTDOWN:
  6908. {
  6909. HRESULT hr;
  6910. VARIANT v;
  6911. // first, kill the internet options modal
  6912. // property sheet if it exists
  6913. // it might be open because that's one of
  6914. // out UI lang change scenarios
  6915. V_VT(&v) = VT_BYREF;
  6916. v.byref = NULL;
  6917. if (_pbbd != NULL && _pbbd->_pctView != NULL)
  6918. {
  6919. hr = _pbbd->_pctView->Exec(&CGID_ShellDocView, SHDVID_GETOPTIONSHWND, 0, NULL, &v);
  6920. if (SUCCEEDED(hr))
  6921. {
  6922. ASSERT(V_VT(&v) == VT_BYREF);
  6923. if (v.byref != NULL)
  6924. {
  6925. // close the lang change modal property sheet
  6926. SendMessage((HWND)v.byref, WM_CLOSE, NULL, NULL);
  6927. }
  6928. }
  6929. }
  6930. // now try to close the browser in general
  6931. if (_pbbd != NULL && _pbbd->_pautoWB2 != NULL)
  6932. _pbbd->_pautoWB2->Quit();
  6933. break;
  6934. }
  6935. case PLUGUI_CMD_QUERY:
  6936. {
  6937. HMODULE hMod;
  6938. // answer if we're an iexplore.exe process because
  6939. // that means we're not sharing any dlls with the shell
  6940. hMod = GetModuleHandle(TEXT("IEXPLORE.EXE"));
  6941. if (hMod != NULL && !g_bRunOnNT5)
  6942. {
  6943. PLUGUI_QUERY puiQuery;
  6944. ASSERT(!g_bRunOnNT5);
  6945. // we indicate that we participate in plugUI shutdown by
  6946. // returning the version number for Office 9
  6947. puiQuery.uQueryVal = 0;
  6948. puiQuery.PlugUIInfo.uMajorVersion = OFFICE_VERSION_9;
  6949. puiQuery.PlugUIInfo.uOleServer = FALSE;
  6950. return puiQuery.uQueryVal;
  6951. }
  6952. break;
  6953. }
  6954. } // switch (wParam)
  6955. break; // PUI_OFFICE_COMMAND
  6956. }
  6957. case WM_SYSCOMMAND:
  6958. //
  6959. // WARNING: User uses low four bits for some undocumented feature
  6960. // (only for SC_*). We need to mask those bits to make this case
  6961. // statement work.
  6962. //
  6963. switch (wParam & 0xfff0) {
  6964. case SC_MAXIMIZE:
  6965. if (GetKeyState(VK_CONTROL) < 0)
  6966. {
  6967. LPTOOLBARITEM ptbi = _GetToolbarItem(ITB_ITBAR);
  6968. if (ptbi->fShow)
  6969. PostMessage(_pbbd->_hwnd, CWM_THEATERMODE, TRUE, 0);
  6970. else
  6971. goto DoDefault;
  6972. }
  6973. else
  6974. goto DoDefault;
  6975. break;
  6976. case SC_CLOSE:
  6977. // Make it posted so that we can detect if it's nested.
  6978. PostMessage(_pbbd->_hwnd, WM_CLOSE, 0, 0);
  6979. break;
  6980. case SC_MINIMIZE:
  6981. goto DoDefault;
  6982. case SC_RESTORE:
  6983. if (_ptheater && !_fMinimized)
  6984. {
  6985. PostMessage(_pbbd->_hwnd, CWM_THEATERMODE, FALSE, 0);
  6986. return 0;
  6987. }
  6988. goto DoDefault;
  6989. default:
  6990. goto DoDefault;
  6991. }
  6992. break;
  6993. case WM_SIZE:
  6994. // WARNING: Remember that we won't get WM_SIZE if we directly process
  6995. // WM_WINDOWPOSCHANGED.
  6996. {
  6997. BOOL fMinimized = (wParam == SIZE_MINIMIZED);
  6998. if (BOOLIFY(_fMinimized) != fMinimized)
  6999. {
  7000. TraceMsg(DM_ONSIZE, "SB::_WndProc WM_SIZE _fMinimized %d -> %d",
  7001. _fMinimized, fMinimized);
  7002. _fMinimized = fMinimized;
  7003. // Pause/Resume toolbars (intentionally ignores _pbbd->_psvPending).
  7004. VARIANT var = { 0 };
  7005. var.vt = VT_I4;
  7006. var.lVal = !_fMinimized;
  7007. _ExecChildren(NULL, TRUE, NULL, OLECMDID_ENABLE_INTERACTION, OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
  7008. // Pause/Resule the view (refrelcts _pbbd->_psvPending too).
  7009. _PauseOrResumeView(_fMinimized);
  7010. }
  7011. }
  7012. #ifndef DISABLE_FULLSCREEN
  7013. if (_ptheater && !_fMinimized)
  7014. _ptheater->RecalcSizing();
  7015. #endif
  7016. goto DoDefault;
  7017. case WM_ACTIVATE:
  7018. #ifdef UNIX
  7019. if (_HandleActivation(wParam) == TRUE)
  7020. {
  7021. _OnActivate(uMsg, wParam, lParam);
  7022. break;
  7023. }
  7024. #endif
  7025. _OnActivate(uMsg, wParam, lParam);
  7026. break;
  7027. case WM_SETFOCUS:
  7028. goto DoDefault;
  7029. case WM_MENUCHAR:
  7030. {
  7031. LRESULT lres = 0;
  7032. // Forwarding for IContextMenu3.
  7033. UINT idCmd = GetMenuItemID((HMENU)lParam, 0); // approximately correct: assume the first item on the menu identifies the range
  7034. if (_pcm && _pcm->HandleMenuMsg2(uMsg, wParam, lParam, &lres) == S_OK)
  7035. ; // do nothing
  7036. else if (_pcmSearch && _pcmSearch->HandleMenuMsg2(uMsg, wParam, lParam, &lres) == S_OK)
  7037. ; // do nothing
  7038. else if (_pcmNsc && InRange(idCmd, FCIDM_FILECTX_FIRST, FCIDM_FILECTX_LAST))
  7039. SHForwardContextMenuMsg(_pcmNsc, uMsg, wParam, lParam, &lres, FALSE);
  7040. else
  7041. lres = v_ForwardMenuMsg(uMsg, wParam, lParam);
  7042. return lres;
  7043. }
  7044. break;
  7045. case WM_CREATE:
  7046. #ifdef KEYBOARDCUES
  7047. SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0);
  7048. #endif
  7049. lRet = SUPERCLASS::WndProcBS(hwnd, uMsg, wParam, lParam);
  7050. if (lRet)
  7051. {
  7052. _OnClose(FALSE);
  7053. _GetMenuBand(TRUE);
  7054. }
  7055. return lRet;
  7056. case WMC_MARSHALIDISPATCHSLOW:
  7057. {
  7058. #ifndef NO_MARSHALLING
  7059. IStream *pIStream;
  7060. HRESULT hres = CreateStreamOnHGlobal(NULL, TRUE, &pIStream);
  7061. if (SUCCEEDED(hres))
  7062. {
  7063. HANDLE hShared = NULL;
  7064. _fMarshalledDispatch = TRUE;
  7065. hres = CoMarshalInterface(pIStream, IID_IDispatch,
  7066. _pbbd->_pautoWB2, MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_NORMAL);
  7067. if (SUCCEEDED(hres))
  7068. {
  7069. _SetWindowsListMarshalled(_pbbd->_pautoWB2);
  7070. ULARGE_INTEGER uliPos;
  7071. const LARGE_INTEGER li = {0,0};
  7072. pIStream->Seek(li, STREAM_SEEK_CUR, &uliPos);
  7073. // And point back to the beginning...
  7074. pIStream->Seek(li, STREAM_SEEK_SET, NULL);
  7075. hShared = SHAllocShared(NULL, uliPos.LowPart + sizeof(DWORD), (DWORD)lParam);
  7076. if (hShared)
  7077. {
  7078. LPBYTE pv = (LPBYTE)SHLockShared(hShared, (DWORD)lParam);
  7079. if (pv)
  7080. {
  7081. *((DWORD*)pv) = uliPos.LowPart;
  7082. pIStream->Read(pv + sizeof(DWORD), uliPos.LowPart, NULL);
  7083. SHUnlockShared(pv);
  7084. }
  7085. else
  7086. {
  7087. SHFreeShared(hShared, (DWORD)lParam);
  7088. hShared = NULL;
  7089. }
  7090. }
  7091. }
  7092. pIStream->Release();
  7093. return (LRESULT)hShared;
  7094. }
  7095. #else
  7096. IDispatch **idispTemp = (IDispatch**)lParam;
  7097. *idispTemp = _pbbd->_pautoWB2;
  7098. return S_OK;
  7099. #endif
  7100. }
  7101. case WM_GETOBJECT:
  7102. if (OBJID_MENU == lParam)
  7103. {
  7104. IAccessible* pacc;
  7105. IMenuBand* pmb = _GetMenuBand(FALSE);
  7106. if (pmb && SUCCEEDED(IUnknown_QueryService(pmb, SID_SMenuBandChild,
  7107. IID_PPV_ARG(IAccessible, &pacc))))
  7108. {
  7109. lRet = LresultFromObject(IID_IAccessible, wParam, pacc);
  7110. pacc->Release();
  7111. return lRet;
  7112. }
  7113. }
  7114. break;
  7115. default:
  7116. lRet = _WndProcBSNT5(hwnd, uMsg, wParam, lParam);
  7117. if (lRet)
  7118. return lRet;
  7119. if (_nMBIgnoreNextDeselect == uMsg)
  7120. {
  7121. _fIgnoreNextMenuDeselect = TRUE;
  7122. TraceMsg(TF_MENUBAND, "MenuBand: Shbrowse.cpp received our private MBIgnoreNextDeselect");
  7123. break;
  7124. }
  7125. else if (GetDDEExecMsg() == uMsg)
  7126. {
  7127. ASSERT(lParam && 0 == ((LPNMHDR)lParam)->idFrom);
  7128. DDEHandleViewFolderNotify(this, _pbbd->_hwnd, (LPNMVIEWFOLDER)lParam);
  7129. LocalFree((LPNMVIEWFOLDER)lParam);
  7130. return TRUE;
  7131. }
  7132. else if (g_msgMSWheel == uMsg)
  7133. {
  7134. // Frame doesn't have scrollbar, let the view have a crack at it (309709)
  7135. return SendMessage(_pbbd->_hwndView, uMsg, wParam, lParam);
  7136. }
  7137. DoDefault:
  7138. lRet = SUPERCLASS::WndProcBS(hwnd, uMsg, wParam, lParam);
  7139. if (WM_COMMAND == uMsg)
  7140. {
  7141. IUnknown_SetSite(_pcmNsc, NULL);
  7142. ATOMICRELEASE(_pcmNsc);
  7143. }
  7144. return lRet;
  7145. }
  7146. return 0;
  7147. }
  7148. HRESULT CShellBrowser2::OnSetFocus()
  7149. {
  7150. TraceMsg(DM_FOCUS, "csb.osf: hf()=%d itbLast=%d", _HasToolbarFocus(), _get_itbLastFocus());
  7151. // forward to whoever had focus last (view or toolbar). i think this
  7152. // was added for ie4:55511 to fix pblm w/ tabbing away from IE and
  7153. // then back. note the check of _get_itbLastFocus w/o the usual
  7154. // _HasToolbarFocus/_FixToolbarFocus magic...
  7155. //
  7156. // this used to be in CCB::OSF but that's bogus since in the desktop
  7157. // case, this means once a deskbar (e.g. address) has focus, we can
  7158. // never get focus back on the desktop (nt5:167864).
  7159. if (_get_itbLastFocus() == ITB_VIEW) {
  7160. // forward it on to view (in basesb)
  7161. _pbsInner->OnSetFocus();
  7162. } else {
  7163. LPTOOLBARITEM ptbi = _GetToolbarItem(_get_itbLastFocus());
  7164. if (ptbi)
  7165. IUnknown_UIActivateIO(ptbi->ptbar, TRUE, NULL);
  7166. }
  7167. return 0;
  7168. }
  7169. LRESULT CALLBACK IEFrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  7170. {
  7171. LRESULT lResult = 0;
  7172. CShellBrowser2* psb = (CShellBrowser2*)GetWindowPtr0(hwnd);
  7173. switch(uMsg)
  7174. {
  7175. case WM_NCCREATE:
  7176. {
  7177. IETHREADPARAM* piei = (IETHREADPARAM*)((LPCREATESTRUCT)lParam)->lpCreateParams;
  7178. ASSERT(psb == NULL);
  7179. #ifndef UNIX
  7180. if (piei->uFlags & COF_EXPLORE)
  7181. {
  7182. CExplorerBrowser_CreateInstance(hwnd, (void **)&psb);
  7183. }
  7184. else
  7185. #endif
  7186. {
  7187. CShellBrowser2_CreateInstance(hwnd, (void **)&psb);
  7188. }
  7189. if (psb)
  7190. {
  7191. SetWindowLongPtr(hwnd, 0, (LONG_PTR)psb);
  7192. _InitAppGlobals();
  7193. // Hack: Let's try only registering dde on iexplorer windows for
  7194. // shell speed. (ie ignore shell folders)
  7195. DWORD dwAttr = SFGAO_FOLDER;
  7196. if ((!(piei->pidl &&
  7197. SUCCEEDED(IEGetAttributesOf(piei->pidl, &dwAttr)) &&
  7198. (dwAttr & SFGAO_FOLDER))) ||
  7199. (piei->uFlags & COF_FIREEVENTONDDEREG))
  7200. {
  7201. //
  7202. // Tell IEDDE that a new browser window is available.
  7203. //
  7204. IEDDE_NewWindow(hwnd);
  7205. //
  7206. // Fire the DdeRegistered event if necessary.
  7207. //
  7208. if (piei->uFlags & COF_FIREEVENTONDDEREG)
  7209. {
  7210. ASSERT(piei->szDdeRegEvent[0]);
  7211. FireEventSzW(piei->szDdeRegEvent);
  7212. }
  7213. }
  7214. return psb->WndProcBS(hwnd, uMsg, wParam, lParam);
  7215. }
  7216. else
  7217. {
  7218. return 0;
  7219. }
  7220. }
  7221. case WM_CREATE:
  7222. {
  7223. lResult = psb ? psb->WndProcBS(hwnd, uMsg, wParam, lParam) : DefWindowProc(hwnd, uMsg, wParam, lParam);
  7224. // if we have a psb and WndProc() failed (!lResult), then fall through
  7225. // and process the WM_NCDESTROY.
  7226. if (!psb || !lResult)
  7227. break;
  7228. if (psb)
  7229. psb->_OnClose(FALSE);
  7230. // Fall Thru because we need to clean up since the create failed.
  7231. // fall through
  7232. }
  7233. case WM_NCDESTROY:
  7234. //
  7235. // Tell IEDDE that a browser window is no longer available.
  7236. //
  7237. IEDDE_WindowDestroyed(hwnd);
  7238. // WM_NCDESTROY is supposed to be the last message we ever
  7239. // receive, but let's be paranoid just in case...
  7240. SetWindowLongPtr(hwnd, 0, (LONG_PTR)0);
  7241. // psb may be NULL if we failed to create the window. An
  7242. // Example includes using Start->Run to open a window to
  7243. // a UNC share that the user doesn't have permissions to see.
  7244. if (psb)
  7245. {
  7246. psb->PutBaseBrowserData()->_hwnd = NULL;
  7247. if (psb->_dwRegisterWinList)
  7248. {
  7249. if (psb->_fMarshalledDispatch)
  7250. {
  7251. IShellWindows* psw = WinList_GetShellWindows(TRUE);
  7252. if (psw)
  7253. {
  7254. psw->Revoke(psb->_dwRegisterWinList);
  7255. psw->Release();
  7256. }
  7257. }
  7258. else
  7259. {
  7260. if (psb->_psw)
  7261. psb->_psw->Revoke(psb->_dwRegisterWinList);
  7262. }
  7263. }
  7264. ATOMICRELEASE(psb->_psw);
  7265. psb->_fMarshalledDispatch = 0;
  7266. psb->_dwRegisterWinList = 0;
  7267. ATOMICRELEASE(psb->_punkMsgLoop); // Release the message loop if the browser is going away
  7268. psb->Release();
  7269. }
  7270. break;
  7271. #ifdef UNIX
  7272. case WM_COPYDATA:
  7273. return psb ? HandleCopyDataUnix(psb, hwnd, uMsg, wParam, lParam) : DefWindowProc(hwnd, uMsg, wParam, lParam);
  7274. #endif
  7275. break;
  7276. default:
  7277. return psb ? psb->WndProcBS(hwnd, uMsg, wParam, lParam) : DefWindowProc(hwnd, uMsg, wParam, lParam);
  7278. }
  7279. return lResult;
  7280. }
  7281. // *** IShellBrowser methods *** (same as IOleInPlaceFrame)
  7282. /*----------------------------------------------------------
  7283. Purpose: IShellBrowser::InsertMenusSB method
  7284. */
  7285. HRESULT CShellBrowser2::InsertMenusSB(HMENU hmenu, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  7286. {
  7287. RIP(IS_VALID_HANDLE(hmenu, MENU));
  7288. if (_hmenuTemplate)
  7289. {
  7290. HMENU hmenuSrc;
  7291. if (_get_itbLastFocus() == ITB_VIEW &&
  7292. _pbbd->_uActivateState == SVUIA_ACTIVATE_FOCUS)
  7293. {
  7294. hmenuSrc = _hmenuTemplate;
  7295. }
  7296. else
  7297. {
  7298. hmenuSrc = _hmenuFull;
  7299. }
  7300. Shell_MergeMenus(hmenu, hmenuSrc, 0, 0, FCIDM_BROWSERLAST, MM_SUBMENUSHAVEIDS);
  7301. lpMenuWidths->width[0] = 1; // File
  7302. lpMenuWidths->width[2] = 2; // Edit, View
  7303. lpMenuWidths->width[4] = 1; // Help
  7304. }
  7305. // Save this away so we can correctly build the menu list object
  7306. _hmenuBrowser = hmenu;
  7307. DEBUG_CODE(_DumpMenus(TEXT("InsertMenusSB"), TRUE);)
  7308. return S_OK;
  7309. }
  7310. /*----------------------------------------------------------
  7311. Purpose: IShellBrowser::SetMenuSB method
  7312. */
  7313. HRESULT CShellBrowser2::SetMenuSB(HMENU hmenu, HOLEMENU hmenuRes, HWND hwnd)
  7314. {
  7315. RIP(NULL == hmenu || IS_VALID_HANDLE(hmenu, MENU));
  7316. // A NULL hmenu means to reinstate the container's original menu
  7317. if (hmenu) {
  7318. _hmenuCur = hmenu;
  7319. } else {
  7320. if (_fRunningInIexploreExe)
  7321. _hmenuCur = _hmenuPreMerged;
  7322. else
  7323. _hmenuCur = _hmenuTemplate;
  7324. }
  7325. _fDispatchMenuMsgs = FALSE;
  7326. _fForwardMenu = FALSE;
  7327. // Normally _hmenuBrowser is set by the caller of InsertMenusSB.
  7328. // However, with the actual web browser, InsertMenusSB is never called.
  7329. // That means _hmenuBrowse is either NULL or non-NULL but invalid.
  7330. // So in that case assume hmenu is equivalent. This essentially makes
  7331. // all messages get sent to the frame, which is what we want.
  7332. HMENU hmenuBrowser;
  7333. if (!IsMenu(_hmenuBrowser)) // We're calling IsMenu on purpose
  7334. _hmenuBrowser = NULL;
  7335. if (NULL != _hmenuBrowser)
  7336. hmenuBrowser = _hmenuBrowser;
  7337. else
  7338. hmenuBrowser = hmenu;
  7339. _menulist.Set(hmenu, hmenuBrowser);
  7340. // Was the help menu merged?
  7341. HMENU hmenuHelp = NULL;
  7342. if (_pbbd->_pctView)
  7343. {
  7344. VARIANTARG vaOut = {0};
  7345. if (S_OK == _pbbd->_pctView->Exec(&CGID_ShellDocView, SHDVID_QUERYMERGEDHELPMENU, 0, NULL, &vaOut))
  7346. {
  7347. // Yes; remove it from the list so it isn't accidentally
  7348. // forwarded on.
  7349. if (VT_INT_PTR == vaOut.vt)
  7350. {
  7351. hmenuHelp = (HMENU)vaOut.byref;
  7352. ASSERT(IS_VALID_HANDLE(hmenuHelp, MENU));
  7353. _menulist.RemoveMenu(hmenuHelp);
  7354. }
  7355. VariantClearLazy(&vaOut);
  7356. vaOut.vt = VT_EMPTY;
  7357. vaOut.byref = NULL;
  7358. if (S_OK == _pbbd->_pctView->Exec(&CGID_ShellDocView, SHDVID_QUERYOBJECTSHELPMENU, 0, NULL, &vaOut))
  7359. {
  7360. if (VT_INT_PTR == vaOut.vt)
  7361. {
  7362. // Add the object's help submenu to the list so it gets forwarded
  7363. HMENU hmenuObjHelp = (HMENU)vaOut.byref;
  7364. ASSERT(IS_VALID_HANDLE(hmenuObjHelp, MENU));
  7365. _menulist.AddMenu(hmenuObjHelp);
  7366. }
  7367. VariantClearLazy(&vaOut);
  7368. }
  7369. }
  7370. }
  7371. // 80734: Was the Go To menu taken from the View menu and grafted onto the
  7372. // main menu by DocHost? The menulist won't detect this graft, so we have
  7373. // to check ourselves and make sure it's not marked as belonging to the
  7374. // docobject.
  7375. //
  7376. // This test is duplicated in CDocObjectHost::_SetMenu
  7377. MENUITEMINFO mii;
  7378. mii.cbSize = sizeof(mii);
  7379. mii.fMask = MIIM_SUBMENU;
  7380. if (hmenu && _hmenuBrowser &&
  7381. GetMenuItemInfo(hmenu, FCIDM_MENU_EXPLORE, FALSE, &mii))
  7382. {
  7383. HMENU hmenuGo = mii.hSubMenu;
  7384. if (GetMenuItemInfo(_hmenuBrowser, FCIDM_MENU_EXPLORE, FALSE, &mii) &&
  7385. mii.hSubMenu == hmenuGo && _menulist.IsObjectMenu(hmenuGo))
  7386. {
  7387. _menulist.RemoveMenu(hmenuGo);
  7388. }
  7389. }
  7390. DEBUG_CODE(_hmenuHelp = hmenuHelp;)
  7391. if (!_fKioskMode)
  7392. {
  7393. if (_fShowMenu)
  7394. _SetMenu(_hmenuCur);
  7395. else
  7396. _SetMenu(NULL);
  7397. }
  7398. DEBUG_CODE(_DumpMenus(TEXT("SetMenuSB"), TRUE););
  7399. return S_OK;
  7400. }
  7401. /*----------------------------------------------------------
  7402. Purpose: Remove menus that are shared with other menus from
  7403. the given browser menu.
  7404. */
  7405. HRESULT CShellBrowser2::RemoveMenusSB(HMENU hmenuShared)
  7406. {
  7407. // Generally, there is no need to remove most of the menus because
  7408. // they were cloned and inserted into this menu. However, the
  7409. // Favorites menu is an exception because it is shared with
  7410. // _hmenuFav.
  7411. return S_OK;
  7412. }
  7413. void CShellBrowser2::_ShowHideProgress()
  7414. {
  7415. if (_hwndProgress) {
  7416. UINT uShow = SW_SHOW;
  7417. if (SendMessage(_hwndProgress, PBM_GETPOS, 0, 0) == 0)
  7418. uShow = SW_HIDE;
  7419. ShowWindow(_hwndProgress, uShow);
  7420. TraceMsg(TF_SHDPROGRESS, "CShellBrowser2::_ShowHideProgress() uShow = %X", uShow);
  7421. }
  7422. }
  7423. HRESULT CShellBrowser2::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam,
  7424. LPARAM lParam, LRESULT *pret)
  7425. {
  7426. HRESULT hres = SUPERCLASS::SendControlMsg(id, uMsg, wParam, lParam, pret);
  7427. if (id == FCW_PROGRESS) {
  7428. if (uMsg == PBM_SETRANGE32 || uMsg == PBM_SETPOS)
  7429. _ShowHideProgress();
  7430. if (_ptheater && _ptheater->_hwndProgress)
  7431. SendMessage(_ptheater->_hwndProgress, uMsg, wParam, lParam);
  7432. }
  7433. return hres;
  7434. }
  7435. HRESULT CShellBrowser2::_QIExplorerBand(REFIID riid, void **ppvObj)
  7436. {
  7437. *ppvObj = NULL;
  7438. HRESULT hr = E_FAIL;
  7439. IDeskBar* pdbBar;
  7440. if (SUCCEEDED(FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdbBar))) && pdbBar)
  7441. {
  7442. IUnknown* punkBS;
  7443. if (SUCCEEDED(pdbBar->GetClient(&punkBS)))
  7444. {
  7445. IBandSite* pbs;
  7446. if (SUCCEEDED(punkBS->QueryInterface(IID_PPV_ARG(IBandSite, &pbs))))
  7447. {
  7448. IDeskBand* pdbBand = FindBandByClsidBS(pbs, CLSID_ExplorerBand);
  7449. if (pdbBand)
  7450. {
  7451. hr = pdbBand->QueryInterface(riid, ppvObj);
  7452. pdbBand->Release();
  7453. }
  7454. pbs->Release();
  7455. }
  7456. punkBS->Release();
  7457. }
  7458. pdbBar->Release();
  7459. }
  7460. return hr;
  7461. }
  7462. HRESULT CShellBrowser2::GetControlWindow(UINT id, HWND * lphwnd)
  7463. {
  7464. // the defaults
  7465. HRESULT hres = E_FAIL;
  7466. *lphwnd = NULL;
  7467. switch (id)
  7468. {
  7469. case FCW_INTERNETBAR:
  7470. if (_GetITBar() && _GetToolbarItem(ITB_ITBAR)->fShow)
  7471. hres = _GetITBar()->GetWindow(lphwnd);
  7472. break;
  7473. case FCW_TOOLBAR:
  7474. *lphwnd = _hwndDummyTB;
  7475. break;
  7476. case FCW_STATUS:
  7477. *lphwnd = _hwndStatus;
  7478. break;
  7479. case FCW_PROGRESS:
  7480. if (!_hwndProgress && _hwndStatus) {
  7481. _hwndProgress = CreateWindowEx(0, PROGRESS_CLASS, NULL,
  7482. WS_CHILD | WS_CLIPSIBLINGS | PBS_SMOOTH,
  7483. 0, 0, 1, 1,
  7484. _hwndStatus, (HMENU)1,
  7485. HINST_THISDLL, NULL);
  7486. // we yank off this bit because we REALLY don't want it because
  7487. // the status bar already draws this for us when we specify rects
  7488. //
  7489. // but the progress bar forces this bit on during creation
  7490. if (_hwndProgress)
  7491. SHSetWindowBits(_hwndProgress, GWL_EXSTYLE, WS_EX_STATICEDGE, 0);
  7492. }
  7493. *lphwnd = _hwndProgress;
  7494. break;
  7495. case FCW_TREE:
  7496. {
  7497. BOOL fExplorerBandVisible;
  7498. if (SUCCEEDED(IsControlWindowShown(FCW_TREE, &fExplorerBandVisible)) && fExplorerBandVisible)
  7499. {
  7500. IOleWindow* pow;
  7501. if (SUCCEEDED(_QIExplorerBand(IID_IOleWindow, (void**)&pow)))
  7502. {
  7503. pow->GetWindow(lphwnd);
  7504. pow->Release();
  7505. }
  7506. }
  7507. }
  7508. break;
  7509. }
  7510. if (*lphwnd) {
  7511. hres = S_OK;
  7512. }
  7513. return hres;
  7514. }
  7515. //==========================================================================
  7516. //
  7517. //==========================================================================
  7518. HRESULT CShellBrowser2::SetToolbarItems(LPTBBUTTON pViewButtons, UINT nButtons,
  7519. UINT uFlags)
  7520. {
  7521. LPTBBUTTON pStart= NULL, pbtn= NULL;
  7522. int nFirstDiff = 0, nTotalButtons = 0;
  7523. BOOL bVisible = FALSE;
  7524. if (uFlags & FCT_CONFIGABLE)
  7525. {
  7526. return S_OK;
  7527. }
  7528. // Allocate buffer for the default buttons plus the ones passed in
  7529. //
  7530. pStart = (LPTBBUTTON)LocalAlloc(LPTR, nButtons * sizeof(TBBUTTON));
  7531. if (!pStart)
  7532. return S_OK;
  7533. pbtn = pStart;
  7534. nTotalButtons = 0;
  7535. if (pViewButtons)
  7536. {
  7537. int i;
  7538. for (i = nButtons - 1; i >= 0; --i)
  7539. {
  7540. // copy in the callers buttons
  7541. //
  7542. pbtn[i] = pViewButtons[i];
  7543. // make sure this is properly set to -1.
  7544. // in win95, we had no strings so extensions couldn't set it, but some didn't initialize to -1
  7545. if ((!pbtn[i].iString || (pbtn[i].iString <= (MAX_TB_BUTTONS + NUMBER_SHELLGLYPHS - 1))))
  7546. {
  7547. // We should not set our own shell iString to -1
  7548. ASSERT(pbtn[i].iString != pbtn[i].iBitmap);
  7549. // comment about Hummingbird passing 0xc always
  7550. COMPILETIME_ASSERT(MAX_TB_BUTTONS + NUMBER_SHELLGLYPHS >= 0xc);
  7551. pbtn[i].iString = -1;
  7552. }
  7553. }
  7554. pbtn += nButtons;
  7555. nTotalButtons += nButtons;
  7556. }
  7557. if (_pxtb)
  7558. {
  7559. // for right now, disable customize for all old style views
  7560. DWORD dwFlags = VBF_NOCUSTOMIZE;
  7561. TCHAR szScratch[32];
  7562. if (_nTBTextRows == -1) {
  7563. if (MLLoadString(IDS_SHELL_TB_TEXTROWS, szScratch, ARRAYSIZE(szScratch)))
  7564. _nTBTextRows = (UINT)StrToInt(szScratch);
  7565. else
  7566. _nTBTextRows = 0;
  7567. }
  7568. if (_nTBTextRows == 1)
  7569. dwFlags |= VBF_ONELINETEXT;
  7570. else if (_nTBTextRows == 2)
  7571. dwFlags |= VBF_TWOLINESTEXT;
  7572. _pxtb->SetCommandTarget((IUnknown *)SAFECAST(this, IOleCommandTarget *), &CGID_ShellBrowser, dwFlags);
  7573. if (_lpPendingButtons)
  7574. LocalFree(_lpPendingButtons);
  7575. _lpPendingButtons = (TBBUTTON*)pStart;
  7576. _nButtonsPending = nTotalButtons;
  7577. }
  7578. else
  7579. {
  7580. LocalFree(pStart);
  7581. }
  7582. return S_OK;
  7583. }
  7584. #ifdef DEBUG
  7585. //---------------------------------------------------------------------------
  7586. // Copy the exception info so we can get debug info for Raised exceptions
  7587. // which don't go through the debugger.
  7588. void _CopyExceptionInfo(LPEXCEPTION_POINTERS pep)
  7589. {
  7590. PEXCEPTION_RECORD per;
  7591. per = pep->ExceptionRecord;
  7592. TraceMsg(DM_ERROR, "Exception %x at %#08x.", per->ExceptionCode, per->ExceptionAddress);
  7593. if (per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
  7594. {
  7595. // If the first param is 1 then this was a write.
  7596. // If the first param is 0 then this was a read.
  7597. if (per->ExceptionInformation[0])
  7598. {
  7599. TraceMsg(DM_ERROR, "Invalid write to %#08x.", per->ExceptionInformation[1]);
  7600. }
  7601. else
  7602. {
  7603. TraceMsg(DM_ERROR, "Invalid read of %#08x.", per->ExceptionInformation[1]);
  7604. }
  7605. }
  7606. }
  7607. #else
  7608. #define _CopyExceptionInfo(x) TRUE
  7609. #endif
  7610. #define SVSI_SELFLAGS (SVSI_SELECT|SVSI_FOCUSED|SVSI_DESELECTOTHERS|SVSI_ENSUREVISIBLE)
  7611. void CShellBrowser2::_AfterWindowCreated(IETHREADPARAM *piei)
  7612. {
  7613. //
  7614. // Let interested people know we are alive
  7615. //
  7616. if (piei->uFlags & COF_SELECT)
  7617. {
  7618. IShellView* psv = _pbbd->_psv ? _pbbd->_psv : _pbbd->_psvPending;
  7619. if (psv)
  7620. psv->SelectItem(piei->pidlSelect, SVSI_SELFLAGS);
  7621. }
  7622. #ifdef UNIX
  7623. //
  7624. // Since on Unix we are using browser window to display
  7625. // help instead of HTML Help Check for Help mode and
  7626. // remove internet decorations and statusbar.
  7627. //
  7628. // Also remove any bars on the browser.
  7629. if (piei->uFlags & COF_HELPMODE)
  7630. {
  7631. #ifdef NO_MARSHALLING
  7632. if (piei->fOnIEThread)
  7633. {
  7634. #endif
  7635. v_ShowControl(FCW_INTERNETBAR, SBSC_HIDE);
  7636. v_ShowControl(FCW_STATUS, SBSC_HIDE);
  7637. #ifdef NO_MARSHALLING
  7638. }
  7639. else
  7640. {
  7641. v_ShowControl(FCW_MENUBAR, SBSC_HIDE);
  7642. v_ShowControl(FCW_ADDRESSBAR, SBSC_HIDE);
  7643. v_ShowControl(FCW_LINKSBAR, SBSC_HIDE);
  7644. v_ShowControl(FCW_TOOLBAND, SBSC_HIDE);
  7645. IUnknown_Exec(_GetITBar(),&CGID_PrivCITCommands, CITIDM_SHOWBRAND, FALSE, NULL, NULL);
  7646. }
  7647. #endif
  7648. _SetBrowserBarState(_idmInfo, NULL, 0);
  7649. _SetBrowserBarState(_idmComm, NULL, 0);
  7650. }
  7651. #endif // UNIX
  7652. //
  7653. // Keep it hidden if this is the first instance which is started
  7654. // with "/automation" flag or this object is being created as the
  7655. // result of our CreateInstance.
  7656. //
  7657. if (!_fAutomation && !piei->piehs)
  7658. {
  7659. if (_fKioskMode)
  7660. {
  7661. // Turn off flag as we need to let the next function set it...
  7662. _fKioskMode = FALSE;
  7663. // Hack -1 implies
  7664. ShowControlWindow((UINT)-1, TRUE);
  7665. }
  7666. UINT nCmdShow = piei->nCmdShow;
  7667. BOOL fSetForeground = FALSE;
  7668. BOOL fStartTheater = FALSE;
  7669. // we need to do this setforegroundwindow
  7670. // because of a bug in user. if the previous thread didn't have
  7671. // activation, ShowWindow will NOT give us activation even though
  7672. // it's supposed to
  7673. switch (nCmdShow) {
  7674. case SW_SHOWNORMAL:
  7675. case SW_SHOWMAXIMIZED:
  7676. case SW_SHOW:
  7677. fSetForeground = TRUE;
  7678. break;
  7679. }
  7680. if (_fUseIEPersistence)
  7681. {
  7682. fStartTheater = SHRegGetBoolUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"),
  7683. TEXT("FullScreen"), FALSE, FALSE);
  7684. }
  7685. if (fStartTheater)
  7686. {
  7687. _TheaterMode(TRUE, FALSE);
  7688. if (fSetForeground)
  7689. nCmdShow = SW_SHOW;
  7690. }
  7691. MSG msg;
  7692. if (!PeekMessage(&msg, _pbbd->_hwnd, WM_CLOSE, WM_CLOSE, PM_NOREMOVE))
  7693. {
  7694. ShowWindow(_pbbd->_hwnd, nCmdShow);
  7695. //
  7696. // AT THIS POINT ALL DDE TRANSACTIONS SHOULD SUCCEED. THE BROWSER
  7697. // WINDOW WAS ADDED TO THE DDE WINITEM LIST ON WM_NCCREATE,
  7698. // AUTOMATION WAS REGISTERED AS STARTED ON THE OnCreate,
  7699. // AND THE WINDOW IS NOW VISIBLE AS A PART OF THE SHOWWINDOW.
  7700. // 99% OF ALL DDE STARTUP BUGS ARE CAUSED BY SOMEBODY CHECKING FOR
  7701. // MESSAGES (PEEKMESSAGE, GETMESSAGE, INTERPROC SENDMESSAGE, ETC.)
  7702. // BEFORE THIS POINT.
  7703. //
  7704. // On UNIX it is not common to force the window to the top of Z-order.
  7705. //
  7706. #ifndef UNIX
  7707. if (fSetForeground)
  7708. SetForegroundWindow(_pbbd->_hwnd);
  7709. #endif
  7710. }
  7711. else
  7712. {
  7713. ASSERT(msg.hwnd == _pbbd->_hwnd);
  7714. }
  7715. }
  7716. _SetTitle(NULL);
  7717. //
  7718. // Delay register our window now.
  7719. // Note that we need to do it after SetEvent(piei->piehs->GetHevent()) to
  7720. // avoid soft dead-lock in OLE, and we need to do it after the
  7721. // ShowWindow above because this will allow DDE messages to get
  7722. // sent to us.
  7723. //
  7724. // RegisterWindow() shouldnt have been called yet, but if it has, we dont want
  7725. // to change its registration class from here. zekel 9-SEP-97
  7726. //
  7727. ASSERT(!_fDidRegisterWindow);
  7728. RegisterWindow(FALSE, (piei->uFlags & COF_EXPLORE) ? SWC_EXPLORER : SWC_BROWSER);
  7729. // Delay loading accelerators from v_initmembers
  7730. ASSERT(MLGetHinst());
  7731. HACCEL hacc = LoadAccelerators(MLGetHinst(), MAKEINTRESOURCE(ACCEL_MERGE));
  7732. ASSERT(hacc);
  7733. SetAcceleratorMenu(hacc);
  7734. // Send size so status bar shows
  7735. SendMessage(_pbbd->_hwnd, WM_SIZE, 0, 0);
  7736. // delay doing a bunch of registrations
  7737. // things we don't want our subclass to inherit
  7738. if (v_InitMembers == CShellBrowser2::v_InitMembers)
  7739. {
  7740. // register to get filesys notifications
  7741. _uFSNotify = RegisterNotify(_pbbd->_hwnd, CWM_FSNOTIFY, NULL, SHELLBROWSER_FSNOTIFY_FLAGS,
  7742. SHCNRF_ShellLevel | SHCNRF_InterruptLevel, TRUE);
  7743. }
  7744. SignalFileOpen(piei->pidl);
  7745. }
  7746. //
  7747. // RegisterWindow() should only be called with Unregister if the caller
  7748. // wants to insure that the new ShellWindowClass is used. this is used
  7749. // by CIEFrameAuto to force the browser window in the 3rdParty winlist.
  7750. //
  7751. HRESULT CShellBrowser2::RegisterWindow(BOOL fForceReregister, int swc)
  7752. {
  7753. if (!_psw)
  7754. _psw = WinList_GetShellWindows(FALSE);
  7755. if (_psw)
  7756. {
  7757. if (fForceReregister && _fDidRegisterWindow)
  7758. {
  7759. _psw->Revoke(_dwRegisterWinList);
  7760. _fDidRegisterWindow = FALSE;
  7761. }
  7762. if (!_fDidRegisterWindow)
  7763. {
  7764. // raymondc- HandleToLong should really be HANDLE_PTR or something - Browser folks need to fix the IDL
  7765. _psw->Register(NULL, HandleToLong(_pbbd->_hwnd), swc, &_dwRegisterWinList);
  7766. _fDidRegisterWindow = TRUE;
  7767. _swcRegistered = swc;
  7768. UpdateWindowList();
  7769. }
  7770. return S_OK;
  7771. }
  7772. return E_FAIL;
  7773. }
  7774. LRESULT CALLBACK IEFrameWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  7775. void InitializeExplorerClass()
  7776. {
  7777. static BOOL fInited = FALSE;
  7778. if (!fInited)
  7779. {
  7780. ENTERCRITICAL;
  7781. if (!fInited) {
  7782. WNDCLASS wc;
  7783. ZeroMemory(&wc, sizeof(wc));
  7784. wc.style = CS_BYTEALIGNWINDOW;
  7785. wc.lpfnWndProc = IEFrameWndProc;
  7786. wc.cbWndExtra = sizeof(void *);
  7787. wc.hInstance = HINST_THISDLL;
  7788. wc.hIcon = LoadIcon(HinstShdocvw(), MAKEINTRESOURCE(ICO_TREEUP));
  7789. wc.hCursor = LoadCursor(NULL, IDC_SIZEWE);
  7790. wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  7791. wc.lpszClassName = c_szExploreClass;
  7792. RegisterClass(&wc);
  7793. #ifndef UNIX
  7794. wc.hIcon = LoadIcon(HinstShdocvw(), MAKEINTRESOURCE(IDI_STATE_NORMAL));
  7795. #else
  7796. if (SHGetCurColorRes() < 2)
  7797. wc.hIcon = LoadIcon(HinstShdocvw(), MAKEINTRESOURCE(IDI_MONOFRAME));
  7798. else
  7799. wc.hIcon = LoadIcon(HinstShdocvw(), MAKEINTRESOURCE(IDI_STATE_NORMAL));
  7800. #endif
  7801. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  7802. wc.lpszClassName = c_szIExploreClass;
  7803. RegisterClass(&wc);
  7804. // shell32 is stuck with this id forever since it came out on win95
  7805. #define IDI_FOLDEROPEN 5 // open folder
  7806. wc.hIcon = LoadIcon(HinstShell32(), MAKEINTRESOURCE(IDI_FOLDEROPEN));
  7807. wc.lpszClassName = c_szCabinetClass;
  7808. RegisterClass(&wc);
  7809. // this needs to be set at the END..
  7810. // because otherwise a race condition occurs and some guys run throught the
  7811. // outter most check and try to create before we're registered.
  7812. fInited = TRUE;
  7813. }
  7814. LEAVECRITICAL;
  7815. }
  7816. }
  7817. // compatability: we need to have the right class name so people can find our window
  7818. //
  7819. LPCTSTR _GetExplorerClassName(UINT uFlags)
  7820. {
  7821. if (uFlags & COF_EXPLORE)
  7822. return c_szExploreClass;
  7823. else if (uFlags & COF_IEXPLORE || WhichPlatform() == PLATFORM_BROWSERONLY)
  7824. return c_szIExploreClass;
  7825. else
  7826. return c_szCabinetClass;
  7827. }
  7828. void TimedDispatchMessage(MSG *pmsg)
  7829. {
  7830. DWORD dwTime;
  7831. if (g_dwStopWatchMode & SPMODE_MSGTRACE)
  7832. dwTime = StopWatch_DispatchTime(TRUE, *pmsg, 0);
  7833. DispatchMessage(pmsg);
  7834. if (g_dwStopWatchMode)
  7835. {
  7836. if (g_dwStopWatchMode & SPMODE_MSGTRACE)
  7837. StopWatch_DispatchTime(FALSE, *pmsg, dwTime);
  7838. if ((g_dwStopWatchMode & SPMODE_SHELL) && (pmsg->message == WM_PAINT))
  7839. StopWatch_TimerHandler(pmsg->hwnd, 1, SWMSG_PAINT, pmsg); // Save tick count for paint msg
  7840. }
  7841. }
  7842. void DesktopChannel();
  7843. void BrowserThreadProc(IETHREADPARAM* piei)
  7844. {
  7845. HMENU hmenu;
  7846. HWND hwnd;
  7847. DWORD dwExStyle = WS_EX_WINDOWEDGE;
  7848. LONG cRefMsgLoop; // the ref count for this thread
  7849. IUnknown *punkMsgLoop; // the ref object (wraps cRefMsgLoop) for this thread
  7850. IUnknown *punkRefProcess; // the process ref this thread holds (may be none)
  7851. #ifdef NO_MARSHALLING
  7852. THREADWINDOWINFO *lpThreadWindowInfo = InitializeThreadInfoStructs();
  7853. if (!lpThreadWindowInfo)
  7854. goto Done;
  7855. #endif
  7856. UINT tidCur = GetCurrentThreadId();
  7857. UINT uFlags = piei->uFlags;
  7858. // Set our priority higher for startup so that we are not starved by background tasks and
  7859. // other pesky system activity
  7860. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
  7861. #ifndef NO_ETW_TRACING
  7862. // Event trace for windows enable by shlwapi.
  7863. if (g_dwStopWatchMode & SPMODE_EVENTTRACE)
  7864. EventTraceHandler(EVENT_TRACE_TYPE_BROWSE_STARTFRAME, NULL);
  7865. #endif
  7866. if (g_dwStopWatchMode & (SPMODE_SHELL | SPMODE_BROWSER | SPMODE_JAVA | SPMODE_MSGTRACE))
  7867. StopWatch_MarkFrameStart(piei->uFlags & COF_EXPLORE ? " (explore)" : "");
  7868. punkRefProcess = piei->punkRefProcess;
  7869. piei->punkRefProcess = NULL; // we took ownership
  7870. LPWSTR pszCloseEvent = (piei->uFlags & COF_FIREEVENTONCLOSE) ? StrDupW(piei->szCloseEvent) : NULL;
  7871. // if we're going to do desktop channel stuff, do it and return
  7872. #ifdef ENABLE_CHANNELS
  7873. if (piei->fDesktopChannel)
  7874. {
  7875. if (piei->pSplash)
  7876. {
  7877. piei->pSplash->Dismiss();
  7878. ATOMICRELEASE(piei->pSplash);
  7879. }
  7880. if (piei->uFlags & COF_FIREEVENTONDDEREG)
  7881. {
  7882. ASSERT(piei->szDdeRegEvent[0]);
  7883. FireEventSzW(piei->szDdeRegEvent);
  7884. }
  7885. DesktopChannel();
  7886. goto Done;
  7887. }
  7888. #endif / ENABLE_CHANNELS
  7889. TraceMsg(TF_SHDTHREAD, "BrowserThreadProc() - IE_ThreadProc(%x) just started.", tidCur);
  7890. InitializeExplorerClass();
  7891. if (SUCCEEDED(SHCreateThreadRef(&cRefMsgLoop, &punkMsgLoop)))
  7892. {
  7893. if (tidCur == g_tidParking)
  7894. {
  7895. SHSetInstanceExplorer(punkMsgLoop); // we are process reference
  7896. }
  7897. SHSetThreadRef(punkMsgLoop);
  7898. }
  7899. // Set our title temporarily (for people who grab our title, like the SHEnumErrorMessage guy
  7900. TCHAR szTempTitle[MAX_PATH];
  7901. if (piei->uFlags & COF_IEXPLORE)
  7902. MLLoadString(IDS_TITLE, szTempTitle, ARRAYSIZE(szTempTitle));
  7903. else
  7904. MLLoadString(IDS_CABINET, szTempTitle, ARRAYSIZE(szTempTitle));
  7905. //
  7906. // APPCOMPAT - apps like WebCD require a non-null menu on the
  7907. // browser. Thankfully USER won't draw a menuband on an empty hmenu.
  7908. //
  7909. hmenu = CreateMenu();
  7910. dwExStyle |= IS_BIDI_LOCALIZED_SYSTEM() ? dwExStyleRTLMirrorWnd | dwExStyleNoInheritLayout: 0L;
  7911. hwnd = SHNoFusionCreateWindowEx(dwExStyle, _GetExplorerClassName(piei->uFlags), szTempTitle,
  7912. WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
  7913. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
  7914. hmenu, HINST_THISDLL, piei);
  7915. if (punkMsgLoop)
  7916. punkMsgLoop->Release(); // browser (in open state) holds the ref
  7917. if (piei->pSplash)
  7918. {
  7919. piei->pSplash->Dismiss();
  7920. ATOMICRELEASE(piei->pSplash);
  7921. }
  7922. if (hwnd)
  7923. {
  7924. #ifdef UNIX
  7925. UnixAdjustWindowSize(hwnd, piei);
  7926. #endif
  7927. if (g_dwStopWatchMode & SPMODE_SHELL) // Create the timer to start watching for paint messages
  7928. StopWatch_TimerHandler(hwnd, 0, SWMSG_CREATE, NULL);
  7929. CShellBrowser2* psb = (CShellBrowser2*)GetWindowPtr0(hwnd);
  7930. if (psb)
  7931. {
  7932. #ifdef NO_MARSHALLING
  7933. AddFirstBrowserToList(psb);
  7934. #endif
  7935. psb->AddRef();
  7936. psb->_AfterWindowCreated(piei);
  7937. SHDestroyIETHREADPARAM(piei);
  7938. piei = NULL;
  7939. TraceMsg(TF_SHDTHREAD, "BrowserThreadProc() - IE_ThreadProc(%x) about to start the message loop", tidCur);
  7940. #ifdef UNIX
  7941. BOOL fNoSignalUI = !!getenv("IE_NO_SIGNAL_UI");
  7942. for (int nMessagePumpCount = 0; nMessagePumpCount < 2; nMessagePumpCount += 2)
  7943. {
  7944. __try
  7945. {
  7946. #endif
  7947. BOOL fThreadPriorityHasBeenReset = FALSE;
  7948. while (1)
  7949. {
  7950. MSG msg;
  7951. BOOL fPeek;
  7952. fPeek = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  7953. if (fPeek)
  7954. {
  7955. #ifndef NO_ETW_TRACING
  7956. if (g_dwStopWatchMode & SPMODE_EVENTTRACE) {
  7957. if (msg.message == WM_KEYDOWN) {
  7958. if (msg.wParam == VK_RETURN) {
  7959. EventTraceHandler(EVENT_TRACE_TYPE_BROWSE_USERINPUTRET, NULL);
  7960. }
  7961. else if (msg.wParam == VK_BACK) {
  7962. EventTraceHandler(EVENT_TRACE_TYPE_BROWSE_USERINPUTBACK, NULL);
  7963. }
  7964. else if (msg.wParam == VK_NEXT) {
  7965. EventTraceHandler(EVENT_TRACE_TYPE_BROWSE_USERINPUTNEXT, NULL);
  7966. }
  7967. else if (msg.wParam == VK_PRIOR) {
  7968. EventTraceHandler(EVENT_TRACE_TYPE_BROWSE_USERINPUTPRIOR, NULL);
  7969. }
  7970. }
  7971. else if (msg.message == WM_LBUTTONUP) {
  7972. EventTraceHandler(EVENT_TRACE_TYPE_BROWSE_USERINPUTLBUT, NULL);
  7973. }
  7974. }
  7975. #endif
  7976. if (g_dwStopWatchMode)
  7977. StopWatch_CheckMsg(hwnd, msg, uFlags == COF_EXPLORE ? " (explore) " : ""); // Key off of WM_KEYDOWN to start timing
  7978. #ifdef NO_MARSHALLING
  7979. CShellBrowser2 *psbOld = psb;
  7980. CShellBrowser2 *psb = CheckAndForwardMessage(lpThreadWindowInfo, psbOld, msg);
  7981. if (!psb)
  7982. psb = psbOld;
  7983. #endif
  7984. if (psb->_pbbd->_hwnd && IsWindow(psb->_pbbd->_hwnd))
  7985. {
  7986. //
  7987. // Directly dispatch WM_CLOSE message to distinguish nested
  7988. // message loop case.
  7989. //
  7990. if ((msg.message == WM_CLOSE) && (msg.hwnd == psb->_pbbd->_hwnd))
  7991. {
  7992. psb->_OnClose(FALSE);
  7993. continue;
  7994. }
  7995. #ifdef NO_MARSHALLING
  7996. HWND hwnd = GetActiveWindow();
  7997. if (!IsNamedWindow(hwnd, TEXT("Internet Explorer_TridentDlgFrame")))
  7998. {
  7999. if (S_OK == psb->v_MayTranslateAccelerator(&msg))
  8000. continue;
  8001. }
  8002. else
  8003. {
  8004. DWORD dwExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  8005. if (dwExStyle & WS_EX_MWMODAL_POPUP)
  8006. {
  8007. if (S_OK == psb->v_MayTranslateAccelerator(&msg))
  8008. continue;
  8009. }
  8010. else
  8011. {
  8012. if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST &&
  8013. (TranslateModelessAccelerator(&msg, hwnd) == S_OK))
  8014. continue;
  8015. }
  8016. }
  8017. #else
  8018. if (S_OK == psb->v_MayTranslateAccelerator(&msg))
  8019. continue;
  8020. #endif
  8021. }
  8022. TranslateMessage(&msg);
  8023. TimedDispatchMessage(&msg);
  8024. }
  8025. #ifdef NO_MARSHALLING
  8026. else if ((cRefMsgLoop == 0) && (lpThreadWindowInfo->cWindowCount == 0))
  8027. #else
  8028. else if (cRefMsgLoop == 0)
  8029. #endif
  8030. {
  8031. TraceMsg(TF_SHDTHREAD, "BrowserThreadProc() - cRefMsgLoop == 0, done");
  8032. break; // exit while (1), no more refs on this thread
  8033. }
  8034. else
  8035. {
  8036. if (!fThreadPriorityHasBeenReset)
  8037. {
  8038. fThreadPriorityHasBeenReset = TRUE;
  8039. // Reset our priority to normal now that we have finished the startup
  8040. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  8041. #ifdef PERF_LOGGING
  8042. HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, TEXT("ExplorerWindowIdle"));
  8043. if (hEvent)
  8044. {
  8045. SetEvent(hEvent);
  8046. CloseHandle(hEvent);
  8047. }
  8048. #endif
  8049. }
  8050. WaitMessage();
  8051. if (g_dwStopWatchMode & SPMODE_MSGTRACE)
  8052. StopWatch_SetMsgLastLocation(2);
  8053. }
  8054. }
  8055. #ifdef UNIX
  8056. }
  8057. __except((fNoSignalUI || nMessagePumpCount > 0)
  8058. ? EXCEPTION_CONTINUE_SEARCH
  8059. : EXCEPTION_EXECUTE_HANDLER)
  8060. {
  8061. // we will try to display a message box to tell the user
  8062. // that a thread has died...
  8063. //
  8064. int result = MLShellMessageBox(NULL, MAKEINTRESOURCE(IDS_EXCEPTIONMSGSH),
  8065. MAKEINTRESOURCE(IDS_TITLE),
  8066. MB_OK |
  8067. MB_APPLMODAL |
  8068. MB_ICONEXCLAMATION |
  8069. MB_SETFOREGROUND);
  8070. if (result != IDNO)
  8071. {
  8072. MwExecuteAtExit(); // why doesn't ExitProcess do this!?!?!?
  8073. ExitProcess(0);
  8074. }
  8075. nMessagePumpCount -= 2; // -=2 for no limit, -=1 to only show panel once
  8076. }
  8077. __endexcept
  8078. }
  8079. #endif
  8080. TraceMsg(TF_SHDTHREAD, "BrowserThreadProc() - IE_ThreadProc(%x) end of message loop", tidCur);
  8081. psb->Release();
  8082. }
  8083. }
  8084. else
  8085. {
  8086. // Unregister any pending that may be there
  8087. WinList_Revoke(piei->dwRegister);
  8088. TraceMsg(TF_WARNING, "BrowserThreadProc() - IE_ThreadProc CreateWindow failed");
  8089. }
  8090. #if defined(ENABLE_CHANNELS) || defined(NO_MARSHALLING)
  8091. Done:
  8092. #endif
  8093. // Make sure we return the thread priority to normal in case this thread is re-used.
  8094. SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  8095. if (pszCloseEvent)
  8096. {
  8097. FireEventSzW(pszCloseEvent);
  8098. LocalFree(pszCloseEvent);
  8099. }
  8100. SHDestroyIETHREADPARAM(piei);
  8101. if (punkRefProcess)
  8102. punkRefProcess->Release();
  8103. #ifdef NO_MARSHALLING
  8104. FreeThreadInfoStructs();
  8105. #endif
  8106. }
  8107. DWORD CALLBACK BrowserProtectedThreadProc(void *pv)
  8108. {
  8109. if (g_dwProfileCAP & 0x00000004)
  8110. StartCAP();
  8111. HRESULT hrInit = OleInitialize(NULL);
  8112. PostMessage(GetShellWindow(), DTM_SETAPPSTARTCUR, 0, 0);
  8113. #ifdef DEBUG
  8114. if (hrInit != S_OK)
  8115. {
  8116. TraceMsg(TF_WARNING, "BrowserProtectedThreadProc: OleInitialize returned %x ?!?", hrInit);
  8117. }
  8118. #endif
  8119. ULONG_PTR dwCookie = 0;
  8120. NT5_ActivateActCtx(NULL, &dwCookie); // Set to inherit the process context
  8121. #if !defined(FULL_DEBUG) && (!defined(UNIX) || (defined(UNIX) && defined(GOLDEN)))
  8122. EXCEPTION_RECORD exr;
  8123. _try
  8124. {
  8125. BrowserThreadProc((IETHREADPARAM*)pv);
  8126. }
  8127. _except((exr = *((GetExceptionInformation())->ExceptionRecord),
  8128. _CopyExceptionInfo(GetExceptionInformation()),
  8129. UnhandledExceptionFilter(GetExceptionInformation())))
  8130. {
  8131. LPCTSTR pszMsg = NULL;
  8132. // we will try to display a message box to tell the user
  8133. // that a thread has died...
  8134. //
  8135. if (GetExceptionCode() == STATUS_NO_MEMORY)
  8136. pszMsg = MAKEINTRESOURCE(IDS_EXCEPTIONNOMEMORY);
  8137. else if (WhichPlatform() == PLATFORM_BROWSERONLY)
  8138. {
  8139. pszMsg = MAKEINTRESOURCE(IDS_EXCEPTIONMSG);
  8140. }
  8141. // don't show the message box on non-nt systems
  8142. // older than millennium (with an older shell)
  8143. // see IE5.5 bug#93165
  8144. else if (g_fRunningOnNT || (GetUIVersion() < 5))
  8145. {
  8146. pszMsg = MAKEINTRESOURCE(IDS_EXCEPTIONMSGSH);
  8147. }
  8148. if (pszMsg)
  8149. {
  8150. MLShellMessageBox(NULL, pszMsg,
  8151. MAKEINTRESOURCE(IDS_TITLE), MB_ICONEXCLAMATION|MB_SETFOREGROUND);
  8152. }
  8153. if (GetExceptionCode() != STATUS_NO_MEMORY)
  8154. IEWriteErrorLog(&exr);
  8155. }
  8156. __endexcept
  8157. #else
  8158. // IEUNIX : This exception handler should only be used in Release
  8159. // version of the product. We are disabling it for debugging purposes.
  8160. BrowserThreadProc((IETHREADPARAM*)pv);
  8161. #endif
  8162. NT5_DeactivateActCtx(dwCookie);
  8163. if (SUCCEEDED(hrInit))
  8164. {
  8165. OleUninitialize();
  8166. }
  8167. return 0;
  8168. }
  8169. // Check if this IETHREADPARAM/LPITEMIDLIST requires launch in a new process
  8170. // and if so launch it and return TRUE.
  8171. //
  8172. BOOL TryNewProcessIfNeeded(LPCITEMIDLIST pidl)
  8173. {
  8174. if (pidl && IsBrowseNewProcessAndExplorer()
  8175. && IsBrowserFrameOptionsPidlSet(pidl, BFO_PREFER_IEPROCESS))
  8176. {
  8177. TCHAR szURL[MAX_URL_STRING];
  8178. HRESULT hres = ::IEGetDisplayName(pidl, szURL, SHGDN_FORPARSING);
  8179. if (SUCCEEDED(hres))
  8180. {
  8181. hres = IENavigateIEProcess(szURL, FALSE);
  8182. if (SUCCEEDED(hres))
  8183. {
  8184. return TRUE;
  8185. }
  8186. }
  8187. }
  8188. return FALSE;
  8189. }
  8190. BOOL TryNewProcessIfNeeded(IETHREADPARAM * piei)
  8191. {
  8192. BOOL bRet = TryNewProcessIfNeeded(piei->pidl);
  8193. if (bRet)
  8194. {
  8195. SHDestroyIETHREADPARAM(piei);
  8196. }
  8197. return bRet;
  8198. }
  8199. // NOTE: this is a ThreadProc (shdocvw creates this as a thread)
  8200. //
  8201. // this takes ownership of piei and will free it
  8202. //
  8203. BOOL SHOpenFolderWindow(IETHREADPARAM* piei)
  8204. {
  8205. BOOL fSuccess = FALSE;
  8206. _InitAppGlobals();
  8207. CABINETSTATE cs;
  8208. GetCabState(&cs);
  8209. //
  8210. // If "/select" switch is specified, but we haven't splitted
  8211. // the pidl yet (because the path is passed rather than pidl),
  8212. // split it here.
  8213. //
  8214. if ((piei->uFlags & COF_SELECT) && piei->pidlSelect == NULL)
  8215. {
  8216. LPITEMIDLIST pidlLast = ILFindLastID(piei->pidl);
  8217. // Warning: pidlLast can be NULL if the command line is
  8218. // sufficiently wacky. E.g.,
  8219. //
  8220. // explorer /select
  8221. //
  8222. if (pidlLast)
  8223. {
  8224. piei->pidlSelect = ILClone(pidlLast);
  8225. pidlLast->mkid.cb = 0;
  8226. }
  8227. }
  8228. if (GetAsyncKeyState(VK_CONTROL) < 0)
  8229. cs.fNewWindowMode = !cs.fNewWindowMode;
  8230. //
  8231. // Check to see if we can reuse the existing window first
  8232. //
  8233. OLECMD rgCmds[1] = {0};
  8234. rgCmds[0].cmdID = SBCMDID_EXPLORERBAR;
  8235. BOOL bForceSameWindow = (piei->uFlags & COF_EXPLORE) &&
  8236. SUCCEEDED(IUnknown_QueryStatus(piei->psbCaller, &CGID_Explorer, ARRAYSIZE(rgCmds), rgCmds, NULL)) &&
  8237. (rgCmds[0].cmdf & OLECMDF_LATCHED);
  8238. if (bForceSameWindow ||
  8239. piei->psbCaller &&
  8240. !(piei->uFlags & COF_CREATENEWWINDOW) &&
  8241. !cs.fNewWindowMode)
  8242. {
  8243. if (piei->pidl)
  8244. {
  8245. UINT uFlags = SBSP_SAMEBROWSER;
  8246. if (piei->uFlags & COF_EXPLORE)
  8247. uFlags |= SBSP_EXPLOREMODE;
  8248. else
  8249. uFlags |= SBSP_OPENMODE;
  8250. if (SUCCEEDED(piei->psbCaller->BrowseObject(piei->pidl, uFlags)))
  8251. goto ReusedWindow;
  8252. }
  8253. }
  8254. //
  8255. // Don't look for an existing window if we are opening an explorer.
  8256. //
  8257. if (!((piei->uFlags & COF_EXPLORE) || (piei->uFlags & COF_NOFINDWINDOW)))
  8258. {
  8259. HWND hwnd;
  8260. IWebBrowserApp* pwba;
  8261. HRESULT hres = WinList_FindFolderWindow(piei->pidl, NULL, &hwnd, &pwba);
  8262. if (hres == S_OK)
  8263. {
  8264. ASSERT(pwba); // WinList_FindFolerWindow should not return S_OK if this fails
  8265. SetForegroundWindow(hwnd);
  8266. // IE30COMPAT - we need to refresh when we hunt and pick up these windows - zekel 31-JUL-97
  8267. // this will happen if we just do a navigate to ourself. this is the
  8268. // same kind of behavior we see when we do a shellexec of an URL.
  8269. //
  8270. // we dont use the pwb from FindFolderWindow because it turns out that RPC will
  8271. // fail the QI for it when we are being called from another process. this
  8272. // occurs when IExplore.exe Sends the WM_COPYDATA to the desktop to navigate
  8273. // a window to an URL that is already there. so instead of using the pwb
  8274. // we do a CDDEAuto_Navigate(). which actually goes and uses pwb itself.
  8275. //
  8276. TCHAR szUrl[MAX_URL_STRING];
  8277. if (SUCCEEDED(IEGetNameAndFlags(piei->pidl, SHGDN_FORPARSING, szUrl, SIZECHARS(szUrl), NULL)))
  8278. {
  8279. BSTR bstrUrl = SysAllocString(szUrl);
  8280. if (bstrUrl)
  8281. {
  8282. pwba->Navigate(bstrUrl, NULL, NULL, NULL, NULL);
  8283. SysFreeString(bstrUrl);
  8284. }
  8285. }
  8286. pwba->Release();
  8287. if (IsIconic(hwnd))
  8288. ShowWindow(hwnd, SW_RESTORE);
  8289. if (piei->nCmdShow)
  8290. ShowWindow(hwnd, piei->nCmdShow);
  8291. goto ReusedWindow;
  8292. }
  8293. else if (hres == E_PENDING)
  8294. goto ReusedWindow; // Assume it will come up sooner or later
  8295. }
  8296. // Okay, we're opening up a new window, let's honor
  8297. // the BrowseNewProcess flag, even though we lose
  8298. // other info (COF_EXPLORE, etc).
  8299. //
  8300. if (TryNewProcessIfNeeded(piei))
  8301. return TRUE;
  8302. if (((piei->uFlags & (COF_INPROC | COF_IEXPLORE)) == (COF_INPROC | COF_IEXPLORE)) &&
  8303. g_tidParking == 0)
  8304. {
  8305. // we're starting from iexplore.exe
  8306. g_tidParking = GetCurrentThreadId();
  8307. }
  8308. if (piei->pidl && IsURLChild(piei->pidl, TRUE))
  8309. piei->uFlags |= COF_IEXPLORE;
  8310. ASSERT(piei->punkRefProcess == NULL);
  8311. SHGetInstanceExplorer(&piei->punkRefProcess); // pick up the process ref (if any)
  8312. if (piei->uFlags & COF_INPROC)
  8313. {
  8314. BrowserProtectedThreadProc(piei);
  8315. fSuccess = TRUE;
  8316. }
  8317. else
  8318. {
  8319. #ifndef NO_MARSHALLING
  8320. DWORD idThread;
  8321. HANDLE hThread = CreateThread(NULL,
  8322. #ifdef DEBUG
  8323. 0, // on debug builds we inherit the default process stack size (so we can identify excessive stack usage)
  8324. #else
  8325. (1024 * 56), // we pre-allocate a 56k stack for browser windows
  8326. #endif
  8327. BrowserProtectedThreadProc,
  8328. piei,
  8329. CREATE_SUSPENDED,
  8330. &idThread);
  8331. if (hThread)
  8332. {
  8333. WinList_RegisterPending(idThread, piei->pidl, NULL, &piei->dwRegister);
  8334. ResumeThread(hThread);
  8335. CloseHandle(hThread);
  8336. fSuccess = TRUE;
  8337. }
  8338. else
  8339. {
  8340. SHDestroyIETHREADPARAM(piei);
  8341. }
  8342. #else
  8343. IEFrameNewWindowSameThread(piei);
  8344. #endif
  8345. }
  8346. return fSuccess;
  8347. ReusedWindow:
  8348. SHDestroyIETHREADPARAM(piei);
  8349. return TRUE;
  8350. }
  8351. //
  8352. // Notes: pidlNew will be freed
  8353. //
  8354. STDAPI SHOpenNewFrame(LPITEMIDLIST pidlNew, ITravelLog *ptl, DWORD dwBrowserIndex, UINT uFlags)
  8355. {
  8356. HRESULT hres;
  8357. IETHREADPARAM* piei = SHCreateIETHREADPARAM(NULL, SW_SHOWNORMAL, ptl, NULL);
  8358. if (piei)
  8359. {
  8360. hres = S_OK;
  8361. if (ptl)
  8362. piei->dwBrowserIndex = dwBrowserIndex;
  8363. if (pidlNew)
  8364. {
  8365. piei->pidl = pidlNew;
  8366. pidlNew = NULL;
  8367. }
  8368. piei->uFlags = uFlags;
  8369. if (!TryNewProcessIfNeeded(piei))
  8370. {
  8371. #ifndef NO_MARSHALLING
  8372. ASSERT(piei->punkRefProcess == NULL);
  8373. SHGetInstanceExplorer(&piei->punkRefProcess); // pick up the process ref (if any)
  8374. DWORD idThread;
  8375. HANDLE hThread = CreateThread(NULL,
  8376. #ifdef DEBUG
  8377. 0, // on debug builds we inherit the default process stack size (so we can identify excessive stack usage)
  8378. #else
  8379. (1024 * 56), // we pre-allocate a 56k stack for browser windows
  8380. #endif
  8381. BrowserProtectedThreadProc,
  8382. piei,
  8383. 0,
  8384. &idThread);
  8385. if (hThread)
  8386. {
  8387. // this handles removing this from the debug memory list of
  8388. // the opening thread.
  8389. CloseHandle(hThread);
  8390. }
  8391. else
  8392. {
  8393. SHDestroyIETHREADPARAM(piei);
  8394. hres = E_FAIL;
  8395. }
  8396. #else
  8397. IEFrameNewWindowSameThread(piei);
  8398. #endif
  8399. }
  8400. }
  8401. else
  8402. hres = E_OUTOFMEMORY;
  8403. ILFree(pidlNew);
  8404. return hres;
  8405. }
  8406. HRESULT CShellBrowser2::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
  8407. OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  8408. {
  8409. HRESULT hres = SUPERCLASS::QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  8410. if (pguidCmdGroup == NULL)
  8411. {
  8412. //
  8413. // If the curretly focused toolbar suppors the IOleCommandTarget
  8414. // ask it the status of clipboard commands.
  8415. // actually we should ask *both* ourselves (the active target)
  8416. // and then the view (the same way our IOCT::Exec does...)
  8417. //
  8418. if (_HasToolbarFocus())
  8419. {
  8420. LPTOOLBARITEM ptbi;
  8421. ptbi = _GetToolbarItem(_get_itbLastFocus());
  8422. if (ptbi && ptbi->ptbar)
  8423. {
  8424. IOleCommandTarget* pcmd;
  8425. HRESULT hresT = ptbi->ptbar->QueryInterface(
  8426. IID_IOleCommandTarget, (void**)&pcmd);
  8427. if (SUCCEEDED(hresT))
  8428. {
  8429. for (ULONG i = 0; i < cCmds; i++)
  8430. {
  8431. switch (rgCmds[i].cmdID)
  8432. {
  8433. case OLECMDID_CUT:
  8434. case OLECMDID_COPY:
  8435. case OLECMDID_PASTE:
  8436. pcmd->QueryStatus(pguidCmdGroup, 1, &rgCmds[i], pcmdtext);
  8437. break;
  8438. }
  8439. }
  8440. pcmd->Release();
  8441. }
  8442. }
  8443. }
  8444. }
  8445. else if (IsEqualGUID(CGID_ShellBrowser, *pguidCmdGroup))
  8446. {
  8447. if (pcmdtext) {
  8448. ASSERT(cCmds == 1);
  8449. switch (pcmdtext->cmdtextf)
  8450. {
  8451. case OLECMDTEXTF_NAME:
  8452. {
  8453. TOOLTIPTEXTA ttt = { NULL };
  8454. CHAR *pszBuffer = ttt.szText;
  8455. CHAR szTemp[MAX_TOOLTIP_STRING];
  8456. ttt.hdr.code = TTN_NEEDTEXTA;
  8457. ttt.hdr.idFrom = rgCmds[0].cmdID;
  8458. ttt.lpszText = ttt.szText;
  8459. OnNotify((LPNMHDR)&ttt);
  8460. if (ttt.hinst)
  8461. {
  8462. LoadStringA(ttt.hinst, (UINT) PtrToUlong(ttt.lpszText), szTemp, ARRAYSIZE(szTemp));
  8463. pszBuffer = szTemp;
  8464. }
  8465. else if (ttt.lpszText)
  8466. pszBuffer = ttt.lpszText;
  8467. pcmdtext->cwActual = SHAnsiToUnicode(pszBuffer, pcmdtext->rgwz, pcmdtext->cwBuf);
  8468. pcmdtext->cwActual -= 1;
  8469. hres = S_OK;
  8470. break;
  8471. }
  8472. default:
  8473. hres = E_FAIL;
  8474. break;
  8475. }
  8476. } else {
  8477. for (ULONG i = 0 ; i < cCmds ; i++) {
  8478. switch(rgCmds[i].cmdID) {
  8479. case FCIDM_PREVIOUSFOLDER:
  8480. if (_ShouldAllowNavigateParent())
  8481. rgCmds[i].cmdf |= OLECMDF_ENABLED;
  8482. else
  8483. rgCmds[i].cmdf &= OLECMDF_ENABLED;
  8484. hres = S_OK;
  8485. break;
  8486. }
  8487. }
  8488. }
  8489. }
  8490. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  8491. {
  8492. // should fill pcmdtext as well
  8493. for (ULONG i = 0 ; i < cCmds ; i++)
  8494. {
  8495. switch (rgCmds[i].cmdID)
  8496. {
  8497. case SBCMDID_SHOWCONTROL:
  8498. case SBCMDID_DOFAVORITESMENU:
  8499. case SBCMDID_ACTIVEOBJECTMENUS:
  8500. case SBCMDID_SETMERGEDWEBMENU:
  8501. rgCmds[i].cmdf = OLECMDF_ENABLED; // support these unconditionally
  8502. break;
  8503. case SBCMDID_DOMAILMENU:
  8504. rgCmds[i].cmdf = SHIsRegisteredClient(NEWS_DEF_KEY) || SHIsRegisteredClient(MAIL_DEF_KEY) ? OLECMDF_ENABLED : 0;
  8505. //If go menu is restricted, disable mail menu on toolbar also
  8506. if (SHRestricted2(REST_GoMenu, NULL, 0))
  8507. rgCmds[i].cmdf = 0;
  8508. break;
  8509. case SBCMDID_SEARCHBAR:
  8510. case SBCMDID_FAVORITESBAR:
  8511. case SBCMDID_HISTORYBAR:
  8512. case SBCMDID_EXPLORERBAR:
  8513. case SBCMDID_DISCUSSIONBAND:
  8514. case SBCMDID_MEDIABAR:
  8515. {
  8516. UINT idm;
  8517. rgCmds[i].cmdf |= OLECMDF_SUPPORTED|OLECMDF_ENABLED;
  8518. switch (rgCmds[i].cmdID) {
  8519. case SBCMDID_DISCUSSIONBAND:
  8520. {
  8521. // Perf: Avoid calling _InfoCLSIDToIdm unless we have loaded
  8522. // the band info already because it is very expensive!
  8523. if (_pbsmInfo && FCIDM_VBBNOHORIZONTALBAR != _idmComm)
  8524. {
  8525. idm = _InfoCLSIDToIdm(&CLSID_DiscussionBand);
  8526. if (idm == -1)
  8527. {
  8528. // The discussion band is not registered
  8529. ClearFlag(rgCmds[i].cmdf, OLECMDF_SUPPORTED|OLECMDF_ENABLED);
  8530. }
  8531. else if (idm == _idmComm)
  8532. {
  8533. rgCmds[i].cmdf |= OLECMDF_LATCHED;
  8534. }
  8535. }
  8536. else
  8537. {
  8538. //
  8539. // Since the band info has not been loaded or idmComm is FCIDM_VBBNONE,
  8540. // we know that the discussion band is not up and is not latched. So
  8541. // we can check the registry instead and avoid defer the cost of
  8542. // initializing _pbsmInfo
  8543. //
  8544. // See if the discussions band is registered for the CATID_CommBand
  8545. idm = -1;
  8546. HKEY hkey = NULL;
  8547. static BOOL fDiscussionBand = -1;
  8548. // We get called a lot, so only read the registry once.
  8549. if (-1 == fDiscussionBand)
  8550. {
  8551. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, c_szDiscussionBandReg, NULL, KEY_READ, &hkey) == ERROR_SUCCESS)
  8552. {
  8553. // We found the discussions band
  8554. fDiscussionBand = 1;
  8555. RegCloseKey(hkey);
  8556. }
  8557. else
  8558. {
  8559. fDiscussionBand = 0;
  8560. }
  8561. }
  8562. if (!fDiscussionBand)
  8563. {
  8564. // The discussions band is not registered
  8565. ClearFlag(rgCmds[i].cmdf, OLECMDF_SUPPORTED|OLECMDF_ENABLED);
  8566. }
  8567. }
  8568. break;
  8569. }
  8570. case SBCMDID_SEARCHBAR: idm=FCIDM_VBBSEARCHBAND ; break;
  8571. case SBCMDID_FAVORITESBAR:
  8572. idm=FCIDM_VBBFAVORITESBAND;
  8573. if (SHRestricted2(REST_NoFavorites, NULL, 0))
  8574. ClearFlag(rgCmds[i].cmdf, OLECMDF_ENABLED);
  8575. break;
  8576. case SBCMDID_HISTORYBAR: idm=FCIDM_VBBHISTORYBAND ; break;
  8577. case SBCMDID_EXPLORERBAR: idm=FCIDM_VBBEXPLORERBAND ; break;
  8578. case SBCMDID_MEDIABAR: idm=FCIDM_VBBMEDIABAND ; break;
  8579. default:
  8580. ASSERT(FALSE);
  8581. return E_FAIL;
  8582. }
  8583. if (idm == _idmInfo)
  8584. rgCmds[i].cmdf |= OLECMDF_LATCHED;
  8585. break;
  8586. }
  8587. }
  8588. }
  8589. hres = S_OK;
  8590. }
  8591. return hres;
  8592. }
  8593. // REARCHITECT (980710 adp) should clean up to do consistent routing. this
  8594. // ad-hoc per-nCmdID stuff is too error-prone.
  8595. HRESULT CShellBrowser2::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
  8596. VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  8597. {
  8598. if (pguidCmdGroup == NULL)
  8599. {
  8600. switch (nCmdID)
  8601. {
  8602. case OLECMDID_SETTITLE:
  8603. // NT #282632: This bug is caused when the current IShellView is a web page and
  8604. // the pending view is a shell folder w/Web View that has certain timing charataristics.
  8605. // MSHTML from the Web View will fire OLECMDID_SETTITLE with the URL of the
  8606. // web view template. The problem is that there is a bug in IE4 SI's shell32
  8607. // that let that message go to the browser (here), even though the view wasn't
  8608. // active. Since we don't know who it came from, we forward it down to the current
  8609. // view who squirls away the title. This title is then given in the Back toolbar
  8610. // button drop down history. This is hack around the IE4 SI shell32 bug is to kill
  8611. // that message. -BryanSt
  8612. TraceMsg(DM_TRACE, "csb.e: SetTitle is called");
  8613. break; // continue.
  8614. // Clipboard commands and common operations will be dispatched
  8615. // to the currently focused toolbar.
  8616. case OLECMDID_CUT:
  8617. case OLECMDID_COPY:
  8618. case OLECMDID_PASTE:
  8619. case OLECMDID_DELETE:
  8620. case OLECMDID_PROPERTIES:
  8621. if (_HasToolbarFocus()) {
  8622. LPTOOLBARITEM ptbi;
  8623. if (ptbi = _GetToolbarItem(_get_itbLastFocus()))
  8624. {
  8625. HRESULT hres = IUnknown_Exec(ptbi->ptbar, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8626. if (SUCCEEDED(hres))
  8627. return hres;
  8628. }
  8629. }
  8630. break; // give the view a chance
  8631. }
  8632. }
  8633. else if (IsEqualGUID(CGID_DefView, *pguidCmdGroup))
  8634. {
  8635. switch (nCmdID)
  8636. {
  8637. case DVID_RESETDEFAULT:
  8638. // 99/02/09 #226140 vtan: Exec command issued from
  8639. // CFolderOptionsPsx::ResetDefFolderSettings()
  8640. // when user clicks "Reset All Folders" in folder
  8641. // options "View" tab. Pass this thru to DefView.
  8642. ASSERTMSG(nCmdexecopt == OLECMDEXECOPT_DODEFAULT, "nCmdexecopt must be OLECMDEXECOPT_DODEFAULT");
  8643. ASSERTMSG(pvarargIn == NULL, "pvarargIn must be NULL");
  8644. ASSERTMSG(pvarargOut == NULL, "pvarargOut must be NULL");
  8645. IUnknown_Exec(_pbbd->_psv, &CGID_DefView, DVID_RESETDEFAULT, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
  8646. return(S_OK);
  8647. break;
  8648. default:
  8649. break;
  8650. }
  8651. }
  8652. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  8653. {
  8654. switch (nCmdID)
  8655. {
  8656. #ifdef UNIX
  8657. case SBCMDID_MSGBAND:
  8658. if (_pbbd->_hwnd)
  8659. {
  8660. pvarargOut->vt = VT_I4;
  8661. pvarargOut->lVal = (LONG)_pbbd->_hwnd;
  8662. return S_OK;
  8663. }
  8664. return S_FALSE;
  8665. #endif
  8666. case SBCMDID_MAYSAVEVIEWSTATE:
  8667. return _fDontSaveViewOptions ? S_FALSE : S_OK; // May need to save out earlier...
  8668. case SBCMDID_CANCELANDCLOSE:
  8669. _CancelPendingNavigationAsync();
  8670. PostMessage(_pbbd->_hwnd, WM_CLOSE, 0, 0);
  8671. return S_OK;
  8672. case SBCMDID_CANCELNAVIGATION:
  8673. //
  8674. // Special code to close the window if the very first navigation caused
  8675. // an asynchronous download (e.g. from athena).
  8676. //
  8677. if (!_pbbd->_pidlCur && pvarargIn && pvarargIn->vt == VT_I4 && pvarargIn->lVal == FALSE)
  8678. {
  8679. _CancelPendingNavigationAsync();
  8680. PostMessage(_pbbd->_hwnd, WM_CLOSE, 0, 0);
  8681. return S_OK;
  8682. }
  8683. break; // fall through
  8684. case SBCMDID_MIXEDZONE:
  8685. _UpdateZonesPane(pvarargIn);
  8686. break;
  8687. case SBCMDID_ISIEMODEBROWSER:
  8688. return v_IsIEModeBrowser() ? S_OK : S_FALSE;
  8689. case SBCMDID_STARTEDFORINTERNET:
  8690. return _fInternetStart ? S_OK : S_FALSE;
  8691. case SBCMDID_ISBROWSERACTIVE:
  8692. return _fActivated ? S_OK : S_FALSE;
  8693. case SBCMDID_SUGGESTSAVEWINPOS:
  8694. if (_ShouldSaveWindowPlacement())
  8695. {
  8696. StorePlacementOfWindow(_pbbd->_hwnd);
  8697. return S_OK;
  8698. }
  8699. return S_FALSE;
  8700. case SBCMDID_ONVIEWMOVETOTOP:
  8701. if (_ptheater)
  8702. {
  8703. return _ptheater->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8704. }
  8705. return S_FALSE;
  8706. }
  8707. }
  8708. else if (IsEqualGUID(CGID_MenuBandHandler, *pguidCmdGroup))
  8709. {
  8710. switch (nCmdID)
  8711. {
  8712. case MBHANDCID_PIDLSELECT:
  8713. {
  8714. LPITEMIDLIST pidl = VariantToIDList(pvarargIn);
  8715. if (pidl)
  8716. {
  8717. if (!ILIsEmpty(pidl))
  8718. {
  8719. if (_pidlMenuSelect)
  8720. KillTimer(_pbbd->_hwnd, SHBTIMER_MENUSELECT);
  8721. // Opening the favorites' shortcuts can be slow. So set a
  8722. // timer so we don't open needlessly as the mouse runs over
  8723. // the menu quickly.
  8724. if (Pidl_Set(&_pidlMenuSelect, pidl))
  8725. {
  8726. if (!SetTimer(_pbbd->_hwnd, SHBTIMER_MENUSELECT, MENUSELECT_TIME, NULL))
  8727. Pidl_Set(&_pidlMenuSelect, NULL);
  8728. }
  8729. }
  8730. ILFree(pidl);
  8731. }
  8732. }
  8733. return S_OK;
  8734. }
  8735. }
  8736. else if (IsEqualGUID(CGID_MenuBand, *pguidCmdGroup))
  8737. {
  8738. switch (nCmdID)
  8739. {
  8740. case MBANDCID_EXITMENU:
  8741. // we're done with the menu band (favorites)
  8742. // kill the timer
  8743. // this is to fix bug #61917 where the status bar would get stack
  8744. // in the simple mode (actually the timer would go off after we
  8745. // navigated to the page with the proper status bar mode, but then
  8746. // we would call _DisplayFavoriteStatus that would put it back in
  8747. // the simple mode)
  8748. if (_pidlMenuSelect)
  8749. KillTimer(_pbbd->_hwnd, SHBTIMER_MENUSELECT);
  8750. return S_OK;
  8751. }
  8752. }
  8753. else if (IsEqualGUID(CGID_FilterObject, *pguidCmdGroup))
  8754. {
  8755. HRESULT hres = E_INVALIDARG;
  8756. switch (nCmdID)
  8757. {
  8758. case PHID_FilterOutPidl:
  8759. {
  8760. LPITEMIDLIST pidl = VariantToIDList(pvarargIn);
  8761. if (pidl)
  8762. {
  8763. // We are filtering out everything except folders, shortcuts, and
  8764. // internet shortcuts
  8765. DWORD dwAttribs = SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_LINK;
  8766. // include everthing by default
  8767. VariantClearLazy(pvarargOut);
  8768. pvarargOut->vt = VT_BOOL;
  8769. pvarargOut->boolVal = VARIANT_FALSE;
  8770. IEGetAttributesOf(pidl, &dwAttribs);
  8771. // include all non file system objects, folders and links
  8772. // (non file system things like the Channel folders contents)
  8773. if (!(dwAttribs & (SFGAO_FOLDER | SFGAO_LINK)) &&
  8774. (dwAttribs & SFGAO_FILESYSTEM))
  8775. pvarargOut->boolVal = VARIANT_TRUE; // don't include
  8776. hres = S_OK;
  8777. ILFree(pidl);
  8778. }
  8779. }
  8780. break;
  8781. default:
  8782. TraceMsg(TF_WARNING, "csb.e: Received unknown CGID_FilterObject cmdid (%d)", nCmdID);
  8783. break;
  8784. }
  8785. return hres;
  8786. }
  8787. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  8788. {
  8789. switch (nCmdID)
  8790. {
  8791. // we reflect AMBIENTPROPCHANGE down because this is how iedisp notifies dochost
  8792. // that an ambient property has changed. we don't need to reflect this down in
  8793. // cwebbrowsersb because only the top-level iwebbrowser2 is allowed to change props
  8794. case SHDVID_AMBIENTPROPCHANGE:
  8795. case SHDVID_PRINTFRAME:
  8796. case SHDVID_MIMECSETMENUOPEN:
  8797. case SHDVID_FONTMENUOPEN:
  8798. if (pvarargIn)
  8799. {
  8800. if ((VT_I4 == pvarargIn->vt) && (DISPID_AMBIENT_OFFLINEIFNOTCONNECTED == pvarargIn->lVal))
  8801. {
  8802. VARIANT_BOOL fIsOffline;
  8803. if (_pbbd->_pautoWB2)
  8804. {
  8805. _pbbd->_pautoWB2->get_Offline(&fIsOffline);
  8806. if (fIsOffline)
  8807. {
  8808. // this top level frame just went Offline
  8809. // - so decr net session count
  8810. _DecrNetSessionCount();
  8811. }
  8812. else
  8813. {
  8814. // this top level frame went online.
  8815. _IncrNetSessionCount();
  8816. }
  8817. }
  8818. }
  8819. }
  8820. break;
  8821. }
  8822. }
  8823. HRESULT hres = SUPERCLASS::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8824. if (pguidCmdGroup == NULL)
  8825. {
  8826. DefaultCommandGroup:
  8827. switch (nCmdID)
  8828. {
  8829. case OLECMDID_REFRESH:
  8830. // FolderOptions.Advanced refreshes all browser windows
  8831. _UpdateRegFlags();
  8832. _SetTitle(NULL); // maybe "full path in title bar" changed
  8833. v_ShowHideChildWindows(FALSE);
  8834. // pass this to the browserbar
  8835. IDeskBar* pdb;
  8836. FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pdb));
  8837. if (pdb)
  8838. {
  8839. IUnknown_Exec(pdb, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8840. pdb->Release();
  8841. }
  8842. hres = S_OK;
  8843. break;
  8844. }
  8845. }
  8846. else if (IsEqualGUID(CGID_ShellBrowser, *pguidCmdGroup))
  8847. {
  8848. // toolbar buttons we put there ourselves
  8849. hres = S_OK; // assume accepted
  8850. switch (nCmdID)
  8851. {
  8852. case FCIDM_PREVIOUSFOLDER:
  8853. v_ParentFolder();
  8854. break;
  8855. case FCIDM_CONNECT:
  8856. DoNetConnect(_pbbd->_hwnd);
  8857. break;
  8858. case FCIDM_DISCONNECT:
  8859. DoNetDisconnect(_pbbd->_hwnd);
  8860. break;
  8861. case FCIDM_GETSTATUSBAR:
  8862. if (pvarargOut->vt == VT_I4)
  8863. pvarargOut->lVal = _fStatusBar;
  8864. break;
  8865. case FCIDM_SETSTATUSBAR:
  8866. if (pvarargIn->vt == VT_I4)
  8867. {
  8868. _fStatusBar = pvarargIn->lVal;
  8869. v_ShowHideChildWindows(FALSE);
  8870. }
  8871. break;
  8872. case FCIDM_PERSISTTOOLBAR:
  8873. _SaveITbarLayout();
  8874. break;
  8875. default:
  8876. // pass off the nCmdID to the view for processing / translation.
  8877. DFVCMDDATA cd;
  8878. cd.pva = pvarargIn;
  8879. cd.hwnd = _pbbd->_hwnd;
  8880. cd.nCmdIDTranslated = 0;
  8881. SendMessage(_pbbd->_hwndView, WM_COMMAND, nCmdID, (LONG_PTR)&cd);
  8882. if (cd.nCmdIDTranslated)
  8883. {
  8884. // We sent the private nCmdID to the view. The view did not
  8885. // process it (probably because it didn't have the focus),
  8886. // but instead translated it into a standard OLECMDID for
  8887. // further processing by the toolbar with the focus.
  8888. pguidCmdGroup = NULL;
  8889. nCmdID = cd.nCmdIDTranslated;
  8890. hres = OLECMDERR_E_NOTSUPPORTED;
  8891. goto DefaultCommandGroup;
  8892. }
  8893. break;
  8894. }
  8895. }
  8896. else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup))
  8897. {
  8898. // these are commands to intercept
  8899. if (_HasToolbarFocus() && _get_itbLastFocus() != ITB_ITBAR)
  8900. {
  8901. int idCmd = -1;
  8902. // certain shell commands we should pick off
  8903. switch (nCmdID)
  8904. {
  8905. case OLECMDID_DELETE:
  8906. case SFVIDM_FILE_DELETE:
  8907. idCmd = FCIDM_DELETE;
  8908. break;
  8909. case OLECMDID_PROPERTIES:
  8910. case SFVIDM_FILE_PROPERTIES:
  8911. idCmd = FCIDM_PROPERTIES;
  8912. break;
  8913. case OLECMDID_CUT:
  8914. case SFVIDM_EDIT_CUT:
  8915. idCmd = FCIDM_MOVE;
  8916. break;
  8917. case OLECMDID_COPY:
  8918. case SFVIDM_EDIT_COPY:
  8919. idCmd = FCIDM_COPY;
  8920. break;
  8921. case OLECMDID_PASTE:
  8922. case SFVIDM_EDIT_PASTE:
  8923. idCmd = FCIDM_PASTE;
  8924. break;
  8925. }
  8926. if (idCmd != -1)
  8927. {
  8928. OnCommand(GET_WM_COMMAND_MPS(idCmd, 0, NULL));
  8929. return S_OK;
  8930. }
  8931. }
  8932. }
  8933. else if (IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
  8934. {
  8935. return IUnknown_Exec(_GetITBar(), pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  8936. }
  8937. else if (IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
  8938. {
  8939. hres = S_OK; // assume we will get it
  8940. switch(nCmdID)
  8941. {
  8942. case SBCMDID_SETMERGEDWEBMENU:
  8943. if (!_hmenuPreMerged)
  8944. _hmenuPreMerged = _MenuTemplate(MENU_PREMERGED, FALSE);
  8945. if (SHRestricted2W(REST_NoHelpMenu, NULL, 0))
  8946. {
  8947. DeleteMenu(_hmenuPreMerged, FCIDM_MENU_HELP, MF_BYCOMMAND);
  8948. }
  8949. SetMenuSB(_hmenuPreMerged, NULL, NULL);
  8950. if (pvarargOut) {
  8951. pvarargOut->vt = VT_INT_PTR;
  8952. pvarargOut->byref = _hmenuPreMerged;
  8953. }
  8954. break;
  8955. case SBCMDID_ACTIVEOBJECTMENUS:
  8956. _fDispatchMenuMsgs = TRUE;
  8957. break;
  8958. case SBCMDID_SENDPAGE:
  8959. case SBCMDID_SENDSHORTCUT:
  8960. _SendCurrentPage(nCmdID == SBCMDID_SENDPAGE ? FORCE_COPY : FORCE_LINK);
  8961. break;
  8962. case SBCMDID_SEARCHBAR:
  8963. case SBCMDID_FAVORITESBAR:
  8964. case SBCMDID_HISTORYBAR:
  8965. case SBCMDID_EXPLORERBAR:
  8966. case SBCMDID_DISCUSSIONBAND:
  8967. case SBCMDID_MEDIABAR:
  8968. {
  8969. UINT idm;
  8970. switch (nCmdID)
  8971. {
  8972. case SBCMDID_SEARCHBAR: idm = FCIDM_VBBSEARCHBAND ; break;
  8973. case SBCMDID_FAVORITESBAR: idm = FCIDM_VBBFAVORITESBAND ; break;
  8974. case SBCMDID_HISTORYBAR: idm = FCIDM_VBBHISTORYBAND ; break;
  8975. case SBCMDID_EXPLORERBAR: idm = FCIDM_VBBEXPLORERBAND ; break;
  8976. case SBCMDID_MEDIABAR: idm = FCIDM_VBBMEDIABAND ; break;
  8977. // The discussion band maps to one of the dynamic bands
  8978. case SBCMDID_DISCUSSIONBAND: idm = _InfoCLSIDToIdm(&CLSID_DiscussionBand) ; break;
  8979. default: idm = -1; break;
  8980. }
  8981. if (idm != -1)
  8982. {
  8983. // default is toggle (-1)
  8984. int i = (pvarargIn && EVAL(pvarargIn->vt == VT_I4)) ? pvarargIn->lVal : -1;
  8985. LPITEMIDLIST pidl = VariantToIDList(pvarargOut); // accepts null variant input
  8986. _SetBrowserBarState(idm, NULL, i, pidl);
  8987. ILFree(pidl); // accepts NULL
  8988. }
  8989. hres = S_OK;
  8990. break;
  8991. }
  8992. case SBCMDID_SHOWCONTROL:
  8993. {
  8994. DWORD dwRet;
  8995. int iControl, iCmd;
  8996. if (nCmdexecopt == OLECMDEXECOPT_DODEFAULT &&
  8997. pvarargIn &&
  8998. pvarargIn->vt == VT_I4)
  8999. {
  9000. iControl = (int)(short)LOWORD(pvarargIn->lVal);
  9001. iCmd = (int)(short)HIWORD(pvarargIn->lVal);
  9002. }
  9003. else
  9004. {
  9005. iControl = (int)(short)LOWORD(nCmdexecopt);
  9006. iCmd = (HIWORD(nCmdexecopt) ? SBSC_SHOW : SBSC_HIDE);
  9007. }
  9008. dwRet = v_ShowControl(iControl, iCmd);
  9009. if (dwRet == (DWORD)-1)
  9010. break;
  9011. if (pvarargOut)
  9012. {
  9013. pvarargOut->vt = VT_I4;
  9014. pvarargOut->lVal = dwRet;
  9015. }
  9016. break;
  9017. }
  9018. case SBCMDID_DOFAVORITESMENU:
  9019. case SBCMDID_DOMAILMENU:
  9020. {
  9021. HMENU hmenu = NULL;
  9022. if (nCmdID == SBCMDID_DOFAVORITESMENU)
  9023. {
  9024. HMENU hmenuWnd = NULL;
  9025. IShellMenu* psm;
  9026. if (SUCCEEDED(_pmb->QueryInterface(IID_PPV_ARG(IShellMenu, &psm))))
  9027. {
  9028. psm->GetMenu(&hmenuWnd, NULL, NULL);
  9029. psm->Release();
  9030. }
  9031. if (hmenuWnd)
  9032. {
  9033. hmenu = SHGetMenuFromID(hmenuWnd, FCIDM_MENU_FAVORITES);
  9034. }
  9035. }
  9036. else
  9037. hmenu = LoadMenuPopup(MENU_MAILNEWS);
  9038. if (hmenu)
  9039. {
  9040. if (pvarargIn && pvarargIn->vt == VT_I4)
  9041. {
  9042. TrackPopupMenu(hmenu, 0,
  9043. GET_X_LPARAM(pvarargIn->lVal), GET_Y_LPARAM(pvarargIn->lVal),
  9044. 0, _GetCaptionWindow(), NULL);
  9045. }
  9046. if (nCmdID == SBCMDID_DOMAILMENU)
  9047. DestroyMenu(hmenu);
  9048. }
  9049. }
  9050. break;
  9051. case SBCMDID_SELECTHISTPIDL:
  9052. {
  9053. // remember most recent hist pidl. if we have history band visible, tell it
  9054. // the hist pidl. if the band is not visible, it is it's responsibility to
  9055. // query the most recent hist pidl via SBCMDID_GETHISTPIDL
  9056. // the semantics of the call from UrlStorage is that if we respond S_OK to
  9057. // to this command, we take ownership of pidl and must ILFree it.
  9058. // when we call the band, on the other hand, they must ILClone it if they want
  9059. // to use it outside of the Exec call.
  9060. if (_pidlLastHist)
  9061. {
  9062. ILFree(_pidlLastHist);
  9063. _pidlLastHist = NULL;
  9064. }
  9065. _pidlLastHist = VariantToIDList(pvarargIn); // take ownership
  9066. if (_poctNsc)
  9067. {
  9068. _poctNsc->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  9069. }
  9070. }
  9071. break;
  9072. case SBCMDID_GETHISTPIDL:
  9073. if (pvarargOut) {
  9074. VariantClearLazy(pvarargOut);
  9075. if (_pidlLastHist)
  9076. {
  9077. InitVariantFromIDList(pvarargOut, _pidlLastHist);
  9078. }
  9079. }
  9080. break;
  9081. case SBCMDID_UNREGISTERNSCBAND:
  9082. if (pvarargIn && pvarargIn->vt == VT_UNKNOWN && pvarargIn->punkVal)
  9083. {
  9084. if (_poctNsc && SHIsSameObject(_poctNsc, pvarargIn->punkVal))
  9085. {
  9086. ATOMICRELEASE(_poctNsc);
  9087. IUnknown_SetSite(_pcmNsc, NULL);
  9088. ATOMICRELEASE(_pcmNsc);
  9089. }
  9090. }
  9091. break;
  9092. case SBCMDID_REGISTERNSCBAND:
  9093. ATOMICRELEASE(_poctNsc);
  9094. IUnknown_SetSite(_pcmNsc, NULL);
  9095. ATOMICRELEASE(_pcmNsc);
  9096. if (pvarargIn && pvarargIn->vt == VT_UNKNOWN && pvarargIn->punkVal)
  9097. {
  9098. pvarargIn->punkVal->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &_poctNsc));
  9099. }
  9100. break;
  9101. case SBCMDID_TOOLBAREMPTY:
  9102. if (pvarargIn && VT_UNKNOWN == pvarargIn->vt && pvarargIn->punkVal)
  9103. {
  9104. if (_IsSameToolbar(INFOBAR_TBNAME, pvarargIn->punkVal))
  9105. _SetBrowserBarState(_idmInfo, NULL, 0);
  9106. else if (_IsSameToolbar(COMMBAR_TBNAME, pvarargIn->punkVal))
  9107. _SetBrowserBarState(_idmComm, NULL, 0);
  9108. else
  9109. _HideToolbar(pvarargIn->punkVal);
  9110. }
  9111. break;
  9112. case SBCMDID_GETTEMPLATEMENU:
  9113. if (pvarargOut)
  9114. {
  9115. pvarargOut->vt = VT_INT_PTR;
  9116. pvarargOut->byref = (LPVOID)_hmenuTemplate;
  9117. }
  9118. break;
  9119. case SBCMDID_GETCURRENTMENU:
  9120. if (pvarargOut)
  9121. {
  9122. pvarargOut->vt = VT_INT_PTR;
  9123. pvarargOut->byref = (LPVOID)_hmenuCur;
  9124. }
  9125. break;
  9126. default:
  9127. //
  9128. // Note that we should return hres from the super class as-is.
  9129. //
  9130. // hres = OLECMDERR_E_NOTSUPPORTED;
  9131. break;
  9132. }
  9133. }
  9134. else if (IsEqualGUID(CGID_ShellDocView, *pguidCmdGroup))
  9135. {
  9136. switch(nCmdID)
  9137. {
  9138. case SHDVID_GETSYSIMAGEINDEX:
  9139. pvarargOut->vt = VT_I4;
  9140. pvarargOut->lVal = _GetIconIndex();
  9141. hres = (pvarargOut->lVal==-1) ? E_FAIL : S_OK;
  9142. break;
  9143. case SHDVID_HELP:
  9144. SHHtmlHelpOnDemandWrap(_pbbd->_hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, 0, ML_CROSSCODEPAGE);
  9145. hres = S_OK;
  9146. break;
  9147. case SHDVID_GETBROWSERBAR:
  9148. {
  9149. const CLSID *pclsid = _InfoIdmToCLSID(_idmInfo);
  9150. // kinda strange to (ab-)use checked menu items as
  9151. // state marker to persist the CLSID between Exec calls (applies also to SHDVID_NAVIGATEBBTOURL below)!!
  9152. // but that's how both SHDVID_GETBROWSERBAR and SHDVID_NAVIGATEBBTOURL are called
  9153. //
  9154. // assume that the currently checked menu points to the explorer bar
  9155. // this navigate to URL is aimed to.
  9156. // Currently Trident's NavigateInBand is the only caller
  9157. // using this command; it calls SHDVID_GETBROWSERBAR first and thus set the _idmInfo
  9158. IBandSite *pbs;
  9159. hres = E_FAIL;
  9160. VariantInit(pvarargOut);
  9161. _GetBrowserBar(IDBAR_VERTICAL, TRUE, &pbs, pclsid);
  9162. if (pbs)
  9163. {
  9164. IDeskBand *pband = _GetInfoBandBS(pbs, *pclsid);
  9165. if (pband)
  9166. {
  9167. pvarargOut->vt = VT_UNKNOWN;
  9168. pvarargOut->punkVal = pband;
  9169. hres = S_OK;
  9170. }
  9171. pbs->Release();
  9172. }
  9173. break;
  9174. }
  9175. case SHDVID_SHOWBROWSERBAR:
  9176. {
  9177. CLSID *pclsid;
  9178. CLSID guid;
  9179. if (pvarargIn->vt == VT_BSTR)
  9180. {
  9181. if (SUCCEEDED(IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_VIEWEXTERNALBAND_BYCLASSID, nCmdexecopt, pvarargIn, NULL)))
  9182. {
  9183. hres = S_OK;
  9184. break;
  9185. }
  9186. // external (can marshal)
  9187. if (!GUIDFromString(pvarargIn->bstrVal, &guid))
  9188. return S_OK; // Invalid CLSID; IE5 returned S_OK so I guess it's ok
  9189. pclsid = &guid;
  9190. }
  9191. else if (pvarargIn->vt == VT_INT_PTR)
  9192. {
  9193. // internal (can't marshal)
  9194. ASSERT(0); // dead code? let's make sure...
  9195. TraceMsg(TF_WARNING, "csb.e: SHDVID_SHOWBROWSERBAR clsid !marshall (!)");
  9196. pclsid = (CLSID *) (pvarargIn->byref);
  9197. }
  9198. else
  9199. {
  9200. ASSERT(0);
  9201. pclsid = NULL;
  9202. break;
  9203. }
  9204. // enforce mediabar restriction: even though menu and toolbar have MediaBar disabled, resp. removed
  9205. // user can still launch thru targeting _media or when mediabar was last open explorer bar before restriction is set
  9206. if ( IsEqualIID(*pclsid, CLSID_MediaBand)
  9207. && SHRestricted2(REST_No_LaunchMediaBar, NULL, 0) )
  9208. {
  9209. hres = E_ACCESSDENIED;
  9210. pclsid = NULL;
  9211. break;
  9212. }
  9213. _SetBrowserBarState(-1, pclsid, nCmdexecopt ? 1 : 0);
  9214. hres = S_OK;
  9215. break;
  9216. }
  9217. case SHDVID_ISBROWSERBARVISIBLE:
  9218. // Quickly return false if both bars are hidden
  9219. hres = S_FALSE;
  9220. if (_idmComm != FCIDM_VBBNOHORIZONTALBAR || _idmInfo != FCIDM_VBBNOVERTICALBAR)
  9221. {
  9222. if (pvarargIn->vt == VT_BSTR)
  9223. {
  9224. // Get the associated id
  9225. CLSID clsid;
  9226. if (GUIDFromString(pvarargIn->bstrVal, &clsid))
  9227. {
  9228. UINT idm = _InfoCLSIDToIdm(&clsid);
  9229. if (_idmComm == idm || _idmInfo == idm)
  9230. {
  9231. // It's visible!
  9232. hres = S_OK;
  9233. }
  9234. }
  9235. }
  9236. }
  9237. return hres;
  9238. case SHDVID_ISEXPLORERBARVISIBLE:
  9239. hres = (_idmInfo != FCIDM_VBBNOVERTICALBAR) ? S_OK : S_FALSE;
  9240. return hres;
  9241. case SHDVID_NAVIGATEBB:
  9242. {
  9243. LPITEMIDLIST pidl = VariantToIDList(pvarargIn);
  9244. if (pidl)
  9245. {
  9246. if (!ILIsEmpty(pidl))
  9247. {
  9248. IBandSite * pbs;
  9249. const CLSID * pclsid = _InfoIdmToCLSID(_idmInfo);
  9250. _GetBrowserBar(IDBAR_VERTICAL, TRUE, &pbs, pclsid);
  9251. if (pbs)
  9252. {
  9253. IDeskBand *pband = _GetInfoBandBS(pbs, *pclsid);
  9254. if (pband)
  9255. {
  9256. IBandNavigate *pbn;
  9257. pband->QueryInterface(IID_PPV_ARG(IBandNavigate, &pbn));
  9258. if (pbn)
  9259. {
  9260. pbn->Select(pidl);
  9261. pbn->Release();
  9262. }
  9263. pband->Release();
  9264. }
  9265. pbs->Release();
  9266. }
  9267. hres = S_OK;
  9268. }
  9269. ILFree(pidl);
  9270. }
  9271. break;
  9272. }
  9273. case SHDVID_NAVIGATEBBTOURL:
  9274. {
  9275. const CLSID *pclsid = _InfoIdmToCLSID(_idmInfo);
  9276. if ( IsEqualIID(*pclsid, CLSID_MediaBand)
  9277. && SHRegGetBoolUSValue(REG_MEDIA_STR, TEXT("SuppressOnlineContent"), FALSE, FALSE))
  9278. {
  9279. hres = E_FAIL;
  9280. break;
  9281. }
  9282. LPITEMIDLIST pidl;
  9283. hres = IEParseDisplayNameWithBCW(CP_ACP, V_BSTR(pvarargIn), NULL, &pidl);
  9284. if (!hres && pidl && !ILIsEmpty(pidl))
  9285. {
  9286. // see comments in SHDVID_GETBROWSERBAR above!
  9287. //
  9288. // assume that the currently checked menu points to the explorer bar
  9289. // this navigate to URL is aimed to.
  9290. // Currently Trident's NavigateInBand is the only caller
  9291. // using this command; it calls SHDVID_GETBROWSERBAR first and thus set the _idmInfo
  9292. IBandSite *pbs;
  9293. _GetBrowserBar(IDBAR_VERTICAL, TRUE, &pbs, pclsid);
  9294. if (pbs)
  9295. {
  9296. IDeskBand *pband = _GetInfoBandBS(pbs, *pclsid);
  9297. if (pband)
  9298. {
  9299. //
  9300. // See if we can use ISearchBandTBHelper which has a "truer" navigate
  9301. // method.
  9302. //
  9303. ISearchBandTBHelper * pSearchBandTBHelper = NULL;
  9304. pband->QueryInterface(IID_ISearchBandTBHelper, (void**)&pSearchBandTBHelper);
  9305. if (pSearchBandTBHelper)
  9306. {
  9307. pSearchBandTBHelper->NavigateToPidl(pidl);
  9308. pSearchBandTBHelper->Release();
  9309. }
  9310. else
  9311. {
  9312. //
  9313. // Probably a different band. See if it implements
  9314. // IBandNavigate
  9315. //
  9316. IBandNavigate * pbn = NULL;
  9317. pband->QueryInterface(IID_PPV_ARG(IBandNavigate, &pbn));
  9318. if (pbn)
  9319. {
  9320. pbn->Select(pidl);
  9321. pbn->Release();
  9322. }
  9323. pband->Release();
  9324. }
  9325. }
  9326. pbs->Release();
  9327. }
  9328. ILFree(pidl);
  9329. }
  9330. break;
  9331. }
  9332. case SHDVID_CLSIDTOIDM:
  9333. ASSERT(pvarargIn && pvarargIn->vt == VT_BSTR && pvarargOut);
  9334. CLSID clsid;
  9335. GUIDFromString(pvarargIn->bstrVal, &clsid);
  9336. pvarargOut->vt = VT_I4;
  9337. pvarargOut->lVal = _InfoCLSIDToIdm(&clsid);
  9338. hres = S_OK;
  9339. break;
  9340. }
  9341. }
  9342. else if (IsEqualGUID(CGID_Theater, *pguidCmdGroup))
  9343. {
  9344. if (_ptheater)
  9345. hres = _ptheater->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  9346. }
  9347. else if (IsEqualGUID(CGID_ExplorerBarDoc, *pguidCmdGroup))
  9348. {
  9349. // These are commands that should be applied to all the explorer bar bands. for example
  9350. // to reflect font size changes to the search band. they should be applied to the
  9351. // contained doc object, changing guid to CGID_MSTHML
  9352. _ExecAllBands(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  9353. }
  9354. else if (IsEqualGUID(CGID_DocHostCmdPriv, *pguidCmdGroup))
  9355. {
  9356. switch(nCmdID)
  9357. {
  9358. // This command is sent by Trident when
  9359. // navigating in a shell view.
  9360. //
  9361. case DOCHOST_DOCHYPERLINK: // Sent by Trident when in a shell view.
  9362. hres = E_FAIL;
  9363. if (VT_BSTR == V_VT(pvarargIn))
  9364. {
  9365. LPITEMIDLIST pidl = NULL;
  9366. hres = IEParseDisplayNameWithBCW(CP_ACP, V_BSTR(pvarargIn), NULL, &pidl);
  9367. if (pidl)
  9368. {
  9369. hres = BrowseObject(pidl, SBSP_SAMEBROWSER);
  9370. ILFree(pidl);
  9371. }
  9372. }
  9373. break;
  9374. default:
  9375. break;
  9376. }
  9377. }
  9378. return hres;
  9379. }
  9380. //*** _IsSameToolbar -- does punkBar have specified name?
  9381. // ENTRY/EXIT
  9382. // fRet TRUE if matches, o.w. FALSE
  9383. //
  9384. BOOL CShellBrowser2::_IsSameToolbar(LPWSTR wszBarName, IUnknown *punkBar)
  9385. {
  9386. BOOL fRet = FALSE;
  9387. IUnknown *punk;
  9388. HRESULT hres = FindToolbar(wszBarName, IID_PPV_ARG(IUnknown, &punk));
  9389. ASSERT((hres == S_OK) == (punk != NULL));
  9390. if (punk)
  9391. {
  9392. if (SHIsSameObject(punkBar, punk))
  9393. {
  9394. fRet = TRUE;
  9395. }
  9396. punk->Release();
  9397. }
  9398. return fRet;
  9399. }
  9400. STDAPI SHGetWindowTitle(LPCITEMIDLIST pidl, LPTSTR pszFullName, DWORD cchSize)
  9401. {
  9402. CABINETSTATE cs;
  9403. GetCabState(&cs);
  9404. return SHTitleFromPidl(pidl, pszFullName, cchSize, cs.fFullPathTitle);
  9405. }
  9406. // pwszName - The Name of the URL, not
  9407. // limited in size, but the result will
  9408. // be truncated if the imput is too long.
  9409. //
  9410. // The title will be generated by taking the
  9411. // title of the HTML page (pszName) and appending
  9412. // the name of the browser to the end in the
  9413. // following format:
  9414. // "HTML_TITLE - BROWSER_NAME", like:
  9415. // "My Web Page - Microsoft Internet Explorer"
  9416. void CShellBrowser2::_SetTitle(LPCWSTR pwszName)
  9417. {
  9418. TCHAR szTitle[MAX_BROWSER_WINDOW_TITLE];
  9419. TCHAR szFullName[MAX_PATH];
  9420. BOOL fNotDisplayable = FALSE;
  9421. if (!pwszName && _fTitleSet)
  9422. {
  9423. // if the content has once set our title,
  9424. // don't revert to our own mocked up name
  9425. return;
  9426. }
  9427. else if (pwszName)
  9428. {
  9429. _fTitleSet = TRUE;
  9430. }
  9431. BOOL fDisplayable = SHIsDisplayable(pwszName, g_fRunOnFE, g_bRunOnNT5);
  9432. if (pwszName && fDisplayable)
  9433. {
  9434. StrCpyN(szFullName, pwszName, ARRAYSIZE(szFullName));
  9435. SHCleanupUrlForDisplay(szFullName);
  9436. }
  9437. else if (_pbbd->_pidlCur)
  9438. {
  9439. SHGetWindowTitle(_pbbd->_pidlCur, szFullName, ARRAYSIZE(szFullName));
  9440. }
  9441. else if (_pbbd->_pidlPending)
  9442. {
  9443. SHGetWindowTitle(_pbbd->_pidlPending, szFullName, ARRAYSIZE(szFullName));
  9444. }
  9445. else
  9446. szFullName[0] = 0;
  9447. // Before adding on the app title truncate the szFullName so that if it is
  9448. // really long then when the app title " - Microsoft Internet Explorer" is
  9449. // appended it fits.
  9450. //
  9451. // Used to be 100, but that wasn't quite enough to display default title.
  9452. //
  9453. ASSERT(96 <= ARRAYSIZE(szFullName));
  9454. SHTruncateString(szFullName, 96); // any more than 60 is useless anyways
  9455. if (szFullName[0])
  9456. {
  9457. TCHAR szBuf[MAX_URL_STRING];
  9458. v_GetAppTitleTemplate(szBuf, szFullName);
  9459. wnsprintf(szTitle, ARRAYSIZE(szTitle), szBuf, szFullName);
  9460. }
  9461. else if (_fInternetStart)
  9462. {
  9463. _GetAppTitle(szTitle, ARRAYSIZE(szTitle));
  9464. }
  9465. else
  9466. szTitle[0] = 0;
  9467. SendMessage(_pbbd->_hwnd, WM_SETTEXT, 0, (LPARAM)szTitle);
  9468. }
  9469. void _SetWindowIcon (HWND hwnd, HICON hIcon, BOOL bLarge)
  9470. {
  9471. HICON hOldIcon;
  9472. //
  9473. // If the shell window is RTL mirrored, then flip the icon now,
  9474. // before inserting them into the system cache, so that they end up
  9475. // normal (not mirrrored) on the shell. This is mainly a concern for
  9476. // 3rd party components. [samera]
  9477. //
  9478. if (IS_PROCESS_RTL_MIRRORED())
  9479. {
  9480. SHMirrorIcon(&hIcon, NULL);
  9481. }
  9482. hOldIcon = (HICON)SendMessage(hwnd, WM_SETICON, bLarge, (LPARAM)hIcon);
  9483. if (hOldIcon &&
  9484. (hOldIcon != hIcon))
  9485. {
  9486. DestroyIcon(hOldIcon);
  9487. }
  9488. }
  9489. void _WindowIconFromImagelist(HWND hwndMain, int nIndex, BOOL bLarge)
  9490. {
  9491. HIMAGELIST himlSysLarge = NULL;
  9492. HIMAGELIST himlSysSmall = NULL;
  9493. Shell_GetImageLists(&himlSysLarge, &himlSysSmall);
  9494. // if we're using the def open icon or if extracting fails,
  9495. // use the icon we've already created.
  9496. HICON hIcon = ImageList_ExtractIcon(g_hinst, bLarge ? himlSysLarge : himlSysSmall, nIndex);
  9497. if (hIcon)
  9498. _SetWindowIcon(hwndMain, hIcon, bLarge);
  9499. }
  9500. int CShellBrowser2::_GetIconIndex(void)
  9501. {
  9502. int iSelectedImage = -1;
  9503. if (_pbbd->_pidlCur)
  9504. {
  9505. if (_pbbd->_pctView) // we must check!
  9506. {
  9507. VARIANT var = {0};
  9508. HRESULT hresT = _pbbd->_pctView->Exec(&CGID_ShellDocView, SHDVID_GETSYSIMAGEINDEX, 0, NULL, &var);
  9509. if (SUCCEEDED(hresT)) {
  9510. if (var.vt==VT_I4) {
  9511. iSelectedImage= var.lVal;
  9512. } else {
  9513. ASSERT(0);
  9514. VariantClearLazy(&var);
  9515. }
  9516. }
  9517. }
  9518. if (iSelectedImage==-1)
  9519. {
  9520. //
  9521. // Put Optimization here.
  9522. //
  9523. IShellFolder *psfParent;
  9524. LPCITEMIDLIST pidlChild;
  9525. if (SUCCEEDED(IEBindToParentFolder(_pbbd->_pidlCur, &psfParent, &pidlChild)))
  9526. {
  9527. // set the small one first to prevent user stretch blt on the large one
  9528. SHMapPIDLToSystemImageListIndex(psfParent, pidlChild, &iSelectedImage);
  9529. psfParent->Release();
  9530. }
  9531. }
  9532. }
  9533. return iSelectedImage;
  9534. }
  9535. bool CShellBrowser2::_IsExplorerBandVisible (void)
  9536. // 99/02/10 #254171 vtan: This function determines whether
  9537. // the explorer band is visible. This class should not really
  9538. // care but it needs to know to change the window's icon.
  9539. // This is a hack and should be moved or re-architected.
  9540. // 99/02/12 #292249 vtan: Re-worked algorithm to use
  9541. // IBandSite::QueryBand and IPersistStream::GetClassID to
  9542. // recognize the explorer band. Note that the old routine
  9543. // used IDeskBand's inclusion of IOleWindow to get the HWND
  9544. // and use the Win32 API IsWindowVisible().
  9545. // 99/06/25 #359477 vtan: Put this code back.
  9546. // IsControlWindowShown uses QueryStatus for the explorer
  9547. // band which doesn't work when v_SetIcon is called. The
  9548. // band is NOT considered latched and therefore not visible.
  9549. {
  9550. IDeskBar *pIDeskBar;
  9551. bool bVisible = false;
  9552. HRESULT hResult = FindToolbar(INFOBAR_TBNAME, IID_PPV_ARG(IDeskBar, &pIDeskBar));
  9553. if (SUCCEEDED(hResult) && (pIDeskBar != NULL))
  9554. {
  9555. UINT uiToolBar;
  9556. uiToolBar = _FindTBar(pIDeskBar);
  9557. if (uiToolBar != static_cast<UINT>(-1))
  9558. {
  9559. LPTOOLBARITEM pToolBarItem;
  9560. pToolBarItem = _GetToolbarItem(uiToolBar);
  9561. if ((pToolBarItem != NULL) && pToolBarItem->fShow) // check this state
  9562. {
  9563. IUnknown *pIUnknown;
  9564. hResult = pIDeskBar->GetClient(reinterpret_cast<IUnknown**>(&pIUnknown));
  9565. if (SUCCEEDED(hResult) && (pIUnknown != NULL))
  9566. {
  9567. IBandSite *pIBandSite;
  9568. hResult = pIUnknown->QueryInterface(IID_IBandSite, reinterpret_cast<void**>(&pIBandSite));
  9569. if (SUCCEEDED(hResult) && (pIBandSite != NULL))
  9570. {
  9571. UINT uiBandIndex;
  9572. DWORD dwBandID;
  9573. uiBandIndex = 0;
  9574. hResult = pIBandSite->EnumBands(uiBandIndex, &dwBandID);
  9575. while (SUCCEEDED(hResult))
  9576. {
  9577. DWORD dwState;
  9578. IDeskBand *pIDeskBand;
  9579. dwState = 0;
  9580. hResult = pIBandSite->QueryBand(dwBandID, &pIDeskBand, &dwState, NULL, 0);
  9581. if (SUCCEEDED(hResult))
  9582. {
  9583. CLSID clsid;
  9584. hResult = IUnknown_GetClassID(pIDeskBand, &clsid);
  9585. if (SUCCEEDED(hResult) && IsEqualGUID(clsid, CLSID_ExplorerBand))
  9586. bVisible = ((dwState & BSSF_VISIBLE) != 0); // and this state
  9587. pIDeskBand->Release();
  9588. hResult = pIBandSite->EnumBands(++uiBandIndex, &dwBandID);
  9589. }
  9590. }
  9591. pIBandSite->Release();
  9592. }
  9593. pIUnknown->Release();
  9594. }
  9595. }
  9596. }
  9597. pIDeskBar->Release();
  9598. }
  9599. return(bVisible);
  9600. }
  9601. void CShellBrowser2::v_SetIcon()
  9602. {
  9603. if (_IsExplorerBandVisible())
  9604. {
  9605. #define IDI_STFLDRPROP 46
  9606. // Explorer tree view pane is visible - use the magnifying glass icon
  9607. HICON hIcon = reinterpret_cast<HICON>(LoadImage(HinstShell32(), MAKEINTRESOURCE(IDI_STFLDRPROP), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0));
  9608. _SetWindowIcon(_pbbd->_hwnd, hIcon, ICON_SMALL);
  9609. hIcon = reinterpret_cast<HICON>(LoadImage(HinstShell32(), MAKEINTRESOURCE(IDI_STFLDRPROP), IMAGE_ICON, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CXICON), 0));
  9610. _SetWindowIcon(_pbbd->_hwnd, hIcon, ICON_BIG);
  9611. }
  9612. else
  9613. {
  9614. // Otherwise use whatever icon it really should be
  9615. int iSelectedImage = _GetIconIndex();
  9616. if (iSelectedImage != -1)
  9617. {
  9618. _WindowIconFromImagelist(_pbbd->_hwnd, iSelectedImage, ICON_SMALL);
  9619. _WindowIconFromImagelist(_pbbd->_hwnd, iSelectedImage, ICON_BIG);
  9620. }
  9621. }
  9622. }
  9623. HRESULT CShellBrowser2::SetTitle(IShellView * psv, LPCWSTR lpszName)
  9624. {
  9625. // If the pending view had it's title set immediately and waits
  9626. // in pending state for a while. And if the current view has script updating
  9627. // the title. Then the current title will be displayed after the navigate
  9628. // is complete. I added psv to fix this problem to CBaseBrowser2, but I
  9629. // didn't fix it here. [mikesh]
  9630. //
  9631. // Don't set title if view is still pending (or you'll show unrated titles)
  9632. // Figure out which object is changing.
  9633. if (SHIsSameObject(_pbbd->_psv, psv))
  9634. {
  9635. _SetTitle(lpszName);
  9636. }
  9637. SUPERCLASS::SetTitle(psv, lpszName);
  9638. return S_OK;
  9639. }
  9640. HRESULT CShellBrowser2::UpdateWindowList(void)
  9641. {
  9642. if (_psw) {
  9643. WinList_NotifyNewLocation(_psw, _dwRegisterWinList, _pbbd->_pidlCur);
  9644. }
  9645. return S_OK;
  9646. }
  9647. HRESULT CShellBrowser2::SetFlags(DWORD dwFlags, DWORD dwFlagMask)
  9648. {
  9649. if (dwFlagMask & BSF_THEATERMODE)
  9650. _TheaterMode(dwFlags & BSF_THEATERMODE, TRUE);
  9651. if (dwFlagMask & BSF_RESIZABLE)
  9652. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_SIZEBOX, (dwFlags & BSF_RESIZABLE) ? WS_SIZEBOX : 0);
  9653. if (dwFlagMask & BSF_CANMAXIMIZE)
  9654. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_MAXIMIZEBOX, (dwFlags & BSF_CANMAXIMIZE) ? WS_MAXIMIZEBOX : 0);
  9655. if ((dwFlagMask & BSF_UISETBYAUTOMATION) && (dwFlags & BSF_UISETBYAUTOMATION))
  9656. {
  9657. _fDontSaveViewOptions = TRUE;
  9658. _fUISetByAutomation = TRUE;
  9659. // to hide any visible browser bar
  9660. //REARCHITECT this will be removed when explorer bars become 1st class toolbars
  9661. _SetBrowserBarState(_idmInfo, NULL, 0);
  9662. _SetBrowserBarState(_idmComm, NULL, 0);
  9663. }
  9664. return SUPERCLASS::SetFlags(dwFlags, dwFlagMask);
  9665. }
  9666. HRESULT CShellBrowser2::GetFlags(DWORD *pdwFlags)
  9667. {
  9668. DWORD dwFlags;
  9669. SUPERCLASS::GetFlags(&dwFlags);
  9670. if (_fUISetByAutomation)
  9671. dwFlags |= BSF_UISETBYAUTOMATION;
  9672. if (_fNoLocalFileWarning)
  9673. dwFlags |= BSF_NOLOCALFILEWARNING;
  9674. if (_ptheater)
  9675. dwFlags |= BSF_THEATERMODE;
  9676. *pdwFlags = dwFlags;
  9677. return S_OK;
  9678. }
  9679. DWORD CShellBrowser2::v_ShowControl(UINT iControl, int iCmd)
  9680. {
  9681. int iShowing = -1;
  9682. int nWhichBand;
  9683. switch (iControl)
  9684. {
  9685. case FCW_STATUS:
  9686. iShowing = (_fStatusBar ? SBSC_SHOW : SBSC_HIDE);
  9687. if (iCmd != SBSC_QUERY && (iShowing != iCmd))
  9688. {
  9689. _fStatusBar = !_fStatusBar;
  9690. // let itbar know that a change has occurred
  9691. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_STATUSCHANGED, 0, NULL, NULL);
  9692. v_ShowHideChildWindows(FALSE);
  9693. }
  9694. break;
  9695. case FCW_INTERNETBAR:
  9696. {
  9697. LPTOOLBARITEM ptbi = _GetToolbarItem(ITB_ITBAR);
  9698. iShowing = (ptbi->fShow ? SBSC_SHOW : SBSC_HIDE);
  9699. if (iCmd != SBSC_QUERY &&
  9700. (iShowing != iCmd))
  9701. {
  9702. ptbi->fShow = !ptbi->fShow;
  9703. v_ShowHideChildWindows(FALSE);
  9704. }
  9705. }
  9706. break;
  9707. case FCW_ADDRESSBAR:
  9708. case FCW_TOOLBAND:
  9709. case FCW_LINKSBAR:
  9710. case FCW_MENUBAR:
  9711. switch(iControl)
  9712. {
  9713. case FCW_ADDRESSBAR:
  9714. nWhichBand = CITIDM_SHOWADDRESS;
  9715. break;
  9716. case FCW_TOOLBAND:
  9717. nWhichBand = CITIDM_SHOWTOOLS;
  9718. break;
  9719. case FCW_LINKSBAR:
  9720. nWhichBand = CITIDM_SHOWLINKS;
  9721. break;
  9722. case FCW_MENUBAR:
  9723. nWhichBand = CITIDM_SHOWMENU;
  9724. break;
  9725. }
  9726. if (iCmd != SBSC_QUERY)
  9727. {
  9728. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands,
  9729. nWhichBand, (iCmd == SBSC_SHOW), NULL, NULL);
  9730. }
  9731. break;
  9732. default:
  9733. break;
  9734. }
  9735. return iShowing;
  9736. }
  9737. HRESULT CShellBrowser2::ShowControlWindow(UINT id, BOOL fShow)
  9738. {
  9739. switch (id)
  9740. {
  9741. case (UINT)-1: // Set into Kiosk mode...
  9742. if (BOOLIFY(_fKioskMode) != fShow)
  9743. {
  9744. _fKioskMode = fShow;
  9745. if (_fKioskMode)
  9746. {
  9747. _wndpl.length = sizeof(WINDOWPLACEMENT);
  9748. GetWindowPlacement(_pbbd->_hwnd, &_wndpl);
  9749. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, 0);
  9750. SHSetWindowBits(_pbbd->_hwnd, GWL_EXSTYLE, WS_EX_WINDOWEDGE, 0);
  9751. _SetMenu(NULL);
  9752. LPTOOLBARITEM ptbi = _GetToolbarItem(ITB_ITBAR);
  9753. if (ptbi)
  9754. {
  9755. ptbi->fShow = FALSE;
  9756. }
  9757. HMONITOR hmon = MonitorFromRect(&_wndpl.rcNormalPosition, MONITOR_DEFAULTTONEAREST);
  9758. RECT rcMonitor;
  9759. GetMonitorRect(hmon, &rcMonitor);
  9760. SetWindowPos(_pbbd->_hwnd, NULL, rcMonitor.top, rcMonitor.left, RECTWIDTH(rcMonitor),
  9761. RECTHEIGHT(rcMonitor), SWP_NOZORDER);
  9762. }
  9763. else
  9764. {
  9765. if (_fShowMenu)
  9766. _SetMenu(_hmenuCur);
  9767. else
  9768. _SetMenu(NULL);
  9769. SHSetWindowBits(_pbbd->_hwnd, GWL_STYLE, WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX, WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX);
  9770. SHSetWindowBits(_pbbd->_hwnd, GWL_EXSTYLE, WS_EX_WINDOWEDGE, WS_EX_WINDOWEDGE);
  9771. SetWindowPlacement(_pbbd->_hwnd, &_wndpl);
  9772. }
  9773. // Let window manager know to recalculate things...
  9774. v_ShowHideChildWindows(FALSE);
  9775. SetWindowPos(_pbbd->_hwnd, NULL, 0, 0, 0, 0,
  9776. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
  9777. }
  9778. break;
  9779. case FCW_INTERNETBAR:
  9780. case FCW_STATUS:
  9781. case FCW_ADDRESSBAR:
  9782. v_ShowControl(id, fShow ? SBSC_SHOW : SBSC_HIDE);
  9783. break;
  9784. case FCW_MENUBAR:
  9785. if (BOOLIFY(_fShowMenu) != BOOLIFY(fShow))
  9786. {
  9787. _fShowMenu = BOOLIFY(fShow);
  9788. if (_fShowMenu)
  9789. {
  9790. _SetMenu(_hmenuCur);
  9791. }
  9792. else
  9793. {
  9794. _SetMenu(NULL);
  9795. }
  9796. // Let window manager know to recalculate things...
  9797. v_ShowControl(id, fShow ? SBSC_SHOW : SBSC_HIDE);
  9798. // Let ITBar know whether to allow selection of menu bar or no
  9799. IUnknown_Exec(_GetITBar(), &CGID_PrivCITCommands, CITIDM_DISABLESHOWMENU, !_fShowMenu, NULL, NULL);
  9800. SetWindowPos(_pbbd->_hwnd, NULL, 0, 0, 0, 0,
  9801. SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_FRAMECHANGED);
  9802. }
  9803. break;
  9804. default:
  9805. return E_INVALIDARG; // Not one of the ones we support...
  9806. }
  9807. return S_OK;
  9808. }
  9809. BOOL CShellBrowser2::_ShouldAllowNavigateParent()
  9810. {
  9811. LPCITEMIDLIST pidl = ILIsRooted(_pbbd->_pidlCur) ? ILGetNext(_pbbd->_pidlCur) : _pbbd->_pidlCur;
  9812. return !ILIsEmpty(pidl);
  9813. }
  9814. HRESULT CShellBrowser2::IsControlWindowShown(UINT id, BOOL *pfShown)
  9815. {
  9816. switch (id)
  9817. {
  9818. case (UINT)-1: // Set into Kiosk mode...
  9819. *pfShown = _fKioskMode;
  9820. break;
  9821. case FCW_INTERNETBAR:
  9822. *pfShown = _GetToolbarItem(ITB_ITBAR)->fShow;
  9823. break;
  9824. case FCW_STATUS:
  9825. *pfShown = _fStatusBar;
  9826. break;
  9827. case FCW_MENUBAR:
  9828. *pfShown = _fShowMenu;
  9829. break;
  9830. case FCW_TREE:
  9831. {
  9832. BOOL fShown;
  9833. OLECMD rgCmds[1] = {0};
  9834. rgCmds[0].cmdID = SBCMDID_EXPLORERBAR;
  9835. QueryStatus(&CGID_Explorer, ARRAYSIZE(rgCmds), rgCmds, NULL);
  9836. fShown = (rgCmds[0].cmdf & OLECMDF_LATCHED);
  9837. if (pfShown != NULL)
  9838. *pfShown = fShown;
  9839. break;
  9840. }
  9841. default:
  9842. return E_INVALIDARG; // Not one of the ones we support...
  9843. }
  9844. return S_OK;
  9845. }
  9846. HRESULT CShellBrowser2::SetReferrer(LPITEMIDLIST pidl)
  9847. {
  9848. //
  9849. // this is only used when we create a new window, and
  9850. // we need some sort of ZoneCrossing context.
  9851. //
  9852. Pidl_Set(&_pidlReferrer, pidl);
  9853. return (_pidlReferrer || !pidl) ? S_OK :E_FAIL;
  9854. }
  9855. HRESULT CShellBrowser2::_CheckZoneCrossing(LPCITEMIDLIST pidl)
  9856. {
  9857. HRESULT hr = S_OK;
  9858. //
  9859. // NOTE - right now we only handle having one or the other - zekel 8-AUG-97
  9860. // we should only have pidlReferrer if we have been freshly
  9861. // created. if we decide to use it on frames that already exist,
  9862. // then we need to decide whether we should show pidlCur or pidlReferrer.
  9863. // by default we give Referrer preference.
  9864. //
  9865. AssertMsg((!_pidlReferrer && !_pbbd->_pidlCur) ||
  9866. (_pidlReferrer && !_pbbd->_pidlCur) ||
  9867. (!_pidlReferrer && _pbbd->_pidlCur),
  9868. TEXT("REVIEW: should this be allowed?? -zekel"));
  9869. LPITEMIDLIST pidlRef = _pidlReferrer ? _pidlReferrer : _pbbd->_pidlCur;
  9870. //
  9871. // Call InternetConfirmZoneCrossingA API only if this is the top-level
  9872. // browser (not a browser control) AND there is a current page.
  9873. //
  9874. if (pidlRef) {
  9875. HRESULT hresT = S_OK;
  9876. // Get the URL of the current page.
  9877. WCHAR szURLPrev[MAX_URL_STRING];
  9878. const WCHAR c_szURLFile[] = L"file:///c:\\"; // dummy one
  9879. LPCWSTR pszURLPrev = c_szURLFile; // assume file:
  9880. // We should get the display name first and then only use
  9881. // the default value if the szURLPrev doesn't have a scheme.
  9882. // Also do this for szURLNew below. This will fix Folder Shortcuts
  9883. // especially to Web Folders. We also need to use the pidlTarget
  9884. // Folder Shortcut pidl.
  9885. if (IsURLChild(pidlRef, FALSE))
  9886. {
  9887. hresT = ::IEGetDisplayName(pidlRef, szURLPrev, SHGDN_FORPARSING);
  9888. pszURLPrev = szURLPrev;
  9889. }
  9890. if (SUCCEEDED(hresT))
  9891. {
  9892. // Get the URL of the new page.
  9893. WCHAR szURLNew[MAX_URL_STRING];
  9894. LPCWSTR pszURLNew = c_szURLFile;
  9895. if (IsURLChild(pidl, FALSE)) {
  9896. hresT = ::IEGetDisplayName(pidl, szURLNew, SHGDN_FORPARSING);
  9897. pszURLNew = szURLNew;
  9898. }
  9899. if (pszURLPrev != pszURLNew && SUCCEEDED(hresT))
  9900. {
  9901. // HACK: This API takes LPTSTR instead of LPCTSTR.
  9902. DWORD err = InternetConfirmZoneCrossing(_pbbd->_hwnd, (LPWSTR)pszURLPrev, (LPWSTR) pszURLNew, FALSE);
  9903. hr = HRESULT_FROM_WIN32(err);
  9904. TraceMsg(DM_ZONE, "CSB::_CheckZoneCrossing InetConfirmZoneXing %hs %hs returned %d", pszURLPrev, pszURLNew, err);
  9905. if (FAILED(hr) &&
  9906. (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr) &&
  9907. (E_OUTOFMEMORY != hr))
  9908. {
  9909. // We only need to investigate an error if it is unexpected. Out of memory and
  9910. // a user cancelling the dialog are valid.
  9911. TraceMsg(DM_ERROR, "CSB::_CheckZoneCrossing ICZC returned error (%d)", err);
  9912. }
  9913. }
  9914. else
  9915. {
  9916. TraceMsg(DM_ZONE, "CSB::_CheckZoneCrossing IEGetDisplayName(pidl) failed %x", hresT);
  9917. }
  9918. }
  9919. else
  9920. {
  9921. TraceMsg(DM_ZONE, "CSB::_CheckZoneCrossing IEGetDisplayName(pidlRef) failed %x", hresT);
  9922. }
  9923. }
  9924. SetReferrer(NULL);
  9925. return hr;
  9926. }
  9927. BOOL CShellBrowser2::v_IsIEModeBrowser()
  9928. {
  9929. //
  9930. // if we didnt register the window or if it is not registered as 3rdparty,
  9931. // then it is allowed to be an IEModeBrowser.
  9932. //
  9933. return (!_fDidRegisterWindow || (_swcRegistered != SWC_3RDPARTY)) &&
  9934. (_fInternetStart || (_pbbd->_pidlCur && IsURLChild(_pbbd->_pidlCur, TRUE)));
  9935. }
  9936. // IServiceProvider::QueryService
  9937. STDMETHODIMP CShellBrowser2::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  9938. {
  9939. if (IsEqualGUID(guidService, SID_SExplorerToolbar))
  9940. {
  9941. LPTOOLBARITEM ptbi = _GetToolbarItem(ITB_ITBAR);
  9942. if (ptbi->ptbar)
  9943. {
  9944. return ptbi->ptbar->QueryInterface(riid, ppvObj);
  9945. }
  9946. }
  9947. else if (IsEqualGUID(guidService, SID_SMenuBandHandler) ||
  9948. IsEqualGUID(guidService, SID_SHostProxyFilter))
  9949. {
  9950. return QueryInterface(riid, ppvObj);
  9951. }
  9952. return SUPERCLASS::QueryService(guidService, riid, ppvObj);
  9953. }
  9954. HRESULT CShellBrowser2::EnableModelessSB(BOOL fEnable)
  9955. {
  9956. HRESULT hres = SUPERCLASS::EnableModelessSB(fEnable);
  9957. //
  9958. // We don't want to leave the frame window disabled if a control left
  9959. // us disabled because of its bug. Instead, we'll put a warning dialog
  9960. // box -- IDS_CLOSEANYWAY. (SatoNa)
  9961. //
  9962. #if 0
  9963. EnableMenuItem(GetSystemMenu(_pbbd->_hwnd, FALSE), SC_CLOSE, (S_OK == _DisableModeless()) ?
  9964. (MF_BYCOMMAND | MF_GRAYED) : (MF_BYCOMMAND| MF_ENABLED));
  9965. #endif
  9966. return hres;
  9967. }
  9968. LPCITEMIDLIST CShellBrowser2::_GetPidl()
  9969. {
  9970. LPCITEMIDLIST pidl = _pbbd->_pidlNewShellView;
  9971. if (pidl == NULL)
  9972. pidl = _pbbd->_pidlPending;
  9973. if (pidl == NULL)
  9974. pidl = _pbbd->_pidlCur;
  9975. return pidl;
  9976. }
  9977. BOOL CShellBrowser2::_DoesPidlRoam(LPCITEMIDLIST pidl)
  9978. {
  9979. WCHAR szPath[MAX_PATH];
  9980. BOOL fRet = SHGetPathFromIDList(pidl, szPath);
  9981. if (fRet)
  9982. {
  9983. fRet = PathIsUNC(szPath);
  9984. }
  9985. return fRet;
  9986. }
  9987. HRESULT CShellBrowser2::_CreateFakeNilPidl(LPITEMIDLIST *ppidl)
  9988. {
  9989. IShellFolder *psfDesktop;
  9990. HRESULT hr = SHGetDesktopFolder(&psfDesktop);
  9991. if (SUCCEEDED(hr))
  9992. {
  9993. IBindCtx *pbc;
  9994. hr = BindCtx_CreateWithMode(STGM_CREATE, &pbc);
  9995. if (SUCCEEDED(hr))
  9996. {
  9997. // the new "nil" clsid
  9998. hr = psfDesktop->ParseDisplayName(NULL, pbc, L"::{cce6191f-13b2-44fa-8d14-324728beef2c}", NULL, ppidl, NULL);
  9999. pbc->Release();
  10000. }
  10001. psfDesktop->Release();
  10002. }
  10003. return hr;
  10004. }
  10005. BOOL CShellBrowser2::_IsPageInternet(LPCITEMIDLIST pidl)
  10006. {
  10007. BOOL fInternet = FALSE;
  10008. if (((NULL == pidl) && IsEqualCLSID(_clsidThis, CLSID_InternetExplorer)) ||
  10009. IsBrowserFrameOptionsPidlSet(pidl, BFO_BROWSER_PERSIST_SETTINGS))
  10010. {
  10011. fInternet = TRUE;
  10012. }
  10013. return fInternet;
  10014. }
  10015. HRESULT CShellBrowser2::_GetPropertyBag(LPCITEMIDLIST pidl, DWORD dwFlags, REFIID riid, void** ppv)
  10016. {
  10017. HRESULT hr;
  10018. if (_IsPageInternet(pidl))
  10019. {
  10020. LPITEMIDLIST pidlIE = IEGetInternetRootID();
  10021. if (pidlIE)
  10022. {
  10023. hr = SHGetViewStatePropertyBag(pidlIE, VS_BAGSTR_EXPLORER, dwFlags, riid, ppv);
  10024. ILFree(pidlIE);
  10025. }
  10026. else
  10027. {
  10028. hr = E_OUTOFMEMORY;
  10029. }
  10030. }
  10031. else if (!pidl || _fNilViewStream)
  10032. {
  10033. // the old-style save-to-stream code faked up a "nil" location in the case of NULL.
  10034. // additionally if we loaded from this fake stream we had to save to it later.
  10035. // the search window actually relies on this behavior since it doesnt get its
  10036. // pidl for navigation until the window is already up.
  10037. // it's too late to change the way search initializes its view window and the
  10038. // solution is nontrivial anyway, so mimic the old behavior here.
  10039. LPITEMIDLIST pidlNil;
  10040. hr = _CreateFakeNilPidl(&pidlNil);
  10041. if (SUCCEEDED(hr))
  10042. {
  10043. hr = SHGetViewStatePropertyBag(pidlNil, VS_BAGSTR_EXPLORER, dwFlags, riid, ppv);
  10044. ILFree(pidlNil);
  10045. }
  10046. _fNilViewStream = TRUE;
  10047. }
  10048. else
  10049. {
  10050. if (_DoesPidlRoam(pidl))
  10051. {
  10052. dwFlags |= SHGVSPB_ROAM;
  10053. }
  10054. hr = SHGetViewStatePropertyBag(pidl, VS_BAGSTR_EXPLORER, dwFlags, riid, ppv);
  10055. }
  10056. return hr;
  10057. }
  10058. HRESULT CShellBrowser2::GetPropertyBag(DWORD dwFlags, REFIID riid, void** ppv)
  10059. {
  10060. LPCITEMIDLIST pidl = _GetPidl();
  10061. return _GetPropertyBag(pidl, dwFlags, riid, ppv);
  10062. }
  10063. HRESULT CShellBrowser2::GetViewStateStream(DWORD grfMode, IStream **ppstm)
  10064. // 99/02/05 #226140 vtan: DefView doesn't perist the dwDefRevCount
  10065. // like ShellBrowser does. When DefView asks ShellBrowser for the
  10066. // view state stream ShellBrowser would blindly return the stream
  10067. // (implemented in the super class CCommonBrowser). In order to
  10068. // ensure the stream's validity the method is now replaced with
  10069. // this code which verifies the dwDefRevCount matches. If there
  10070. // is a mismatch the function bails with an error otherwise it
  10071. // calls the regularly scheduled program (super CCommonBrowser).
  10072. // This will have to be revisited when separating frame
  10073. // state from view state.
  10074. {
  10075. HRESULT hResult;
  10076. IStream* pIStream;
  10077. LPCITEMIDLIST pIDL;
  10078. pIDL = _GetPidl();
  10079. pIStream = v_GetViewStream(pIDL, STGM_READ, L"CabView");
  10080. if (pIStream != NULL)
  10081. {
  10082. CABSH cabinetStateHeader;
  10083. hResult = _FillCabinetStateHeader(pIStream, &cabinetStateHeader);
  10084. pIStream->Release();
  10085. if (SUCCEEDED(hResult) &&
  10086. ((cabinetStateHeader.fMask & CABSHM_REVCOUNT) != 0) &&
  10087. (g_dfs.dwDefRevCount != cabinetStateHeader.dwRevCount))
  10088. {
  10089. *ppstm = NULL;
  10090. return(E_FAIL);
  10091. }
  10092. }
  10093. return(SUPERCLASS::GetViewStateStream(grfMode, ppstm));
  10094. }
  10095. LRESULT CALLBACK CShellBrowser2::DummyTBWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  10096. {
  10097. CShellBrowser2* pSB = (CShellBrowser2*)GetWindowPtr0(hwnd); // GetWindowLong(hwnd, 0)
  10098. LRESULT lRes = 0L;
  10099. if (uMsg < WM_USER)
  10100. return(::DefWindowProcWrap(hwnd, uMsg, wParam, lParam));
  10101. else
  10102. {
  10103. switch (uMsg) {
  10104. case TB_ADDBITMAP:
  10105. pSB->_pxtb->AddBitmap(&CGID_ShellBrowser, BITMAP_NORMAL, (UINT)wParam, (TBADDBITMAP*)lParam, &lRes, RGB(192,192,192));
  10106. pSB->_pxtb->AddBitmap(&CGID_ShellBrowser, BITMAP_HOT, (UINT)wParam, (TBADDBITMAP*)lParam, &lRes, RGB(192,192,192));
  10107. break;
  10108. default:
  10109. if (pSB->_pxtb)
  10110. pSB->_pxtb->SendToolbarMsg(&CGID_ShellBrowser, uMsg, wParam, lParam, &lRes);
  10111. return lRes;
  10112. }
  10113. }
  10114. return lRes;
  10115. }
  10116. // When a view adds buttons with no text, the CInternet toolbar may call back and ask
  10117. // for the tooltip strings. Unfortunately, at that time _pbbd->_hwndView is not yet set and therefore
  10118. // the tooltip texts will not be set.
  10119. //
  10120. // So, to get around that, we do not add the buttons if there is no _pbbd->_hwndView (see ::SetToolbarItem)
  10121. // The CBaseBrowser2's ::_SwitchActivationNow() is the one that sets the _pbbd->_hwndView. So when this hwnd is
  10122. // set then we add the buttons
  10123. //
  10124. // We send the WM_NOTIFYFORMAT because when CInternetToolbar::AddButtons calls back with the WM_NOTIFYs
  10125. // for the tooltips, we need to know whether or not the view is UNICODE or not.
  10126. HRESULT CShellBrowser2::_SwitchActivationNow()
  10127. {
  10128. ASSERT(_pbbd->_psvPending);
  10129. #if 0
  10130. // if we have a progress control, make sure it's off before we switch activation
  10131. if (_hwndProgress)
  10132. SendControlMsg(FCW_PROGRESS, PBM_SETRANGE32, 0, 0, NULL);
  10133. #endif
  10134. SUPERCLASS::_SwitchActivationNow();
  10135. // need to do this as close to the assign of _pbbd->_hwndView as possible
  10136. _fUnicode = (SendMessage (_pbbd->_hwndView, WM_NOTIFYFORMAT,
  10137. (WPARAM)_pbbd->_hwnd, NF_QUERY) == NFR_UNICODE);
  10138. if (_lpButtons) {
  10139. LocalFree(_lpButtons);
  10140. _lpButtons = NULL;
  10141. _nButtons = 0;
  10142. }
  10143. if (_lpPendingButtons)
  10144. {
  10145. _lpButtons = _lpPendingButtons;
  10146. _nButtons = _nButtonsPending;
  10147. _lpPendingButtons = NULL;
  10148. _nButtonsPending = 0;
  10149. if ((_pxtb) && (_pbbd->_hwndView))
  10150. _pxtb->AddButtons(&CGID_ShellBrowser, _nButtons, _lpButtons);
  10151. }
  10152. return S_OK;
  10153. }
  10154. #ifdef DEBUG
  10155. /*----------------------------------------------------------
  10156. Purpose: Dump the menu handles for this browser. Optionally
  10157. breaks after dumping handles.
  10158. */
  10159. void
  10160. CShellBrowser2::_DumpMenus(
  10161. IN LPCTSTR pszMsg,
  10162. IN BOOL bBreak)
  10163. {
  10164. if (IsFlagSet(g_dwDumpFlags, DF_DEBUGMENU))
  10165. {
  10166. ASSERT(pszMsg);
  10167. TraceMsg(TF_ALWAYS, "CShellBrowser2: Dumping menus for %#08x %s", (void *)this, pszMsg);
  10168. TraceMsg(TF_ALWAYS, " _hmenuTemplate = %x, _hmenuFull = %x, _hmenuBrowser = %x",
  10169. _hmenuTemplate, _hmenuFull, _hmenuBrowser);
  10170. TraceMsg(TF_ALWAYS, " _hmenuCur = %x, _hmenuPreMerged = %x, _hmenuHelp = %x",
  10171. _hmenuCur, _hmenuPreMerged, _hmenuHelp);
  10172. _menulist.Dump(pszMsg);
  10173. if (bBreak && IsFlagSet(g_dwBreakFlags, BF_ONDUMPMENU))
  10174. DebugBreak();
  10175. }
  10176. }
  10177. #endif
  10178. HRESULT CShellBrowser2::SetBorderSpaceDW(IUnknown* punkSrc, LPCBORDERWIDTHS pborderwidths)
  10179. {
  10180. return SUPERCLASS::SetBorderSpaceDW(punkSrc, pborderwidths);
  10181. }
  10182. //
  10183. // This is a helper member of CBaseBroaser class (non-virtual), which
  10184. // returns the effective client area. We get this rectangle by subtracting
  10185. // the status bar area from the real client area.
  10186. //
  10187. HRESULT CShellBrowser2::_GetEffectiveClientArea(LPRECT lprectBorder, HMONITOR hmon)
  10188. {
  10189. static const int s_rgnViews[] = {1, 0, 1, FCIDM_STATUS, 0, 0};
  10190. // n.b. do *not* call SUPER/_psbInner
  10191. ASSERT(hmon == NULL);
  10192. GetEffectiveClientRect(_pbbd->_hwnd, lprectBorder, (LPINT)s_rgnViews);
  10193. return S_OK;
  10194. }
  10195. // Should we return more informative return values?
  10196. // "Browser Helper Objects"
  10197. BOOL CShellBrowser2::_LoadBrowserHelperObjects(void)
  10198. {
  10199. BOOL bRet = FALSE;
  10200. BOOL bNoExplorer = FALSE;
  10201. HKEY hkey;
  10202. // We shouldn't load browser extensions if we're in fail-safe mode, or if the user asked us to disable these extensions/
  10203. // In the future, we should allow disabling on a per-extension basis (when not in safe mode)
  10204. if ((!SHRegGetBoolUSValue(TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\Main"), TEXT("Enable Browser Extensions"), FALSE, TRUE))
  10205. || (GetSystemMetrics(SM_CLEANBOOT)!=0))
  10206. {
  10207. return TRUE;
  10208. }
  10209. if (_pbbd->_pautoWB2 &&
  10210. RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_EXPLORER TEXT("\\Browser Helper Objects"), &hkey) == ERROR_SUCCESS)
  10211. {
  10212. TCHAR szGUID[64];
  10213. DWORD cb = ARRAYSIZE(szGUID);
  10214. for (int i = 0;
  10215. RegEnumKeyEx(hkey, i, szGUID, &cb, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
  10216. i++)
  10217. {
  10218. // If we're not in IEXPLORE's process
  10219. //
  10220. if (!_fRunningInIexploreExe)
  10221. {
  10222. // Check to see if there's a "NoExplorer" value
  10223. //
  10224. bNoExplorer = (ERROR_SUCCESS == SHGetValue(hkey, szGUID, TEXT("NoExplorer"), NULL, NULL, NULL));
  10225. }
  10226. // If we're in IEXPLORE.EXE or we're in EXPLORER.EXE but there's no "NoExplorer" value, then
  10227. // go ahead and load the BHO
  10228. if (_fRunningInIexploreExe || !bNoExplorer)
  10229. {
  10230. CLSID clsid;
  10231. IObjectWithSite *pows;
  10232. if (GUIDFromString(szGUID, &clsid) &&
  10233. !(SHGetObjectCompatFlags(NULL, &clsid) & OBJCOMPATF_UNBINDABLE) &&
  10234. SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IObjectWithSite, &pows))))
  10235. {
  10236. pows->SetSite(_pbbd->_pautoWB2); // give the poinetr to IWebBrowser2
  10237. SA_BSTRGUID strClsid;
  10238. // now register this object so that it can be found through automation.
  10239. SHTCharToUnicode(szGUID, strClsid.wsz, ARRAYSIZE(strClsid.wsz));
  10240. strClsid.cb = lstrlenW(strClsid.wsz) * sizeof(WCHAR);
  10241. VARIANT varUnknown = {0};
  10242. varUnknown.vt = VT_UNKNOWN;
  10243. varUnknown.punkVal = pows;
  10244. _pbbd->_pautoWB2->PutProperty(strClsid.wsz, varUnknown);
  10245. pows->Release(); // Instead of calling variantClear()
  10246. bRet = TRUE;
  10247. }
  10248. }
  10249. cb = ARRAYSIZE(szGUID);
  10250. }
  10251. RegCloseKey(hkey);
  10252. }
  10253. return bRet;
  10254. }
  10255. HRESULT CShellBrowser2::OnViewWindowActive(IShellView * psv)
  10256. {
  10257. _pbsInner->SetActivateState(SVUIA_ACTIVATE_FOCUS);
  10258. return SUPERCLASS::OnViewWindowActive(psv);
  10259. }
  10260. HRESULT CShellBrowser2::_PositionViewWindow(HWND hwnd, LPRECT prc)
  10261. {
  10262. if (hwnd == _hwndDelayedSize)
  10263. {
  10264. _fHaveDelayedSize = TRUE;
  10265. _rcDelayedSize = *prc;
  10266. }
  10267. else
  10268. {
  10269. RECT rc = *prc;
  10270. if (_ptheater) {
  10271. InflateRect(&rc, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
  10272. }
  10273. SetWindowPos(hwnd, NULL,
  10274. rc.left, rc.top,
  10275. rc.right - rc.left,
  10276. rc.bottom - rc.top,
  10277. SWP_NOZORDER | SWP_NOACTIVATE);
  10278. }
  10279. return S_OK;
  10280. }
  10281. HRESULT CShellBrowser2::OnFocusChangeIS(IUnknown* punkSrc, BOOL fSetFocus)
  10282. {
  10283. if (fSetFocus && _ptheater && SHIsSameObject(punkSrc, _GetITBar())) {
  10284. _ptheater->Exec(&CGID_Theater, THID_TOOLBARACTIVATED, 0, NULL, NULL);
  10285. }
  10286. return SUPERCLASS::OnFocusChangeIS(punkSrc, fSetFocus);
  10287. }
  10288. HRESULT CShellBrowser2::Offline(int iCmd)
  10289. {
  10290. HRESULT hresIsOffline = SUPERCLASS::Offline(iCmd);
  10291. if (iCmd == SBSC_TOGGLE)
  10292. {
  10293. VARIANTARG var = {0};
  10294. if (_pbbd->_pctView && SUCCEEDED(_pbbd->_pctView->Exec(&CGID_Explorer, SBCMDID_GETPANE, PANE_OFFLINE, NULL, &var))
  10295. && V_UI4(&var) != PANE_NONE)
  10296. {
  10297. SendControlMsg(FCW_STATUS, SB_SETICON, V_UI4(&var),
  10298. (hresIsOffline == S_OK) ? (LPARAM) OfflineIcon() : NULL, NULL);
  10299. if (hresIsOffline == S_OK) {
  10300. InitTitleStrings();
  10301. SendControlMsg(FCW_STATUS, SB_SETTIPTEXT, V_UI4(&var),
  10302. (LPARAM) g_szWorkingOfflineTip, NULL);
  10303. }
  10304. }
  10305. }
  10306. return hresIsOffline;
  10307. }
  10308. HRESULT CShellBrowser2::_FreshenComponentCategoriesCache(BOOL bForceUpdate)
  10309. {
  10310. CATID catids[2] ;
  10311. ULONG cCatids = 0 ;
  10312. catids[0] = CATID_InfoBand ;
  10313. catids[1] = CATID_CommBand ;
  10314. // Check if our CATIDs are cached...
  10315. if (!bForceUpdate)
  10316. {
  10317. for(ULONG i=0; i< ARRAYSIZE(catids); i++)
  10318. {
  10319. if (S_OK != SHDoesComCatCacheExist(catids[i], TRUE))
  10320. {
  10321. bForceUpdate = TRUE ;
  10322. break ;
  10323. }
  10324. }
  10325. }
  10326. if (bForceUpdate)
  10327. {
  10328. // Create an event for the comcat task to signal when it's
  10329. // done. We need to do this because sometimes the task hasn't
  10330. // finished by the time the user opens the "Explorer Bars"
  10331. // submenu, and so they won't see the Bloomberg bar (for
  10332. // example) that they just installed unless we wait for the task
  10333. // to complete.
  10334. if (_hEventComCat == NULL)
  10335. _hEventComCat = CreateEvent(NULL, FALSE, FALSE, NULL);
  10336. return SHWriteClassesOfCategories(ARRAYSIZE(catids), catids, 0, NULL,
  10337. TRUE, FALSE /*no wait*/, _hEventComCat) ;
  10338. }
  10339. return S_FALSE ;
  10340. }
  10341. void CShellBrowser2::_QueryHKCRChanged()
  10342. {
  10343. ASSERT(g_fRunningOnNT && GetUIVersion() >= 5);
  10344. // In an integrated installation >= v5 on NT, we have the benefit
  10345. // of an HKCR change notification. Posting this message will cause
  10346. // the desktop to check to see if HKCR was modified recently; if so,
  10347. // the _SetupAppRan handler will execute in the desktop process.
  10348. // This causes, among other evil, freshening of our component categories cache.
  10349. // it is ok that this is isnt synchronous because the update
  10350. // is async regardless.
  10351. PostMessage(GetShellWindow(), DTM_QUERYHKCRCHANGED,
  10352. QHKCRID_VIEWMENUPOPUP, (LPARAM)NULL) ;
  10353. }
  10354. #ifdef UNIX
  10355. BOOL CShellBrowser2::_HandleActivation(WPARAM wParam)
  10356. {
  10357. LPTOOLBARITEM ptbi;
  10358. IDockingWindow *ptbTmp;
  10359. IOleCommandTarget* pcmdt;
  10360. // Activation is explicitly handled only in MOTIF LOOK
  10361. if (MwCurrentLook() != LOOK_MOTIF)
  10362. return FALSE;
  10363. // Get InetnetToolbar IDockingWindow interface
  10364. ptbi = _GetToolbarItem(ITB_ITBAR);
  10365. if (!ptbi)
  10366. return FALSE;
  10367. ptbTmp = ptbi->ptbar;
  10368. if (ptbTmp)
  10369. {
  10370. // Exec Command. IOleCommandTarget::Exec for CInternetToobar window
  10371. // forwards the commands to the address band.
  10372. HRESULT hres = ptbTmp->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pcmdt));
  10373. if (SUCCEEDED(hres))
  10374. {
  10375. if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE)
  10376. {
  10377. // Did we have toobar focus when deactivated.
  10378. if (_fSetAddressBarFocus)
  10379. {
  10380. VARIANTARG vaOut = {0};
  10381. hres = pcmdt->Exec(&CGID_Explorer, SBCMDID_SETADDRESSBARFOCUS, 0, NULL, &vaOut);
  10382. // SERADDRESSBARFOCUS command handled by the retrieved IOleCommandTarget.
  10383. // No need to process any furthur.
  10384. if (SUCCEEDED(hres))
  10385. {
  10386. pcmdt->Release();
  10387. return TRUE;
  10388. }
  10389. }
  10390. }
  10391. else
  10392. {
  10393. // Focus should only be set to the Addressbar if we already had
  10394. // focus there before losing activation, otherwise do default
  10395. // processing.
  10396. VARIANTARG vaOut = {0};
  10397. hres = pcmdt->Exec(&CGID_Explorer, SBCMDID_HASADDRESSBARFOCUS, 0, NULL, &vaOut);
  10398. _fSetAddressBarFocus = SUCCEEDED(hres);
  10399. }
  10400. pcmdt->Release();
  10401. }
  10402. }
  10403. return FALSE;
  10404. }
  10405. #endif