Advertisement
Guest User

win2k/private/shell/browseui/itbar.cpp

a guest
Jan 28th, 2013
1,688
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 318.04 KB | None | 0 0
  1. #include "priv.h"
  2. #include "sccls.h"
  3.  
  4. #include "itbdrop.h"
  5. #include <urlhist.h>
  6. #include "autocomp.h"
  7. #include "itbar.h"
  8. #include "address.h"
  9. #include "isfband.h"
  10. #include <winbase.h>
  11. #include "qlink.h"
  12. #include "inpobj.h"
  13. #include "basebar.h"
  14. #include "shbrowse.h"
  15. #include "menuisf.h"
  16. #include "menuband.h"
  17. #include "brand.h"
  18. #include "resource.h"
  19. #include "theater.h"
  20. #include "browmenu.h"
  21. #include "util.h"
  22. #include "tbmenu.h"
  23. #include "apithk.h"
  24. #include "shbrows2.h"
  25. #include "stdenum.h"
  26. #include "iehelpid.h"
  27.  
  28. #define WANT_CBANDSITE_CLASS
  29. #include "bandsite.h"
  30. #include "schedule.h"
  31. #include "uemapp.h"
  32.  
  33. #include "mluisupp.h"
  34.  
  35. #ifdef UNIX
  36. extern "C"  const GUID  CLSID_MsgBand;
  37. #endif
  38.  
  39. // The edit button hackery needs to be moved to shdocvw.  This define identifies this code.
  40. #define EDIT_HACK
  41.  
  42. // Offset of the comctl32 default bitmaps
  43. #define OFFSET_HIST             (MAX_TB_BUTTONS - 1 + 0)   // 15
  44. #define OFFSET_STD              (MAX_TB_BUTTONS - 1 + 6)   // 21
  45. #define OFFSET_VIEW             (MAX_TB_BUTTONS - 1 + 21)  // 36
  46.  
  47. // This is the offset in the toolbar for the Shell glyphs and the Shell toolbar labels
  48. #define SHELLTOOLBAR_OFFSET     (MAX_TB_BUTTONS - 1 + 1)  // 16
  49. #define FONTGLYPH_OFFSET        (MAX_TB_BUTTONS - 1 + 38) // 53
  50. #define BRIEFCASEGLYPH_OFFSET   (MAX_TB_BUTTONS - 1 + 34) // 49
  51. #define RNAUIGLYPH_OFFSET       (MAX_TB_BUTTONS - 1 + 36) // 51
  52. #define WEBCHECKGLYPH_OFFSET    (MAX_TB_BUTTONS - 1 + 42) // 57
  53. #ifdef EDIT_HACK
  54. #define EDITGLYPH_OFFSET        (9)
  55. #endif
  56.  
  57. #define IDT_UPDATETOOLBAR       0x1
  58. #define TIMEOUT_UPDATETOOLBAR   400
  59.  
  60. const GUID CLSID_Separator = { 0x67077B90L, 0x4F9D, 0x11D0, 0xB8, 0x84, 0x00, 0xAA, 0x00, 0xB6, 0x01, 0x04 };
  61.  
  62. extern HRESULT VariantClearLazy(VARIANTARG *pvarg);
  63.  
  64. // How many CT_TABLE structures to allocated at a time.
  65. #define TBBMPLIST_CHUNK     5
  66.  
  67. #define MAX_EXTERNAL_BAND_NAME_LEN 64
  68.  
  69. #define MAX_TB_COMPRESSED_WIDTH 42
  70. // 16 is added to the the MAX_TB defines. This is added through the strings
  71. // in the RC file. This is done so that the localization folks can increase
  72. // or decrease the width of the toolbar buttons
  73. #define MAX_TB_WIDTH_LORES      38
  74. #define MAX_TB_WIDTH_HIRES      60
  75.  
  76. // Dimensions of Coolbar Glyphs ..
  77. #define TB_SMBMP_CX               16
  78. #define TB_SMBMP_CY               16
  79. #define TB_BMP_CX               20
  80. #define TB_BMP_CY               20
  81.  
  82. #define CX_SEPARATOR    6     // we override toolbar control's default separator width of 8
  83.  
  84. #define DM_TBSITE   0
  85. #define DM_TBCMD    0
  86. #define DM_TBREF    TF_SHDREF
  87. #define DM_LAYOUT   0
  88. #define DM_ITBAR    0
  89.  
  90. #define TF_TBCUST   0x01000000
  91.  
  92. #if CBIDX_LAST != 5
  93. #error Expected CBIDX_LAST to have value of 5
  94. #endif
  95.  
  96. #if (FCIDM_EXTERNALBANDS_LAST - FCIDM_EXTERNALBANDS_FIRST + 1) < MAXEXTERNALBANDS
  97. #error Insufficient range for FCIDM_EXTERNALBANDS_FIRST to FCIDM_EXTERNALBANDS_LAST
  98. #endif
  99.  
  100.  
  101. __inline UINT EXTERNALBAND_VBF_BIT(UINT uiBandExt)
  102. {
  103.     ASSERT(uiBandExt < MAXEXTERNALBANDS);
  104.  
  105.     // Formula: take 1, shift left by uiBandExt + 16
  106.     //      => a bit in range (0x80000000, 0x00010000)
  107.     UINT uBit = 1 << (uiBandExt + 16);
  108.     ASSERT(uBit & VBF_EXTERNALBANDS);
  109.  
  110.     return uBit;
  111. }
  112.  
  113. __inline BOOL IS_EXTERNALBAND(int idBand)
  114. {
  115.     return (InRange(idBand, CBIDX_EXTERNALFIRST, CBIDX_EXTERNALLAST));
  116. }
  117.  
  118. __inline int MAP_TO_EXTERNAL(int idBand)
  119. {
  120.     ASSERT(IS_EXTERNALBAND(idBand));
  121.  
  122.     // CBIDX_LAST is one-based, mapping is zero-based
  123.     return (idBand - (1 + CBIDX_LAST));
  124. }
  125.  
  126.  
  127. // maximum number of menu items in the context menus for back and forward.
  128. #define MAX_NAV_MENUITEMS               9
  129.  
  130. #define DEFAULT_SEARCH_GUID    SRCID_SFileSearch //SRCID_SWebSearch
  131.  
  132. #define SZ_PROP_CUSTDLG     TEXT("Itbar custom dialog hwnd")
  133.  
  134. #define REG_KEY_BANDSTATE  TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar")
  135.  
  136. DWORD DoNetConnect(HWND hwnd);
  137. DWORD DoNetDisconnect(HWND hwnd);
  138.  
  139.  
  140. void _LoadToolbarGlyphs(HWND hwnd, IMLCACHE *pimlCache, int cx, int idBmp);
  141.  
  142. BOOL _UseSmallIcons();
  143.  
  144.  
  145. typedef struct tagTBBMP_LIST
  146. {
  147.     HINSTANCE hInst;
  148.     UINT_PTR  uiResID;
  149.     UINT  uiOffset;
  150.     BITBOOL  fNormal:1;
  151.     BITBOOL  fHot:1;
  152.     BITBOOL  fDisabled:1;
  153. } TBBMP_LIST;
  154.  
  155. typedef struct tagCMDMAP
  156. {
  157.     GUID    guidButtonGroup;
  158.     UINT    nCmdID;
  159.     LPARAM lParam;  // app's data
  160. } CMDMAP;
  161.  
  162. typedef struct tagCMDMAPCUSTOMIZE
  163. {
  164.     TBBUTTON btn;
  165.     CMDMAP cm;
  166. } CMDMAPCUSTOMIZE;
  167.  
  168. typedef struct {
  169.  
  170.     // the IOleCommandTarget info:
  171.     GUID guid;
  172.     UINT nCmdID;
  173.     UINT fButtonState;
  174. } BUTTONSAVEINFO;
  175.  
  176. #define TBSI_VERSION            7
  177. typedef struct {
  178.     int cVersion;
  179. } TOOLBARSAVEINFO;
  180.  
  181. typedef struct {
  182.     HDSA hdsa;
  183.     BITBOOL fAdjust:1;
  184.     BITBOOL fDirty:1;
  185. } CUSTOMIZEINFO, *LPCUSTOMIZEINFO;
  186.  
  187. //Current latest version.
  188. #define CBS_VERSION             17
  189.  
  190. // NOTE: Be very careful changing COOLBARSAVE because _LoadUpgradeSettings makes
  191. // assumptions about the layout of the structure.  To avoid breaking that
  192. // upgrade code, be sure you:
  193. //
  194. //  - don't change the order of existing members
  195. //  - always add new members to the end of the structure.
  196. //  - update _LoadUpgradeSettings if appropriate
  197. //
  198. typedef struct tagCOOLBARSAVE
  199. {
  200.     UINT        cbVer;
  201.     UINT        uiMaxTBWidth;
  202.     UINT        uiMaxQLWidth;
  203. #ifdef UNIX
  204.     BITBOOL     fUnUsed : 28;       // unused
  205. #endif
  206.     BITBOOL     fVertical : 1;      // The bar is oriented vertically
  207.     BITBOOL     fNoText :1;         // "NoText"
  208.     BITBOOL     fList : 1;          // toolbar is TBSTYLE_LIST (text on right) + TBSTYLE_EX_MIXEDBUTTONS
  209.     BITBOOL     fAutoHide : 1;      // Auto hide toolbar in theater mode
  210.     BITBOOL     fStatusBar : 1;     // Status bar in theater mode
  211.     BITBOOL     fSaveInShellIntegrationMode : 1;     // Did we save in shell integration mode?
  212.     UINT        uiVisible;          // "Visible bands"
  213.     UINT        cyRebar;
  214.     BANDSAVE    bs[CBANDSMAX];
  215.     CLSID       aclsidExternalBands[ MAXEXTERNALBANDS ];  // Check classid
  216.     CLSID       clsidVerticalBar;       //clsid of bar persisted within vertical band
  217.     CLSID       clsidHorizontalBar;
  218. } COOLBARSAVE, *LPCOOLBARSAVE;
  219.  
  220. //Flags for dwFlags passed to UpdateToolbarDisplay()
  221. #define UTD_TEXTLABEL  0x00000001
  222. #define UTD_VISIBLE    0x00000002
  223.  
  224. static const TCHAR c_szRegKeyCoolbar[] = TSZIEPATH TEXT("\\Toolbar");
  225. static const TCHAR c_szValueTheater[]  = TEXT("Theater");
  226.  
  227. typedef struct tagFOLDERSEARCHITEM
  228. {
  229.     UINT    idCmd;
  230.     GUID    guidSearch;
  231.     int     iIcon;
  232.     WCHAR   wszUrl[MAX_URL_STRING];
  233.     WCHAR   wszName[80];           // friendly name
  234. }FOLDERSEARCHITEM, *LPFOLDERSEARCHITEM;
  235.  
  236. BOOL NavigateSearchBar(IWebBrowser2 *pwb2, LPCWSTR pwszUrl);
  237. BOOL _GetSearchHKEY(LPGUID lpguidSearch, HKEY *phkey);
  238.  
  239. #define REG_SZ_STATIC       TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FindExtensions\\Static")
  240. #define REG_SZ_SEARCH_GUID  TEXT("SearchGUID")
  241. #define REG_SZ_SEARCH_URL   TEXT("SearchGUID\\Url")
  242.  
  243. #define VIEW_OFFSET (SHELLGLYPHS_OFFSET + HIST_MAX + STD_MAX)
  244. #define VIEW_ALLFOLDERS  (VIEW_NETCONNECT + 14)
  245.  
  246. static const TBBUTTON    c_tbExplorer[] =
  247. {
  248.     // override default toolbar width for separators; iBitmap member of
  249.     // TBBUTTON struct is a union of bitmap index & separator width
  250.  
  251.     { 0, TBIDM_BACK  ,      0,               BTNS_DROPDOWN | BTNS_SHOWTEXT, {0,0}, 0, 0 },
  252.     { 1, TBIDM_FORWARD,     0,               BTNS_DROPDOWN, {0,0}, 0, 1 },
  253.  
  254.     { 2, TBIDM_STOPDOWNLOAD, TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 2 },
  255.     { 3, TBIDM_REFRESH,      TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 3 },
  256.     { 4, TBIDM_HOME,         TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 4 },
  257.  
  258.     { VIEW_PARENTFOLDER + VIEW_OFFSET,    TBIDM_PREVIOUSFOLDER,   TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, VIEW_PARENTFOLDER + VIEW_OFFSET },
  259.     { VIEW_NETCONNECT + VIEW_OFFSET,      TBIDM_CONNECT,          TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, VIEW_NETCONNECT + VIEW_OFFSET },
  260.     { VIEW_NETDISCONNECT + VIEW_OFFSET,   TBIDM_DISCONNECT,       TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, VIEW_NETDISCONNECT + VIEW_OFFSET },
  261.  
  262.     { CX_SEPARATOR, 0,          TBSTATE_ENABLED, BTNS_SEP, {0,0}, 0, -1 },
  263.     { 5, TBIDM_SEARCH,       TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, 5 },
  264.     { VIEW_ALLFOLDERS + VIEW_OFFSET,    TBIDM_ALLFOLDERS,         TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, VIEW_ALLFOLDERS + VIEW_OFFSET },
  265.     { 6, TBIDM_FAVORITES,       TBSTATE_ENABLED,  BTNS_SHOWTEXT, {0,0}, 0, 6 },
  266.     { 12, TBIDM_HISTORY,        TBSTATE_ENABLED, BTNS_SHOWTEXT, {0,0}, 0, 12},
  267.     { CX_SEPARATOR,    0,       TBSTATE_ENABLED, BTNS_SEP, {0,0}, 0, -1 },
  268. #ifndef DISABLE_FULLSCREEN
  269.     // IE UNIX : No theater mode for beta1
  270.     { 14, TBIDM_THEATER,         TBSTATE_ENABLED, BTNS_BUTTON, {0,0}, 0, 14 },
  271. #endif
  272. };
  273.  
  274. static const BROWSER_RESTRICTIONS c_rest[] = {
  275.     REST_BTN_BACK,
  276.     REST_BTN_FORWARD,
  277.     REST_BTN_STOPDOWNLOAD,
  278.     REST_BTN_REFRESH,
  279.     REST_BTN_HOME,
  280.     REST_BROWSER_NONE,      // no policy for up
  281.     REST_BROWSER_NONE,      // no policy for map drive
  282.     REST_BROWSER_NONE,      // no policy for disconnect drive
  283.     REST_BROWSER_NONE,      // separator
  284.     REST_BTN_SEARCH,
  285.     REST_BTN_ALLFOLDERS,
  286.     REST_BTN_FAVORITES,
  287.     REST_BTN_HISTORY,
  288.     REST_BROWSER_NONE,      // separator
  289. #ifndef DISABLE_FULLSCREEN
  290.     REST_BTN_THEATER,
  291. #endif
  292. };
  293.  
  294. #define SUPERCLASS CBaseBar
  295.  
  296. class CInternetToolbar :
  297.    public CBaseBar,
  298.    public IDockingWindow,
  299.    public IObjectWithSite,  // *not* CObjectWithSite (want _ptbSite)
  300.    public IExplorerToolbar,
  301.    public DWebBrowserEvents,
  302.    public IPersistStreamInit,
  303.    public IShellChangeNotify,
  304.    public ISearchItems
  305. {
  306. public:
  307.     // *** IUnknown ***
  308.     virtual STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
  309.     virtual STDMETHODIMP_(ULONG) AddRef(void) { return SUPERCLASS::AddRef(); };
  310.     virtual STDMETHODIMP_(ULONG) Release(void){ return SUPERCLASS::Release(); };
  311.  
  312.     // *** IOleWindow methods ***
  313.     virtual STDMETHODIMP GetWindow(HWND * lphwnd) { return SUPERCLASS::GetWindow(lphwnd);};
  314.     virtual STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) {return SUPERCLASS::ContextSensitiveHelp(fEnterMode);};
  315.  
  316.     // *** IDockingWindow methods ***
  317.     virtual STDMETHODIMP ShowDW(BOOL fShow);
  318.     virtual STDMETHODIMP CloseDW(DWORD dwReserved);
  319.     virtual STDMETHODIMP ResizeBorderDW(LPCRECT prcBorder, IUnknown* punkToolbarSite, BOOL fReserved);
  320.  
  321.     // *** IObjectWithSite methods ***
  322.     virtual STDMETHODIMP SetSite(IUnknown* punkSite);
  323.     // BUGBUG is E_NOTIMPL ok?
  324.     virtual STDMETHODIMP GetSite(REFIID riid, void** ppvSite) { ASSERT(0); return E_NOTIMPL; };
  325.  
  326.     // *** IInputObjectSite methods ***
  327.     virtual STDMETHODIMP OnFocusChangeIS(IUnknown *punk, BOOL fSetFocus);
  328.  
  329.     // *** IInputObject methods ***
  330.     virtual STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg);
  331.  
  332.     // *** IServiceProvider methods ***
  333.     virtual STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, LPVOID* ppvObj);
  334.  
  335.     // *** IExplorerToolbar method ***
  336.     virtual STDMETHODIMP SetCommandTarget(IUnknown* punkCmdTarget, const GUID* pguidButtonGroup, DWORD dwFlags);
  337.     virtual STDMETHODIMP AddStdBrowserButtons(void);
  338.  
  339.     virtual STDMETHODIMP AddButtons(const GUID* pguidButtonGroup, UINT nButtons, const TBBUTTON * lpButtons);
  340.     virtual STDMETHODIMP AddString(const GUID * pguidButtonGroup, HINSTANCE hInst, UINT_PTR uiResID, LONG_PTR *pOffset);
  341.     virtual STDMETHODIMP GetButton(const GUID* pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton);
  342.     virtual STDMETHODIMP GetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT * pfState);
  343.     virtual STDMETHODIMP SetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT fState);
  344.     virtual STDMETHODIMP AddBitmap(const GUID * pguidButtonGroup, UINT uiBMPType, UINT uiCount, TBADDBITMAP * ptb,
  345.                                    LRESULT * pOffset, COLORREF rgbMask);
  346.     virtual STDMETHODIMP GetBitmapSize(UINT * uiID);
  347.     virtual STDMETHODIMP SendToolbarMsg(const GUID * pguidButtonGroup, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT * plRes);
  348.  
  349.     virtual STDMETHODIMP SetImageList( const GUID* pguidCmdGroup, HIMAGELIST himlNormal, HIMAGELIST himlHot, HIMAGELIST himlDisabled);
  350.     virtual STDMETHODIMP ModifyButton( const GUID * pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton);
  351.  
  352.     // IOleCommandTarget
  353.     virtual STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup,
  354.                                      ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext);
  355.     virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup,
  356.                               DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn,
  357.                               VARIANTARG *pvarargOut);
  358.  
  359.     // IPersistStreamInit
  360.     STDMETHOD(GetClassID)(GUID *pguid);
  361.     STDMETHOD(Load)(IStream *pStm);
  362.     STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
  363.     STDMETHOD(InitNew)(void);
  364.     STDMETHOD(IsDirty)(void);
  365.     STDMETHOD(GetSizeMax)(ULARGE_INTEGER  *pcbSize);
  366.  
  367.     /* IDispatch methods */
  368.     virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo);
  369.  
  370.     virtual STDMETHODIMP GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo);
  371.  
  372.     virtual STDMETHODIMP GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames,
  373.                                        LCID lcid, DISPID * rgdispid);
  374.  
  375.     virtual STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,
  376.                                 DISPPARAMS * pdispparams, VARIANT * pvarResult,
  377.                                 EXCEPINFO * pexcepinfo,UINT * puArgErr);
  378.  
  379.     // IShellChangeNotify
  380.     virtual STDMETHODIMP OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
  381.  
  382.     // CBaseBar overrides
  383.     virtual LRESULT v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  384.  
  385.     // *** ISearchItems methods ***
  386.     virtual STDMETHODIMP GetDefaultSearchUrl(LPWSTR pwzUrl, UINT cch);
  387.  
  388.     CInternetToolbar();
  389. protected:
  390.     virtual ~CInternetToolbar();
  391.     static LRESULT CALLBACK SizableWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  392.     void _OnCommand(WPARAM wParam, LPARAM lParam);
  393.     BOOL _SendToToolband(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres);
  394.     LRESULT _OnNotify(LPNMHDR pnmh);
  395.     void _OnTooltipNeeded(LPTOOLTIPTEXT pnmTT);
  396.     void _QueryStatusTip(IOleCommandTarget *pct, LPTOOLTIPTEXT pnmTT, UINT uiCmd, const GUID* pguid);
  397.  
  398.     BOOL _UpEnabled();
  399.     void _UpdateCommonButton(int iCmd, UINT nCmdID);
  400.     void _UpdateToolbar(BOOL fForce);
  401.     void _UpdateToolbarNow();
  402.     void _UpdateGroup(const GUID *pguidCmdGroup, int cnt, OLECMD rgcmds[], const GUID* pguidButton, const int buttonsInternal[]);
  403.     void _CSHSetStatusBar(BOOL fOn);
  404.     void _StartDownload();
  405.     void _StopDownload(BOOL fClosing);
  406.     void _SendDocCommand(UINT idCmd);
  407.     BOOL _CompressBands(BOOL fCompress, UINT uRowsNew, BOOL fForceUpdate);
  408.     void _TrackSliding(int x, int y);
  409.     HRESULT _DoNavigateA(LPSTR pszURL,int iNewSelection);
  410.     HRESULT _DoNavigateW(LPWSTR pwzURL,int iNewSelection);
  411.     HRESULT _DoNavigate(BSTR bstrURL,int iNewSelection);
  412.     void _Unadvise(void);
  413.     LRESULT _OnBeginDrag(NMREBAR* pnm);
  414.  
  415.     void _InsertURL(LPTSTR pszURL);
  416.  
  417.     void _ShowContextMenu(HWND hwnd, LPARAM lParam, LPRECT prcExclude);
  418.     BOOL _ShowBackForwardMenu(BOOL fForward, POINT pt, LPRECT prcExclude);
  419.     // search helper methods
  420.     BOOL _GetFolderSearchData();
  421.     void _SetSearchStuff();
  422.     BOOL _GetSearchUrl(LPWSTR pwszUrl, DWORD cch);
  423.     HRESULT _GetFolderSearches(IFolderSearches **ppfs);
  424.  
  425.  
  426.     void _ReloadButtons();
  427.     void _UpdateToolsStyle(BOOL fList);
  428.     void _InitBitmapDSA();
  429.     void _InitForScreenSize();
  430.     void _InitToolbar();
  431.     BOOL _FoldersButtonAvailable();
  432.     void _AdminMarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons);
  433.     void _MarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons);
  434.     void _AddCommonButtons();
  435.     HRESULT _CreateBands();
  436.     BOOL    _ShowBands(UINT fVisible);
  437.     HRESULT _ShowTools(PBANDSAVE pbs);
  438.     HRESULT _ShowAddressBand(PBANDSAVE pbs);
  439.     HRESULT _ShowExternalBand(PBANDSAVE pbs, int idBand );
  440.     HRESULT _ShowLinks(PBANDSAVE pbs);
  441.     HRESULT _ShowBrand(PBANDSAVE pbs);
  442.     HRESULT _ShowMenu(PBANDSAVE pbs);
  443.     void _ShowBandCommon(PBANDSAVE pbs, LPBANDITEMDATA pbid, BOOL fShow);
  444.     void _EnsureAllBandsShown();
  445.     HRESULT _GetMinRowHeight();
  446.  
  447.     HBITMAP _LoadBackBmp(LPTSTR * ppszBitmap, BMPCACHE * pbmpCache, BOOL fInternet);
  448.     HBITMAP _LoadBackBitmap();
  449.     void    _SetBackground();
  450.     void    _CommonHandleFileSysChange(LONG lEvent, LPITEMIDLIST* ppidl);
  451.     LPITEMIDLIST _GetCurrentPidl(void);
  452.     int     _ConvertHwndToID(HWND hwnd);
  453.  
  454.     HRESULT _GetPersistedBand(const CLSID clsid, REFIID riid, void ** ppiface);
  455.  
  456.     // Multiple command target
  457.     LRESULT _AddBitmapFromForeignModule(UINT uiGetMSG, UINT uiSetMSG, UINT uiCount, HINSTANCE hinst,
  458.                                         UINT_PTR nID, COLORREF rgbMask);
  459.  
  460.     HRESULT _LoadDefaultSettings(void);
  461.     HRESULT _LoadUpgradeSettings(ULONG cbRead);
  462.     HRESULT _LoadDefaultWidths(void);
  463.     void _TryLoadIE3Settings();
  464.     HRESULT _UpdateToolbarDisplay(DWORD dwFlags, UINT uVisibleBands, BOOL fNoText, BOOL fPersist);
  465.     void _UpdateBrandSize();
  466.     void _ShowVisible(DWORD dwVisible, BOOL fPersist);
  467.     void _BuildSaveStruct(COOLBARSAVE* pcs);
  468.     void _RestoreSaveStruct(COOLBARSAVE* pcs);
  469.     void _GetVisibleBrowserBar(UINT idBar, CLSID *pclsidOut);
  470.  
  471.     LPBANDITEMDATA _AddNewBand(IDeskBand* pdb, DWORD dwID);
  472.  
  473.     void _TheaterModeLayout(BOOL fEnter);
  474.  
  475.     HBITMAP          _bmpBack; // this is the state we think the itbar is in
  476.     static BMPCACHE  s_bmpBackShell; // this is the state of the shell bmp cache
  477.     static BMPCACHE  s_bmpBackInternet; // this is the state of the internet bmp cache
  478.     static IMLCACHE  s_imlTBGlyphs;
  479.  
  480.     HWND            _hwndMenu;
  481.     HWND            _hwndAddressBand;
  482.  
  483.     IDockingWindowSite* _ptbsite;
  484.     IOleCommandTarget*  _ptbsitect;
  485.     IBrowserService2*   _pbs2;
  486.     IServiceProvider*   _psp;
  487.     IBandProxy *        _pbp;
  488.  
  489.     BITBOOL            _fCreatedBandProxy:1;
  490.     BITBOOL            _fBackEnabled:1;
  491.     BITBOOL            _fForwardEnabled:1;
  492.     BITBOOL            _fEditEnabled:1;
  493.     BITBOOL            _fShow:1;
  494.     BITBOOL            _fAnimating:1;
  495.     BITBOOL            _fCompressed:1;
  496.     BITBOOL            _fUserNavigated :1;
  497.     BITBOOL            _fAutoCompInitialized :1;
  498.     BITBOOL            _fDirty:1;
  499.     BITBOOL            _fUsingDefaultBands:1;
  500.     BITBOOL            _fTransitionToHTML:1;
  501.     BITBOOL            _fInitialPidlIsWeb:1;
  502.     BITBOOL            _fTheater: 1; // are we in theater mode?  claim no border space
  503.     BITBOOL            _fAutoHide :1;
  504.     BITBOOL            _fRebarDragging :1;
  505.     BITBOOL            _fShellView:1;   // are we in shell view or web view?
  506.     BITBOOL            _fNoShowMenu:1;    // can show menu band?
  507.     BITBOOL            _fUpdateToolbarTimer:1;
  508.     BITBOOL            _fNeedUpdateToolbar:1;
  509.     BITBOOL            _fNavigateComplete:1;
  510.     BITBOOL            _fLoading:1;     // are we still loading the bar?
  511.     BITBOOL            _fDestroyed:1;   // Did we destroy our member varibles and are shutting down? If so, don't use the varibles. (Stress bug w/messages coming in)
  512.  
  513.     UINT            _nVisibleBands;     // bitmask of which bands are visible: VBF_*
  514.  
  515.     IWebBrowser2*   _pdie;
  516.     DWORD           _dwcpCookie;        // DIID_DWebBrowserEvents2
  517.     int             _xCapture;
  518.     int             _yCapture;
  519.     // for multiple command target support
  520.     HDSA            _hdsaTBBMPs;
  521.     UINT            _uiMaxTBWidth;
  522.     UINT            _uiTBTextRows;
  523.     UINT            _uiTBDefaultTextRows;
  524.     // search stuff
  525.     HDPA            _hdpaFSI; // folder search items
  526.     GUID            _guidCurrentSearch;
  527.     GUID            _guidDefaultSearch;
  528.  
  529.     COOLBARSAVE     _cs;             //Coolbar layout info from registry!
  530.  
  531.     struct EXTERNALBANDINFO {
  532.         CLSID       clsid;          // CLSID of the band
  533.         LPWSTR      pwszName;       // Band name
  534.         LPWSTR      pwszHelp;       // Band help text
  535.     };
  536.     EXTERNALBANDINFO _rgebi[ MAXEXTERNALBANDS ];
  537.  
  538.     void _LoadExternalBandInfo();
  539.  
  540.     TBBUTTON _tbExplorer[ARRAYSIZE(c_tbExplorer)];
  541.     int      _iButtons;
  542.  
  543.  
  544. #ifdef EDIT_HACK
  545.     // Variables for customizing the edit button glyph
  546.     HIMAGELIST      _himlEdit;          // Monochrome Image list for the edit button
  547.     HIMAGELIST      _himlEditHot;       // Hot image list for edit button
  548.     int             _iEditIcon;         // index of current edit icon
  549.  
  550.     // Functions for managing a custom edit glyph
  551.     void _InitEditButtonStyle();
  552.     void _SetEditGlyph(int iIcon);
  553.     void _RefreshEditGlyph();
  554.     void _UpdateEditButton();
  555.     static HIMAGELIST _CreateGrayScaleImagelist(HBITMAP hbmpImage, HBITMAP hbmpMask);
  556.     static BSTR _GetEditProgID(IHTMLDocument2* pHTMLDocument);
  557.  
  558.     //
  559.     // We can have multiple edit verbs associated with a document.  The following class
  560.     // maintains a list of verbs.
  561.     //
  562.     #define FCIDM_EDITFIRST  2000
  563.     #define FCIDM_EDITLAST   2100
  564.     #define SZ_EDITVERB_PROP  TEXT("CEditVerb_This")
  565.     #define IL_EDITBUTTON 2     // Index of image list used for the edit button
  566.     #define IL_SEARCHBUTTON 3   //                   ||             search button
  567.  
  568.     // MSAA Menu Info declarations.
  569.     // These will eventually be incorporated into oleacc.h - but for the
  570.     // moment, we declare them privately...
  571.     #define MSAA_MENU_SIG  0xAA0DF00DL
  572.  
  573.     class CEditVerb
  574.     {
  575.     public:
  576.         CEditVerb();
  577.         ~CEditVerb();
  578.  
  579.         // Functions for managing the verbs
  580.         BOOL Add(LPTSTR pszProgID);
  581.         UINT GetSize() { return _nElements; }
  582.         void RemoveAll();
  583.  
  584.         // Functions to access the default edit verb
  585.         int   GetIcon() { return (_nElements && _pVerb[_nDefault].fShowIcon) ? _GetVerb(_nDefault).iIcon : -1; }
  586.         BOOL  GetToolTip(LPTSTR pszToolTip, UINT cchMax, BOOL fStripAmpersands = TRUE);
  587.         BOOL  GetMenuText(LPTSTR pszText, UINT cchMax) { return GetToolTip(pszText, cchMax, FALSE); }
  588.         void  Edit(LPCTSTR pszUrl) { _Edit(pszUrl, _nDefault); }
  589.  
  590.         // Pop-up menu
  591.         BOOL ShowEditMenu(POINT pt, HWND hwnd, LPTSTR pszUrl);
  592.  
  593.         // Get default editor from the registry
  594.         void InitDefaultEditor(HKEY hkey = NULL);
  595.  
  596.     protected:
  597.         struct MSAAMenuInfo
  598.         {
  599.             DWORD m_MSAASig;  // Must be MSAA_MENU_SIG
  600.             DWORD m_CharLen;  // Length in characters of text, excluding terminating NUL
  601.             LPWSTR m_pWStr;   // Menu text, in UNICODE, with terminating UNICODE-NUL.
  602.         };
  603.  
  604.         struct EDITVERB
  605.         {
  606.             MSAAMenuInfo m_MSAA;     // MSAA info - must be first element.
  607.             HKEY    hkeyProgID;      // Key the we shellexec
  608.             BITBOOL fUseOpenVerb:1;  // use open verb instead of edit
  609.             BITBOOL fInit:1;         // true if the data below has beed initialized
  610.             BITBOOL fShowIcon:1;     // true if icon should show up on button
  611.             int     iIcon;           // cached icon index
  612.             UINT    idCmd;           // menu id
  613.             LPTSTR  pszDesc;         // executable name or document name
  614.             LPTSTR  pszMenuText;     // Menu text
  615.             LPTSTR  pszExe;          // Path of the exe used to edit
  616.         };
  617.  
  618.         EDITVERB* _Add(HKEY hkeyProgID, BOOL fPermitOpenVerb, BOOL fCheckForOfficeApp, BOOL fShowIcon);
  619.         EDITVERB& _GetVerb(UINT nIndex);
  620.         void      _FetchInfo(UINT nIndex);
  621.         void      _Edit(LPCTSTR pszUrl, UINT nIndex);
  622.         LPCTSTR   _GetDescription(EDITVERB& rVerb);
  623.         void      _SetMSAAMenuInfo(EDITVERB& rVerb);
  624.         void      _ClearMSAAMenuInfo(EDITVERB& rVerb);
  625.         void      _FormatMenuText(UINT nIndex);
  626.         BOOL      _IsUnique(EDITVERB& rNewVerb);
  627.         BOOL      _IsHtmlStub(LPCWSTR pszPath);
  628.         LPCTSTR   _GetExePath(EDITVERB& rVerb);
  629.         LPCTSTR   _GetDefaultEditor();
  630.  
  631.         static LRESULT CALLBACK _WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  632.  
  633.         // Member data
  634.         UINT        _nElements;         // number of edit verbs
  635.         UINT        _nDefault;          // Default edit verb
  636.         EDITVERB*   _pVerb;             // array of edit verbs
  637.         WNDPROC     _lpfnOldWndProc;    // former wndProc
  638.         LPWSTR      _pszDefaultEditor;  // Friendly name of default HTML editor
  639.         BOOL        _fInitEditor;       // if we checked for a default editor
  640.     };
  641.     CEditVerb  _aEditVerb;
  642.  
  643. #endif
  644.  
  645.     // internal bandsite class
  646.     class CBrowserToolsBand;
  647.     class CITBandSite : public CBandSite
  648.     {
  649.         CITBandSite();
  650.  
  651.         virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  652.         virtual STDMETHODIMP AddBand(IUnknown *punk);
  653.         virtual STDMETHODIMP HasFocusIO();
  654.  
  655.     protected:
  656.         virtual void v_SetTabstop(LPREBARBANDINFO prbbi);
  657.         BOOL _SetMinDimensions();
  658.         friend class CInternetToolbar;
  659.         friend class CBrowserToolsBand;
  660.  
  661.         virtual HRESULT _OnContextMenu(WPARAM wParm, LPARAM lParam);
  662.         virtual HRESULT _Initialize(HWND hwndParent);
  663.  
  664.     };
  665.     CITBandSite _bs;
  666.  
  667.  
  668. #define TOOLSBANDCLASS CInternetToolbar::CBrowserToolsBand
  669.     class CBrowserToolsBand : public CToolbarBand
  670.     {
  671.         CMDMAP* _GetCmdMapByIndex(int nIndex) { return _GetCmdMap(nIndex, TRUE);};
  672.         CMDMAP* _GetCmdMapByID(int id)  { return _GetCmdMap(id, FALSE);};
  673.         LRESULT _ToolsCustNotify (LPNMHDR pnmh);  // Handle TBCustomization Notify
  674.         BOOL _SaveRestoreToolbar(BOOL fSave);
  675.         void _FreeCustomizeInfo();
  676.         void _FreeCmdMap(CMDMAP*);
  677.         BOOL _RemoveAllButtons();
  678.         int _CommandFromIndex(UINT uIndex);
  679.         HRESULT _ConvertCmd(const GUID* pguidButtonGroup, UINT id, GUID* pguidOut, UINT * pid);
  680.         void _OnDeletingButton(TBNOTIFY* ptbn);
  681.         LONG_PTR _AddString(LPWSTR pwstr);
  682.         void _PreProcessButtonString(TBBUTTON *ptbn, DWORD dwFlags);
  683.         void _PreProcessExternalTBButton(TBBUTTON *ptbn);
  684.         UINT _ProcessExternalButtons(PTBBUTTON ptbb, UINT cButtons);
  685.         void _GetButtons(IOleCommandTarget* pct, const GUID* pguid, HDSA hdsa);
  686.         void _RecalcButtonWidths();
  687.  
  688.         void            _UpdateTextSettings(INT_PTR ids);
  689.         static BOOL_PTR CALLBACK _BtnAttrDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  690.         static void     _PopulateComboBox(HWND hwnd, const int iResource[], UINT cResources);
  691.         static void     _SetComboSelection(HWND hwnd, int iCurOption);
  692.         void            _SetDialogSelections(HWND hDlg, BOOL fSmallIcons);
  693.         static void     _PopulateDialog(HWND hDlg);
  694.         void            _OnBeginCustomize(LPNMTBCUSTOMIZEDLG pnm);
  695.  
  696.         BOOL _BuildButtonDSA();
  697.         CMDMAPCUSTOMIZE* _GetCmdMapCustomize(GUID* guid, UINT nCmdID);
  698.  
  699.         virtual STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut);
  700.  
  701.         virtual STDMETHODIMP GetClassID(CLSID *pClassID) {return E_NOTIMPL;};
  702.         virtual STDMETHODIMP Load(IStream *pStm) {return E_NOTIMPL;};
  703.         virtual STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty) {return E_NOTIMPL;};
  704.  
  705.         // *** IUnknown ***
  706.         virtual STDMETHODIMP_(ULONG) AddRef(void) { return CToolBand::AddRef(); };
  707.         virtual STDMETHODIMP_(ULONG) Release(void){ return CToolBand::Release(); };
  708.         virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  709.  
  710.         // *** IDeskBand methods ***
  711.         virtual STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD fViewMode, DESKBANDINFO* pdbi);
  712.  
  713.         // *** IWinEventHandler methods ***
  714.         virtual STDMETHODIMP OnWinEvent(HWND hwnd, UINT dwMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres);
  715.  
  716.         // *** IDockingWindow methods ***
  717.         virtual STDMETHODIMP CloseDW(DWORD dwReserved) { return S_OK;};
  718.  
  719.         // *** IInputObject methods ***
  720.         virtual STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg);
  721.  
  722.     protected:
  723.         IOleCommandTarget* _CommandTargetFromCmdMap(CMDMAP* pcm);
  724.         LRESULT _OnToolbarDropDown(TBNOTIFY *ptbn);
  725.         virtual LRESULT _OnNotify(LPNMHDR pnmh);
  726.         LRESULT _OnContextMenu(LPARAM lParam, WPARAM wParam);
  727.         CMDMAP* _GetCmdMap(int i, BOOL fByIndex);
  728.         void _OnEndCustomize();
  729.         LRESULT _TryShowBackForwardMenu(DWORD dwItemSpec, LPPOINT ppt, LPRECT prcExclude);
  730.         CBrowserToolsBand();
  731.         void _FreeBtnsAdded();
  732.  
  733.         friend class CInternetToolbar;
  734.         friend class CITBandSite;
  735.  
  736.         GUID            _guidCurrentButtonGroup;
  737.         IOleCommandTarget* _pctCurrentButtonGroup;
  738.         LPTBBUTTON      _pbtnsAdded;
  739.         int             _cBtnsAdded;
  740.         DWORD            _nNextCommandID;
  741.         CUSTOMIZEINFO *_pcinfo;
  742.         BITBOOL    _fCustomize :1;
  743.         BITBOOL    _fNeedFreeCmdMapsAdded :1;
  744.     };
  745.  
  746.     CBrowserToolsBand _btb;
  747.  
  748.     friend class CBrowserToolsBand;
  749.     friend class CITBandSite;
  750.     friend void CInternetToolbar_CleanUp();
  751.     friend void CInternetToolbar_Preload();
  752.     friend void ITBar_LoadToolbarGlyphs(HWND hwnd);
  753. };
  754.  
  755. //
  756. // Gets the stream corresponding to the type of the given pidl
  757. //     If the stream already doesn't exist, then it returns NULL.
  758.  
  759. HRESULT _GetStreamName(DWORD dwITBS, LPTSTR pszName, DWORD cchSize)
  760. {
  761.     HRESULT hr = S_OK;
  762.  
  763.     ASSERT(pszName);
  764.  
  765.     switch (dwITBS)
  766.     {
  767.     case ITBS_WEB:
  768.         StrCpyN(pszName, TEXT("WebBrowser"), cchSize);
  769.         break;
  770.  
  771.     case ITBS_SHELL:
  772.         StrCpyN(pszName, TEXT("ShellBrowser"), cchSize);
  773.         break;
  774.  
  775.     case ITBS_EXPLORER:
  776.         StrCpyN(pszName, TEXT("Explorer"), cchSize);
  777.         break;
  778.  
  779.     default:
  780.         hr = E_FAIL;
  781.         break;
  782.     }
  783.  
  784.     if (FAILED(hr))
  785.         pszName[0] = '\0';
  786.  
  787.     return hr;
  788. }
  789.  
  790.  
  791. //
  792. // Gets the stream corresponding to the type of the given pidl
  793. //     If the stream already doesn't exist, then it returns NULL.
  794.  
  795. IStream *GetRegStream(BOOL fInternet, LPCTSTR pszValue, DWORD grfMode)
  796. {
  797.     IStream *pstm = NULL;
  798.     HKEY    hkToolbar;
  799.  
  800.     if (RegCreateKey(HKEY_CURRENT_USER, c_szRegKeyCoolbar, &hkToolbar) == ERROR_SUCCESS)
  801.     {
  802.         TCHAR   szStreamName[MAX_PATH];
  803.  
  804.         if (SUCCEEDED(_GetStreamName(fInternet, szStreamName, ARRAYSIZE(szStreamName))))
  805.             pstm = OpenRegStream(hkToolbar, szStreamName, pszValue, grfMode);
  806.  
  807.         RegCloseKey(hkToolbar);
  808.     }
  809.  
  810.     return(pstm);
  811. }
  812.  
  813.  
  814. //
  815. // Gets the stream corresponding to the type of the given pidl
  816. //     If the stream already doesn't exist, then it returns NULL.
  817.  
  818. IStream *GetITBarStream(BOOL fInternet, DWORD grfMode)
  819. {
  820.     return GetRegStream(fInternet, TEXT("ITBarLayout"), grfMode);
  821. }
  822.  
  823.  
  824. IMLCACHE CInternetToolbar::s_imlTBGlyphs = {NULL};
  825. BMPCACHE CInternetToolbar::s_bmpBackShell = {NULL};
  826. BMPCACHE CInternetToolbar::s_bmpBackInternet = {NULL};
  827. BOOL g_fSmallIcons = FALSE;
  828.  
  829. void IMLCACHE_CleanUp(IMLCACHE * pimlCache, DWORD dwFlags)
  830. {
  831.     for (int i = 0; i < CIMLISTS; i++)
  832.     {
  833.         if (pimlCache->arhimlPendingDelete[i])
  834.             ImageList_Destroy(pimlCache->arhimlPendingDelete[i]);
  835.  
  836.         if ((dwFlags & IML_DESTROY) && pimlCache->arhiml[i])
  837.             ImageList_Destroy(pimlCache->arhiml[i]);
  838.     }
  839. }
  840.  
  841. void ITBar_LoadToolbarGlyphs(HWND hwnd)
  842. {
  843.     int cx, idBmp;
  844.  
  845.     g_fSmallIcons = _UseSmallIcons();
  846.  
  847.     if (g_fSmallIcons) {
  848.         cx = TB_SMBMP_CX;
  849.         idBmp = IDB_IETOOLBAR16;
  850.     } else {
  851.         cx = TB_BMP_CX;
  852.         idBmp = IDB_IETOOLBAR;
  853.     }
  854.  
  855.     if (SHGetCurColorRes() > 8)
  856.         idBmp += DELTA_HICOLOR;
  857.  
  858.     _LoadToolbarGlyphs(hwnd, &CInternetToolbar::s_imlTBGlyphs, cx, idBmp);
  859. }
  860.  
  861.  
  862. void CInternetToolbar_Preload()
  863. {
  864.    ENTERCRITICAL;
  865.    ITBar_LoadToolbarGlyphs(NULL);
  866.    Brand_InitBrandContexts();
  867.    LEAVECRITICAL;
  868. }
  869.  
  870.  
  871. void CInternetToolbar_CleanUp()
  872. {
  873.     TraceMsg(DM_ITBAR, "CInternetToolbar: Destroying shared GDI objects");
  874.     if (CInternetToolbar::s_bmpBackInternet.hbmp)
  875.         DeleteObject(CInternetToolbar::s_bmpBackInternet.hbmp);
  876.     if (CInternetToolbar::s_bmpBackShell.hbmp)
  877.         DeleteObject(CInternetToolbar::s_bmpBackShell.hbmp);
  878.  
  879.     IMLCACHE_CleanUp(&CInternetToolbar::s_imlTBGlyphs, IML_DESTROY);
  880. }
  881.  
  882. STDAPI CInternetToolbar_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  883. {
  884.     // aggregation checking is handled in class factory
  885.  
  886.     CInternetToolbar *pitbar = new CInternetToolbar();
  887.     if (pitbar)
  888.     {
  889.         *ppunk = SAFECAST(pitbar, IDockingWindow *);
  890.         return S_OK;
  891.     }
  892.  
  893.     return E_OUTOFMEMORY;
  894. }
  895.  
  896. LRESULT CInternetToolbar::v_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  897. {
  898.     if ( uMsg == WM_SYSCOLORCHANGE )
  899.     {
  900.         // refresh the back drop incase the colours have changed
  901.         _SetBackground();
  902.     }
  903.  
  904.     return SUPERCLASS::v_WndProc( hwnd, uMsg, wParam, lParam );
  905. }
  906.  
  907. void CInternetToolbar::_LoadExternalBandInfo()
  908. {
  909. #ifdef DEBUG
  910.     int i;
  911.     // Should have been zero-initialized
  912.     for (i = 0; i < ARRAYSIZE(_rgebi); i++)
  913.     {
  914.  
  915.         ASSERT(IsEqualGUID(_rgebi[i].clsid, GUID_NULL));
  916.         ASSERT(_rgebi[i].pwszName == NULL);
  917.         ASSERT(_rgebi[i].pwszHelp == NULL);
  918.     }
  919. #endif
  920.  
  921.     HKEY hkey;
  922.     DWORD dwClsidIndex = 0;
  923.     if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_KEY_BANDSTATE, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  924.     {
  925.         TCHAR tszReg[MAX_PATH];
  926.         StrCpy(tszReg, TEXT("CLSID\\"));
  927.         const int cchClsidPrefix = 6;      // 6 = strlen("CLSID\\")
  928.         LPTSTR ptszClsid = tszReg + cchClsidPrefix;
  929.         DWORD cchClsid;
  930.         for (DWORD dwIndex = 0;
  931.              cchClsid = ARRAYSIZE(tszReg) - cchClsidPrefix,
  932.              dwClsidIndex < ARRAYSIZE(_rgebi) &&
  933.              RegEnumValue( hkey, dwIndex, ptszClsid, &cchClsid, NULL, NULL, NULL, NULL ) == ERROR_SUCCESS;
  934.              dwIndex++)
  935.         {
  936.             CLSID clsid;
  937.             if (GUIDFromString( ptszClsid, &clsid ))
  938.             {
  939.                 // Don't save the CLSID until we're sure it worked
  940.                 _rgebi[dwClsidIndex].clsid = clsid;
  941.  
  942.                 HKEY hkeyClsid;
  943.                 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, tszReg, 0, KEY_READ, &hkeyClsid) == ERROR_SUCCESS)
  944.                 {
  945.                     WCHAR wszBuf[MAX_PATH];
  946.  
  947.                     // Get the name; use SHLoadRegUIString so the app can localize
  948.                     SHLoadRegUIStringW( hkeyClsid, L"", wszBuf, ARRAYSIZE(wszBuf) );
  949.                     Str_SetPtrW( &_rgebi[dwClsidIndex].pwszName, wszBuf);
  950.  
  951.                     // Get the help; use SHLoadRegUIString so the app can localize
  952.                     SHLoadRegUIStringW( hkeyClsid, L"HelpText", wszBuf, ARRAYSIZE(wszBuf) );
  953.                     Str_SetPtrW( &_rgebi[dwClsidIndex].pwszHelp, wszBuf);
  954.  
  955.                     RegCloseKey(hkeyClsid);
  956.                 }
  957.  
  958.                 dwClsidIndex++;
  959.             }
  960.         }
  961.         RegCloseKey( hkey );
  962.     }
  963. }
  964.  
  965. CInternetToolbar::CInternetToolbar() : CBaseBar(), _yCapture(-1), _iButtons(-1)
  966. #ifdef EDIT_HACK
  967. , _iEditIcon(-1)
  968. #endif
  969. {
  970.  
  971.     DllAddRef();
  972.  
  973.     if (GetSystemMetrics(SM_CXSCREEN) < 650)
  974.         _uiMaxTBWidth = MAX_TB_WIDTH_LORES;
  975.     else
  976.         _uiMaxTBWidth = MAX_TB_WIDTH_HIRES;
  977.  
  978.     ASSERT(_fLoading == FALSE);
  979.     ASSERT(_btb._guidCurrentButtonGroup == CLSID_NULL);
  980.     _btb._nNextCommandID = 1000;
  981.  
  982.     _LoadExternalBandInfo();
  983. }
  984.  
  985. void CInternetToolbar::_Unadvise(void)
  986. {
  987.     if(_dwcpCookie)
  988.     {
  989.         ConnectToConnectionPoint(NULL, DIID_DWebBrowserEvents2, FALSE, _pdie, &_dwcpCookie, NULL);
  990.     }
  991. }
  992.  
  993. int CALLBACK DeleteDPAPtrCB(void *pItem, void *pData)
  994. {
  995.     LocalFree(pItem);
  996.     return TRUE;
  997. }
  998.  
  999. CInternetToolbar::~CInternetToolbar()
  1000. {
  1001.     ATOMICRELEASE(_pdie);
  1002.  
  1003.     if(_pbp && _fCreatedBandProxy)
  1004.         _pbp->SetSite(NULL);
  1005.  
  1006.     ATOMICRELEASE(_pbp);
  1007.  
  1008.     ASSERT(!_ptbsite && !_ptbsitect && !_psp && !_pbs2);
  1009.     SetSite(NULL);
  1010.  
  1011.     DPA_DestroyCallback(_hdpaFSI, DeleteDPAPtrCB, NULL);
  1012.  
  1013.     for (int i = 0; i < ARRAYSIZE(_rgebi); i++)
  1014.     {
  1015.         Str_SetPtrW( &_rgebi[i].pwszName, NULL);
  1016.         Str_SetPtrW( &_rgebi[i].pwszHelp, NULL);
  1017.     }
  1018.  
  1019.     TraceMsg(TF_SHDLIFE, "dtor CInternetToolbar %x", this);
  1020.     DllRelease();
  1021. }
  1022.  
  1023. #define IID_DWebBrowserEvents DIID_DWebBrowserEvents
  1024.  
  1025.  
  1026. HRESULT CInternetToolbar::QueryInterface(REFIID riid, void ** ppvObj)
  1027. {
  1028.     static const QITAB qit[] = {
  1029.         // perf: last tuned 980728
  1030.         QITABENTMULTI(CInternetToolbar, IDispatch, DWebBrowserEvents),  // IID_IDispatch
  1031.         QITABENT(CInternetToolbar, IExplorerToolbar),       // IID_IDispatch
  1032.         QITABENT(CInternetToolbar, IObjectWithSite),        // IID_IObjectWithSite
  1033.         QITABENT(CInternetToolbar, IPersistStreamInit),     // IID_IPersistStreamInit
  1034.         QITABENT(CInternetToolbar, IDockingWindow),         // IID_IDockingWindow
  1035.         QITABENT(CInternetToolbar, DWebBrowserEvents),      // IID_DWebBrowserEvents
  1036.         QITABENT(CInternetToolbar, IShellChangeNotify),     // rare IID_IShellChangeNotify
  1037.         QITABENT(CInternetToolbar, ISearchItems),           // rare IID_ISearchItems
  1038.         { 0 },
  1039.     };
  1040.  
  1041.     HRESULT hres = QISearch(this, qit, riid, ppvObj);
  1042.     if (FAILED(hres))
  1043.         hres = SUPERCLASS::QueryInterface(riid, ppvObj);
  1044.  
  1045.     return hres;
  1046. }
  1047.  
  1048. /* IDispatch methods */
  1049. HRESULT CInternetToolbar::GetTypeInfoCount(UINT *pctinfo)
  1050. {
  1051.     return(E_NOTIMPL);
  1052. }
  1053.  
  1054. HRESULT CInternetToolbar::GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo)
  1055. {
  1056.     return(E_NOTIMPL);
  1057. }
  1058.  
  1059. HRESULT CInternetToolbar::GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames,
  1060.                                         LCID lcid, DISPID * rgdispid)
  1061. {
  1062.     return(E_NOTIMPL);
  1063. }
  1064.  
  1065. #if 0
  1066. //  BUGBUG - StevePro changed it so this code isnt called
  1067. //  this is a goodness, because it calls SHVerbExists() which
  1068. //  is a TCHAR API, that is actually compiled as an ANSI API
  1069. //  and since we are UNICODE it just always fails.
  1070. //  leaving this in so that we know about the issue of
  1071. //  frontpad.exe possibly needing to be disabled.
  1072. BOOL _ShowEditForExtension(LPCTSTR pszExtension)
  1073. {
  1074.     TCHAR szBuf[MAX_PATH];
  1075.     if (SHVerbExists(pszExtension, TEXT("edit"), szBuf)) {
  1076.         // don't show it if it's just our own
  1077.         if (StrStrI(szBuf, TEXT("frontpad.exe"))) {
  1078.             return FALSE;
  1079.         }
  1080.         return TRUE;
  1081.     }
  1082.  
  1083.     return FALSE;
  1084. }
  1085. #endif
  1086.  
  1087. #ifdef EDIT_HACK
  1088. //+-------------------------------------------------------------------------
  1089. // This function scans the html document for META tags that indicate the
  1090. // program that was used to create the HTML page.  Examples are:
  1091. //
  1092. //  <meta name="ProgID" content="word.document" >
  1093. //  <meta name="ProgID" content="excel.sheet" >
  1094. //
  1095. // If a match is found, the content of the first match is returned.  This
  1096. // progid is used to edit the document.
  1097. //--------------------------------------------------------------------------
  1098. BSTR CInternetToolbar::_GetEditProgID
  1099. (
  1100.     IHTMLDocument2* pHTMLDocument
  1101. )
  1102. {
  1103.     BSTR bstrProgID = NULL;
  1104.  
  1105.     //
  1106.     // First get all document elements.  Note that this is very fast in
  1107.     // ie5 because the collection directly accesses the internal tree.
  1108.     //
  1109.     IHTMLElementCollection * pAllCollection;
  1110.     if (SUCCEEDED(pHTMLDocument->get_all(&pAllCollection)))
  1111.     {
  1112.         IHTMLMetaElement* pMetaElement;
  1113.         IHTMLBodyElement* pBodyElement;
  1114.         IHTMLFrameSetElement* pFrameSetElement;
  1115.         IDispatch* pDispItem;
  1116.  
  1117.         //
  1118.         // Now we scan the document for meta tags.  Since these must reside in
  1119.         // in the head, and since Trident always creates a body tag, we can
  1120.         // stop looking when we hit the body.
  1121.         //
  1122.         // Note, the alternative of using pAllCollection->tags to return the
  1123.         // collection of meta tags is likely more expensive because it will
  1124.         // walk the whole tree (unless Trident optimizes this).
  1125.         //
  1126.         long lItemCnt;
  1127.         VARIANT vEmpty;
  1128.         V_VT(&vEmpty) = VT_EMPTY;
  1129.  
  1130.         VARIANT vIndex;
  1131.         V_VT(&vIndex) = VT_I4;
  1132.  
  1133.         EVAL(SUCCEEDED(pAllCollection->get_length(&lItemCnt)));
  1134.  
  1135.         for (long lItem = 0; lItem < lItemCnt; lItem++)
  1136.         {
  1137.             V_I4(&vIndex) = lItem;
  1138.  
  1139.             if (S_OK == pAllCollection->item(vIndex, vEmpty, &pDispItem))
  1140.             {
  1141.                 //
  1142.                 // First see if it's a meta tag
  1143.                 //
  1144.                 if (SUCCEEDED(pDispItem->QueryInterface(IID_IHTMLMetaElement,
  1145.                                                     (void **)&pMetaElement)))
  1146.                 {
  1147.                     BSTR bstrName = NULL;
  1148.  
  1149.                     //
  1150.                     // We have a META element, check its NAME and CONTENT
  1151.                     //
  1152.                     if ( SUCCEEDED(pMetaElement->get_name(&bstrName)) && (bstrName != NULL) &&
  1153.                          (StrCmpIW(bstrName, OLESTR("ProgId")) == 0) &&
  1154.                          SUCCEEDED(pMetaElement->get_content(&bstrProgID)) && (bstrProgID != NULL)
  1155.                        )
  1156.                     {
  1157.                         // We got the ProgID, so terminate the search;
  1158.                         lItem = lItemCnt;
  1159.                     }
  1160.  
  1161.                     if (bstrName != NULL)
  1162.                         SysFreeString(bstrName);
  1163.  
  1164.                     pMetaElement->Release();
  1165.                 }
  1166.                 //
  1167.                 // Next check for the body tag
  1168.                 //
  1169.                 else if (SUCCEEDED(pDispItem->QueryInterface(IID_IHTMLBodyElement,
  1170.                                                     (void **)&pBodyElement)) )
  1171.                 {
  1172.                     // Found the body tag, so terminate the search
  1173.                     lItem = lItemCnt;
  1174.                     pBodyElement->Release();
  1175.                 }
  1176.                 //
  1177.                 // Finally, check for a frameset tag
  1178.                 //
  1179.                 else if (SUCCEEDED(pDispItem->QueryInterface(IID_IHTMLFrameSetElement,
  1180.                                                     (void **)&pFrameSetElement)) )
  1181.                 {
  1182.                     // Found a frameset tag, so terminate the search
  1183.                     lItem = lItemCnt;
  1184.                     pFrameSetElement->Release();
  1185.                 }
  1186.                 pDispItem->Release();
  1187.             }
  1188.         }
  1189.         // Make sure that these don't have to be cleared (should not have been modified)
  1190.         ASSERT(vEmpty.vt == VT_EMPTY);
  1191.         ASSERT(vIndex.vt == VT_I4);
  1192.  
  1193.         pAllCollection->Release();
  1194.     }
  1195.  
  1196.     return bstrProgID;
  1197. }
  1198.  
  1199. //+-------------------------------------------------------------------------
  1200. // Returns grey-scale image from the icon passed in.
  1201. //--------------------------------------------------------------------------
  1202. HIMAGELIST CInternetToolbar::_CreateGrayScaleImagelist(HBITMAP hbmpImage, HBITMAP hbmpMask)
  1203. {
  1204.     // Determine the button dimensions
  1205.     int cx = g_fSmallIcons ? TB_SMBMP_CX : TB_BMP_CX;
  1206.     int cy = g_fSmallIcons ? TB_SMBMP_CY : TB_BMP_CY;
  1207.  
  1208.     // Start with a 24 bit color image list
  1209.     HIMAGELIST himlEdit = ImageList_Create(cx, cy, ILC_COLOR24 | ILC_MASK, 1, 1);
  1210.     if (NULL == himlEdit)
  1211.     {
  1212.         return NULL;
  1213.     }
  1214.  
  1215.     ImageList_Add(himlEdit, hbmpImage, hbmpMask);
  1216.  
  1217.     // Get the dib section from the image list
  1218.     IMAGEINFO ii;
  1219.     if (ImageList_GetImageInfo(himlEdit, 0, &ii))
  1220.     {
  1221.         DIBSECTION ds = {0};
  1222.         if (GetObject(ii.hbmImage, sizeof(ds), &ds))
  1223.         {
  1224.             //
  1225.             // Map each pixel to a monochrome equivalent.
  1226.             //
  1227.             BYTE* pBits = (BYTE*)ds.dsBm.bmBits;
  1228.             BYTE* pScan = pBits;
  1229.             int xWid = ds.dsBm.bmWidth;
  1230.             int yHei = ds.dsBm.bmHeight;
  1231.             long cbScan = ((xWid * 24 + 31) & ~31) / 8;
  1232.  
  1233.             for (int y=0; y < yHei; ++y)
  1234.             {
  1235.                 for (int x=0; x < xWid; ++x)
  1236.                 {
  1237.                     //
  1238.                     // Map to equivalent gray color by setting r,g,b to the same value.
  1239.                     // Using the average of r,g,b can be too dark, and using the max
  1240.                     // of r,g,b can be too bright.  So, as a simple algorithm we use
  1241.                     // the average of the two schemes.  This is cheaper than using true
  1242.                     // intensity matching.
  1243.                     //
  1244.                     BYTE nMax = max(max(pScan[0], pScan[1]), pScan[2]);
  1245.                     BYTE nAve = ((UINT)pScan[0] + pScan[1] + pScan[2])/3;
  1246.                     pScan[0] = pScan[1] = pScan[2] = ((UINT)nMax + nAve)/2;
  1247.  
  1248.                     // Increment to next pixel
  1249.                     pScan += 3;
  1250.                 }
  1251.  
  1252.                 // Increment to the next scan line
  1253.                 pBits += cbScan;
  1254.                 pScan = pBits;
  1255.             }
  1256.         }
  1257.     }
  1258.     return himlEdit;
  1259. }
  1260.  
  1261. //+-------------------------------------------------------------------------
  1262. // Returns image and mask bitmaps for the desired image list item
  1263. //--------------------------------------------------------------------------
  1264. BOOL MyImageList_GetBitmaps
  1265. (
  1266.     HIMAGELIST himl,        // image list to use
  1267.     int iImage,             // image to copy
  1268.     int x,                  // x-offset to draw in bitmap
  1269.     int y,                  // x-offset to draw in bitmap
  1270.     int cx,                 // width of bitmap
  1271.     int cy,                 // height of bitmap
  1272.     HBITMAP* phbmpImage,    // returned color bitmap
  1273.     HBITMAP* phbmpMask      // returned mask bitmap
  1274. )
  1275. {
  1276.     ASSERT(phbmpImage);
  1277.     ASSERT(phbmpMask);
  1278.  
  1279.     BOOL fRet = FALSE;
  1280.     HDC hdc = GetDC(NULL);
  1281.     HDC hdcDst = CreateCompatibleDC(hdc);
  1282.     if (hdcDst)
  1283.     {
  1284.         HBITMAP hbmpImage = CreateCompatibleBitmap(hdc, cx, cy);
  1285.         if (hbmpImage)
  1286.         {
  1287.             HBITMAP hbmpMask = CreateBitmap(cx, cy, 1, 1, NULL);
  1288.             if (hbmpMask)
  1289.             {
  1290.                 // Draw  mask bitmap
  1291.                 HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcDst, hbmpMask);
  1292.                 PatBlt(hdcDst, 0, 0, cx, cy, WHITENESS);
  1293.                 ImageList_Draw(himl, iImage, hdcDst, x, y, ILD_MASK);
  1294.  
  1295.                 // Draw image bitmap
  1296.                 SelectObject(hdcDst, hbmpImage);
  1297.                 ImageList_Draw(himl, iImage, hdcDst, x, y, ILD_NORMAL);
  1298.  
  1299.                 SelectObject(hdcDst, hbmpOld);
  1300.  
  1301.                 *phbmpImage = hbmpImage;
  1302.                 *phbmpMask  = hbmpMask;
  1303.                 fRet = TRUE;
  1304.             }
  1305.             else
  1306.             {
  1307.                 DeleteObject(hbmpImage);
  1308.             }
  1309.         }
  1310.         DeleteDC(hdcDst);
  1311.     }
  1312.     ReleaseDC(NULL, hdc);
  1313.  
  1314.     return fRet;
  1315. }
  1316. extern HBITMAP CreateMirroredBitmap( HBITMAP hbmOrig);
  1317.  
  1318. //+-------------------------------------------------------------------------
  1319. // Creates a special image list for the edit button and configures the edit
  1320. // button to use it.  If the hIcon is -1, the edit button is reset to use
  1321. // it's default glyph.
  1322. //--------------------------------------------------------------------------
  1323. void CInternetToolbar::_SetEditGlyph
  1324. (
  1325.     int iIcon   // new edit button glyph, index into shell image cache
  1326. )
  1327. {
  1328.     // If no toolbar, we just need to see if we need to free the old image lists.
  1329.     if (_btb._hwnd == NULL)
  1330.     {
  1331.         if (iIcon == -1)
  1332.         {
  1333.             if (_himlEdit)
  1334.             {
  1335.                 ImageList_Destroy(_himlEdit);
  1336.                 _himlEdit = NULL;
  1337.             }
  1338.             if (_himlEditHot)
  1339.             {
  1340.                 ImageList_Destroy(_himlEditHot);
  1341.                 _himlEditHot = NULL;
  1342.             }
  1343.         }
  1344.         else
  1345.         {
  1346.             // Can't set the glyph if no toolbar!
  1347.             ASSERT(FALSE);
  1348.         }
  1349.         return;
  1350.     }
  1351.  
  1352.     UINT uiCmd = -1;
  1353.     // Dochost merges under one of two clsids, so have to check both
  1354.     if (FAILED(_btb._ConvertCmd(&CLSID_InternetButtons, DVIDM_EDITPAGE, NULL, &uiCmd)) &&
  1355.         FAILED(_btb._ConvertCmd(&CLSID_MSOButtons, DVIDM_EDITPAGE, NULL, &uiCmd)))
  1356.     {
  1357.         // The edit button is not on toolbar, so free the edit glyphs
  1358.         iIcon = -1;
  1359.     }
  1360.  
  1361.     // If the current icon is already set, we are done
  1362.     if (_iEditIcon == iIcon)
  1363.     {
  1364.         if (_himlEdit)
  1365.         {
  1366.             // Set up the new image lists
  1367.             SendMessage(_btb._hwnd, TB_SETIMAGELIST, IL_EDITBUTTON, (LPARAM)_himlEdit);
  1368.             if (_himlEditHot)
  1369.             {
  1370.                 SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, IL_EDITBUTTON, (LPARAM)_himlEditHot);
  1371.             }
  1372.  
  1373.             // Redirect the edit button to the new image list
  1374.             TBBUTTONINFO tbi = {0};
  1375.             tbi.cbSize = sizeof(tbi);
  1376.             tbi.dwMask = TBIF_IMAGE;
  1377.             tbi.iImage = MAKELONG(0, IL_EDITBUTTON);
  1378.  
  1379.             SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
  1380.         }
  1381.         return;
  1382.     }
  1383.  
  1384.     _iEditIcon = iIcon;
  1385.  
  1386.     if (-1 == iIcon)
  1387.     {
  1388.         if (_himlEdit)
  1389.         {
  1390.             if (uiCmd != -1)
  1391.             {
  1392.                 // Reset to the original edit glyph
  1393.                 TBBUTTONINFO tbi = {0};
  1394.                 tbi.cbSize = sizeof(tbi);
  1395.                 tbi.dwMask = TBIF_IMAGE;
  1396.                 tbi.iImage = EDITGLYPH_OFFSET;
  1397.                 SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
  1398.             }
  1399.  
  1400.             // Destroy the custom edit glyphs.  Note that we have to reset the primary image list
  1401.             // or the image sizes are screwed up.
  1402.             SendMessage(_btb._hwnd, TB_SETIMAGELIST, IL_EDITBUTTON, (LPARAM)NULL);
  1403.             ImageList_Destroy(_himlEdit);
  1404.             _himlEdit = NULL;
  1405.         }
  1406.  
  1407.         if (_himlEditHot)
  1408.         {
  1409.             SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, IL_EDITBUTTON, (LPARAM)NULL);
  1410.             ImageList_Destroy(_himlEditHot);
  1411.             _himlEditHot = NULL;
  1412.         }
  1413.     }
  1414.     else
  1415.     {
  1416.         // Determine the button dimensions
  1417.         int cx = g_fSmallIcons ? TB_SMBMP_CX : TB_BMP_CX;
  1418.         int cy = g_fSmallIcons ? TB_SMBMP_CY : TB_BMP_CY;
  1419.  
  1420.         // Get the image bitmaps
  1421.         HBITMAP hbmpImage = NULL;
  1422.         HBITMAP hbmpMask = NULL;
  1423.         BOOL bMirrored = IS_WINDOW_RTL_MIRRORED(_btb._hwnd);
  1424.         HIMAGELIST himlSmall;
  1425.         int cxSmall;
  1426.         int cySmall;
  1427.  
  1428.         if (Shell_GetImageLists(NULL, &himlSmall) &&
  1429.             ImageList_GetIconSize(himlSmall, &cxSmall, &cySmall) &&
  1430.             MyImageList_GetBitmaps(himlSmall, iIcon, (cx - cxSmall)/2, (cy - cySmall)/2,
  1431.                                    cx, cy, &hbmpImage, &hbmpMask))
  1432.         {
  1433.             if (bMirrored)
  1434.             {
  1435.                 HBITMAP hbmpTemp;
  1436.  
  1437.                 hbmpTemp = CreateMirroredBitmap(hbmpImage);
  1438.                 if (hbmpTemp)
  1439.                 {
  1440.                     DeleteObject(hbmpImage);
  1441.                     hbmpImage = hbmpTemp;
  1442.                 }
  1443.                 hbmpTemp = CreateMirroredBitmap(hbmpMask);
  1444.                 if (hbmpTemp)
  1445.                 {
  1446.                     DeleteObject(hbmpMask);
  1447.                     hbmpMask = hbmpTemp;
  1448.                 }
  1449.             }
  1450.             // Create a monochrome glyph for the edit button
  1451.             HIMAGELIST himlEdit = _CreateGrayScaleImagelist(hbmpImage, hbmpMask);
  1452.             SendMessage(_btb._hwnd, TB_SETIMAGELIST, IL_EDITBUTTON, (LPARAM)himlEdit);
  1453.             if (_himlEdit)
  1454.             {
  1455.                 ImageList_Destroy(_himlEdit);
  1456.             }
  1457.             _himlEdit = himlEdit;
  1458.  
  1459.             // Create a hot glyph for the edit button
  1460.             HIMAGELIST himlEditHot = ImageList_Create(cx, cy, ILC_COLORDDB | ILC_MASK, 1, 1);
  1461.             int nIndex = ImageList_Add(himlEditHot, hbmpImage, hbmpMask);
  1462.  
  1463.             SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, IL_EDITBUTTON, (LPARAM)himlEditHot);
  1464.             if (_himlEditHot)
  1465.             {
  1466.                 ImageList_Destroy(_himlEditHot);
  1467.             }
  1468.             _himlEditHot = himlEditHot;
  1469.  
  1470.             // Redirect the edit button to the new image list
  1471.             if (_himlEdit)
  1472.             {
  1473.                 TBBUTTONINFO tbi = {0};
  1474.                 tbi.cbSize = sizeof(tbi);
  1475.                 tbi.dwMask = TBIF_IMAGE;
  1476.                 tbi.iImage = MAKELONG(nIndex, IL_EDITBUTTON);
  1477.  
  1478.                 SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
  1479.             }
  1480.  
  1481.             DeleteObject(hbmpImage);
  1482.             DeleteObject(hbmpMask);
  1483.         }
  1484.         else
  1485.         {
  1486.             // Couldn't create images so use the default edit glyph
  1487.             _SetEditGlyph(-1);
  1488.         }
  1489.     }
  1490. }
  1491.  
  1492. //+-------------------------------------------------------------------------
  1493. // Initializes the edit button to display a drop-down menu if there are
  1494. // multiple verbs.  Also optionally displays a custion glyph.
  1495. //--------------------------------------------------------------------------
  1496. void CInternetToolbar::_InitEditButtonStyle()
  1497. {
  1498.     // If we have or want a custon edit glyph, load it
  1499.     _SetEditGlyph(_aEditVerb.GetIcon());
  1500.  
  1501.     UINT uiCmd;
  1502.  
  1503.     // Dochost merges under one of two clsids, so have to check both
  1504.     if (SUCCEEDED(_btb._ConvertCmd(&CLSID_InternetButtons, DVIDM_EDITPAGE, NULL, &uiCmd)) ||
  1505.         SUCCEEDED(_btb._ConvertCmd(&CLSID_MSOButtons, DVIDM_EDITPAGE, NULL, &uiCmd)))
  1506.     {
  1507.         ASSERT(uiCmd != -1);
  1508.  
  1509.         // If multiple verbs, make the button a split button
  1510.         TBBUTTONINFO tbi = {0};
  1511.         tbi.cbSize = sizeof(tbi);
  1512.         tbi.dwMask = TBIF_STYLE | TBIF_STATE;
  1513.         tbi.fsState = 0;
  1514.  
  1515.         if (_aEditVerb.GetSize() > 1)
  1516.         {
  1517.             tbi.fsStyle |= BTNS_DROPDOWN;
  1518.         }
  1519.  
  1520.         if (_aEditVerb.GetSize() > 0)
  1521.         {
  1522.             tbi.fsState = TBSTATE_ENABLED;
  1523.         }
  1524.         SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCmd, (LPARAM)&tbi);
  1525.     }
  1526. }
  1527.  
  1528. //+-------------------------------------------------------------------------
  1529. // If the edit button is displaying a custon glyph, this function reloads
  1530. // the glyph.
  1531. //--------------------------------------------------------------------------
  1532. void CInternetToolbar::_RefreshEditGlyph()
  1533. {
  1534.     // If we have a custon edit glyph, reload it
  1535.     if (_himlEdit)
  1536.     {
  1537.         // Refresh the edit glyph
  1538.         _iEditIcon = -1;
  1539.         _InitEditButtonStyle();
  1540.     }
  1541. }
  1542.  
  1543. //+-------------------------------------------------------------------------
  1544. // Updates the edit button based on the document type currently loaded
  1545. //--------------------------------------------------------------------------
  1546. void CInternetToolbar::_UpdateEditButton()
  1547. {
  1548.     _aEditVerb.RemoveAll();
  1549.     _fEditEnabled = FALSE;
  1550.  
  1551.     //
  1552.     // First add editors associated with the url
  1553.     //
  1554.     BSTR bstrUrl = NULL;
  1555.     _pdie->get_LocationURL(&bstrUrl);
  1556.     if (bstrUrl)
  1557.     {
  1558.         LPTSTR pszExt;
  1559.         //
  1560.         // Find the cache file associated with the url.  The file extension for this entry
  1561.         // is based off of the mime type. (Note that get_mimeType on the document
  1562.         // returns a frindly name that is hard to translate back to an actual mimetype.
  1563.         // So we use the file extension instead.)
  1564.         //
  1565.         WCHAR szCacheFileName[MAX_PATH];
  1566.         *szCacheFileName = 0;
  1567.         if (FAILED(URLToCacheFile(bstrUrl, szCacheFileName, ARRAYSIZE(szCacheFileName))))
  1568.         {
  1569.             // If we can't get a file associated with the url, probably want to disable the edit button
  1570.             // because most apps need a file to edit.
  1571.             SysFreeString(bstrUrl);
  1572.             return;
  1573.         }
  1574.  
  1575.         pszExt = PathFindExtension(szCacheFileName);
  1576.  
  1577.         // bug 79055 - The cache has a bug where some html entries are not
  1578.         // given a file extension.  Too risky to fix for 5.x, so we'll just
  1579.         // assume .htm for http if no extension is present.
  1580.         if (L'\0' == *pszExt && GetUrlScheme(bstrUrl) == URL_SCHEME_HTTP)
  1581.         {
  1582.             StrCpyN(szCacheFileName, L".htm", ARRAYSIZE(szCacheFileName));
  1583.             pszExt = szCacheFileName;
  1584.         }
  1585.  
  1586.         if (*pszExt)
  1587.         {
  1588.             _aEditVerb.Add(pszExt);
  1589.  
  1590.             // If ".html", use the ".htm" editors too
  1591.             if (StrCmpI(pszExt, L".html") == 0 )
  1592.             {
  1593.                 //  This is an html document, so add the .htm editors
  1594.                 if (!_aEditVerb.Add(TEXT(".htm")) && StrCmpI(pszExt, L".html") != 0)
  1595.                 {
  1596.                     _aEditVerb.Add(TEXT(".html"));
  1597.                 }
  1598.             }
  1599.         }
  1600.  
  1601.         SysFreeString(bstrUrl);
  1602.     }
  1603.  
  1604.     //
  1605.     // See if the feature to search the doc for the progid is enabled
  1606.     //
  1607.     static int fCheckDocForProgID = -1;
  1608.     if (fCheckDocForProgID == -1)
  1609.     {
  1610.         fCheckDocForProgID = SHRegGetBoolUSValue(REGSTR_PATH_MAIN,
  1611.                  TEXT("CheckDocumentForProgID"), FALSE, TRUE) ? 1 : 0;
  1612.     }
  1613.  
  1614.     // Check for a meta tag that specifies a progid for editing this document
  1615.     if (fCheckDocForProgID)
  1616.     {
  1617.         //
  1618.         // Next see if this is an html document with a progid
  1619.         //
  1620.         IWebBrowser2*       pWB2 = NULL;
  1621.         IDispatch *         pDispatch = NULL;
  1622.         IHTMLDocument2 *    pHTMLDocument = NULL;
  1623.  
  1624.         // Get the html document currently loaded
  1625.         if (_psp &&
  1626.             SUCCEEDED(_psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&pWB2)) &&
  1627.             SUCCEEDED(pWB2->get_Document(&pDispatch)) &&
  1628.             SUCCEEDED(pDispatch->QueryInterface(IID_IHTMLDocument2, (void **)&pHTMLDocument)))
  1629.         {
  1630.             //
  1631.             // Check the current document for a META tag specifying the program to use to
  1632.             // edit this file.
  1633.             //
  1634.             BSTR bstrProgID = _GetEditProgID(pHTMLDocument);
  1635.             if (bstrProgID)
  1636.             {
  1637.                 USES_CONVERSION;
  1638.                 _aEditVerb.Add(W2T(bstrProgID));
  1639.                 SysFreeString(bstrProgID);
  1640.             }
  1641.         }
  1642.  
  1643.         SAFERELEASE(pWB2);
  1644.         SAFERELEASE(pDispatch);
  1645.         SAFERELEASE(pHTMLDocument);
  1646.     }
  1647.  
  1648.  
  1649.     _fEditEnabled = (_aEditVerb.GetSize() > 0);
  1650.  
  1651.     // Update edit glyph, drop-down style, & enabled state
  1652.     _InitEditButtonStyle();
  1653. }
  1654. #endif //EDIT_HACK
  1655.  
  1656. HRESULT CInternetToolbar::Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,
  1657.                                  DISPPARAMS * pdispparams, VARIANT * pvarResult,
  1658.                                  EXCEPINFO * pexcepinfo,UINT * puArgErr)
  1659. {
  1660.     ASSERT(pdispparams);
  1661.     if(!pdispparams)
  1662.         return E_INVALIDARG;
  1663.  
  1664.     switch(dispidMember)
  1665.     {
  1666.  
  1667.     case DISPID_NAVIGATECOMPLETE2:
  1668.     {
  1669.         //
  1670.         // Notify the brand and theater mode objects about whether we're in shell or
  1671.         // web mode. Wait til now to do it (rather than doing it in SetCommandTarget)
  1672.         // because they might want to ask the browser about the new pidl, which isn't
  1673.         // yet filled in at SetCommandTarget time.
  1674.         //
  1675.         DWORD nCmdexecopt = _fShellView ? CITE_SHELL : CITE_INTERNET;
  1676.  
  1677.         LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_BRAND);
  1678.         if (pbid)
  1679.         {
  1680.             IUnknown_Exec(pbid->pdb, &CGID_PrivCITCommands, CITIDM_ONINTERNET, nCmdexecopt, NULL, NULL);
  1681.         }
  1682.  
  1683.         if (_fTheater)
  1684.         {
  1685.             IUnknown_Exec(_ptbsite, &CGID_Theater, THID_ONINTERNET, nCmdexecopt, NULL, NULL);
  1686.         }
  1687.  
  1688.         _fNavigateComplete = TRUE;
  1689.     }
  1690.     break;
  1691.  
  1692.     case DISPID_BEFORENAVIGATE:
  1693.     {
  1694.         BOOL fWeb = FALSE;
  1695.  
  1696.         ASSERT((pdispparams->rgvarg[5].vt == VT_BSTR) &&
  1697.                (pdispparams->rgvarg[5].bstrVal != NULL));
  1698.  
  1699.         PARSEDURL pu = { 0 };
  1700.         USES_CONVERSION;
  1701.  
  1702.         pu.cbSize = SIZEOF(pu);
  1703.         ParseURL(W2T(pdispparams->rgvarg[5].bstrVal), &pu);
  1704.  
  1705.         if ((URL_SCHEME_UNKNOWN != pu.nScheme) && (URL_SCHEME_FILE != pu.nScheme))
  1706.             fWeb = TRUE;
  1707.  
  1708.         UINT uiState = 0;
  1709.         GetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, &uiState);
  1710.  
  1711.         if ((uiState & TBSTATE_HIDDEN) && fWeb)
  1712.         {
  1713.  
  1714.             _fTransitionToHTML = TRUE;
  1715.             uiState &= ~TBSTATE_HIDDEN;
  1716.             SetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, uiState);
  1717.         }
  1718.  
  1719.         // Default to the edit button hidden
  1720.         _fEditEnabled = FALSE;
  1721.     }
  1722.     break;
  1723.  
  1724.     case DISPID_DOWNLOADBEGIN:// This is when we just started to navigate?  No bits?
  1725.         _StartDownload();
  1726.         break;
  1727.  
  1728.     case DISPID_DOWNLOADCOMPLETE:    // we be done
  1729.         _fTransitionToHTML = FALSE;
  1730.         _StopDownload(FALSE);
  1731.         break;
  1732.  
  1733.     case DISPID_DOCUMENTCOMPLETE:   // This is where we have all the bits
  1734.     {
  1735.         //
  1736.         // Sometimes we get a premature document complete.  We can catch this
  1737.         // by checking to see if we have received a DISPID_NAVIGATECOMPLETE2 event.
  1738.         //
  1739.         if (_fNavigateComplete)
  1740.         {
  1741.             _fNavigateComplete = FALSE;
  1742.             _UpdateEditButton();
  1743.         }
  1744.         break;
  1745.     }
  1746.  
  1747.     case DISPID_COMMANDSTATECHANGE:
  1748.         BOOL fEnable;
  1749.  
  1750.         if(!pdispparams || (pdispparams->cArgs != 2) ||
  1751.            (pdispparams->rgvarg[0].vt != VT_BOOL) ||
  1752.            (pdispparams->rgvarg[1].vt != VT_I4))
  1753.             return E_INVALIDARG;
  1754.  
  1755.         fEnable = (BOOL) pdispparams->rgvarg[0].boolVal;
  1756.         UINT uiCmd;
  1757.  
  1758.         switch (pdispparams->rgvarg[1].lVal)
  1759.         {
  1760.         case CSC_UPDATECOMMANDS:
  1761.             // corresponds to OLECMDID_UPDATECOMMANDS from Exec()
  1762.             _UpdateToolbar(FALSE);
  1763.             break;
  1764.  
  1765.         case CSC_NAVIGATEBACK:
  1766.             _fBackEnabled = fEnable;
  1767.             _btb._ConvertCmd(&CLSID_CommonButtons, TBIDM_BACK, NULL, &uiCmd);
  1768.             SendMessage(_btb._hwnd, TB_ENABLEBUTTON, uiCmd,    MAKELONG(fEnable, 0));
  1769.             break;
  1770.  
  1771.         case CSC_NAVIGATEFORWARD:
  1772.             _fForwardEnabled = fEnable;
  1773.             _btb._ConvertCmd(&CLSID_CommonButtons, TBIDM_FORWARD, NULL, &uiCmd);
  1774.             SendMessage(_btb._hwnd, TB_ENABLEBUTTON, uiCmd, MAKELONG(fEnable, 0));
  1775.             break;
  1776.  
  1777.         default:
  1778.             return(E_INVALIDARG);
  1779.         }
  1780.  
  1781.         // BUGBUG need to handle the case of navigation failure and
  1782.         // do some cleanup
  1783.  
  1784.     }
  1785.  
  1786.     return S_OK;
  1787. }
  1788.  
  1789. //***   CInternetToolbar::IInputObjectSite::* {
  1790.  
  1791. HRESULT CInternetToolbar::OnFocusChangeIS(IUnknown *punk, BOOL fSetFocus)
  1792. {
  1793.     return UnkOnFocusChangeIS(_ptbsite, SAFECAST(this, IInputObject*), fSetFocus);
  1794. }
  1795.  
  1796. // }
  1797.  
  1798. //***   CInternetToolbar::IInputObject::* {
  1799.  
  1800. HRESULT CInternetToolbar::TranslateAcceleratorIO(LPMSG lpMsg)
  1801. {
  1802.     LPBANDITEMDATA pbid;
  1803.  
  1804.     if (_fShow)
  1805.     {
  1806.         if (lpMsg->message == WM_KEYDOWN)
  1807.         {
  1808.             switch (lpMsg->wParam)
  1809.             {
  1810.             case VK_F4:
  1811.         Laddrband:
  1812.                 if (_nVisibleBands & VBF_ADDRESS)
  1813.                 {
  1814.                     pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  1815.                     if (EVAL(pbid))
  1816.                     {
  1817.                         HRESULT hrT;
  1818.  
  1819.                         hrT = UnkTranslateAcceleratorIO(pbid->pdb, lpMsg);
  1820.                         ASSERT(hrT == S_OK);
  1821.                     }
  1822.                 }
  1823.                 return S_OK;    // (even if we just eat it)
  1824.             }
  1825.         }
  1826.         else if(lpMsg->message == WM_SYSCHAR)
  1827.         {
  1828.             static CHAR szAccel[2] = "\0";
  1829.             CHAR   szChar [2] = "\0";
  1830.  
  1831.             if ('\0' == szAccel[0])
  1832.                 MLLoadStringA(IDS_ADDRBAND_ACCELLERATOR, szAccel, ARRAYSIZE(szAccel));
  1833.  
  1834.             szChar[0] = (CHAR)lpMsg->wParam;
  1835.            
  1836.             if (lstrcmpiA(szChar,szAccel) == 0)
  1837.             {
  1838.                 goto Laddrband;
  1839.             }
  1840.         }
  1841.         return _bs.TranslateAcceleratorIO(lpMsg);
  1842.     }
  1843.     return S_FALSE;
  1844. }
  1845.  
  1846.  
  1847. // }
  1848.  
  1849. HRESULT CInternetToolbar::SetSite(IUnknown* punkSite)
  1850. {
  1851.     ATOMICRELEASE(_ptbsite);
  1852.     ATOMICRELEASE(_ptbsitect);
  1853.     ATOMICRELEASE(_pbs2);
  1854.     ATOMICRELEASE(_psp);
  1855.  
  1856.     _Unadvise();
  1857.  
  1858.     ATOMICRELEASE(_pdie);
  1859.  
  1860.     ASSERT(_ptbsite==NULL);
  1861.     ASSERT(_ptbsitect==NULL);
  1862.     ASSERT(_pbs2==NULL);
  1863.     ASSERT(_pdie==NULL);
  1864.  
  1865.     if (_pbp && _fCreatedBandProxy)
  1866.         _pbp->SetSite(punkSite);
  1867.  
  1868.     if (punkSite)
  1869.     {
  1870.         punkSite->QueryInterface(IID_IDockingWindowSite, (void **)&_ptbsite);
  1871.         punkSite->QueryInterface(IID_IOleCommandTarget, (void **)&_ptbsitect);
  1872.         punkSite->QueryInterface(IID_IBrowserService2, (void **)&_pbs2);
  1873.         punkSite->QueryInterface(IID_IServiceProvider, (void **)&_psp);
  1874.  
  1875.         if (_psp)
  1876.         {
  1877.             _psp->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (void **)&_pdie);
  1878.             ASSERT(_pdie);
  1879.         }
  1880.         else
  1881.         {
  1882.             ASSERT(0);
  1883.         }
  1884.  
  1885.     }
  1886.     else
  1887.     {
  1888.         SetClient(NULL);
  1889.     }
  1890.  
  1891.  
  1892.     return S_OK;
  1893. }
  1894.  
  1895.  
  1896. //***
  1897. //
  1898. void CInternetToolbar::_UpdateGroup(const GUID *pguidCmdGroup, int cnt,
  1899.     OLECMD rgcmds[], const GUID* pguidButton, const int buttonsInternal[])
  1900. {
  1901.  
  1902.     if (!IsEqualGUID(*pguidButton, CLSID_CommonButtons) &&
  1903.         !IsEqualGUID(*pguidButton, _btb._guidCurrentButtonGroup))
  1904.         return; // we don't have any buttons at this time, so no use checking
  1905.  
  1906.     if (_ptbsitect) {
  1907.         _ptbsitect->QueryStatus(pguidCmdGroup, cnt, rgcmds, NULL);
  1908.  
  1909.         // make sure stop is enabled while we are animating
  1910.         if (_fAnimating && pguidCmdGroup == NULL && rgcmds[0].cmdID == OLECMDID_STOP) {
  1911.             rgcmds[0].cmdf = OLECMDF_ENABLED;
  1912.         }
  1913.     }
  1914.  
  1915.     for (int i = 0; i < cnt; i++)
  1916.     {
  1917.         // do nothing if command is not available or not in our table
  1918.         if (rgcmds[i].cmdf & OLECMDF_SUPPORTED)
  1919.         {
  1920.             UINT idBut;
  1921.             if (SUCCEEDED(_btb._ConvertCmd(pguidButton, buttonsInternal[i], NULL, (UINT*)&idBut)))
  1922.             {
  1923.                 SendMessage(_btb._hwnd, TB_ENABLEBUTTON, idBut,
  1924.                     (rgcmds[i].cmdf & OLECMDF_ENABLED) ? TRUE : FALSE);
  1925.  
  1926.                 SendMessage(_btb._hwnd, TB_CHECKBUTTON, idBut,
  1927.                     (rgcmds[i].cmdf & OLECMDF_LATCHED) ? TRUE : FALSE);
  1928.             }
  1929.         }
  1930.     }
  1931.     return;
  1932. }
  1933.  
  1934. void CInternetToolbar::_UpdateToolbar(BOOL fForce)
  1935. {
  1936.     if (fForce || SHIsChildOrSelf(GetForegroundWindow(), _hwnd) == S_OK)
  1937.     {
  1938.         if (!_fUpdateToolbarTimer)
  1939.         {
  1940.             SetTimer(_hwnd, IDT_UPDATETOOLBAR, TIMEOUT_UPDATETOOLBAR, NULL);
  1941.             _fUpdateToolbarTimer = TRUE;
  1942.             _UpdateToolbarNow();
  1943.         }
  1944.         else
  1945.         {
  1946.             _fNeedUpdateToolbar = TRUE;
  1947.         }
  1948.     }
  1949. }
  1950.  
  1951. BOOL CInternetToolbar::_UpEnabled()
  1952. {
  1953.     OLECMD rgcmd = { FCIDM_PREVIOUSFOLDER, 0 };
  1954.     _ptbsitect->QueryStatus(&CGID_ShellBrowser, 1, &rgcmd, NULL);
  1955.  
  1956.     return (rgcmd.cmdf & OLECMDF_ENABLED);
  1957. }
  1958.  
  1959. void CInternetToolbar::_UpdateCommonButton(int iCmd, UINT nCmdID)
  1960. {
  1961.     switch (nCmdID) {
  1962.     case TBIDM_THEATER:
  1963.         SendMessage(_btb._hwnd, TB_CHECKBUTTON, iCmd, _fTheater);
  1964.         break;
  1965.  
  1966.     case TBIDM_PREVIOUSFOLDER:
  1967.     case TBIDM_BACK:
  1968.     case TBIDM_FORWARD:
  1969.         {
  1970.             BOOL fEnabled;
  1971.  
  1972.             switch (nCmdID) {
  1973.             case TBIDM_PREVIOUSFOLDER:  fEnabled = _UpEnabled();       break;
  1974.             case TBIDM_BACK:            fEnabled = _fBackEnabled;      break;
  1975.             case TBIDM_FORWARD:         fEnabled = _fForwardEnabled;   break;
  1976.             }
  1977.  
  1978.             SendMessage(_btb._hwnd, TB_ENABLEBUTTON, iCmd, MAKELONG(fEnabled, 0));
  1979.         }
  1980.         break;
  1981.     }
  1982. }
  1983.  
  1984. void CInternetToolbar::_UpdateToolbarNow()
  1985. {
  1986.     _fNeedUpdateToolbar = FALSE;
  1987.  
  1988.     {
  1989.         // MUST not be static (due to ConvertCmd overwrite)
  1990.         OLECMD rgcmds[] = {
  1991.             { OLECMDID_STOP, 0 }, // NOTE: must be first
  1992.             { OLECMDID_REFRESH, 0 },
  1993.         };
  1994.  
  1995.         static const int buttonsInternal[] = { // MUST be in same order as above array
  1996.             TBIDM_STOPDOWNLOAD,
  1997.             TBIDM_REFRESH,
  1998.         };
  1999.         _UpdateGroup(NULL, ARRAYSIZE(buttonsInternal), rgcmds, &CLSID_CommonButtons, buttonsInternal);
  2000.     }
  2001.  
  2002.     {
  2003.         OLECMD rgcmds[] = {
  2004.             { SBCMDID_SEARCHBAR, 0 },
  2005.             { SBCMDID_FAVORITESBAR, 0 },
  2006.             { SBCMDID_HISTORYBAR, 0 },
  2007. #ifdef ENABLE_CHANNELPANE
  2008.             { SBCMDID_CHANNELSBAR, 0 },
  2009. #endif
  2010.             { SBCMDID_EXPLORERBAR, 0 },
  2011.         };
  2012.         static const int buttonsInternal[] = { // MUST be in same order as above array
  2013.             TBIDM_SEARCH,
  2014.             TBIDM_FAVORITES,
  2015.             TBIDM_HISTORY,
  2016. #ifdef ENABLE_CHANNELPANE
  2017.             TBIDM_CHANNELS,
  2018. #endif
  2019.             TBIDM_ALLFOLDERS,
  2020.         };
  2021.  
  2022.         _UpdateGroup(&CGID_Explorer, ARRAYSIZE(buttonsInternal), rgcmds, &CLSID_CommonButtons, buttonsInternal);
  2023.     }
  2024.  
  2025.     int nButtons = (int) SendMessage(_btb._hwnd, TB_BUTTONCOUNT, 0, 0L);
  2026.  
  2027.     for (int nIndex = 0; nIndex < nButtons; nIndex++)
  2028.     {
  2029.         CMDMAP* pcm = _btb._GetCmdMapByIndex(nIndex);
  2030.         if (pcm)
  2031.         {
  2032.             int iCmd = _btb._CommandFromIndex(nIndex);
  2033.             if (IsEqualGUID(pcm->guidButtonGroup, CLSID_CommonButtons))
  2034.             {
  2035.                 _UpdateCommonButton(iCmd, pcm->nCmdID);
  2036.             }
  2037.             else
  2038.             {
  2039.                 // If either of these rip, the button is stale
  2040.                 ASSERT(IsEqualGUID(pcm->guidButtonGroup, _btb._guidCurrentButtonGroup));
  2041.                 ASSERT(_btb._pctCurrentButtonGroup);
  2042.  
  2043.                 OLECMD ocButton;
  2044.                 ocButton.cmdID = pcm->nCmdID;
  2045.                 ocButton.cmdf = 0;
  2046.  
  2047.                 if (SUCCEEDED(_btb._pctCurrentButtonGroup->QueryStatus(&pcm->guidButtonGroup, 1, &ocButton, NULL)))
  2048.                 {
  2049.                     SendMessage(_btb._hwnd, TB_ENABLEBUTTON, iCmd,
  2050.                                 (ocButton.cmdf & OLECMDF_ENABLED) ? TRUE : FALSE);
  2051.  
  2052.                     SendMessage(_btb._hwnd, TB_CHECKBUTTON, iCmd,
  2053.                                 (ocButton.cmdf & OLECMDF_LATCHED) ? TRUE : FALSE);
  2054.                 }
  2055.             }
  2056.         }
  2057.     }
  2058.  
  2059.     _btb._BandInfoChanged();
  2060. }
  2061.  
  2062. void CInternetToolbar::_StartDownload()
  2063. {
  2064.     UINT uiCmd;
  2065.     if (SUCCEEDED(_btb._ConvertCmd(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, NULL, &uiCmd)))
  2066.     {
  2067.         SendMessage(_btb._hwnd, TB_ENABLEBUTTON, uiCmd, MAKELONG(TRUE, 0));
  2068.  
  2069.         _fAnimating = TRUE;
  2070.     }
  2071. }
  2072.  
  2073. //
  2074. // Parameters:
  2075. //  fClosing -- TRUE only if we are calling this from CloseDW member.
  2076. //              In that case, we can skip all UI-update code.
  2077. //
  2078. void CInternetToolbar::_StopDownload(BOOL fClosing)
  2079. {
  2080.     _fAnimating = FALSE;
  2081. }
  2082.  
  2083. HRESULT CInternetToolbar::CloseDW(DWORD dwReserved)
  2084. {
  2085.     _fDestroyed = TRUE; // Stop using the member variables, they are invalid.
  2086.     _StopDownload(TRUE);
  2087.  
  2088.     ASSERT(!_btb._pcinfo);
  2089.     ATOMICRELEASE(_btb._pctCurrentButtonGroup);
  2090.  
  2091.     _btb._FreeBtnsAdded();
  2092.  
  2093.     if (_btb._hwnd)
  2094.     {
  2095.         _btb._RemoveAllButtons();
  2096.  
  2097.         SendMessage(_btb._hwnd, TB_SETIMAGELIST, 0, NULL);
  2098.         SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, 0, NULL);
  2099.  
  2100.         DSA_Destroy(_hdsaTBBMPs);
  2101.         _hdsaTBBMPs = NULL;  // So we don't try to re-destroy in _InitBitmapDSA()
  2102.         _hdsaTBBMPs = NULL;
  2103.     }
  2104. #ifdef EDIT_HACK
  2105.     _SetEditGlyph(-1);
  2106. #endif
  2107.  
  2108.     _bs._Close();
  2109.  
  2110.     SUPERCLASS::CloseDW(dwReserved);
  2111.  
  2112.     _btb._hwnd = NULL;
  2113.  
  2114.     // We advise during ShowDW, so unadvise here. Also, we hit a stress
  2115.     // case where it seems that an event came in after closedw but before
  2116.     // one of the other _Unadvise calls. This event percolated down to
  2117.     // a reference to _hdsaCT which we freed above, causing a GPF.
  2118.     //
  2119.     _Unadvise();
  2120.  
  2121.     return S_OK;
  2122. }
  2123.  
  2124. void CInternetToolbar::CITBandSite::v_SetTabstop(LPREBARBANDINFO prbbi)
  2125. {
  2126.     // Don't set tabstops for all bands in the browser case.  A band
  2127.     // can still make itself a tabstop by setting WS_TABSTOP.
  2128.     return;
  2129. }
  2130.  
  2131. BOOL CInternetToolbar::CITBandSite::_SetMinDimensions()
  2132. {
  2133.     INT_PTR fRedraw = SendMessage(_hwnd, WM_SETREDRAW, FALSE, 0);
  2134.  
  2135.     int icBands = (int) SendMessage( _hwnd, RB_GETBANDCOUNT, 0, 0 );
  2136.     for (int i = 0; i < icBands; i++)
  2137.     {
  2138.         REBARBANDINFO rbbi;
  2139.         rbbi.cbSize = sizeof(REBARBANDINFO);
  2140.         rbbi.fMask = RBBIM_ID | RBBIM_CHILDSIZE;
  2141.         if (SendMessage(_hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  2142.         {
  2143.             LPBANDITEMDATA pbid = (LPBANDITEMDATA)_GetBandItemDataStructByID(rbbi.wID);
  2144.             if (EVAL(pbid) && IS_VALID_HANDLE(pbid->hwnd, WND))
  2145.             {
  2146.                 rbbi.cxMinChild = pbid->ptMinSize.x;
  2147.                 rbbi.cyMinChild = pbid->ptMinSize.y;
  2148.             }
  2149.             else
  2150.             {
  2151.                 rbbi.cxMinChild = 0;
  2152.                 rbbi.cyMinChild = 0;
  2153.             }
  2154.  
  2155.             SendMessage(_hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
  2156.         }
  2157.     }
  2158.  
  2159.     SendMessage(_hwnd, WM_SETREDRAW, fRedraw, 0);
  2160.  
  2161.     return TRUE;
  2162. }
  2163.  
  2164.  
  2165. BOOL HimlCacheDirty(IMLCACHE* pimlCache, BOOL fSmallIcons)
  2166. {
  2167.  
  2168.     if (fSmallIcons != pimlCache->fSmallIcons)
  2169.         return TRUE;
  2170.  
  2171.     COLORREF cr3D = GetSysColor(COLOR_3DFACE);
  2172.  
  2173.     if (cr3D != pimlCache->cr3D)
  2174.         return TRUE;
  2175.  
  2176.     for (int i = 0; i < CIMLISTS; i++)
  2177.         if (!pimlCache->arhiml[i])
  2178.             return TRUE;
  2179.  
  2180.     return FALSE;
  2181. }
  2182.  
  2183.  
  2184. #define SZ_REGKEY_SMALLICONS       REGSTR_PATH_EXPLORER TEXT("\\SmallIcons")
  2185. #define SZ_REGVALUE_SMALLICONS     TEXT("SmallIcons")
  2186.  
  2187. BOOL _DefaultToSmallIcons()
  2188. {
  2189.     // On NT5, we want to default to small icons.
  2190.     return (GetUIVersion() >= 5) || SHRestricted2(REST_SMALLICONS, NULL, 0);
  2191. }
  2192.  
  2193. BOOL _UseSmallIcons()
  2194. {
  2195.     BOOL fDefaultToSmall = _DefaultToSmallIcons();
  2196.  
  2197.     return SHRegGetBoolUSValue(SZ_REGKEY_SMALLICONS, SZ_REGVALUE_SMALLICONS,
  2198.                                         FALSE, fDefaultToSmall);
  2199. }
  2200.  
  2201.  
  2202. BOOL _UseMapNetDrvBtns()
  2203. {
  2204. #define SZ_REGKEY_ADVFOLDER        TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced")
  2205. #define SZ_REGVALUE_MAPNETDRV      TEXT("MapNetDrvBtn")
  2206.  
  2207.     DWORD dwData = 0;
  2208.     if (GetUIVersion() >= 4)
  2209.     {
  2210.         DWORD cbData = SIZEOF(dwData);
  2211.         DWORD dwDefault = 0;
  2212.         DWORD cbDefault = SIZEOF(dwDefault);
  2213.  
  2214.         SHRegGetUSValue(SZ_REGKEY_ADVFOLDER, SZ_REGVALUE_MAPNETDRV, NULL,
  2215.                             &dwData, &cbData, FALSE, &dwDefault, cbDefault);
  2216.     }
  2217.     return dwData;
  2218. }
  2219.  
  2220. void _LoadToolbarGlyphs(HWND hwnd, IMLCACHE *pimlCache, int cx, int idBmp)
  2221. {
  2222.     // set uMsg and uFlags for first iteration of loop (default state)
  2223.     UINT uMsg = TB_SETIMAGELIST;
  2224.     UINT uFlags = LR_CREATEDIBSECTION;
  2225.     int i;
  2226.     HBITMAP hBMP;
  2227.     BOOL fSmallIcons = g_fSmallIcons;
  2228.  
  2229.     if (HimlCacheDirty(pimlCache, fSmallIcons))
  2230.     {
  2231.         COLORREF cr3D   = GetSysColor(COLOR_3DFACE);
  2232.         COLORREF crMask = RGB( 255, 0, 255 );
  2233.  
  2234. #ifdef UNIX
  2235.         if (SHGetCurColorRes() < 2 )
  2236.         {
  2237.             crMask = CLR_NONE;
  2238.         }
  2239. #endif
  2240.  
  2241.         ENTERCRITICAL;
  2242.  
  2243.         if (!HimlCacheDirty(pimlCache, fSmallIcons) )
  2244.             goto DontReload;
  2245.  
  2246.  
  2247.         for (i = 0; i < CIMLISTS; i++)
  2248.         {
  2249.             if ((!pimlCache->arhiml[i]) || (cr3D != pimlCache->cr3D) || fSmallIcons != pimlCache->fSmallIcons)
  2250.             {
  2251.  
  2252.                 TraceMsg(DM_ITBAR, "CInternetToolbar: Loading New Images");
  2253.  
  2254.                 if (pimlCache->arhimlPendingDelete[i])
  2255.                     ImageList_Destroy(pimlCache->arhimlPendingDelete[i]);
  2256.  
  2257.  
  2258.                 pimlCache->arhimlPendingDelete[i] = pimlCache->arhiml[i];
  2259.                 pimlCache->arhiml[i] = ImageList_LoadImage(HINST_THISDLL,
  2260.                                                MAKEINTRESOURCE(idBmp + i), cx, 0, crMask,
  2261.                                                IMAGE_BITMAP, uFlags);
  2262.  
  2263.                 if (pimlCache->arhiml[i])
  2264.                 {
  2265.                     // add shell glyphs
  2266.                     int idShellBmp = IDB_SHSTD;
  2267.                     int iDelta = idBmp - IDB_IETOOLBAR;
  2268.                     idShellBmp += iDelta;
  2269.                     hBMP = LoadBitmap(HINST_THISDLL, MAKEINTRESOURCE(idShellBmp + i));
  2270.                     ImageList_AddMasked(pimlCache->arhiml[i], (HBITMAP)hBMP, crMask);
  2271.                     DeleteObject(hBMP);
  2272.                 }
  2273.             }
  2274.         }
  2275.         pimlCache->cr3D = cr3D;
  2276.         pimlCache->fSmallIcons = fSmallIcons;
  2277. DontReload:
  2278.         LEAVECRITICAL;
  2279.     }
  2280.  
  2281.     if (hwnd) {
  2282.         ASSERT(IS_VALID_HANDLE(hwnd, WND));
  2283.  
  2284.         for (i = 0; i < CIMLISTS; i++)
  2285.         {
  2286.             SendMessage(hwnd, uMsg, 0, (LPARAM) pimlCache->arhiml[i]);
  2287.  
  2288.             // set uMsg and uFlags for last iteration of loop (hot state)
  2289.             uMsg = TB_SETHOTIMAGELIST;
  2290.             uFlags = 0;
  2291.         }
  2292.     }
  2293. }
  2294.  
  2295.  
  2296. void CInternetToolbar::_InitBitmapDSA()
  2297. {
  2298.     DSA_Destroy(_hdsaTBBMPs);
  2299.     _hdsaTBBMPs = DSA_Create(SIZEOF(TBBMP_LIST), TBBMPLIST_CHUNK);
  2300.  
  2301.     if (_hdsaTBBMPs) {
  2302.         TBBMP_LIST tbl = { HINST_COMMCTRL, 0, 0, TRUE, TRUE, FALSE };
  2303.  
  2304.         tbl.uiResID = IDB_STD_SMALL_COLOR;
  2305.         tbl.uiOffset = OFFSET_STD;
  2306.         DSA_AppendItem(_hdsaTBBMPs, &tbl);
  2307.         tbl.uiResID = IDB_STD_LARGE_COLOR;
  2308.         DSA_AppendItem(_hdsaTBBMPs, &tbl);
  2309.  
  2310.         tbl.uiResID = IDB_VIEW_SMALL_COLOR;
  2311.         tbl.uiOffset = OFFSET_VIEW;
  2312.         DSA_AppendItem(_hdsaTBBMPs, &tbl);
  2313.         tbl.uiResID = IDB_VIEW_LARGE_COLOR;
  2314.         DSA_AppendItem(_hdsaTBBMPs, &tbl);
  2315.  
  2316.         tbl.uiResID = IDB_HIST_SMALL_COLOR;
  2317.         tbl.uiOffset = OFFSET_HIST;
  2318.         DSA_AppendItem(_hdsaTBBMPs, &tbl);
  2319.         tbl.uiResID = IDB_HIST_LARGE_COLOR;
  2320.         DSA_AppendItem(_hdsaTBBMPs, &tbl);
  2321.     }
  2322. }
  2323.  
  2324. void CInternetToolbar::_InitForScreenSize()
  2325. {
  2326.     TCHAR szScratch[16];
  2327.     if (GetSystemMetrics(SM_CXSCREEN) < 650)
  2328.     {
  2329.         MLLoadString(IDS_TB_WIDTH_EXTRA_LORES, szScratch, ARRAYSIZE(szScratch));
  2330.         _uiMaxTBWidth = MAX_TB_WIDTH_LORES;
  2331.     }
  2332.     else
  2333.     {
  2334.         MLLoadString(IDS_TB_WIDTH_EXTRA_HIRES, szScratch, ARRAYSIZE(szScratch));
  2335.         _uiMaxTBWidth = MAX_TB_WIDTH_HIRES;
  2336.     }
  2337.     _uiMaxTBWidth += StrToInt(szScratch) * WIDTH_FACTOR;
  2338. }
  2339.  
  2340.  
  2341. // removes all buttons marked hidden.  returns the number
  2342. // of buttons left
  2343. int RemoveHiddenButtons(TBBUTTON* ptbn, int iCount)
  2344. {
  2345.     int i;
  2346.     int iTotal = 0;
  2347.     TBBUTTON* ptbn1 = ptbn;
  2348.     for (i = 0; i < iCount; i++, ptbn1++)
  2349.     {
  2350.         if (!(ptbn1->fsState & TBSTATE_HIDDEN))
  2351.         {
  2352.             if (ptbn1 != ptbn)
  2353.             {
  2354.                 *ptbn = *ptbn1;
  2355.             }
  2356.             ptbn++;
  2357.             iTotal++;
  2358.         }
  2359.     }
  2360.     return iTotal;
  2361. }
  2362.  
  2363. #ifdef DEBUG
  2364. void _AssertRestrictionOrderIsCorrect()
  2365. {
  2366.     COMPILETIME_ASSERT(ARRAYSIZE(c_tbExplorer) == ARRAYSIZE(c_rest));
  2367.  
  2368.     for (UINT i = 0; i < ARRAYSIZE(c_tbExplorer); i++)
  2369.     {
  2370.         // If any of these rip, it means that c_rest and c_tbExplorer have
  2371.         // gotten out of sync.  Need to fix up c_rest to match c_tbExplorer.
  2372.         switch (c_tbExplorer[i].idCommand)
  2373.         {
  2374.             case TBIDM_BACK:            ASSERT(c_rest[i] == REST_BTN_BACK);         break;
  2375.             case TBIDM_FORWARD:         ASSERT(c_rest[i] == REST_BTN_FORWARD);      break;
  2376.             case TBIDM_STOPDOWNLOAD:    ASSERT(c_rest[i] == REST_BTN_STOPDOWNLOAD); break;
  2377.             case TBIDM_REFRESH:         ASSERT(c_rest[i] == REST_BTN_REFRESH);      break;
  2378.             case TBIDM_HOME:            ASSERT(c_rest[i] == REST_BTN_HOME);         break;
  2379.             case TBIDM_SEARCH:          ASSERT(c_rest[i] == REST_BTN_SEARCH);       break;
  2380.             case TBIDM_HISTORY:         ASSERT(c_rest[i] == REST_BTN_HISTORY);      break;
  2381.             case TBIDM_FAVORITES:       ASSERT(c_rest[i] == REST_BTN_FAVORITES);    break;
  2382.             case TBIDM_ALLFOLDERS:      ASSERT(c_rest[i] == REST_BTN_ALLFOLDERS);   break;
  2383.             case TBIDM_THEATER:         ASSERT(c_rest[i] == REST_BTN_THEATER);      break;
  2384.             default:                    ASSERT(c_rest[i] == REST_BROWSER_NONE);     break;
  2385.         }
  2386.     }
  2387. }
  2388. #endif
  2389.  
  2390. __inline BOOL CInternetToolbar::_FoldersButtonAvailable()
  2391. {
  2392.     return (GetUIVersion() >= 4);
  2393. }
  2394.  
  2395. void CInternetToolbar::_AdminMarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons)
  2396. {
  2397.     // We only have policies for web buttons.
  2398.     ASSERT(!_fShellView);
  2399.  
  2400.     // Caller should have checked this.
  2401.     ASSERT(SHRestricted2(REST_SPECIFYDEFAULTBUTTONS, NULL, 0));
  2402.  
  2403.     // SHRestricted2 returns 0 if it can't find the policy.  Assert that
  2404.     // this lines up with RESTOPT_BTN_STATE_DEFAULT.
  2405.     COMPILETIME_ASSERT(RESTOPT_BTN_STATE_DEFAULT == 0);
  2406.  
  2407.     for (UINT i = 0; i < cButtons; i++)
  2408.     {
  2409.         if (c_rest[i] != 0) {
  2410.             DWORD dwRest = SHRestricted2(c_rest[i], NULL, 0);
  2411.             ptbb[i].fsState = SHBtnStateFromRestriction(dwRest, ptbb[i].fsState);
  2412.         }
  2413.     }
  2414.  
  2415.     // Folders button is not available on non-integrated platforms, so
  2416.     // set state to hidden even if policy specifies that it should be shown.
  2417.     ASSERT(c_tbExplorer[10].idCommand == TBIDM_ALLFOLDERS);
  2418.     if (!_FoldersButtonAvailable())
  2419.         ptbb[10].fsState |= TBSTATE_HIDDEN;
  2420. }
  2421.  
  2422. void CInternetToolbar::_MarkDefaultButtons(PTBBUTTON ptbb, UINT cButtons)
  2423. {
  2424.     if (_fShellView)
  2425.     {
  2426.         ASSERT(c_tbExplorer[2].idCommand == TBIDM_STOPDOWNLOAD);
  2427.         ptbb[2].fsState |= TBSTATE_HIDDEN;
  2428.         ASSERT(c_tbExplorer[3].idCommand == TBIDM_REFRESH);
  2429.         ptbb[3].fsState |= TBSTATE_HIDDEN;
  2430.         ASSERT(c_tbExplorer[4].idCommand == TBIDM_HOME);
  2431.         ptbb[4].fsState |= TBSTATE_HIDDEN;
  2432.  
  2433.         ASSERT(c_tbExplorer[9].idCommand == TBIDM_SEARCH);
  2434.         ASSERT(c_tbExplorer[12].idCommand == TBIDM_HISTORY);
  2435.         ASSERT(c_tbExplorer[13].idCommand == 0);    // (a separator)
  2436.  
  2437.         if (GetUIVersion() < 5)
  2438.         {
  2439.             ptbb[9].fsState |= TBSTATE_HIDDEN;
  2440.             ptbb[12].fsState |= TBSTATE_HIDDEN;
  2441.             ptbb[13].fsState |= TBSTATE_HIDDEN;
  2442.         }
  2443.         else
  2444.         {
  2445.             if (SHRestricted(REST_NOSHELLSEARCHBUTTON))
  2446.             {
  2447.                 ptbb[9].fsState |= TBSTATE_HIDDEN;
  2448.             }
  2449.             ASSERT(c_tbExplorer[6].idCommand == TBIDM_CONNECT);
  2450.             ASSERT(c_tbExplorer[7].idCommand == TBIDM_DISCONNECT);
  2451.             if (SHRestricted(REST_NONETCONNECTDISCONNECT))
  2452.             {
  2453.                 ptbb[6].fsState |= TBSTATE_HIDDEN;
  2454.                 ptbb[7].fsState |= TBSTATE_HIDDEN;
  2455.             }
  2456.         }
  2457.  
  2458.         ASSERT(c_tbExplorer[11].idCommand == TBIDM_FAVORITES);
  2459.         ptbb[11].fsState |= TBSTATE_HIDDEN;
  2460.     }
  2461.  
  2462.     ASSERT(c_tbExplorer[5].idCommand == TBIDM_PREVIOUSFOLDER);
  2463.     if (!_fShellView)
  2464.         ptbb[5].fsState |= TBSTATE_HIDDEN;
  2465.  
  2466.     ASSERT(c_tbExplorer[6].idCommand == TBIDM_CONNECT);
  2467.     ASSERT(c_tbExplorer[7].idCommand == TBIDM_DISCONNECT);
  2468.     if (!_fShellView || !_UseMapNetDrvBtns())
  2469.     {
  2470.         ptbb[6].fsState |= TBSTATE_HIDDEN;
  2471.         ptbb[7].fsState |= TBSTATE_HIDDEN;
  2472.     }
  2473.  
  2474.     // If this TBIDM_ALLFOLDERS assertion rips, remember to fix up _AdminMarkDefaultButtons too.
  2475.     ASSERT(c_tbExplorer[10].idCommand == TBIDM_ALLFOLDERS);
  2476.     if (!_fShellView || GetUIVersion() < 5)
  2477.         ptbb[10].fsState |= TBSTATE_HIDDEN;
  2478.  
  2479.     ASSERT(c_tbExplorer[14].idCommand == TBIDM_THEATER);
  2480.     ptbb[14].fsState |= TBSTATE_HIDDEN;
  2481. }
  2482.  
  2483. void CInternetToolbar::_AddCommonButtons()
  2484. {
  2485.     TBBUTTON    tbExplorer[ARRAYSIZE(c_tbExplorer)];
  2486.  
  2487.     memcpy(tbExplorer, c_tbExplorer, SIZEOF(TBBUTTON) * ARRAYSIZE(c_tbExplorer));
  2488.  
  2489.     _MarkDefaultButtons(tbExplorer, ARRAYSIZE(c_tbExplorer));
  2490.  
  2491. #ifdef DEBUG
  2492.     _AssertRestrictionOrderIsCorrect();
  2493. #endif
  2494.  
  2495.     if (!_fShellView && SHRestricted2(REST_SPECIFYDEFAULTBUTTONS, NULL, 0))
  2496.         _AdminMarkDefaultButtons(tbExplorer, ARRAYSIZE(c_tbExplorer));
  2497.  
  2498.     int iButtons = RemoveHiddenButtons(tbExplorer, ARRAYSIZE(tbExplorer));
  2499.  
  2500.     for (int i = 0; i < iButtons; i++)
  2501.     {
  2502.         if (!(tbExplorer[i].fsStyle & BTNS_SEP))
  2503.         {
  2504.             CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, SIZEOF(CMDMAP));
  2505.             if (pcm)
  2506.             {
  2507.                 pcm->guidButtonGroup = CLSID_CommonButtons;
  2508.                 pcm->nCmdID = tbExplorer[i].idCommand;
  2509.  
  2510.                 tbExplorer[i].idCommand = _btb._nNextCommandID++;
  2511.                 tbExplorer[i].dwData = (LPARAM)pcm;
  2512.             }
  2513.         }
  2514.     }
  2515.  
  2516.     SendMessage(_btb._hwnd, TB_ADDBUTTONS, iButtons, (LPARAM) tbExplorer);
  2517.  
  2518.     _btb._RecalcButtonWidths();
  2519. }
  2520.  
  2521. #define IS_LIST_STYLE(hwnd) (BOOLIFY(GetWindowLong(hwnd, GWL_STYLE) & TBSTYLE_LIST))
  2522.  
  2523. void CInternetToolbar::_UpdateToolsStyle(BOOL fList)
  2524. {
  2525.     if (BOOLIFY(fList) != IS_LIST_STYLE(_btb._hwnd))
  2526.     {
  2527.         _fDirty = TRUE;
  2528.  
  2529.         // toggle TBSTYLE_LIST
  2530.         SHSetWindowBits(_btb._hwnd, GWL_STYLE, TBSTYLE_LIST, fList ? TBSTYLE_LIST : 0);
  2531.         // toggle TBSTYLE_EX_MIXEDBUTTONS
  2532.         SendMessage(_btb._hwnd, TB_SETEXTENDEDSTYLE, TBSTYLE_EX_MIXEDBUTTONS, fList ? TBSTYLE_EX_MIXEDBUTTONS : 0);
  2533.     }
  2534. }
  2535.  
  2536. void CInternetToolbar::_InitToolbar()
  2537. {
  2538.     TCHAR szShellTBText[1024];  // This should be enough
  2539.     ZeroMemory(szShellTBText, sizeof(szShellTBText));
  2540.     int nRows = _fCompressed ? 0 : _uiTBTextRows;
  2541.  
  2542.     // this tells the toolbar what version we are
  2543.     SendMessage(_btb._hwnd, TB_BUTTONSTRUCTSIZE,    SIZEOF(TBBUTTON), 0);
  2544.     SendMessage(_btb._hwnd, TB_SETEXTENDEDSTYLE,    0,
  2545.                     TBSTYLE_EX_DRAWDDARROWS | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
  2546.     SendMessage(_btb._hwnd, TB_SETMAXTEXTROWS,      nRows, 0L);
  2547.     SendMessage(_btb._hwnd, TB_SETDROPDOWNGAP,  GetSystemMetrics(SM_CXEDGE) / 2, 0);
  2548.     SendMessage(_btb._hwnd, CCM_SETVERSION, COMCTL32_VERSION, 0);
  2549.  
  2550.     _UpdateToolsStyle(_cs.fList);
  2551.  
  2552.     ITBar_LoadToolbarGlyphs(_btb._hwnd);
  2553.     _InitBitmapDSA();
  2554.  
  2555.     _InitForScreenSize();
  2556.  
  2557.     SendMessage(_btb._hwnd, TB_ADDSTRING, (WPARAM)MLGetHinst(), IDS_IE_TB_LABELS);
  2558.  
  2559.     _AddCommonButtons();
  2560.  
  2561.     INT_PTR nRet = SendMessage(_btb._hwnd, TB_ADDSTRING, (WPARAM)MLGetHinst(), IDS_SHELL_TB_LABELS);
  2562.     ASSERT(nRet == SHELLTOOLBAR_OFFSET);
  2563. }
  2564.  
  2565. HRESULT CInternetToolbar::_ShowTools(PBANDSAVE pbs)
  2566. {
  2567.     HRESULT         hr  = S_OK;
  2568.     LPBANDITEMDATA  pbid = _bs._GetBandItemDataStructByID(CBIDX_TOOLS);
  2569.  
  2570.     if (!pbid) {
  2571.         ASSERT(!_btb._hwnd);
  2572.  
  2573.         _btb._hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
  2574.                                 WS_CHILD | TBSTYLE_FLAT |
  2575.                                 TBSTYLE_TOOLTIPS |
  2576.                                 WS_CLIPCHILDREN |
  2577.                                 WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN |
  2578.                                 CCS_NORESIZE,
  2579.                                 0, 0, 0, 0, _bs._hwnd, (HMENU) FCIDM_TOOLBAR, HINST_THISDLL, NULL);
  2580.  
  2581.         if (_btb._hwnd) {
  2582.             _btb._hwnd = _btb._hwnd;
  2583.             _InitToolbar();
  2584.             pbid = _AddNewBand((IDeskBand*)&_btb, CBIDX_TOOLS);
  2585.         }
  2586.  
  2587.         if (!pbid)
  2588.             return E_OUTOFMEMORY;
  2589.     } else {
  2590.         pbs = NULL;
  2591.     }
  2592.  
  2593.     _ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_TOOLS);
  2594.     return hr;
  2595. }
  2596.  
  2597. void CInternetToolbar::_ShowBandCommon(PBANDSAVE pbs, LPBANDITEMDATA pbid, BOOL fShow)
  2598. {
  2599.     REBARBANDINFO   rbbi;
  2600.  
  2601.     pbid->fShow = BOOLIFY(fShow);
  2602.     pbid->pdb->ShowDW(pbid->fShow);
  2603.  
  2604.     INT_PTR i = BandIDtoIndex(_bs._hwnd, pbid->dwBandID);
  2605.  
  2606.     if (pbs)
  2607.     {
  2608.         rbbi.cbSize = sizeof(REBARBANDINFO);
  2609.         rbbi.fMask = RBBIM_SIZE | RBBIM_STYLE;
  2610.  
  2611.         // we just want to change the RBBS_BREAK bit
  2612.         // assert that our caller doesn't expect to set any other bits
  2613.         // ASSERT(!(pbs->fStyle & ~RBBS_BREAK)); <--- I hit this assert all the time
  2614.  
  2615.         // get old style
  2616.         SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM)&rbbi);
  2617.  
  2618.         rbbi.fStyle = (rbbi.fStyle & ~RBBS_BREAK) | (pbs->fStyle & RBBS_BREAK);
  2619.         rbbi.cx = pbs->cx;
  2620.  
  2621.         SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM)&rbbi);
  2622.     }
  2623.  
  2624.  
  2625.     if ( pbid->dwModeFlags & DBIMF_BREAK )
  2626.     {
  2627.         rbbi.cbSize = sizeof(REBARBANDINFO);
  2628.         rbbi.fMask = RBBIM_STYLE;
  2629.         if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  2630.         {
  2631.             // in theater mode we don't allow bands to have breaks
  2632.             if ((rbbi.fStyle & RBBS_BREAK ) && _fTheater)
  2633.             {
  2634.                 rbbi.fStyle &= ~RBBS_BREAK;
  2635.                 SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
  2636.             }
  2637.         }
  2638.     }
  2639.  
  2640.     SendMessage(_bs._hwnd, RB_SHOWBAND, i, pbid->fShow);
  2641. }
  2642.  
  2643.  
  2644. HRESULT CInternetToolbar::_GetPersistedBand(const CLSID clsid, REFIID riid, void ** ppiface)
  2645. {
  2646.     HRESULT hr  = E_FAIL;
  2647.     TCHAR szStreamName[MAX_PATH];
  2648.  
  2649.     if (SUCCEEDED(_GetStreamName(_fInitialPidlIsWeb, szStreamName, ARRAYSIZE(szStreamName))))
  2650.     {
  2651.         static BOOL fBrowserOnly = (WhichPlatform() != PLATFORM_INTEGRATED);
  2652.         TCHAR szKey[MAX_PATH];
  2653.         TCHAR szGUID[MAX_PATH];
  2654.  
  2655.         wnsprintf(szKey, ARRAYSIZE(szKey), TEXT("Software\\Microsoft\\Internet Explorer\\Toolbar\\%s"), szStreamName);
  2656.         SHStringFromGUID(clsid, szGUID, ARRAYSIZE(szGUID));
  2657.  
  2658.         if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, szKey, szGUID, NULL, NULL, NULL))
  2659.         {
  2660.             // Was the stream saved by an Integrated shell and we are in browser only mode?
  2661.             if ((_cs.fSaveInShellIntegrationMode) && fBrowserOnly)
  2662.             {
  2663.                 // Yes, so we need to ignore the stream.
  2664.             }
  2665.             else
  2666.             {
  2667.                 IStream * pstm = GetRegStream(_fInitialPidlIsWeb, szGUID, STGM_READ);
  2668.                 if (pstm)
  2669.                 {
  2670.                     hr = _bs.LoadFromStreamBS(pstm, riid, ppiface);
  2671.                     pstm->Release();
  2672.                 }
  2673.             }
  2674.         }
  2675.     }
  2676.  
  2677.     if (FAILED(hr))
  2678.     {
  2679.         hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, ppiface);
  2680.         if (SUCCEEDED(hr))
  2681.         {
  2682.             IPersistStreamInit * ppsi;
  2683.             ((IUnknown *) *ppiface)->QueryInterface(IID_IPersistStreamInit, (void **) &ppsi);
  2684.             if (ppsi)
  2685.             {
  2686.                 ppsi->InitNew();
  2687.                 ppsi->Release();
  2688.             }
  2689.         }
  2690.     }
  2691.  
  2692.     return hr;
  2693. }
  2694.  
  2695.  
  2696. HRESULT CInternetToolbar::_ShowExternalBand( PBANDSAVE pbs, int idBand )
  2697. {
  2698.     HRESULT hr;
  2699.     if (IS_EXTERNALBAND(idBand))
  2700.     {
  2701.         int idBandExt = MAP_TO_EXTERNAL(idBand);
  2702.  
  2703.         if (!IsEqualCLSID(_rgebi[idBandExt].clsid, GUID_NULL))
  2704.         {
  2705.             LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID( idBand );
  2706.             BOOL fIsVisible = _nVisibleBands & EXTERNALBAND_VBF_BIT(idBandExt);
  2707.             if (!pbid && fIsVisible)
  2708.             {
  2709.                 IDeskBand *pitbBand;
  2710.                 hr = _GetPersistedBand(_rgebi[idBandExt].clsid, IID_IDeskBand, (void **) &pitbBand);
  2711.                 if (SUCCEEDED(hr))
  2712.                 {
  2713.                     pbid = _AddNewBand( pitbBand, idBand );
  2714.                     pitbBand->Release();
  2715.                 }
  2716.                 if (!pbid)
  2717.                     return E_OUTOFMEMORY;
  2718.             } else {
  2719.                 pbs = NULL;
  2720.                 if (!pbid)
  2721.                     return S_OK;
  2722.             }
  2723.             _ShowBandCommon(pbs, pbid, fIsVisible );
  2724.         }
  2725.     }
  2726.     return S_OK;
  2727. }
  2728.  
  2729.  
  2730. HRESULT CInternetToolbar::_ShowAddressBand(PBANDSAVE pbs)
  2731. {
  2732.     HRESULT         hr  = S_OK;
  2733.     LPBANDITEMDATA  pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  2734.     if (!pbid)
  2735.     {
  2736.         IDeskBand *pitbAddressBand;
  2737.  
  2738.         hr = _GetPersistedBand(CLSID_AddressBand, IID_IDeskBand, (void **)&pitbAddressBand);
  2739.         if (SUCCEEDED(hr))
  2740.         {
  2741.             pbid = _AddNewBand(pitbAddressBand, CBIDX_ADDRESS);
  2742.             if (pbid)
  2743.                 _hwndAddressBand = pbid->hwnd;
  2744.  
  2745.             pitbAddressBand->Release();
  2746.         }
  2747.  
  2748.         ASSERT(IS_VALID_HANDLE(_hwndAddressBand, WND));
  2749.         if (!pbid)
  2750.             return E_OUTOFMEMORY;
  2751.     } else
  2752.         pbs = NULL;
  2753.  
  2754.  
  2755.     _ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_ADDRESS);
  2756.     return S_OK;
  2757. }
  2758.  
  2759. LPBANDITEMDATA CInternetToolbar::_AddNewBand(IDeskBand* pdb, DWORD dwID)
  2760. {
  2761.     if (SUCCEEDED(_bs._AddBandByID(pdb, dwID)))
  2762.     {
  2763.         return _bs._GetBandItemDataStructByID(dwID);
  2764.     }
  2765.     return NULL;
  2766. }
  2767.  
  2768.  
  2769. HRESULT CInternetToolbar::_ShowLinks(PBANDSAVE pbs)
  2770. {
  2771.     HRESULT hr = S_OK;
  2772.  
  2773.     LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_LINKS);
  2774.     if (!pbid)
  2775.     {
  2776.         IDeskBand* pdbLinks = NULL;
  2777.  
  2778.         // Check if custom link band GUID is present in the registry,
  2779.         // and if so, do a full CoCreateInstance using this GUID.
  2780.         // Otherwise, just do the normal internal call to the link's band factory.
  2781.  
  2782.         if (!_fInitialPidlIsWeb ||
  2783.             FAILED(CreateFromRegKey(c_szRegKeyCoolbar, TEXT("QuickLinksCLSID"), IID_IDeskBand, (void **)&pdbLinks)))
  2784.         {
  2785.             hr = _GetPersistedBand(CLSID_QuickLinks, IID_IDeskBand, (void **)&pdbLinks);
  2786.             IUnknown_Exec(pdbLinks, &CLSID_QuickLinks, QLCMD_SINGLELINE, 1, NULL, NULL);
  2787.         }
  2788.  
  2789.         if (pdbLinks)
  2790.         {
  2791.             // mark it so ISFBand knows it's qlinks (for UAssist)
  2792.             VARIANTARG v;
  2793. #ifdef DEBUG
  2794.             {
  2795.                 // n.b. we overwrite old persisted guys (which should be -1)
  2796.                 IUnknown_Exec(pdbLinks, &CGID_ISFBand, ISFBID_PRIVATEID, 0, NULL, &v);
  2797.                 ASSERT(v.lVal == -1 || v.lVal == CSIDL_FAVORITES);
  2798.             }
  2799. #endif
  2800.             v.vt = VT_I4;
  2801.             v.lVal = CSIDL_FAVORITES;   // close enough for our purposes...
  2802.             IUnknown_Exec(pdbLinks, &CGID_ISFBand, ISFBID_PRIVATEID, 0, &v, NULL);
  2803.             pbid = _AddNewBand(pdbLinks, CBIDX_LINKS);
  2804.  
  2805.             pdbLinks->Release();
  2806.         }
  2807.  
  2808.         if (!pbid)
  2809.             return E_OUTOFMEMORY;
  2810.     } else
  2811.         pbs = NULL;
  2812.  
  2813.     _ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_LINKS);
  2814.     return hr;
  2815. }
  2816.  
  2817. HRESULT CInternetToolbar::_ShowMenu(PBANDSAVE pbs)
  2818. {
  2819.     LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_MENU);
  2820.     if (!pbid)
  2821.     {
  2822.         CFavoritesCallback* pfcb = new CFavoritesCallback();
  2823.         if (pfcb)
  2824.         {
  2825.             IShellMenu* psm = (IShellMenu*)new CMenuBand();
  2826.             if (psm)
  2827.             {
  2828.                 VARIANTARG var;
  2829.  
  2830.                 if (SUCCEEDED(IUnknown_Exec(_pbs2, &CGID_Explorer, SBCMDID_GETCURRENTMENU, 0, NULL, &var)) &&
  2831.                         var.vt == VT_INT_PTR && var.byref)
  2832.                 {
  2833.                     IDeskBand* pdbMenu;
  2834.                     psm->Initialize(pfcb, -1, ANCESTORDEFAULT, SMINIT_HORIZONTAL | SMINIT_TOPLEVEL);
  2835.                     if (SUCCEEDED(psm->SetMenu((HMENU)var.byref, GetParent(_hwnd), SMSET_DONTOWN)))
  2836.                     {
  2837.                         if (SUCCEEDED(psm->QueryInterface(IID_IDeskBand, (void**)&pdbMenu)))
  2838.                         {
  2839.                             pbid = _AddNewBand(pdbMenu, CBIDX_MENU);
  2840.                             if (pbid)
  2841.                             {
  2842.                                 // Tell the menuband we're not a real bar/bandsite/band
  2843.                                 IUnknown_Exec(pbid->pdb, &CGID_MenuBand, MBANDCID_NOTAREALSITE, TRUE, NULL, NULL);
  2844.  
  2845.                                 _bs.SetBandState(CBIDX_MENU, BSSF_NOTITLE, BSSF_NOTITLE);
  2846.                                 _hwndMenu = pbid->hwnd;
  2847.                             }
  2848.  
  2849.                             ASSERT(IS_VALID_HANDLE(_hwndMenu, WND));
  2850.  
  2851.                             pdbMenu->Release();
  2852.                         }
  2853.                     }
  2854.                 }
  2855.                 psm->Release();
  2856.             }
  2857.             pfcb->Release();
  2858.         }
  2859.  
  2860.         if (!pbid)
  2861.             return E_OUTOFMEMORY;
  2862.     } else
  2863.         pbs = NULL;
  2864.  
  2865.  
  2866.     _ShowBandCommon(pbs, pbid, _nVisibleBands & VBF_MENU);
  2867.     return S_OK;
  2868. }
  2869.  
  2870. HRESULT _GetBackBitmapLocation(LPTSTR psz, BOOL fInternet)
  2871. {
  2872.     HRESULT hres = E_FAIL;
  2873.     DWORD dwType;
  2874.     DWORD dwcbData;
  2875.  
  2876.     // IE4 shipped back bitmap customization affecting both browser and shell.
  2877.     // IE5 wants these to be separate customizations.  But in the roaming
  2878.     // case a customized IE4 customer shouldn't lose customization when going
  2879.     // to the IE5 machine.  So we might need to check twice:
  2880.     //
  2881.     if (fInternet)
  2882.     {
  2883.         // Try the IE5 internet location.
  2884.         dwcbData = MAX_PATH * SIZEOF(TCHAR);
  2885.         hres = SHGetValue(HKEY_CURRENT_USER, c_szRegKeyCoolbar, TEXT("BackBitmapIE5"), &dwType, psz, &dwcbData);
  2886.     }
  2887.     else
  2888.     {
  2889.         // Try the NT5 shell location.
  2890.         dwcbData = MAX_PATH * SIZEOF(TCHAR);
  2891.         hres = SHGetValue(HKEY_CURRENT_USER, c_szRegKeyCoolbar, TEXT("BackBitmapShell"), &dwType, psz, &dwcbData);
  2892.     }
  2893.     if (ERROR_SUCCESS != hres)
  2894.     {
  2895.         // Try the old combined internet/shell location
  2896.         dwcbData = MAX_PATH * SIZEOF(TCHAR);
  2897.         hres = SHGetValue(HKEY_CURRENT_USER, c_szRegKeyCoolbar, TEXT("BackBitmap"), &dwType, psz, &dwcbData);
  2898.     }
  2899.     if (ERROR_SUCCESS != hres)
  2900.     {
  2901.         *psz = '\0';
  2902.     }
  2903.  
  2904.     return hres;
  2905. }
  2906.  
  2907. HBITMAP CInternetToolbar::_LoadBackBmp(LPTSTR * ppszBitmap, BMPCACHE * pbmpCache, BOOL fInternet)
  2908. {
  2909.     HIGHCONTRAST    hc;
  2910.     HBITMAP     hbmp = pbmpCache->hbmp;
  2911.     COLORREF    cr3D = GetSysColor(COLOR_3DFACE);
  2912.     TCHAR       szScratch[MAX_PATH];
  2913.     LPTSTR      pszBitmap = NULL;
  2914.     BOOL        fBitmapInvalid = FALSE;
  2915.  
  2916.  
  2917.     ENTERCRITICAL;
  2918.  
  2919.     // If the stashed hbmp's cr3D color changed, we need to mark invalid
  2920.     if (pbmpCache->hbmp && pbmpCache->cr3D != cr3D)
  2921.         fBitmapInvalid = TRUE;
  2922.  
  2923.     // get the location spec for the bitmap
  2924.     hc.cbSize = sizeof(HIGHCONTRAST);
  2925.     if ((SystemParametersInfoA(SPI_GETHIGHCONTRAST, hc.cbSize, (LPVOID) &hc, FALSE)) &&
  2926.         (hc.dwFlags & HCF_HIGHCONTRASTON))
  2927.     {
  2928.         // we have no bitmap in high contrast
  2929.     }
  2930.     else if (SUCCEEDED(_GetBackBitmapLocation(szScratch, fInternet)))
  2931.     {
  2932.         pszBitmap = szScratch;
  2933.     }
  2934.  
  2935.     // if they are removing the bitmap, we need to mark invalid
  2936.     if (!pszBitmap && *ppszBitmap)
  2937.         fBitmapInvalid = TRUE;
  2938.  
  2939.     // or it's location has been changed, we need to mark invalid
  2940.     if (pszBitmap && (!*ppszBitmap || lstrcmpi(pszBitmap, *ppszBitmap)))
  2941.         fBitmapInvalid = TRUE;
  2942.  
  2943.     if (fBitmapInvalid)
  2944.     {
  2945.         TraceMsg(DM_ITBAR, "CInternetToolbar: Loading Background Bitmap");
  2946.  
  2947.         Str_SetPtr(ppszBitmap, pszBitmap);
  2948.  
  2949.         hbmp=NULL;
  2950.         if (*ppszBitmap)
  2951.         {
  2952.             if ((*ppszBitmap)[0])
  2953.                 hbmp = (HBITMAP) LoadImage(NULL, szScratch, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION | LR_LOADFROMFILE | LR_LOADMAP3DCOLORS );
  2954.  
  2955.             if (!hbmp)
  2956.             {
  2957. #ifdef OLD_SWIRLY_BACKDROP
  2958.                 if (SHGetCurColorRes() <= 8)
  2959.                     hbmp = (HBITMAP) LoadImage(HINST_THISDLL, MAKEINTRESOURCE(IDB_BACK), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS );
  2960. #endif
  2961.             }
  2962.         }
  2963.  
  2964. #ifdef OLD_LEGACY_BAD_COLOUR_CODE
  2965.         if (hbmp)
  2966.         {
  2967.             // mapping needed ?
  2968.             // BUGBUG: this will be removed as soon as I get the new backdrop....
  2969.             if ( /* cr3D != RGB(192,192,192) */ FALSE)
  2970.             {
  2971.                 RGBQUAD     rgbTable[256];
  2972.                 RGBQUAD     rgbFace;
  2973.                 HDC         dc;
  2974.                 HBITMAP     hbmSave;
  2975.                 UINT        i;
  2976.                 UINT        n;
  2977.  
  2978.                 dc = CreateCompatibleDC(NULL);
  2979.                 hbmSave = (HBITMAP)SelectObject(dc, hbmp);
  2980.                 n = GetDIBColorTable(dc, 0, 256, rgbTable);
  2981.  
  2982.                 rgbFace.rgbRed   = GetRValue(cr3D);
  2983.                 rgbFace.rgbGreen = GetGValue(cr3D);
  2984.                 rgbFace.rgbBlue  = GetBValue(cr3D);
  2985.  
  2986.                 for (i = 0; i < n; i++)
  2987.                 {
  2988.                     if ( rgbTable[i].rgbRed == 192 && rgbTable[i].rgbGreen == 192 && rgbTable[i].rgbBlue == 192 )
  2989.                     {
  2990.                         rgbTable[i] = rgbFace;
  2991.                     }
  2992.                     else
  2993.                     {
  2994.                         rgbTable[i].rgbRed   = (rgbTable[i].rgbRed   * rgbFace.rgbRed  ) / 192;
  2995.                         rgbTable[i].rgbGreen = (rgbTable[i].rgbGreen * rgbFace.rgbGreen) / 192;
  2996.                         rgbTable[i].rgbBlue  = (rgbTable[i].rgbBlue  * rgbFace.rgbBlue ) / 192;
  2997.                     }
  2998.                 }
  2999.  
  3000.                 SetDIBColorTable(dc, 0, n, rgbTable);
  3001.                 SelectObject(dc, hbmSave);
  3002.                 DeleteDC(dc);
  3003.             }
  3004.         }
  3005. #endif
  3006.  
  3007.         if (pbmpCache->hbmp)
  3008.             DeleteObject(pbmpCache->hbmp);
  3009.         pbmpCache->hbmp = hbmp;
  3010.         pbmpCache->cr3D = cr3D;
  3011.     }
  3012.  
  3013.     LEAVECRITICAL;
  3014.  
  3015.     return hbmp;
  3016. }
  3017.  
  3018. HBITMAP CInternetToolbar::_LoadBackBitmap()
  3019. {
  3020.     if (SHIsLowMemoryMachine(ILMM_IE4))
  3021.         return NULL;
  3022.  
  3023.     if (_fInitialPidlIsWeb)
  3024.     {
  3025.         static LPTSTR s_pszBitmapInternet = NULL;
  3026.         return _LoadBackBmp(&s_pszBitmapInternet, &s_bmpBackInternet, _fInitialPidlIsWeb);
  3027.     }
  3028.     else
  3029.     {
  3030.         static LPTSTR s_pszBitmapShell = NULL;
  3031.         return _LoadBackBmp(&s_pszBitmapShell, &s_bmpBackShell, _fInitialPidlIsWeb);
  3032.     }
  3033. }
  3034.  
  3035. void CInternetToolbar::_SetBackground()
  3036. {
  3037.     REBARBANDINFO   rbbi;
  3038.     HBITMAP         hbmp;
  3039.  
  3040.     // Theater mode doesn't allow bitmap customization, so don't bother loading one from the cache
  3041.     if (_fTheater)
  3042.         hbmp = NULL;
  3043.     else
  3044.         hbmp = _LoadBackBitmap();
  3045.  
  3046.     // don't bother updating the bkcolor if we know we'll just set it to CLR_NONE below (otherwise rebar invalidates)
  3047.     if (!hbmp)
  3048.         SendMessage(_bs._hwnd, RB_SETBKCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
  3049.  
  3050.     // If we think we have a bitmap, or the cache thinks we have a bitmap, we have some work to do
  3051.     if (_bmpBack || hbmp)
  3052.     {
  3053.         BOOL fRemove = (NULL!=_bmpBack && NULL==hbmp);
  3054.  
  3055.         if (hbmp)
  3056.             SendMessage(_bs._hwnd, RB_SETBKCOLOR, 0, (LPARAM)CLR_NONE);
  3057.         _bmpBack = hbmp;
  3058.  
  3059.         rbbi.cbSize = sizeof(REBARBANDINFO);
  3060.  
  3061.         INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
  3062.  
  3063.         INT icBands = (INT) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
  3064.         for (int i = 0; i < icBands; i++)
  3065.         {
  3066.             rbbi.fMask = RBBIM_ID | RBBIM_CHILD | RBBIM_BACKGROUND;
  3067.             if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  3068.             {
  3069.                 if (rbbi.wID != CBIDX_BRAND && rbbi.hbmBack != hbmp)
  3070.                 {
  3071.                     rbbi.fMask = RBBIM_BACKGROUND;
  3072.                     rbbi.hbmBack = hbmp;
  3073.                     SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
  3074.                     InvalidateRect(rbbi.hwndChild, NULL, TRUE);
  3075.                 }
  3076.             }
  3077.         }
  3078.         SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
  3079.  
  3080.         // When removing the background bitmap, we need to invalidate *outside*
  3081.         // of the WM_SETREDRAW so we actually erase the background properly
  3082.         //
  3083.         if (fRemove)
  3084.             InvalidateRect(_bs._hwnd, NULL, TRUE);
  3085.  
  3086.     }
  3087. }
  3088.  
  3089.  
  3090. HRESULT CInternetToolbar::_ShowBrand(PBANDSAVE pbs)
  3091. {
  3092.     REBARBANDINFO       rbbi;
  3093.     LPBANDITEMDATA      pbid;
  3094.     INT_PTR             i;
  3095.     HRESULT             hr = S_OK;
  3096.     BOOL                fCreated = FALSE;
  3097.  
  3098.     pbid = _bs._GetBandItemDataStructByID(CBIDX_BRAND);
  3099.     if (!pbid)
  3100.     {
  3101.         IDeskBand *pdbBrandBand;
  3102.         hr = CBrandBand_CreateInstance(NULL, (IUnknown **)&pdbBrandBand, NULL);
  3103.         if (SUCCEEDED(hr))
  3104.         {
  3105.             pbid = _AddNewBand(pdbBrandBand, CBIDX_BRAND);
  3106.             fCreated = TRUE;
  3107.             pdbBrandBand->Release();
  3108.         }
  3109.         else
  3110.             return hr;
  3111.     }
  3112.  
  3113.     if (!pbid)
  3114.         return E_OUTOFMEMORY;
  3115.  
  3116.     pbid->pdb->ShowDW(TRUE);
  3117.  
  3118.     i = BandIDtoIndex(_bs._hwnd, CBIDX_BRAND);
  3119.     if (fCreated)
  3120.     {
  3121.         // add these to ::IDeskBand::GetBandInfo()
  3122.         rbbi.cbSize = sizeof(REBARBANDINFO);
  3123.         rbbi.fMask = RBBIM_STYLE;
  3124.         rbbi.fStyle = RBBS_FIXEDSIZE | RBBS_VARIABLEHEIGHT;
  3125.  
  3126.         if (pbs)
  3127.         {
  3128.             rbbi.fMask |= RBBIM_SIZE;
  3129.             rbbi.fStyle |= pbs->fStyle;
  3130.             rbbi.cx = pbs->cx;
  3131.         }
  3132.         SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM)&rbbi);
  3133.         // this can cause the band to move because a fixed size band
  3134.         // is forced in a particular location.
  3135.         // so we need to re-fetch the index
  3136.         i = BandIDtoIndex(_bs._hwnd, CBIDX_BRAND);
  3137.     }
  3138.     SendMessage(_bs._hwnd, RB_SHOWBAND, i, _nVisibleBands & VBF_BRAND);
  3139.     return S_OK;
  3140. }
  3141.  
  3142. void CInternetToolbar::_EnsureAllBandsShown()
  3143. {
  3144.     if (_hwnd) {
  3145.  
  3146.         INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
  3147.  
  3148.         _ShowMenu(NULL);
  3149.         _ShowTools(NULL);
  3150.         _ShowAddressBand(NULL);
  3151.         _ShowLinks(NULL);
  3152.         _ShowBrand(NULL);
  3153.         for (int i = CBIDX_EXTERNALFIRST; i <= CBIDX_EXTERNALLAST; i++) {
  3154.             _ShowExternalBand( NULL, i );
  3155.         }
  3156.         _SetBackground();
  3157.         _bs._SetMinDimensions();
  3158.         SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
  3159.     }
  3160. }
  3161.  
  3162. BOOL CInternetToolbar::_ShowBands(UINT fVisible)
  3163. {
  3164.     fVisible &= VBF_VALID;
  3165.  
  3166.     if (fVisible == _nVisibleBands)
  3167.         return(TRUE);
  3168.  
  3169.     _nVisibleBands = fVisible;
  3170.     _EnsureAllBandsShown();
  3171.     ShowDW(_fShow);
  3172.  
  3173.     return(TRUE);
  3174. }
  3175.  
  3176. HRESULT CInternetToolbar::_CreateBands()
  3177. {
  3178.     HRESULT hres = S_OK;
  3179.  
  3180.     if (!_hwnd && _ptbsite)
  3181.     {
  3182.         HWND hwndParent;
  3183.  
  3184.         hres= _ptbsite->GetWindow(&hwndParent);
  3185.         if (SUCCEEDED(hres))
  3186.         {
  3187.             TCHAR szScratch[16];
  3188.             int i;
  3189.  
  3190.             // Check if coolbar layout had already been loaded from the registry
  3191.             if(_cs.cbVer != CBS_VERSION)
  3192.             {
  3193.                 TraceMsg(DM_ITBAR, "CInternetToolbar:ShowDW failed. Bad Version");
  3194.                 ASSERT(0);
  3195.  
  3196.                 return(S_FALSE);
  3197.             }
  3198.  
  3199.             _nVisibleBands = _cs.uiVisible;
  3200.  
  3201.             _InitComCtl32();    // don't check result, if this fails our CreateWindows will fail
  3202.  
  3203.             MLLoadString(IDS_WEB_TB_TEXTROWS, szScratch, ARRAYSIZE(szScratch));
  3204.             _uiTBTextRows = _uiTBDefaultTextRows = StrToInt(szScratch);
  3205.  
  3206.             _fCompressed = (_cs.fNoText != FALSE);
  3207.  
  3208.             _hwnd = SHCreateWorkerWindow(SizableWndProc, hwndParent, 0, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  3209.                                        (HMENU)FCIDM_REBAR, this);
  3210.  
  3211.             if (!IS_VALID_HANDLE(_hwnd, WND))
  3212.             {
  3213.                 TraceMsg(TF_ERROR, "_hwnd failed");
  3214.                 return E_OUTOFMEMORY;
  3215.             }
  3216.  
  3217.             // delay until now
  3218.             // this sets up the parent child chain so that these children can
  3219.             // queryservice through us
  3220.             SetClient(SAFECAST(&_bs, IInputObjectSite*));
  3221.  
  3222.             INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
  3223.  
  3224.             for (i = 0; i < CBANDSMAX; i++)
  3225.             {
  3226.                 hres = S_OK;
  3227.                 switch (_cs.bs[i].wID)
  3228.                 {
  3229.                 case CBIDX_TOOLS:
  3230.                     if(!SHRestricted2W(REST_NoToolBar, NULL, 0))
  3231.                     {
  3232.                         hres = _ShowTools(_cs.bs + i);
  3233.                     }
  3234.                     else
  3235.                     {
  3236.                         _nVisibleBands &= ~VBF_TOOLS;
  3237.                     }
  3238.                     break;
  3239.  
  3240.                 case CBIDX_ADDRESS:
  3241.                     if(!SHRestricted2W(REST_NoAddressBar, NULL, 0))
  3242.                     {
  3243.                         hres = _ShowAddressBand(_cs.bs + i);
  3244.                     }
  3245.                     else
  3246.                     {
  3247.                         _nVisibleBands &= ~VBF_ADDRESS;
  3248.                     }
  3249.                     break;
  3250.  
  3251.                 case CBIDX_LINKS:
  3252.                     if(!SHRestricted2W(REST_NoLinksBar, NULL, 0))
  3253.                     {
  3254.                         hres = _ShowLinks(_cs.bs + i);
  3255.                     }
  3256.                     else
  3257.                     {
  3258.                         _nVisibleBands &= ~VBF_LINKS;
  3259.                     }
  3260.                     break;
  3261.  
  3262.                 case CBIDX_BRAND:
  3263.                     hres = _ShowBrand(_cs.bs + i);
  3264.                     break;
  3265.  
  3266.                 case CBIDX_MENU:
  3267.                     hres = _ShowMenu(_cs.bs + i);
  3268.                     break;
  3269.  
  3270.                 case 0xFFFFFFFF:
  3271.                 {
  3272.                     // Out of bands; stop loop.
  3273.                     i = CBANDSMAX;
  3274.                     break;
  3275.                 }
  3276.  
  3277.                 default:
  3278.                     if (IS_EXTERNALBAND(_cs.bs[i].wID))
  3279.                     {
  3280.                         for (DWORD j = 0; j < MAXEXTERNALBANDS; j++)
  3281.                         {
  3282.                             if (_cs.aclsidExternalBands[MAP_TO_EXTERNAL(_cs.bs[i].wID)] == _rgebi[j].clsid)
  3283.                             {
  3284.                                 CLSID clsidTemp = _rgebi[j].clsid;
  3285.                                 _rgebi[j].clsid = _rgebi[MAP_TO_EXTERNAL(_cs.bs[i].wID)].clsid;
  3286.                                 _rgebi[MAP_TO_EXTERNAL(_cs.bs[i].wID)].clsid = clsidTemp;
  3287.                                 hres = _ShowExternalBand(_cs.bs + i, _cs.bs[i].wID);
  3288.                                 break;
  3289.                             }
  3290.                         }
  3291.                     }
  3292.                     break;
  3293.                 }
  3294.  
  3295.                 if (hres != S_OK)
  3296.                     TraceMsg(TF_ERROR, "CInternetToolbar::_CreateBands -- band ID %x creation failed", _cs.bs[i].wID);
  3297.             }
  3298.  
  3299.             // Add any remaining bands
  3300.             _EnsureAllBandsShown();
  3301.  
  3302.             _SetBackground();
  3303.             _bs._SetMinDimensions();
  3304.  
  3305.             SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
  3306.         }
  3307.     }
  3308.     return hres;
  3309. }
  3310.  
  3311. HRESULT CInternetToolbar::ShowDW(BOOL fShow)
  3312. {
  3313.     if ((g_dwProfileCAP & 0x00000008) && s_imlTBGlyphs.arhiml[0]) {
  3314.         StartCAP();
  3315.     }
  3316.  
  3317.     HRESULT hres = _CreateBands();
  3318.     if (FAILED(hres))
  3319.         return hres;
  3320.  
  3321.     if (!_nVisibleBands && fShow)
  3322.         return(FALSE);
  3323.  
  3324.     _fShow = fShow;
  3325.  
  3326.     _bs.UIActivateDBC(fShow ? DBC_SHOW : DBC_HIDE);
  3327.  
  3328.     ResizeBorderDW(NULL, NULL, FALSE);
  3329.     ShowWindow(_hwnd, fShow ? SW_SHOW : SW_HIDE);
  3330.  
  3331.  
  3332.     BOOL fConnect = (fShow && _dwcpCookie == 0);
  3333.     if (fConnect || (!fShow && _dwcpCookie != 0))
  3334.     {
  3335.         ConnectToConnectionPoint(SAFECAST(this, IDockingWindow*), DIID_DWebBrowserEvents2, fConnect, _pdie, &_dwcpCookie, NULL);
  3336.     }
  3337.  
  3338.     return hres;
  3339. }
  3340.  
  3341. int ITBar_TrackPopupMenuEx(HMENU hmenu, UINT uFlags, int x, int y, HWND hwnd, LPRECT prcExclude)
  3342. {
  3343.     TPMPARAMS tpm;
  3344.     if (prcExclude) {
  3345.         tpm.cbSize = SIZEOF(TPMPARAMS);
  3346.         CopyRect(&tpm.rcExclude, prcExclude);
  3347.     }
  3348.     return TrackPopupMenuEx(hmenu, uFlags, x, y, hwnd, prcExclude ? &tpm : NULL);
  3349. }
  3350.  
  3351. /*******************************************************************
  3352.  
  3353. NAME:       CInternetToolbar::_ShowBackForwardMenu
  3354.  
  3355. SYNOPSIS:
  3356. NOTES:
  3357. ********************************************************************/
  3358. BOOL CInternetToolbar::_ShowBackForwardMenu(BOOL fForward, POINT pt, LPRECT prcExclude)
  3359. {
  3360.     BOOL fRet = FALSE;
  3361.     HMENU hmenuBF = CreatePopupMenu();
  3362.  
  3363.     ASSERT(hmenuBF);
  3364.  
  3365.     ASSERT(_pbs2);
  3366.     ITravelLog *ptl;
  3367.     _pbs2->GetTravelLog(&ptl);
  3368.     if(ptl)
  3369.     {
  3370.         if(S_OK == ptl->InsertMenuEntries(_pbs2, hmenuBF, 0, 1, MAX_NAV_MENUITEMS, fForward ? TLMENUF_FORE : TLMENUF_BACK))
  3371.         {
  3372.         // If any menu items were added, show the menu and navigate to it
  3373.             int nIndex;
  3374.  
  3375. #ifndef MAINWIN
  3376.             if (nIndex = ITBar_TrackPopupMenuEx (hmenuBF, TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, _hwnd, prcExclude))
  3377. #else
  3378.             // Because mainwin doesn't support win95 look and feel we are
  3379.             // having a problem to keep the popup from dismissing when we
  3380.             // pass NULL as noDismissal area.
  3381.             RECT rect;
  3382.             GetWindowRect( _hwnd, &rect );
  3383.             if (nIndex = (int)TrackPopupMenu (hmenuBF,
  3384.                 TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
  3385.                 pt.x, pt.y, 0, _hwnd,
  3386.                 &rect))
  3387. #endif
  3388.                 ptl->Travel(_pbs2, (fForward ? nIndex : -nIndex));
  3389.  
  3390.             fRet = TRUE;
  3391.         }
  3392.         ptl->Release();
  3393.     }
  3394.  
  3395.     DestroyMenu (hmenuBF);
  3396.     return fRet;
  3397. }
  3398.  
  3399. // get per folder search items and default search
  3400. BOOL CInternetToolbar::_GetFolderSearchData()
  3401. {
  3402.     int iInserted=0;
  3403.  
  3404.     if (_pbs2)
  3405.     {
  3406.         LPCBASEBROWSERDATA pbbd;
  3407.  
  3408.         if (SUCCEEDED(_pbs2->GetBaseBrowserData(&pbbd)) && (pbbd->_psfPending || pbbd->_psf))
  3409.         {
  3410.             IShellFolder2 * psf2;
  3411.             IShellFolder*   psf = pbbd->_psfPending ? pbbd->_psfPending : pbbd->_psf;
  3412.  
  3413.             if (SUCCEEDED(psf->QueryInterface(IID_IShellFolder2, (LPVOID*)&psf2)))
  3414.             {
  3415.                 LPENUMEXTRASEARCH penum;
  3416.                 GUID              guid;
  3417.  
  3418.                 if (SUCCEEDED(psf2->GetDefaultSearchGUID(&guid)))
  3419.                     _guidDefaultSearch = guid;
  3420.  
  3421.                 // get per folder search items
  3422.                 if (_hdpaFSI && SUCCEEDED(psf2->EnumSearches(&penum)))
  3423.                 {
  3424.                     EXTRASEARCH  xs;
  3425.  
  3426.                     while(penum->Next(1, &xs, NULL) == S_OK)
  3427.                     {
  3428.                         LPFOLDERSEARCHITEM pfsi = (LPFOLDERSEARCHITEM)LocalAlloc(LPTR, sizeof(FOLDERSEARCHITEM));
  3429.                         if (pfsi)
  3430.                         {
  3431.                             pfsi->idCmd = -1;
  3432.                             pfsi->guidSearch = xs.guidSearch;
  3433.                             StrCpyNW(pfsi->wszUrl, xs.wszUrl, ARRAYSIZE(pfsi->wszUrl));
  3434.                             StrCpyNW(pfsi->wszName, xs.wszFriendlyName, ARRAYSIZE(pfsi->wszName));
  3435.  
  3436.                             if (DPA_InsertPtr(_hdpaFSI, iInserted, pfsi) != -1)
  3437.                                 iInserted++;
  3438.                             else
  3439.                                 LocalFree(pfsi);
  3440.                         }
  3441.                     }
  3442.                     penum->Release();
  3443.                 }
  3444.                 psf2->Release();
  3445.             }
  3446.         }
  3447.     }
  3448.  
  3449.     return (iInserted > 0);
  3450. }
  3451.  
  3452. BOOL NavigateSearchBar(IWebBrowser2 *pwb2, LPCWSTR pwszUrl)
  3453. {
  3454.     BOOL          bRet  = FALSE;
  3455.     SA_BSTR       bstr;
  3456.     VARIANT       var;
  3457.     VARIANT       varEmpty = {0};
  3458.  
  3459.     SHStringFromGUIDW(CLSID_SearchBand, bstr.wsz, ARRAYSIZE(bstr.wsz));
  3460.     bstr.cb = lstrlenW(bstr.wsz) * sizeof(WCHAR);
  3461.  
  3462.     var.vt = VT_BSTR;
  3463.     var.bstrVal = bstr.wsz;
  3464.  
  3465.     // show a search bar
  3466.     if (SUCCEEDED(pwb2->ShowBrowserBar(&var, &varEmpty, &varEmpty)))
  3467.     {
  3468.         VARIANT varTargetFrame = {0};
  3469.         VARIANT varFlags = {0};
  3470.  
  3471.         StrCpyNW(bstr.wsz, pwszUrl, ARRAYSIZE(bstr.wsz));
  3472.         bstr.cb = lstrlenW(bstr.wsz) * sizeof(WCHAR);
  3473.  
  3474.         varFlags.vt = VT_I4;
  3475.         varFlags.lVal = navBrowserBar;
  3476.  
  3477.         var.vt = VT_BSTR;
  3478.         var.bstrVal = bstr.wsz;
  3479.  
  3480.         // navigate the search bar to the correct url
  3481.         if (SUCCEEDED(pwb2->Navigate2(&var, &varFlags, &varTargetFrame, &varEmpty, &varEmpty)))
  3482.             bRet = TRUE;
  3483.     }
  3484.     return bRet;
  3485. }
  3486.  
  3487. void RestrictItbarViewMenu(HMENU hmenu, IUnknown *punkBar )
  3488. {
  3489.     BOOL fIsRestricted = SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0);
  3490.     if (fIsRestricted) {
  3491.         _EnableMenuItem(hmenu, FCIDM_VIEWLINKS, FALSE);
  3492.         _EnableMenuItem(hmenu, FCIDM_VIEWMENU, FALSE);
  3493.         _EnableMenuItem(hmenu, FCIDM_VIEWADDRESS, FALSE);
  3494.         _EnableMenuItem(hmenu, FCIDM_VIEWTOOLS, FALSE);
  3495.     }
  3496.  
  3497.     for (int i = 0; i < MAXEXTERNALBANDS; i++) {
  3498.         OLECMD cmd = { CITIDM_VIEWEXTERNALBAND_FIRST + i, 0 };
  3499.         OLECMDTEXTV<MAX_EXTERNAL_BAND_NAME_LEN> cmdtv;
  3500.         OLECMDTEXT *pcmdText = &cmdtv;
  3501.         pcmdText->cmdtextf = OLECMDTEXTF_NAME;
  3502.         pcmdText->cwActual = 0;
  3503.         pcmdText->cwBuf = MAX_EXTERNAL_BAND_NAME_LEN;
  3504.  
  3505.         IUnknown_QueryStatus( punkBar, &CGID_PrivCITCommands, 1, &cmd, pcmdText );
  3506.         if (cmd.cmdf & OLECMDF_SUPPORTED) {
  3507.             DWORD dwMenuCommand = FCIDM_EXTERNALBANDS_FIRST + i;
  3508.             InsertMenu( hmenu, FCIDM_VIEWCONTEXTMENUSEP, MF_BYCOMMAND, dwMenuCommand, pcmdText->rgwz );
  3509.             if (cmd.cmdf & OLECMDF_ENABLED) {
  3510.                 _CheckMenuItem( hmenu, dwMenuCommand, TRUE );
  3511.             }
  3512.             if (fIsRestricted) {
  3513.                 _EnableMenuItem( hmenu, dwMenuCommand, FALSE );
  3514.             }
  3515.         }
  3516.     }
  3517. }
  3518.  
  3519. void CInternetToolbar::_ShowContextMenu(HWND hwnd, LPARAM lParam, LPRECT prcExclude)
  3520. {
  3521.     // Bail if this context menu doesn't correspond to a band (fixes NT5 #181899)
  3522.     POINT pt;
  3523.     int iIndex = _bs._ContextMenuHittest(lParam, &pt);
  3524.     int idBandActive = _bs._IndexToBandID(iIndex);
  3525.     if (!InRange(idBandActive, CBIDX_FIRST, CBANDSMAX))
  3526.         return;
  3527.  
  3528.     // Bail if we can't find the resource
  3529.     HMENU hmenuITB = LoadMenuPopup(MENU_ITOOLBAR);
  3530.     if (!hmenuITB)
  3531.         return;
  3532.  
  3533.     UEMFireEvent(&UEMIID_SHELL, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_UICONTEXT, idBandActive == -1 ? UIBL_CTXTITBBKGND : UIBL_CTXTITBITEM);
  3534.  
  3535.     // Set the initial state of the menu
  3536.     _CheckMenuItem (hmenuITB, FCIDM_VIEWTOOLS, _nVisibleBands & VBF_TOOLS);
  3537.     _CheckMenuItem (hmenuITB, FCIDM_VIEWADDRESS, _nVisibleBands & VBF_ADDRESS);
  3538.     _CheckMenuItem (hmenuITB, FCIDM_VIEWLINKS, _nVisibleBands & VBF_LINKS);
  3539.  
  3540.     int cItemsBelowSep = 4;
  3541.  
  3542.     // only in theater mode can we autohide
  3543.     if (!_fTheater)
  3544.     {
  3545.         DeleteMenu(hmenuITB, FCIDM_VIEWAUTOHIDE, MF_BYCOMMAND);
  3546.         cItemsBelowSep--;
  3547.         if (_nVisibleBands & VBF_MENU || _fNoShowMenu)
  3548.             DeleteMenu(hmenuITB, FCIDM_VIEWMENU, MF_BYCOMMAND);
  3549.     }
  3550.     else
  3551.     {
  3552.         if (_fNoShowMenu)
  3553.             DeleteMenu(hmenuITB, FCIDM_VIEWMENU, MF_BYCOMMAND);
  3554.         DeleteMenu(hmenuITB, FCIDM_VIEWTOOLS, MF_BYCOMMAND);
  3555.         _CheckMenuItem (hmenuITB, FCIDM_VIEWAUTOHIDE, _fAutoHide);
  3556.         _CheckMenuItem (hmenuITB, FCIDM_VIEWMENU, _nVisibleBands & VBF_MENU);
  3557.     }
  3558.  
  3559.     // if it was done via the keyboard, but focus wasn't on the tools band,
  3560.     // then don't have customize menu option
  3561.     // or if click didn't happen on the band
  3562.     if (!(_btb._fCustomize && idBandActive == CBIDX_TOOLS))
  3563.     {
  3564.         DeleteMenu(hmenuITB, FCIDM_VIEWTOOLBARCUSTOMIZE, MF_BYCOMMAND);
  3565.         cItemsBelowSep--;
  3566.     }
  3567.  
  3568.     BOOL fGoButtonAvailable =
  3569.         WasOpenedAsBrowser(static_cast<IExplorerToolbar *>(this)) || (GetUIVersion() >= 5);
  3570.  
  3571.     // Only show the go button item when you click on the address bar
  3572.     if (idBandActive != CBIDX_ADDRESS || !fGoButtonAvailable)
  3573.     {
  3574.         DeleteMenu(hmenuITB, FCIDM_VIEWGOBUTTON, MF_BYCOMMAND);
  3575.         cItemsBelowSep--;
  3576.     }
  3577.     else
  3578.     {
  3579.         BOOL fShowGoButton = SHRegGetBoolUSValue(REGSTR_PATH_MAIN,
  3580.                                 TEXT("ShowGoButton"), FALSE, /*default*/TRUE);
  3581.         _CheckMenuItem(hmenuITB, FCIDM_VIEWGOBUTTON, fShowGoButton);
  3582.     }
  3583.  
  3584.     if (_fTheater || _btb._fCustomize || SHRestricted2(REST_LOCKICONSIZE, NULL, 0))
  3585.     {
  3586.         DeleteMenu(hmenuITB, FCIDM_VIEWTEXTLABELS, MF_BYCOMMAND);
  3587.         cItemsBelowSep--;
  3588.     }
  3589.     else
  3590.     {
  3591.         // If customize is unavailable, then there's no way for the user to
  3592.         // turn list style on/off.  In this case we want toggling text labels
  3593.         // to work the way it did in IE4 -- that is, switch between "text on
  3594.         // all buttons" and "text on no buttons".  So, if we're in "selective
  3595.         // text on right" mode, we say that labels are turned off.  If the user
  3596.         // picks this menu option, we'll go into "text on all buttons" mode.
  3597.  
  3598.         BOOL fChecked = !_fCompressed && !IS_LIST_STYLE(_btb._hwnd);
  3599.         _CheckMenuItem(hmenuITB, FCIDM_VIEWTEXTLABELS, fChecked);
  3600.     }
  3601.  
  3602.     if (!cItemsBelowSep)
  3603.         DeleteMenu(hmenuITB, FCIDM_VIEWCONTEXTMENUSEP, MF_BYCOMMAND);
  3604.  
  3605.     RestrictItbarViewMenu(hmenuITB, SAFECAST( this, IOleCommandTarget* ) );
  3606.     ITBar_TrackPopupMenuEx(hmenuITB, TPM_LEFTBUTTON | TPM_RIGHTBUTTON, pt.x, pt.y, _hwnd, prcExclude);
  3607.  
  3608.     // HACK: since the ITBar isn't a real bar/bandsite, we have to
  3609.     // do this so any menuband that might be up can take back the
  3610.     // mouse capture.
  3611.     LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_MENU);
  3612.     if (pbid)
  3613.         IUnknown_Exec(pbid->pdb, &CGID_MenuBand, MBANDCID_RECAPTURE, 0, NULL, NULL);
  3614.  
  3615.     DestroyMenu (hmenuITB);
  3616. }
  3617.  
  3618.  
  3619. void CInternetToolbar::_QueryStatusTip(IOleCommandTarget *pct, LPTOOLTIPTEXT pnmTT, UINT uiCmd, const GUID* pguid)
  3620. {
  3621.     OLECMD rgcmd = { uiCmd, 0 };
  3622.     OLECMDTEXTV<MAX_TOOLTIP_STRING> cmdtv;
  3623.     OLECMDTEXT *pcmdText = &cmdtv;
  3624.  
  3625.     pcmdText->cwBuf = MAX_TOOLTIP_STRING;
  3626.     pcmdText->cmdtextf = OLECMDTEXTF_NAME;
  3627.     pcmdText->rgwz[0] = 0;
  3628.     pct->QueryStatus(pguid, 1, &rgcmd, pcmdText);
  3629.     if (rgcmd.cmdf & OLECMDF_ENABLED)
  3630.     {
  3631.         SHUnicodeToTChar(pcmdText->rgwz, pnmTT->szText, MAX_TOOLTIP_STRING);
  3632.     }
  3633.  
  3634. }
  3635.  
  3636. BOOL _IsDocHostGUID(const GUID* pguid)
  3637. {
  3638.     // Dochost merges under one of two clsids, so have to check both
  3639.     BOOL fRet = IsEqualGUID(*pguid, CLSID_InternetButtons) ||
  3640.                 IsEqualGUID(*pguid, CLSID_MSOButtons);
  3641.     return fRet;
  3642. }
  3643.  
  3644. void CInternetToolbar::_OnTooltipNeeded(LPTOOLTIPTEXT pnmTT)
  3645. {
  3646.  
  3647.     UINT uiCmd;
  3648.     GUID guid;
  3649.  
  3650.     ASSERT(pnmTT->hdr.hwndFrom == (HWND)SendMessage(_btb._hwnd, TB_GETTOOLTIPS, 0, 0));
  3651.     _btb._ConvertCmd(NULL, (UINT)pnmTT->hdr.idFrom, &guid, &uiCmd);
  3652.  
  3653.     // Make sure tooltips don't filter out ampersands
  3654.     LONG lStyle = GetWindowLong(pnmTT->hdr.hwndFrom, GWL_STYLE);
  3655.     if (!IsFlagSet(lStyle, TTS_NOPREFIX))
  3656.     {
  3657.         SetWindowLong(pnmTT->hdr.hwndFrom, GWL_STYLE, lStyle | TTS_NOPREFIX);
  3658.     }
  3659.  
  3660.     if (IsEqualGUID(guid, CLSID_CommonButtons))
  3661.     {
  3662.         switch (uiCmd)
  3663.         {
  3664.  
  3665.         case TBIDM_FORWARD:
  3666.         case TBIDM_BACK:
  3667.             if (_ptbsite)
  3668.             {
  3669.                 IBrowserService *pbsvc;
  3670.  
  3671.                 if (SUCCEEDED(_ptbsite->QueryInterface(IID_IBrowserService, (void **)&pbsvc)))
  3672.                 {
  3673.                     // BUGBUG raymondc - make ITravelLog UNICODE someday
  3674.                     ITravelLog *ptl;
  3675.                     pbsvc->GetTravelLog( &ptl );
  3676.                     if (ptl)
  3677.                     {
  3678.                         WCHAR szTemp[ARRAYSIZE(pnmTT->szText)];
  3679.                         if (uiCmd == TBIDM_BACK)
  3680.                             ptl->GetToolTipText(pbsvc, TLOG_BACK, 0, szTemp, ARRAYSIZE(szTemp));
  3681.                         else if (uiCmd == TBIDM_FORWARD)
  3682.                             ptl->GetToolTipText(pbsvc, TLOG_FORE, 0, szTemp, ARRAYSIZE(szTemp));
  3683.  
  3684.                         SHUnicodeToTChar(szTemp, pnmTT->szText, ARRAYSIZE(pnmTT->szText));
  3685.  
  3686.                         ptl->Release();
  3687.                     }
  3688.                     pbsvc->Release();
  3689.                     return;
  3690.                 }
  3691.             }
  3692.         }
  3693.     }
  3694.     // Dochost merges under one of two clsids, so have to check both
  3695.     else if (_IsDocHostGUID(&guid))
  3696.     {
  3697. #ifdef EDIT_HACK
  3698.         if (uiCmd == DVIDM_EDITPAGE)
  3699.             _aEditVerb.GetToolTip(pnmTT->szText, ARRAYSIZE(pnmTT->szText));
  3700. #endif
  3701.     }
  3702. }
  3703.  
  3704. LRESULT CInternetToolbar::_OnBeginDrag(NMREBAR *pnm)
  3705. {
  3706.     if (SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0)) {
  3707.         return 1;
  3708.     }
  3709.  
  3710.     if (_fTheater) {
  3711.         // if we're in theater mode, we do our own drag handling where we force
  3712.         // all  the mouse moves into the middle of the band, thereby disallowing
  3713.         // the user to make a multi line rebar
  3714.         SetCapture(_hwnd);
  3715.         SendMessage(_bs._hwnd, RB_BEGINDRAG, pnm->uBand, (LPARAM)-2);
  3716.         _fRebarDragging = TRUE;
  3717.         return 1;
  3718.     }
  3719.     return SHRestricted2(REST_NoToolbarOptions, NULL, 0);
  3720. }
  3721.  
  3722. LRESULT CInternetToolbar::_OnNotify(LPNMHDR pnmh)
  3723. {
  3724.     LRESULT lres = 0;
  3725.     if (!_pdie)
  3726.         return 0;
  3727.  
  3728.     if (pnmh->code == TTN_NEEDTEXT  && pnmh->hwndFrom == (HWND)SendMessage(_btb._hwnd, TB_GETTOOLTIPS, 0, 0)) {
  3729.         _OnTooltipNeeded((LPTOOLTIPTEXT)pnmh);
  3730.         return 0;
  3731.     }
  3732.  
  3733.     if(_SendToToolband(pnmh->hwndFrom, WM_NOTIFY,0, (LPARAM)pnmh, &lres))
  3734.         return lres;
  3735.  
  3736.     switch (pnmh->idFrom) {
  3737.     case FCIDM_REBAR:
  3738.         switch (pnmh->code) {
  3739.  
  3740.         case RBN_BEGINDRAG:
  3741.             return _OnBeginDrag((NMREBAR*)pnmh);
  3742.  
  3743.         case RBN_HEIGHTCHANGE:
  3744.             ResizeBorderDW(NULL, NULL, FALSE);
  3745.             break;
  3746.  
  3747.         case RBN_CHILDSIZE:
  3748.         {
  3749.             // make the brand always take the full height
  3750.             NMREBARCHILDSIZE *pnm = (NMREBARCHILDSIZE*)pnmh;
  3751.             if (pnm->wID == CBIDX_BRAND) {
  3752.                 pnm->rcChild.top = pnm->rcBand.top;
  3753.                 pnm->rcChild.bottom = pnm->rcBand.bottom;
  3754.             }
  3755.             break;
  3756.         }
  3757.  
  3758.         case RBN_LAYOUTCHANGED:
  3759.             //Because the layout has changed, remember to save later!
  3760.             _fDirty = TRUE;
  3761.             _UpdateBrandSize();
  3762.  
  3763.             if (_ptbsitect)
  3764.                 _ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
  3765.             break;
  3766.  
  3767.         case RBN_GETOBJECT:
  3768.         {
  3769.             NMOBJECTNOTIFY *pnmon = (NMOBJECTNOTIFY *)pnmh;
  3770.             if (IsEqualIID(*pnmon->piid, IID_IDropTarget))
  3771.             {
  3772.                 HWND hwnd;
  3773.  
  3774.                 switch (pnmon->iItem) {
  3775.                 case CBIDX_MENU:
  3776.                 case CBIDX_LINKS:
  3777.                 {
  3778.                      LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(pnmon->iItem);
  3779.                      if (pbid && pbid->pdb)
  3780.                      {
  3781.                         pnmon->hResult = pbid->pdb->QueryInterface(IID_IDropTarget, (LPVOID*)&pnmon->pObject);
  3782.                      }
  3783.                      break;
  3784.                 }
  3785.  
  3786.                 case CBIDX_TOOLS:
  3787.                     hwnd = _btb._hwnd;
  3788.                     pnmon->hResult = (HRESULT)SendMessage(hwnd, TB_GETOBJECT,
  3789.                                         (WPARAM)&IID_IDropTarget, (LPARAM)&pnmon->pObject);
  3790.                     break;
  3791.  
  3792.                 case CBIDX_ADDRESS:
  3793.                     if (_ptbsite) {
  3794.                         pnmon->hResult = _ptbsite->QueryInterface(IID_IDropTarget, (LPVOID*)&pnmon->pObject);
  3795.                     }
  3796.                     break;
  3797.                 }
  3798.             }
  3799.             ASSERT((SUCCEEDED(pnmon->hResult) && pnmon->pObject) ? (IS_VALID_CODE_PTR(pnmon->pObject, IUnknown)) : (pnmon->pObject == NULL));
  3800.             return TRUE;
  3801.         }
  3802.  
  3803.         case RBN_CHEVRONPUSHED:
  3804.         {
  3805.             LPNMREBARCHEVRON pnmch = (LPNMREBARCHEVRON) pnmh;
  3806.             if (pnmch->wID == CBIDX_TOOLS)
  3807.             {
  3808.                 int idMenu = MENU_TBMENU;
  3809.                 // this must be the tools band (not enumerated in bandsite)
  3810.                 MapWindowPoints(pnmh->hwndFrom, HWND_DESKTOP, (LPPOINT)&pnmch->rc, 2);
  3811.                 if (!_btb._fCustomize)
  3812.                     idMenu = 0;
  3813.  
  3814.                 ToolbarMenu_Popup(_hwnd, &pnmch->rc, NULL, _btb._hwnd, idMenu, (DWORD)pnmch->lParamNM);
  3815.                 return TRUE;
  3816.             }
  3817.             _bs._OnNotify(pnmh);
  3818.             break;
  3819.         }
  3820.  
  3821.         default:
  3822.             return _bs._OnNotify(pnmh);
  3823.  
  3824.         } // switch (pnmh->code)
  3825.         break;
  3826.  
  3827.     default:
  3828.         //AssertMsg(0, "Unknown notify from hwnd(%x), id(%x)", pnmh->hwndFrom, pnmh->idFrom);
  3829.         break;
  3830.  
  3831.     } // switch (pnmh->idFrom)
  3832.     return 0;
  3833. }
  3834.  
  3835.  
  3836. /*******************************************************************
  3837.  
  3838. NAME:       CInternetToolbar::_DoNavigateA
  3839.  
  3840. SYNOPSIS:   Called when the user types in or selects a URL
  3841. to navigate to through the address bar
  3842.  
  3843. NOTES:      This function calls the helper function _DoNavigate.
  3844. This is just here to convert the ANSI string to
  3845. a BSTR.
  3846.  
  3847. ********************************************************************/
  3848. HRESULT CInternetToolbar::_DoNavigateA(LPSTR pszURL, int iNewSelection)
  3849. {
  3850.     ASSERT(pszURL);    // must have valid URL to navigate to
  3851.  
  3852.     SA_BSTR sstrText;
  3853.     sstrText.cb = SHAnsiToUnicode(pszURL, sstrText.wsz, ARRAYSIZE(sstrText.wsz));
  3854.  
  3855.     return _DoNavigate(sstrText.wsz, iNewSelection);
  3856. }
  3857.  
  3858. /*******************************************************************
  3859.  
  3860. NAME:       CInternetToolbar::_DoNavigateW
  3861.  
  3862. SYNOPSIS:   Called when the user types in or selects a URL
  3863. to navigate to through the address bar
  3864.  
  3865. NOTES:      This function calls the helper function _DoNavigate.
  3866. This is just here to convert the Unicode string to
  3867. a BSTR.
  3868.  
  3869. ********************************************************************/
  3870. HRESULT CInternetToolbar::_DoNavigateW(LPWSTR pwzURL, int iNewSelection)
  3871. {
  3872.     ASSERT(pwzURL);    // must have valid URL to navigate to
  3873.  
  3874.     SA_BSTR sstrPath;
  3875.     StrCpyNW(sstrPath.wsz, pwzURL, ARRAYSIZE(sstrPath.wsz));
  3876.     sstrPath.cb = lstrlenW(sstrPath.wsz) * SIZEOF(WCHAR);
  3877.  
  3878.     return _DoNavigate(sstrPath.wsz, iNewSelection);
  3879. }
  3880.  
  3881. /*******************************************************************
  3882.  
  3883. NAME:       CInternetToolbar::_DoNavigate
  3884.  
  3885. SYNOPSIS:   Called when the user types in or selects a URL
  3886. to navigate to through the address bar
  3887.  
  3888. ENTRY:      bstrURL - string of URL to navigate to, in BSTR form
  3889. iNewSelection - index of current selection in address
  3890. bar combo box
  3891.  
  3892. ********************************************************************/
  3893. HRESULT CInternetToolbar::_DoNavigate(BSTR bstrURL,int iNewSelection)
  3894. {
  3895.     HRESULT hr;
  3896.  
  3897.     ASSERT(bstrURL); // must have valid URL to browse to
  3898.     ASSERT(_pdie);  // must have valid pointer to automation interface
  3899.  
  3900.     VARIANTARG v;
  3901.     VariantInit (&v);
  3902.  
  3903.     v.vt = VT_I4;
  3904.     v.lVal = navAllowAutosearch;
  3905.  
  3906.     // call automation interface to make browser navigate to this URL
  3907.     hr = _pdie->Navigate(bstrURL, &v, PVAREMPTY, PVAREMPTY, PVAREMPTY);
  3908.  
  3909.     VariantClearLazy(&v);
  3910.  
  3911.     return hr;
  3912. }
  3913.  
  3914. LPITEMIDLIST CInternetToolbar::_GetCurrentPidl(void)
  3915. {
  3916.     LPITEMIDLIST pidl = NULL;
  3917.  
  3918.     ASSERT(_pbs2);
  3919.     if (_pbs2)
  3920.     {
  3921.         _pbs2->GetPidl(&pidl);
  3922.     }
  3923.  
  3924.     return pidl;
  3925. }
  3926.  
  3927. void CInternetToolbar::_CommonHandleFileSysChange(LONG lEvent, LPITEMIDLIST* ppidl)
  3928. {
  3929.     // stuff that needs to be done tree or no tree
  3930.     switch (lEvent) {
  3931.  
  3932.         // README:
  3933.         // If you need to add events here, then you must change SHELLBROWSER_FSNOTIFY_FLAGS in
  3934.         // shbrowse.cpp in order to get the notifications
  3935.     case SHCNE_DRIVEREMOVED:
  3936.     case SHCNE_MEDIAREMOVED:
  3937.     case SHCNE_MEDIAINSERTED:
  3938.     case SHCNE_DRIVEADD:
  3939.     case SHCNE_UPDATEIMAGE:
  3940.         // Forward this command to CAddressBand::FileSysChange()
  3941.         // by using IToolbandHelper::OnWinEvent().
  3942.         ASSERT(_hwndAddressBand);
  3943.         {
  3944.             LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  3945.  
  3946.             ASSERT(pbid && pbid->pdb);     // pbid->pdb is a IDeskBand pointer
  3947.             if (pbid)
  3948.             {
  3949.                 // REVIEW: why don't we use IShellChangeNotify here?
  3950.                 //
  3951.                 IUnknown_FileSysChange(pbid->pdb, (DWORD)lEvent, (LPCITEMIDLIST*)ppidl);
  3952.             }
  3953.         }
  3954.         break;
  3955.     }
  3956. }
  3957.  
  3958. HRESULT CInternetToolbar::OnChange(LONG lEvent, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
  3959. {
  3960. #ifdef DEBUG
  3961.     //
  3962.     // We are only called after we have been initialized
  3963.     //
  3964.     LPITEMIDLIST pidl = _GetCurrentPidl();
  3965.     if (EVAL(pidl))
  3966.     {
  3967.         ILFree(pidl);
  3968.     }
  3969. #endif
  3970.  
  3971.     LPITEMIDLIST ppidl[2] = {(LPITEMIDLIST)pidl1, (LPITEMIDLIST)pidl2};
  3972.     _CommonHandleFileSysChange(lEvent, ppidl);
  3973.  
  3974.     return S_OK;
  3975. }
  3976.  
  3977. void CInternetToolbar::_OnCommand(WPARAM wParam, LPARAM lParam)
  3978. {
  3979.     if (!_pdie)
  3980.         return;
  3981.  
  3982.     HWND hwndControl = GET_WM_COMMAND_HWND(wParam, lParam);
  3983.     UINT idCmd = GET_WM_COMMAND_ID(wParam, lParam);
  3984.  
  3985.     // If this is a command from the toolbar, and it is not one of the StdBrowseButtons
  3986.     // call Exec() on the appropriate CmdTarget
  3987.     if (hwndControl == _btb._hwnd)
  3988.     {
  3989.         UINT uiInternalCmdID = idCmd;
  3990.  
  3991.         // Convert to the real thing and get the guid
  3992.         CMDMAP* pcm = _btb._GetCmdMapByID(idCmd);
  3993.  
  3994.         IOleCommandTarget* pct = _btb._CommandTargetFromCmdMap(pcm);
  3995.         if (pct) {
  3996.             VARIANTARG var;
  3997.             var.vt = VT_I4;
  3998.             var.lVal = uiInternalCmdID;
  3999.             if (SHIsSameObject(_btb._pctCurrentButtonGroup, pct)) {
  4000.                 // give the browser a chance to pick this off in case
  4001.                 // focus doesn't belong to the view currently
  4002.                 if (SUCCEEDED(_ptbsitect->Exec(&IID_IExplorerToolbar, pcm->nCmdID, 0, NULL, &var)))
  4003.                     return;
  4004.             }
  4005.  
  4006.             UEMFireEvent(&UEMIID_BROWSER, UEME_UITOOLBAR, UEMF_XEVENT,
  4007.                 UIG_COMMON, (LPARAM)pcm->nCmdID);
  4008.             pct->Exec(&pcm->guidButtonGroup, (DWORD)pcm->nCmdID, 0, NULL, &var);
  4009.         }
  4010.         return;
  4011.     }
  4012.  
  4013.     if (_SendToToolband(hwndControl, WM_COMMAND, wParam, lParam, NULL))
  4014.         return;
  4015.  
  4016.  
  4017.     // this switch block actually executes
  4018.     switch(idCmd)
  4019.     {
  4020.     case FCIDM_VIEWTOOLBARCUSTOMIZE:
  4021.         ASSERT(!SHRestricted2(REST_NOTOOLBARCUSTOMIZE, NULL, 0));
  4022.         SendMessage (_btb._hwnd, TB_CUSTOMIZE, 0, 0L);
  4023.         break;
  4024.  
  4025.     case FCIDM_DRIVELIST:
  4026.         _SendToToolband(_hwndAddressBand, WM_COMMAND, wParam, lParam, NULL);
  4027.         break;
  4028.  
  4029.     case FCIDM_VIEWADDRESS:
  4030.     case FCIDM_VIEWTOOLS:
  4031.     case FCIDM_VIEWMENU:
  4032.     case FCIDM_VIEWLINKS:
  4033.         if (!SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0)
  4034.             && !SHRestricted2(REST_NoToolbarOptions, NULL, 0)) {
  4035.             DWORD dw = _nVisibleBands;
  4036.             switch (idCmd)
  4037.             {
  4038.             case FCIDM_VIEWTOOLS:
  4039.                 dw ^= VBF_TOOLS;
  4040.                 break;
  4041.             case FCIDM_VIEWMENU:
  4042.                 dw ^= VBF_MENU;
  4043.                 break;
  4044.             case FCIDM_VIEWADDRESS:
  4045.                 dw ^= VBF_ADDRESS;
  4046.                 break;
  4047.             case FCIDM_VIEWLINKS:
  4048.                 dw ^= VBF_LINKS;
  4049.                 break;
  4050.             }
  4051.             if ( !( dw & ~VBF_BRAND))
  4052.             {
  4053.                 _pdie->put_ToolBar( FALSE );
  4054.             }
  4055.  
  4056.             _ShowVisible(dw, TRUE);
  4057.         }
  4058.         return;
  4059.  
  4060.     case FCIDM_VIEWAUTOHIDE:
  4061.     {
  4062.         ASSERT(_fTheater);
  4063.         _fAutoHide = !_fAutoHide;
  4064.  
  4065.         VARIANTARG v = {0};
  4066.         v.vt = VT_I4;
  4067.         v.lVal = _fAutoHide;
  4068.         IUnknown_Exec(_ptbsite, &CGID_Theater, THID_SETTOOLBARAUTOHIDE, 0, &v, NULL);
  4069.  
  4070.         ResizeBorderDW(NULL, NULL, FALSE);
  4071.  
  4072.         break;
  4073.     }
  4074.  
  4075.     case FCIDM_VIEWTEXTLABELS:
  4076.         if(!SHRestricted2(REST_NoToolbarOptions, NULL, 0))
  4077.         {
  4078.             if (!_btb._fCustomize && IS_LIST_STYLE(_btb._hwnd))
  4079.             {
  4080.                 // If customize is unavailable, then there's no way for the user to
  4081.                 // turn list style on/off.  In this case we want toggling text labels
  4082.                 // to work the way it did in IE4 -- that is, switch between "text on
  4083.                 // all buttons" and "text on no buttons".  So, if we're in "selective
  4084.                 // text on right" mode, we say that labels are turned off.  If the user
  4085.                 // picks this menu option, we'll go into "text on all buttons" mode.
  4086.  
  4087.                 _UpdateToolsStyle(FALSE);
  4088.  
  4089.                 // Make ourselves believe that text labels are turned off (so
  4090.                 // that _UpdateToolbarDisplay will turn them on)
  4091.  
  4092.                 _fCompressed = TRUE;
  4093.             }
  4094.             _UpdateToolbarDisplay(UTD_TEXTLABEL, 0, !_fCompressed, TRUE);
  4095.         }
  4096.         return;
  4097.  
  4098.     case FCIDM_VIEWGOBUTTON:
  4099.         ASSERT(_hwndAddressBand);
  4100.         _SendToToolband(_hwndAddressBand, WM_COMMAND, wParam, lParam, NULL);
  4101.         break;
  4102.  
  4103.     default:
  4104.         if (InRange( idCmd, FCIDM_EXTERNALBANDS_FIRST, FCIDM_EXTERNALBANDS_LAST ))
  4105.         {
  4106.             if (!SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0))
  4107.             {
  4108.                 DWORD dw = _nVisibleBands;
  4109.                 dw ^= EXTERNALBAND_VBF_BIT(idCmd - FCIDM_EXTERNALBANDS_FIRST);
  4110.                 if ( !( dw & ~VBF_BRAND))
  4111.                 {
  4112.                     _pdie->put_ToolBar( FALSE );
  4113.                 }
  4114.                 _ShowVisible(dw, TRUE);
  4115.             }
  4116.             return;
  4117.         }
  4118.         break;
  4119.     }
  4120. }
  4121.  
  4122. // get the doc property, then get the command target from that and do it
  4123. void CInternetToolbar::_SendDocCommand(UINT idCmd)
  4124. {
  4125.     // BUGBUG: if this fails, we should maybe do the invoke with a
  4126.     // proper verb?
  4127.     if (_ptbsitect)
  4128.     {
  4129.         VARIANTARG varIn;
  4130.         VARIANTARG varOut;
  4131.         VARIANTARG *pvarIn = &varIn;
  4132.         VARIANTARG *pvarOut = &varOut;
  4133.  
  4134.         VariantInit(&varIn);
  4135.         VariantInit(&varOut);
  4136.  
  4137.  
  4138.         switch (idCmd) {
  4139.         case OLECMDID_HIDETOOLBARS:
  4140.         case OLECMDID_PRINT:
  4141.             // word & excel barf if there are arguments passed to print
  4142.             pvarIn = NULL;
  4143.             pvarOut = NULL;
  4144.             break;
  4145.  
  4146.         case OLECMDID_ZOOM:
  4147.             // get the zoom range
  4148.             int iMax, iMin;
  4149.             if (FAILED(_ptbsitect->Exec(NULL, OLECMDID_GETZOOMRANGE, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &varOut)))
  4150.                 goto Bail;
  4151.  
  4152.             if (varOut.vt == VT_I4)
  4153.             {
  4154.                 iMin = (int)(short)LOWORD(varOut.lVal);
  4155.                 iMax = (int)(short)HIWORD(varOut.lVal);
  4156.             }
  4157.             else
  4158.                 goto Bail;
  4159.  
  4160.             varOut.vt = VT_EMPTY; // return to VariantInit state
  4161.  
  4162.             // get the current zoom depth
  4163.             if (FAILED(_ptbsitect->Exec(NULL, OLECMDID_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, NULL, &varIn)))
  4164.                 goto Bail;
  4165.  
  4166.             if (varIn.vt == VT_I4) {
  4167.                 varIn.lVal++;
  4168.                 if ((int)varIn.lVal > iMax) {
  4169.                     varIn.lVal = iMin;
  4170.                 }
  4171.             } else {
  4172.                 goto Bail;
  4173.             }
  4174.  
  4175.             break;
  4176.  
  4177.         }
  4178.  
  4179. #ifdef FEATURE_IE40
  4180.         _ptbsitect->Exec(NULL, idCmd, OLECMDEXECOPT_DONTPROMPTUSER, pvarIn, pvarOut);
  4181. #else
  4182.         _ptbsitect->Exec(NULL, idCmd, OLECMDEXECOPT_PROMPTUSER, pvarIn, pvarOut);
  4183. #endif
  4184.  
  4185. Bail:
  4186.     VariantClearLazy(&varIn);
  4187.     VariantClearLazy(&varOut);
  4188.  
  4189.     }
  4190. }
  4191.  
  4192. BOOL CInternetToolbar::_CompressBands(BOOL fCompress, UINT uRowsNew, BOOL fForceUpdate)
  4193. {
  4194.     UINT_PTR uRowsOld = SendMessage(_btb._hwnd, TB_GETTEXTROWS, 0, 0L);
  4195.     if (fCompress)
  4196.         uRowsNew = 0;
  4197.  
  4198.     if (!fForceUpdate && (uRowsOld == uRowsNew)) {
  4199.         // same as what we've already got, blow it off
  4200.         return FALSE;
  4201.     }
  4202.  
  4203.     _fCompressed = fCompress;
  4204.  
  4205.     // Change the size of the Brand window and add ot remove the text
  4206.     SendMessage(_btb._hwnd, TB_SETMAXTEXTROWS, uRowsNew, 0L);
  4207.  
  4208.     UINT uWidthNew = _fCompressed ? MAX_TB_COMPRESSED_WIDTH : _uiMaxTBWidth;
  4209.     SendMessage(_btb._hwnd, TB_SETBUTTONWIDTH, 0, (LPARAM) MAKELONG(0, uWidthNew));
  4210.  
  4211.     _btb._BandInfoChanged();
  4212.  
  4213.     _UpdateBrandSize();
  4214.     _bs._SetMinDimensions();
  4215.  
  4216.     return TRUE;
  4217. }
  4218.  
  4219. #define ABS(x)  (((x) < 0) ? -(x) : (x))
  4220.  
  4221. void CInternetToolbar::_TrackSliding(int x, int y)
  4222. {
  4223.     INT_PTR cBands    = SendMessage(_bs._hwnd, RB_GETBANDCOUNT, 0, 0L);
  4224.     INT_PTR cRows     = SendMessage(_bs._hwnd, RB_GETROWCOUNT, 0, 0L);
  4225.     INT_PTR cyHalfRow = SendMessage(_bs._hwnd, RB_GETROWHEIGHT, cBands-1, 0L) / 2;
  4226.     RECT rc;
  4227.     int cyBefore;
  4228.     int c;
  4229.     BOOL_PTR fChanged = FALSE;
  4230.  
  4231.     // do this instead of GetClientRect so that we include borders
  4232.     GetWindowRect(_bs._hwnd, &rc);
  4233.     MapWindowPoints(HWND_DESKTOP, _bs._hwnd, (LPPOINT)&rc, 2);
  4234.     cyBefore = rc.bottom - rc.top;
  4235.  
  4236.     c = y - _yCapture;
  4237.     rc.bottom = y;
  4238.  
  4239.     // was there enough change?
  4240.     if (ABS(c) <= cyHalfRow)
  4241.         return;
  4242.  
  4243.     if ((cRows == 1) || _fCompressed) {
  4244.  
  4245.         if (c < -cyHalfRow)
  4246.             fChanged = _CompressBands(TRUE, 0, FALSE);
  4247.         else
  4248.             fChanged = _CompressBands(FALSE, _uiTBTextRows, FALSE);
  4249.  
  4250.     }
  4251.  
  4252.     if (!fChanged) {
  4253.         // if the compressing bands didn't change anything, try to fit it to size
  4254.         fChanged = SendMessage(_bs._hwnd, RB_SIZETORECT, 0, (LPARAM)&rc);
  4255.     }
  4256.  
  4257.  
  4258.     // TODO: There is a drawing glitch when you resize from 3 bars (No Text) to 3 bars
  4259.     // with text. The _yCapture gets set to a value greater than y. So on the
  4260.     // next MOUSEMOVE it figures that the user moved up and switches from 3 bars with text
  4261.     // to 2 bars with text.
  4262.     if (fChanged)
  4263.     {
  4264.         _UpdateBrandSize();
  4265.         GetWindowRect(_bs._hwnd, &rc);
  4266.         _yCapture += (rc.bottom - rc.top) - cyBefore;
  4267.         _fDirty = TRUE; //Since the band layout changed, set the dirty bit ON.
  4268.         if (_ptbsitect)
  4269.             _ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
  4270.     }
  4271. }
  4272.  
  4273.  
  4274. void CInternetToolbar::_ShowVisible(DWORD dwVisibleBands, BOOL fPersist)
  4275. {
  4276.     // BUGBUG (scotth): is this even necessary now that we have a
  4277.     //  menu band always showing?
  4278.     BOOL fShowInitial = (! (_nVisibleBands & ~VBF_BRAND));
  4279.  
  4280.     _UpdateToolbarDisplay(UTD_VISIBLE, dwVisibleBands, _fCompressed, fPersist);
  4281.  
  4282.     if (fShowInitial)
  4283.         _pdie->put_ToolBar(TRUE);
  4284. }
  4285.  
  4286.  
  4287. HRESULT CInternetToolbar::_UpdateToolbarDisplay(DWORD dwFlags, UINT uVisibleBands, BOOL fNoText, BOOL fPersist)
  4288. {
  4289.     _fDirty = TRUE;  //Since we are making changes, set the dirty bit!
  4290.  
  4291.     //Update the back bitmap
  4292.     _SetBackground();
  4293.  
  4294.     //Show the bands.
  4295.     if(dwFlags & UTD_VISIBLE)
  4296.         _ShowBands(uVisibleBands);
  4297.  
  4298.     //Show/Hide the text.
  4299.     if(dwFlags & UTD_TEXTLABEL)
  4300.         _CompressBands(fNoText, _uiTBTextRows, TRUE);
  4301.  
  4302.     if (!_fTheater && fPersist && _ptbsitect)
  4303.         _ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
  4304.  
  4305.     return S_OK;
  4306. }
  4307.  
  4308. void CInternetToolbar::_UpdateBrandSize()
  4309. {
  4310.     LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_BRAND);
  4311.     if (pbid && ((_nVisibleBands & (VBF_TOOLS | VBF_BRAND)) == (VBF_TOOLS | VBF_BRAND))) {
  4312.         BOOL fMinAlways = _fCompressed;
  4313.  
  4314.         if (!fMinAlways) {
  4315.  
  4316.             INT_PTR iTools = BandIDtoIndex(_bs._hwnd, CBIDX_TOOLS);
  4317.             INT_PTR iBrand = BandIDtoIndex(_bs._hwnd, CBIDX_BRAND);
  4318.  
  4319.             if (iBrand < iTools && !_fTheater)
  4320.                 fMinAlways = TRUE;
  4321.         }
  4322.  
  4323.         VARIANTARG v = {0};
  4324.         v.vt = VT_I4;
  4325.         v.lVal = fMinAlways;
  4326.         IUnknown_Exec(pbid->pdb, &CGID_PrivCITCommands, CITIDM_BRANDSIZE, 0, &v, NULL);
  4327.     }
  4328. }
  4329.  
  4330. LRESULT CALLBACK CInternetToolbar::SizableWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  4331. {
  4332.     CInternetToolbar* pitbar = (CInternetToolbar*)GetWindowPtr0(hwnd); // GetWindowLong(hwnd, 0)
  4333.  
  4334.     switch(uMsg)
  4335.     {
  4336.     case WM_SETCURSOR:
  4337.         if ((HWND)wParam == hwnd && LOWORD(lParam) == HTCLIENT && !SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0)) {
  4338.             SetCursor(LoadCursor(NULL, IDC_SIZENS));
  4339.             return TRUE;
  4340.         }
  4341.         goto DoDefault;
  4342.  
  4343.     case WM_SYSCOLORCHANGE:
  4344.     case WM_WININICHANGE:
  4345.         if (FALSE == pitbar->_fDestroyed)
  4346.         {
  4347.             DWORD dwSection = SHIsExplorerIniChange(wParam, lParam);
  4348.  
  4349.             BOOL fRebuild = (uMsg == WM_SYSCOLORCHANGE) ||
  4350.                             (dwSection == EICH_KWINEXPLSMICO) ||
  4351.                             (wParam == SPI_SETNONCLIENTMETRICS);
  4352.  
  4353.             if (fRebuild)
  4354.             {
  4355.                 pitbar->_InitForScreenSize();
  4356.                 ITBar_LoadToolbarGlyphs(pitbar->_btb._hwnd);
  4357.                 pitbar->_InitBitmapDSA();
  4358.                 pitbar->_SetSearchStuff();
  4359.                 pitbar->_ReloadButtons();
  4360. #ifdef EDIT_HACK
  4361.                 if (uMsg == WM_SYSCOLORCHANGE)
  4362.                 {
  4363.                     pitbar->_RefreshEditGlyph();
  4364.                 }
  4365. #endif
  4366.             }
  4367.            
  4368. #ifdef EDIT_HACK
  4369.             if (dwSection == EICH_KINET)
  4370.             {
  4371.                 pitbar->_aEditVerb.InitDefaultEditor();
  4372.                 pitbar->_UpdateEditButton();
  4373.             }
  4374. #endif
  4375.  
  4376.             SendMessage(pitbar->_bs._hwnd, uMsg, wParam, lParam);
  4377.             pitbar->_SendToToolband(HWND_BROADCAST, uMsg, wParam, lParam, NULL);
  4378.  
  4379.             if (fRebuild)
  4380.             {
  4381.                 pitbar->_SetBackground();
  4382.                 InvalidateRect(pitbar->_bs._hwnd, NULL, TRUE);
  4383.                 pitbar->_bs._SetMinDimensions();
  4384.             }
  4385.         }
  4386.         break;
  4387.  
  4388.     case WM_LBUTTONDOWN:
  4389.         //            RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
  4390.         // Don't allow toolbar resizing in theater mode
  4391.         if (!pitbar->_fTheater && !SHRestricted2(REST_NOBANDCUSTOMIZE, NULL, 0)) {
  4392.             pitbar->_xCapture = GET_X_LPARAM(lParam);
  4393.             pitbar->_yCapture = GET_Y_LPARAM(lParam);
  4394.             SetCapture(hwnd);
  4395.         }
  4396.         break;
  4397.  
  4398.     case WM_MOUSEMOVE:
  4399.         //            RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
  4400.  
  4401.         if (pitbar->_yCapture != -1)
  4402.         {
  4403.             if (hwnd != GetCapture())
  4404.                 pitbar->_yCapture = -1;
  4405.             else
  4406.                 pitbar->_TrackSliding(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
  4407.         } else if (pitbar->_fRebarDragging) {
  4408.             RECT rc;
  4409.             POINT pt;
  4410.             GetClientRect(pitbar->_bs._hwnd, &rc);
  4411.             GetCursorPos(&pt);
  4412.             MapWindowPoints(HWND_DESKTOP, pitbar->_bs._hwnd, &pt, 1);
  4413.             rc.bottom /= 2;
  4414.             if (pt.y > rc.bottom)
  4415.                 pt.y = rc.bottom;
  4416.             SendMessage(pitbar->_bs._hwnd, RB_DRAGMOVE, 0, MAKELPARAM(pt.x, pt.y));
  4417.         }
  4418.         break;
  4419.  
  4420.     case WM_LBUTTONUP:
  4421.     case WM_RBUTTONUP:
  4422.         //            RelayToToolTips(prb->hwndToolTips, hwnd, wMsg, wParam, lParam);
  4423.  
  4424.         pitbar->_yCapture = -1;
  4425.         if (pitbar->_fRebarDragging) {
  4426.             pitbar->_fRebarDragging = FALSE;
  4427.             SendMessage(pitbar->_bs._hwnd, RB_ENDDRAG, 0, 0);
  4428.         }
  4429.         if (GetCapture() == hwnd)
  4430.             ReleaseCapture();
  4431.         break;
  4432.  
  4433.     case WM_CONTEXTMENU:
  4434.         pitbar->_bs.OnWinEvent(pitbar->_hwnd, uMsg, wParam, lParam, NULL);
  4435.         break;
  4436.  
  4437.     case WM_VKEYTOITEM:
  4438.     case WM_CHARTOITEM:
  4439.         // We must swallow these messages to avoid infinit SendMessage
  4440.         break;
  4441.  
  4442.     case WM_NOTIFY:
  4443.         // We must swallow these messages to avoid infinit SendMessage
  4444.         return pitbar->_OnNotify((LPNMHDR)lParam);
  4445.  
  4446.     case WM_NOTIFYFORMAT:
  4447.         if (NF_QUERY == lParam)
  4448.             return (DLL_IS_UNICODE ? NFR_UNICODE : NFR_ANSI);
  4449.         break;
  4450.  
  4451.     case WM_COMMAND:
  4452.         pitbar->_OnCommand(wParam, lParam);
  4453.         break;
  4454.  
  4455.     case WM_ERASEBKGND:
  4456.         {
  4457.             HDC hdc = (HDC)wParam;
  4458.             RECT rc;
  4459.             GetClientRect(hwnd, &rc);
  4460.             SHFillRectClr(hdc, &rc, (pitbar->_fTheater) ? RGB(0,0,0) : GetSysColor(COLOR_3DFACE));
  4461.             break;
  4462.          }
  4463.  
  4464.     case WM_PALETTECHANGED:
  4465.         //
  4466.         // BUGBUG: we could optimize this by realizing and checking the
  4467.         // return value
  4468.         //
  4469.         // for now we will just invalidate ourselves and all children...
  4470.         //
  4471.         RedrawWindow(hwnd, NULL, NULL,
  4472.                      RDW_INVALIDATE  | RDW_ERASE | RDW_ALLCHILDREN);
  4473.         break;
  4474.  
  4475.     case WM_TIMER:
  4476.         switch (wParam) {
  4477.         case IDT_UPDATETOOLBAR:
  4478.             pitbar->_fUpdateToolbarTimer = FALSE;
  4479.             KillTimer(hwnd, wParam);
  4480.             if (pitbar->_fNeedUpdateToolbar)
  4481.                 pitbar->_UpdateToolbarNow();
  4482.             break;
  4483.         }
  4484.         break;
  4485.  
  4486.     case WM_DESTROY:
  4487.         pitbar->_Unadvise(); // remove ref-loop with _pdie
  4488.         TraceMsg(DM_TBREF, "Called RemoveProp. Called Release new _cRef=%d", pitbar->_cRef);
  4489.         goto DoDefault;
  4490.  
  4491. DoDefault:
  4492.     default:
  4493.         return(DefWindowProcWrap(hwnd, uMsg, wParam, lParam));
  4494.     }
  4495.  
  4496.     return 0L;
  4497. }
  4498.  
  4499.  
  4500. HRESULT CInternetToolbar::ResizeBorderDW(LPCRECT prcBorder,
  4501.                                          IUnknown* punkToolbarSite,
  4502.                                          BOOL fReserved)
  4503. {
  4504.     TraceMsg(DM_LAYOUT, "CITB::ResizeBorder called (_fShow==%d)", _fShow);
  4505.     HRESULT hres = S_OK;
  4506.  
  4507.     ASSERT(_ptbsite);
  4508.     if (_ptbsite)
  4509.     {
  4510.         RECT rcRequest = { 0, 0, 0, 0 };
  4511.  
  4512.         if (_fShow)
  4513.         {
  4514.             RECT rcRebar, rcBorder;
  4515.             int  cx,cy;
  4516.  
  4517.             GetWindowRect(_bs._hwnd, &rcRebar);
  4518.             cx = rcRebar.right - rcRebar.left;
  4519.             cy = rcRebar.bottom - rcRebar.top;
  4520.  
  4521.             int iExtra = 3;
  4522.             if (_fTheater) {
  4523.                 // 1 for the 1 pixel border on the bottom
  4524.                 iExtra = 1;
  4525.             }
  4526.  
  4527.             TraceMsg(DM_LAYOUT, "CITB::ResizeBorder cy = %d", cy);
  4528.  
  4529.             if (!prcBorder) {
  4530.                 _ptbsite->GetBorderDW(SAFECAST(this, IDockingWindow*), &rcBorder);
  4531.                 prcBorder = &rcBorder;
  4532.             }
  4533.  
  4534.             cx = prcBorder->right - prcBorder->left;
  4535.  
  4536.  
  4537.             SetWindowPos(_bs._hwnd, NULL, 0, 0,
  4538.                          cx, cy,  SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
  4539.  
  4540.             GetWindowRect(_bs._hwnd, &rcRebar);
  4541.  
  4542.  
  4543.             rcRequest.top = rcRebar.bottom - rcRebar.top + iExtra;
  4544.             SetWindowPos(_hwnd, NULL, prcBorder->left, prcBorder->top,
  4545.                          rcRebar.right - rcRebar.left, rcRequest.top, SWP_NOZORDER | SWP_NOACTIVATE);
  4546.  
  4547.         }
  4548.  
  4549.         if (_fTheater && _fAutoHide) {
  4550.             // if we're in theater mode, then we should request no space
  4551.             rcRequest.left = rcRequest.top = 0;
  4552.         }
  4553.  
  4554.         TraceMsg(DM_LAYOUT, "CITB::ResizeBorder calling RequstBS with %d,%d,%d,%d",
  4555.                  rcRequest.left, rcRequest.top, rcRequest.right, rcRequest.bottom);
  4556.         _ptbsite->RequestBorderSpaceDW(SAFECAST(this, IDockingWindow*), &rcRequest);
  4557.  
  4558.         TraceMsg(DM_LAYOUT, "CITB::ResizeBorder calling SetBS with %d,%d,%d,%d",
  4559.                  rcRequest.left, rcRequest.top, rcRequest.right, rcRequest.bottom);
  4560.         _ptbsite->SetBorderSpaceDW(SAFECAST(this, IDockingWindow*), &rcRequest);
  4561.     }
  4562.  
  4563.     return hres;
  4564. }
  4565.  
  4566. HRESULT CInternetToolbar::QueryStatus(const GUID *pguidCmdGroup,
  4567.                                       ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pcmdtext)
  4568. {
  4569.     HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;
  4570.  
  4571.     ASSERT(_hwndAddressBand);
  4572.     LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  4573.     if (pbid && pbid->pdb)
  4574.     {
  4575.         IOleCommandTarget *poct;
  4576.         if (SUCCEEDED(pbid->pdb->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&poct)))
  4577.         {
  4578.             hr = poct->QueryStatus(pguidCmdGroup, cCmds, rgCmds, pcmdtext);
  4579.             poct->Release();
  4580.         }
  4581.     }
  4582.  
  4583.     if (pguidCmdGroup && IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
  4584.     {
  4585.         hr = S_OK;
  4586.         for (ULONG i = 0 ; i < cCmds; i++)
  4587.         {
  4588.             rgCmds[i].cmdf = 0;
  4589.             switch (rgCmds[i].cmdID)
  4590.             {
  4591.             case CITIDM_VIEWTOOLS:
  4592.                 if (_nVisibleBands & VBF_TOOLS)
  4593.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4594.                 break;
  4595.  
  4596.             case CITIDM_VIEWMENU:
  4597.                 if (_nVisibleBands & VBF_MENU)
  4598.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4599.                 break;
  4600.  
  4601.             case CITIDM_VIEWTOOLBARCUSTOMIZE:
  4602.                 if (_btb._fCustomize)
  4603.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4604.                 break;
  4605.  
  4606.             case CITIDM_VIEWAUTOHIDE:
  4607.                 if (_fAutoHide)
  4608.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4609.                 break;
  4610.  
  4611.             case CITIDM_VIEWADDRESS:
  4612.                 if (_nVisibleBands & VBF_ADDRESS)
  4613.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4614.                 break;
  4615.  
  4616.             case CITIDM_VIEWLINKS:
  4617.                 if (_nVisibleBands & VBF_LINKS)
  4618.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4619.                 break;
  4620.  
  4621.             case CITIDM_TEXTLABELS:
  4622.                 if (!_fCompressed)
  4623.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4624.                 break;
  4625.  
  4626.             case CITIDM_EDITPAGE:
  4627.                 if (_fEditEnabled)
  4628.                     rgCmds[i].cmdf = OLECMDF_ENABLED;
  4629. #ifdef EDIT_HACK
  4630.                 // The tooltip text is also used for the menu
  4631.                 if (pcmdtext)
  4632.                 {
  4633.                     TCHAR szBuf[MAX_PATH];
  4634.                     if ((pcmdtext->cmdtextf == OLECMDTEXTF_NAME) &&
  4635.                          _aEditVerb.GetMenuText(szBuf, ARRAYSIZE(szBuf)))
  4636.                     {
  4637.                         SHTCharToUnicode(szBuf, pcmdtext->rgwz, pcmdtext->cwBuf);
  4638.                         pcmdtext->cwActual = lstrlenW(pcmdtext->rgwz) + 1;
  4639.                     }
  4640.                     else
  4641.                     {
  4642.                         pcmdtext->cwActual = 0;
  4643.                     }
  4644.                 }
  4645. #endif
  4646.                 break;
  4647.             default:
  4648.                 if (InRange( rgCmds[i].cmdID, CITIDM_VIEWEXTERNALBAND_FIRST, CITIDM_VIEWEXTERNALBAND_LAST)) {
  4649.                     int iBand = rgCmds[i].cmdID - CITIDM_VIEWEXTERNALBAND_FIRST;
  4650.                     if (!IsEqualCLSID( _rgebi[iBand].clsid, GUID_NULL )) {
  4651.                         rgCmds[i].cmdf |= OLECMDF_SUPPORTED;
  4652.                         if (_nVisibleBands & EXTERNALBAND_VBF_BIT( iBand )) {
  4653.                             rgCmds[i].cmdf |= OLECMDF_ENABLED;
  4654.                         }
  4655.                         if (pcmdtext)
  4656.                         {
  4657.                             pcmdtext->rgwz[0] = TEXT('\0');
  4658.                             switch (pcmdtext->cmdtextf)
  4659.                             {
  4660.                             case OLECMDTEXTF_NAME:
  4661.                                 if (_rgebi[iBand].pwszName)
  4662.                                     Str_GetPtrW(_rgebi[iBand].pwszName, pcmdtext->rgwz, pcmdtext->cwBuf );
  4663.                                 break;
  4664.  
  4665.                             case OLECMDTEXTF_STATUS:
  4666.                                 if (_rgebi[iBand].pwszHelp)
  4667.                                     Str_GetPtrW(_rgebi[iBand].pwszHelp, pcmdtext->rgwz, pcmdtext->cwBuf );
  4668.                                 break;
  4669.  
  4670.                             default:
  4671.                                 break;
  4672.                             }
  4673.                             pcmdtext->cwActual = lstrlen( pcmdtext->rgwz );
  4674.                         }
  4675.                     }
  4676.                 }
  4677.                 break;
  4678.             }
  4679.         }
  4680.     }
  4681.     return hr;
  4682. }
  4683.  
  4684. void CInternetToolbar::_RestoreSaveStruct(COOLBARSAVE* pcs)
  4685. {
  4686.     REBARBANDINFO rbbi;
  4687.     rbbi.cbSize = sizeof(REBARBANDINFO);
  4688.     int i;
  4689.  
  4690.     _fAutoHide = pcs->fAutoHide;
  4691.     _ShowVisible(pcs->uiVisible, FALSE);
  4692.  
  4693.     BOOL fAllowRetry = TRUE;
  4694.     BOOL fNeedRetry = FALSE;
  4695.     INT_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
  4696. Retry:
  4697.     for (i = 0; i < CBANDSMAX; i++) {
  4698.  
  4699.         INT_PTR iIndex = SendMessage(_bs._hwnd, RB_IDTOINDEX, pcs->bs[i].wID, 0);
  4700.         if (iIndex != -1) {
  4701.             SendMessage(_bs._hwnd, RB_MOVEBAND, iIndex, i);
  4702.             rbbi.fMask = RBBIM_STYLE;
  4703.             if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi)) {
  4704.                 rbbi.fMask = RBBIM_SIZE | RBBIM_STYLE;
  4705.                 rbbi.cx = pcs->bs[i].cx;
  4706.                 rbbi.fStyle = pcs->bs[i].fStyle;
  4707.                 SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
  4708.             }
  4709.  
  4710.             // the SetBandInfo could have potentially caused items to shift around
  4711.             // verify that this didn't happen.
  4712.             iIndex = SendMessage(_bs._hwnd, RB_IDTOINDEX, pcs->bs[i].wID, 0);
  4713.             if (iIndex != i) {
  4714.                 fNeedRetry = TRUE;
  4715.             }
  4716.         }
  4717.     }
  4718.  
  4719.     if (fAllowRetry && fNeedRetry) {
  4720.         fAllowRetry = FALSE;
  4721.         goto Retry;
  4722.     }
  4723.  
  4724.     _CSHSetStatusBar(pcs->fStatusBar);
  4725.     _UpdateToolsStyle(pcs->fList);
  4726.  
  4727.     RECT rc;
  4728.     GetWindowRect(_bs._hwnd, &rc);
  4729.     SetWindowPos(_bs._hwnd, NULL, 0,0, RECTWIDTH(rc), pcs->cyRebar, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  4730.  
  4731.     SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
  4732. }
  4733.  
  4734. void CInternetToolbar::_CSHSetStatusBar(BOOL fOn)
  4735. {
  4736.     VARIANTARG v = { 0 };
  4737.     v.vt = VT_I4;
  4738.     v.lVal = fOn;
  4739.     IUnknown_Exec(_ptbsite, &CGID_ShellBrowser, FCIDM_SETSTATUSBAR,
  4740.         0, &v, NULL);
  4741. }
  4742.  
  4743. void CInternetToolbar::_TheaterModeLayout(BOOL fEnter)
  4744. {
  4745.     static const struct {
  4746.         int id;
  4747.         int cx;
  4748.     } c_layout[] =
  4749.     {
  4750.         { CBIDX_TOOLS, 400 },
  4751.         { CBIDX_MENU, 200 },
  4752.         { CBIDX_ADDRESS, 300 },
  4753.         { CBIDX_LINKS, 40 }
  4754.     };
  4755.  
  4756.     REBARBANDINFO rbbi;
  4757.     rbbi.cbSize = sizeof(REBARBANDINFO);
  4758.  
  4759.     BOOL_PTR fRedraw = SendMessage(_bs._hwnd, WM_SETREDRAW, FALSE, 0);
  4760.     SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_AUTOSIZE, 0);
  4761.     if (fEnter) {
  4762.         _BuildSaveStruct(&_cs);
  4763.  
  4764.         // turn off text labels
  4765.         COOLBARSAVE cs;
  4766.         DWORD dwType, cbSize = sizeof(COOLBARSAVE);
  4767.         if (SHRegGetUSValue(c_szRegKeyCoolbar, c_szValueTheater, &dwType, (LPVOID)&cs, &cbSize, FALSE, NULL, 0) == ERROR_SUCCESS &&
  4768.            cs.cbVer == CBS_VERSION) {
  4769.             _RestoreSaveStruct(&cs);
  4770.             _UpdateToolbarDisplay(UTD_TEXTLABEL, 0, TRUE, TRUE);
  4771.         } else {
  4772.             _UpdateToolbarDisplay(UTD_TEXTLABEL, 0, TRUE, TRUE);
  4773.             _ShowVisible(VBF_TOOLS | VBF_BRAND, FALSE); // only show tools band by default
  4774.             RECT rc = { 0, 0, GetSystemMetrics(SM_CXSCREEN), 20 }; // something arbitrarily small vertically
  4775.             SendMessage(_bs._hwnd, RB_SIZETORECT, 0, (LPARAM)&rc);
  4776.  
  4777.             int cBands = (int) SendMessage(_bs._hwnd, RB_GETBANDCOUNT, 0, 0L);
  4778.             int i;
  4779.             // strip off all blanks
  4780.             rbbi.fMask = RBBIM_STYLE;
  4781.             for (i = 0; i < cBands; i++) {
  4782.                 if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  4783.                 {
  4784.                     rbbi.fStyle &= ~RBBS_BREAK;
  4785.                     SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
  4786.                 }
  4787.             }
  4788.  
  4789.             // then move into the proper order and size
  4790.             for (i = 0; i < ARRAYSIZE(c_layout); i++) {
  4791.                 INT_PTR iIndex = SendMessage(_bs._hwnd, RB_IDTOINDEX, c_layout[i].id, 0);
  4792.                 if (iIndex != -1) {
  4793.                     SendMessage(_bs._hwnd, RB_MOVEBAND, iIndex, i);
  4794.  
  4795.                     rbbi.fMask = RBBIM_SIZE;
  4796.                     rbbi.cx = c_layout[i].cx;
  4797.                     SendMessage(_bs._hwnd, RB_SETBANDINFO, i, (LPARAM) &rbbi);
  4798.                 }
  4799.             }
  4800.             _CSHSetStatusBar(FALSE);  // default value in theater mode
  4801.         }
  4802.         SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_BANDBORDERS | WS_BORDER, RBS_BANDBORDERS);
  4803.     } else {
  4804.         COOLBARSAVE cs;
  4805.         _BuildSaveStruct(&cs);
  4806.         SHRegSetUSValue(c_szRegKeyCoolbar, c_szValueTheater, REG_BINARY,
  4807.                         (LPVOID)&cs, sizeof(COOLBARSAVE), SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  4808.         _RestoreSaveStruct(&_cs);
  4809.         _UpdateToolbarDisplay(UTD_TEXTLABEL, 0, _cs.fNoText, FALSE);
  4810.         SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_BANDBORDERS | WS_BORDER, RBS_BANDBORDERS | WS_BORDER);
  4811.     }
  4812.  
  4813.     _SetBackground();
  4814.     SHSetWindowBits(_bs._hwnd, GWL_STYLE, RBS_AUTOSIZE, RBS_AUTOSIZE);
  4815.     SendMessage(_bs._hwnd, WM_SETREDRAW, fRedraw, 0);
  4816.  
  4817.     SetWindowPos(_bs._hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
  4818. }
  4819.  
  4820. HRESULT CInternetToolbar::_GetMinRowHeight()
  4821. {
  4822.     UINT iHeight = 0;
  4823.     int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
  4824.     for (int i = 0; i < icBands; i++) {
  4825.         REBARBANDINFO rbbi;
  4826.         rbbi.cbSize = sizeof(REBARBANDINFO);
  4827.         rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE;
  4828.         if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM)&rbbi)) {
  4829.             // go until the end of the row
  4830.             if (rbbi.fStyle & RBBS_BREAK)
  4831.                 break;
  4832.  
  4833.             if (!(rbbi.fStyle & RBBS_HIDDEN)) {
  4834.                 if (rbbi.cyMinChild > iHeight)
  4835.                     iHeight = rbbi.cyMinChild;
  4836.             }
  4837.         }
  4838.     }
  4839.  
  4840.     return ResultFromShort(iHeight);
  4841. }
  4842.  
  4843. BOOL IsBarRefreshable(IDeskBar* pdb)
  4844. {
  4845.     ASSERT(pdb);
  4846.     BOOL fIsRefreshable = TRUE;
  4847.     VARIANT varClsid = {0};
  4848.  
  4849.     if (SUCCEEDED(IUnknown_Exec(pdb, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, 1, NULL, &varClsid)) && (varClsid.vt == VT_BSTR))
  4850.     {
  4851.         CLSID clsidBar;
  4852.  
  4853.         //if the bar is hidden, it returns GUID_NULL, so don't refresh it
  4854.         if ( GUIDFromString(varClsid.bstrVal, &clsidBar) &&
  4855.              (IsEqualGUID(clsidBar, GUID_NULL)) )
  4856.         {
  4857.             fIsRefreshable = FALSE;
  4858.         }
  4859.         else
  4860.         {
  4861.             //APPHACK for office discussions band (and possibly others)
  4862.             //CLSID\GUID\Instance
  4863.             WCHAR wszKey[6+40+1+9];
  4864.             DWORD dwValue, dwType=REG_DWORD, dwcbData = 4;
  4865.             wnsprintf(wszKey, ARRAYSIZE(wszKey), L"CLSID\\%s\\Instance", varClsid.bstrVal);
  4866.  
  4867.             if ( (SHGetValue(HKEY_CLASSES_ROOT, wszKey, L"DontRefresh", &dwType, &dwValue, &dwcbData) == ERROR_SUCCESS) &&
  4868.                  (dwValue != 0) )
  4869.             {
  4870.                 fIsRefreshable = FALSE;
  4871.             }
  4872.         }
  4873.         VariantClear(&varClsid);
  4874.     }
  4875.     return fIsRefreshable;
  4876. }
  4877.  
  4878. HRESULT CInternetToolbar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
  4879.     DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  4880. {
  4881.     HRESULT hr = OLECMDERR_E_UNKNOWNGROUP;  // assume failure
  4882.  
  4883.     if (!pguidCmdGroup) {
  4884.         goto Lother;
  4885.     } else if (IsEqualGUID(CLSID_CommonButtons, *pguidCmdGroup)) {
  4886.         if (pvarargOut) {
  4887.             ASSERT(pvarargOut && pvarargOut->vt == VT_I4);
  4888.             UINT uiInternalCmdID = pvarargOut->lVal;
  4889.  
  4890.             if (nCmdID == TBIDM_SEARCH && uiInternalCmdID == -1)
  4891.                 _btb._ConvertCmd(pguidCmdGroup, nCmdID, NULL, &uiInternalCmdID);
  4892.  
  4893.             switch (nCmdID) {
  4894.             case TBIDM_BACK:
  4895.             case TBIDM_FORWARD:
  4896.             case TBIDM_STOPDOWNLOAD:
  4897.             case TBIDM_REFRESH:
  4898.             case TBIDM_HOME:
  4899.             case TBIDM_SEARCH:
  4900.             case TBIDM_FAVORITES:
  4901.             case TBIDM_HISTORY:
  4902.             case TBIDM_ALLFOLDERS:
  4903. #ifdef ENABLE_CHANNELPANE
  4904.             case TBIDM_CHANNELS:
  4905. #endif
  4906.                 if (!SendMessage(_btb._hwnd, TB_ISBUTTONENABLED, uiInternalCmdID, 0))
  4907.                     return S_OK;
  4908.                 break;
  4909.             }
  4910.             if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER) {
  4911.                 // the user hit the drop down
  4912.                 if (_ptbsitect && pvarargIn && pvarargIn->vt == VT_INT_PTR) {
  4913.                     // v.vt = VT_I4;
  4914.                     POINT pt;
  4915.                     RECT* prc = (RECT*)pvarargIn->byref;
  4916.                     pt.x = prc->left;
  4917.                     pt.y = prc->bottom;
  4918.  
  4919.                     switch (nCmdID) {
  4920.                     case TBIDM_BACK:
  4921.                         _ShowBackForwardMenu(FALSE, pt, prc);
  4922.                         break;
  4923.  
  4924.                     case TBIDM_FORWARD:
  4925.                         _ShowBackForwardMenu(TRUE, pt, prc);
  4926.                         break;
  4927.                     }
  4928.                     // VariantClearLazy(&v);
  4929.                 }
  4930.                 return S_OK;
  4931.             }
  4932.  
  4933.             switch(nCmdID) {
  4934.  
  4935.             case TBIDM_PREVIOUSFOLDER:
  4936.                 _ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PREVIOUSFOLDER, 0, NULL, NULL);
  4937.                 break;
  4938.  
  4939.             case TBIDM_CONNECT:
  4940.                 DoNetConnect(_hwnd);
  4941.                 break;
  4942.  
  4943.             case TBIDM_DISCONNECT:
  4944.                 DoNetDisconnect(_hwnd);
  4945.                 break;
  4946.  
  4947.             case TBIDM_BACK:
  4948.                 _pdie->GoBack();
  4949.                 break;
  4950.  
  4951.             case TBIDM_FORWARD:
  4952.                 _pdie->GoForward();
  4953.                 break;
  4954.  
  4955.             case TBIDM_HOME:
  4956.                 _pdie->GoHome();
  4957.                 break;
  4958.  
  4959.             case TBIDM_SEARCH:
  4960.                 if (_ptbsitect)
  4961.                 {
  4962.                     VARIANTARG vaOut = {0};
  4963.                     VARIANTARG* pvaOut = NULL;
  4964.                     LPITEMIDLIST pidl = NULL;
  4965.  
  4966.                     // i'm leaving this not #ifdefed out because it is used by explorer bar
  4967.                     // persistance (reljai)
  4968.                     //_SetSearchStuff initializes _guidDefaultSearch, which may or may not have
  4969.                     // been called yet
  4970.                     if (IsEqualGUID(_guidDefaultSearch, GUID_NULL))
  4971.                         _SetSearchStuff();
  4972.  
  4973.                     // see if what the state of search pane is, so we can toggle it...
  4974.                     OLECMD rgcmds[] = {{ SBCMDID_SEARCHBAR, 0 },};
  4975.                    
  4976.                     if (_ptbsitect)
  4977.                         _ptbsitect->QueryStatus(&CGID_Explorer, ARRAYSIZE(rgcmds), rgcmds, NULL);
  4978.                     // not pressed, then show the pane
  4979.                     if (!(rgcmds[0].cmdf & OLECMDF_LATCHED))
  4980.                     {
  4981.                         WCHAR       wszUrl[MAX_URL_STRING];
  4982.  
  4983.                         if (_GetSearchUrl(wszUrl, ARRAYSIZE(wszUrl)))
  4984.                         {
  4985.                             CLSID clsid;
  4986.  
  4987.                             if (GUIDFromString(wszUrl, &clsid))
  4988.                             {
  4989.                                 IContextMenu* pcm;
  4990.  
  4991.                                 if (SUCCEEDED(SHCoCreateInstance(NULL, &clsid, NULL, IID_IContextMenu, (void **)&pcm)))
  4992.                                 {
  4993.                                     CMINVOKECOMMANDINFO ici = {0};
  4994.                                     CHAR                szGuid[GUIDSTR_MAX];
  4995.                                     BOOL                bSetSite = TRUE;
  4996.  
  4997.                                     ici.cbSize = SIZEOF(ici);
  4998.                                     ici.hwnd = _hwnd;
  4999.                                     ici.lpVerb = (LPSTR)MAKEINTRESOURCE(0);
  5000.                                     ici.nShow  = SW_NORMAL;
  5001.                                     SHStringFromGUIDA(_guidDefaultSearch, szGuid, ARRAYSIZE(szGuid));
  5002.                                     ici.lpParameters = szGuid;
  5003.  
  5004.                                     // in case of rooted browser we need to open the search in the new window
  5005.                                     // 'coz otherwise the pane opens in the same window and user starts search
  5006.                                     // and browseobject (or someone) detects the rooted case and launches new
  5007.                                     // browser for our search results view (which is blank because it cannot do
  5008.                                     // search by itself and also there is not search pane) (reljai)
  5009.                                     if (_pbs2)
  5010.                                     {
  5011.                                         LPITEMIDLIST pidl;
  5012.  
  5013.                                         if (SUCCEEDED(_pbs2->GetPidl(&pidl)))
  5014.                                         {
  5015.                                             bSetSite = !ILIsRooted(pidl);
  5016.                                             ILFree(pidl);
  5017.                                         }
  5018.                                     }
  5019.                                     // if there is no site, InvokeCommand bellow will launch new browser w/ the
  5020.                                     // search pane open
  5021.                                     if (bSetSite)
  5022.                                         IUnknown_SetSite(pcm, _psp);
  5023.                                     hr = pcm->InvokeCommand(&ici);
  5024.                                     if (bSetSite)
  5025.                                         IUnknown_SetSite(pcm, NULL);
  5026.                                     pcm->Release();
  5027.                                 }
  5028.                                 break;
  5029.                             }
  5030.                             //_guidCurrentSearch = _guidDefaultSearch;//done on set state
  5031.                             IECreateFromPathW(wszUrl, &pidl);
  5032.                             // this is a hack but VariantToConstIDList supports it, and it's the easiest
  5033.                             // way to pass the pidl, so...
  5034.                             InitVariantFromIDList(&vaOut, pidl);
  5035.                             pvaOut = &vaOut;
  5036.                         }
  5037.                     }
  5038.  
  5039.                     hr = _ptbsitect->Exec(&CGID_Explorer, SBCMDID_SEARCHBAR, OLECMDEXECOPT_DONTPROMPTUSER, NULL, pvaOut); // vaIn:NULL means toggle
  5040.                     ASSERT(SUCCEEDED(hr));
  5041.                     if (pvaOut)
  5042.                         VariantClear(pvaOut);
  5043.                     ILFree(pidl);
  5044.                 }
  5045.                 else
  5046.                 {
  5047.                     TraceMsg(DM_ERROR, "CIEA::GS: no IOleCommandTarget!");
  5048.                 }
  5049.                 break;
  5050.  
  5051.             case TBIDM_FAVORITES:
  5052.             case TBIDM_HISTORY:
  5053.             case TBIDM_ALLFOLDERS:
  5054. #ifdef ENABLE_CHANNELPANE
  5055.             case TBIDM_CHANNELS:
  5056. #endif
  5057.                 if (_ptbsitect) {
  5058.                     static const int tbtab[] = {
  5059.                         TBIDM_FAVORITES    , TBIDM_HISTORY    ,   TBIDM_ALLFOLDERS  ,
  5060. #ifdef ENABLE_CHANNELPANE
  5061.                         TBIDM_CHANNELS  ,
  5062. #endif
  5063.                     };
  5064.                     static const int cttab[] = {
  5065.                         SBCMDID_FAVORITESBAR, SBCMDID_HISTORYBAR, SBCMDID_EXPLORERBAR,
  5066. #ifdef ENABLE_CHANNELPANE
  5067.                         SBCMDID_CHANNELSBAR ,
  5068. #endif
  5069.                     };
  5070.                     HRESULT hres;
  5071.                     int idCT;
  5072.  
  5073.                     idCT = SHSearchMapInt(tbtab, cttab, ARRAYSIZE(tbtab), nCmdID);
  5074.                     hres = _ptbsitect->Exec(&CGID_Explorer, idCT, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);  // vaIn:NULL means toggle
  5075.                     ASSERT(SUCCEEDED(hres));
  5076.                 }
  5077.                 else
  5078.                 {
  5079.                     TraceMsg(DM_ERROR, "CIEA::GS: no IOleCommandTarget!");
  5080.                 }
  5081.                 break;
  5082.  
  5083.             case TBIDM_THEATER:
  5084.                 {
  5085.                     VARIANT_BOOL b;
  5086.                     if (SUCCEEDED(_pdie->get_TheaterMode(&b)))
  5087.                         _pdie->put_TheaterMode( b == VARIANT_TRUE ? VARIANT_FALSE : VARIANT_TRUE);
  5088.                     break;
  5089.                 }
  5090.  
  5091.             case TBIDM_STOPDOWNLOAD:
  5092.                 if (_fTransitionToHTML)
  5093.                 {
  5094.                     UINT uiState;
  5095.                     _fTransitionToHTML = FALSE;
  5096.                     if (SUCCEEDED(GetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, &uiState)))
  5097.                     {
  5098.                         uiState |= TBSTATE_HIDDEN;
  5099.                         SetState(&CLSID_CommonButtons, TBIDM_STOPDOWNLOAD, uiState);
  5100.                     }
  5101.                     SendMessage(_hwndAddressBand, CB_SETEDITSEL, NULL, (LPARAM)MAKELONG(-1,0));
  5102.                 }
  5103.                 _pdie->Stop();
  5104.                 break;
  5105.  
  5106.             case TBIDM_REFRESH:
  5107.             {
  5108.                 VARIANT v = {0};
  5109.                 v.vt = VT_I4;
  5110.                 v.lVal = (GetAsyncKeyState(VK_CONTROL) < 0) ?
  5111.                          OLECMDIDF_REFRESH_COMPLETELY|OLECMDIDF_REFRESH_PROMPTIFOFFLINE :
  5112.                          OLECMDIDF_REFRESH_NO_CACHE|OLECMDIDF_REFRESH_PROMPTIFOFFLINE;
  5113.                 _pdie->Refresh2(&v);
  5114.  
  5115.                 if (_hwndAddressBand)
  5116.                 {
  5117.                     LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  5118.  
  5119.                     ASSERT(pbid && pbid->pdb);     // pbid->pdb is a IDeskBand pointer
  5120.                     if (pbid && pbid->pdb)
  5121.                     {
  5122.                         IAddressBand *pab = NULL;
  5123.                         if (SUCCEEDED(pbid->pdb->QueryInterface(IID_IAddressBand, (LPVOID*)&pab)))
  5124.                         {
  5125.                             VARIANTARG varType = {0};
  5126.                             varType.vt = VT_I4;
  5127.                             varType.lVal = OLECMD_REFRESH_TOPMOST;
  5128.                             pab->Refresh(&varType);
  5129.                             pab->Release();
  5130.                         }
  5131.                     }
  5132.                 }
  5133.  
  5134.                 // pass this to vert and horz bars
  5135.                 IDockingWindowFrame *psb;
  5136.                 if (_psp && SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_IDockingWindowFrame, (void**)&psb)))
  5137.                 {
  5138.                     IDeskBar* pdb;
  5139.  
  5140.                     if (SUCCEEDED(psb->FindToolbar(INFOBAR_TBNAME, IID_IDeskBar, (void **)&pdb)) && pdb &&
  5141.                         IsBarRefreshable(pdb))
  5142.                     {
  5143.                         IUnknown_Exec(pdb, NULL, OLECMDID_REFRESH, OLECMDIDF_REFRESH_NORMAL|OLECMDIDF_REFRESH_PROMPTIFOFFLINE, NULL, NULL);
  5144.                         pdb->Release();
  5145.                     }
  5146.                     if (SUCCEEDED(psb->FindToolbar(COMMBAR_TBNAME, IID_IDeskBar, (void **)&pdb)) && pdb &&
  5147.                         IsBarRefreshable(pdb))
  5148.                     {
  5149.                         IUnknown_Exec(pdb, NULL, OLECMDID_REFRESH, OLECMDIDF_REFRESH_NORMAL|OLECMDIDF_REFRESH_PROMPTIFOFFLINE, NULL, NULL);
  5150.                         pdb->Release();
  5151.                     }
  5152.                     psb->Release();
  5153.                 }
  5154.  
  5155.             }
  5156.                 break;
  5157.             }
  5158.         }
  5159.     }
  5160.     else if (IsEqualGUID(IID_IExplorerToolbar, *pguidCmdGroup))
  5161.     {
  5162.         switch (nCmdID)
  5163.         {
  5164.         case ETCMDID_GETBUTTONS:
  5165.             {
  5166.                 if (_iButtons == -1)
  5167.                 {
  5168.                     // haven't initialized yet
  5169.                     _iButtons = ARRAYSIZE(c_tbExplorer);
  5170.                     memcpy(_tbExplorer, c_tbExplorer, SIZEOF(TBBUTTON) * ARRAYSIZE(c_tbExplorer));
  5171.                     if (GetUIVersion() < 5)
  5172.                     {
  5173.                         // we don't want up button and network drive buttons available
  5174.                         // on < nt5 shell (by trident pm design)
  5175.  
  5176.                         // no customization in shell view on < nt5
  5177.                         ASSERT(!_fShellView);
  5178.  
  5179.                         ASSERT(c_tbExplorer[5].idCommand == TBIDM_PREVIOUSFOLDER);
  5180.                         _tbExplorer[5].fsState |= TBSTATE_HIDDEN;
  5181.  
  5182.                         ASSERT(c_tbExplorer[6].idCommand == TBIDM_CONNECT);
  5183.                         _tbExplorer[6].fsState |= TBSTATE_HIDDEN;
  5184.  
  5185.                         ASSERT(c_tbExplorer[7].idCommand == TBIDM_DISCONNECT);
  5186.                         _tbExplorer[7].fsState |= TBSTATE_HIDDEN;
  5187.  
  5188.                         ASSERT(c_tbExplorer[10].idCommand == TBIDM_ALLFOLDERS);
  5189.                         if (!_FoldersButtonAvailable())
  5190.                             _tbExplorer[10].fsState |= TBSTATE_HIDDEN;
  5191.                     }
  5192.                     else
  5193.                     {
  5194.                         ASSERT(c_tbExplorer[9].idCommand == TBIDM_SEARCH);
  5195.                         if (_fShellView && SHRestricted(REST_NOSHELLSEARCHBUTTON))
  5196.                             _tbExplorer[9].fsState |= TBSTATE_HIDDEN;
  5197.                            
  5198.                         ASSERT(c_tbExplorer[6].idCommand == TBIDM_CONNECT);
  5199.                         ASSERT(c_tbExplorer[7].idCommand == TBIDM_DISCONNECT);
  5200.                         if (SHRestricted(REST_NONETCONNECTDISCONNECT))
  5201.                         {
  5202.                             _tbExplorer[6].fsState |= TBSTATE_HIDDEN;
  5203.                             _tbExplorer[7].fsState |= TBSTATE_HIDDEN;
  5204.                         }
  5205.                     }
  5206.                     _iButtons = RemoveHiddenButtons(_tbExplorer, ARRAYSIZE(_tbExplorer));
  5207.                 }
  5208.  
  5209.                 pvarargOut->vt = VT_BYREF;
  5210.                 pvarargOut->byref = (LPVOID)_tbExplorer;
  5211.                 *pvarargIn->plVal = _iButtons;
  5212.             }
  5213.             return S_OK;
  5214.         }
  5215.     }
  5216.     else if (IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup))
  5217.     {
  5218.         DWORD dw;
  5219.         hr = S_OK;
  5220.         switch (nCmdID)
  5221.         {
  5222.         case CITIDM_GETFOLDERSEARCHES:
  5223.             {
  5224.                 hr = E_INVALIDARG;
  5225.  
  5226.                 if (pvarargOut)
  5227.                 {
  5228.                     IFolderSearches *pfs;
  5229.                     hr = _GetFolderSearches(&pfs);
  5230.  
  5231.                     if (SUCCEEDED(hr))
  5232.                     {
  5233.                         VariantClear(pvarargOut);
  5234.                         pvarargOut->vt = VT_UNKNOWN;
  5235.                         pvarargOut->punkVal = pfs;
  5236.                     }
  5237.                 }
  5238.             }
  5239.             break;
  5240.  
  5241.         case CITIDM_SET_DIRTYBIT:
  5242.             _fDirty = BOOLIFY(nCmdexecopt);
  5243.             break;
  5244.  
  5245.         case CITIDM_GETMINROWHEIGHT:
  5246.             hr = _GetMinRowHeight();
  5247.             break;
  5248.  
  5249.         case CITIDM_VIEWTOOLBARCUSTOMIZE:
  5250.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWTOOLBARCUSTOMIZE, _hwnd, 0));
  5251.             break;
  5252.  
  5253.         case CITIDM_TEXTLABELS:
  5254.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWTEXTLABELS, _hwnd, 0));
  5255.             break;
  5256.  
  5257.         case CITIDM_EDITPAGE:
  5258.             // BUGBUG: temp code -- edit code moving to dochost.cpp
  5259.             _btb.Exec(&CLSID_InternetButtons, DVIDM_EDITPAGE, 0, NULL, NULL);
  5260.             break;
  5261.  
  5262.         case CITIDM_ONINTERNET:
  5263.             switch (nCmdexecopt) {
  5264.             case CITE_INTERNET:
  5265.                 _fInitialPidlIsWeb = TRUE;
  5266.                 _fShellView = !_fInitialPidlIsWeb;
  5267.                 break;
  5268.             case CITE_SHELL:
  5269.                 _fInitialPidlIsWeb = FALSE;
  5270.                 _fShellView = !_fInitialPidlIsWeb;
  5271.                 break;
  5272.             case CITE_QUERY:
  5273.                 return ResultFromScode(_fShellView ? CITE_SHELL : CITE_INTERNET);
  5274.                 break;
  5275.             }
  5276.             return ResultFromScode(_fInitialPidlIsWeb ? CITE_INTERNET : CITE_SHELL);
  5277.  
  5278.         case CITIDM_VIEWTOOLS:
  5279.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWTOOLS, _hwnd, 0));
  5280.             break;
  5281.  
  5282.         case CITIDM_VIEWAUTOHIDE:
  5283.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWAUTOHIDE, _hwnd, 0));
  5284.             break;
  5285.  
  5286.         case CITIDM_VIEWADDRESS:
  5287.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWADDRESS, _hwnd, 0));
  5288.             break;
  5289.  
  5290.         case CITIDM_VIEWLINKS:
  5291.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWLINKS, _hwnd, 0));
  5292.             break;
  5293.  
  5294.         case CITIDM_VIEWMENU:
  5295.             _OnCommand(GET_WM_COMMAND_MPS(FCIDM_VIEWMENU, _hwnd, 0));
  5296.             break;
  5297.  
  5298.         case CITIDM_SHOWTOOLS:
  5299.             dw = VBF_TOOLS;
  5300.             goto ShowABand;
  5301.  
  5302.         case CITIDM_SHOWADDRESS:
  5303.             dw = VBF_ADDRESS;
  5304.             goto ShowABand;
  5305.  
  5306.         case CITIDM_SHOWLINKS:
  5307.             dw = VBF_LINKS;
  5308.             goto ShowABand;
  5309.  
  5310. #ifdef UNIX
  5311.         case CITIDM_SHOWBRAND:
  5312.             dw = VBF_BRAND;
  5313.             goto ShowABand;
  5314. #endif
  5315.  
  5316.         case CITIDM_SHOWMENU:
  5317.             dw = VBF_MENU;
  5318. ShowABand:
  5319.             if (nCmdexecopt)
  5320.                 dw |= _nVisibleBands;           // Set
  5321.             else
  5322.                 dw = (_nVisibleBands & ~dw);    // Clear
  5323.  
  5324.             _ShowVisible(dw, TRUE);
  5325.             _fUsingDefaultBands = FALSE;
  5326.             break;
  5327.  
  5328.         case CITIDM_DISABLESHOWMENU:
  5329.             _fNoShowMenu = BOOLIFY(nCmdexecopt);
  5330.             break;
  5331.  
  5332.         case CITIDM_STATUSCHANGED:
  5333.             _fDirty = TRUE;
  5334.             if (_ptbsitect)
  5335.                 _ptbsitect->Exec(&CGID_ShellBrowser, FCIDM_PERSISTTOOLBAR, 0, NULL, NULL);
  5336.             break;
  5337.  
  5338.         case CITIDM_THEATER:
  5339.  
  5340.             if (_fShow) {
  5341.  
  5342.                 // IF YOU SEE HTIS ASSERT, TRY TO REMEMBER WHAT YOU DID AND CALL CHEE
  5343.                 ASSERT(_fTheater || _nVisibleBands & VBF_MENU);
  5344.  
  5345.                 switch (nCmdexecopt)
  5346.                 {
  5347.  
  5348.                 case THF_ON:
  5349.                     _fTheater = TRUE;
  5350.                     ResizeBorderDW(NULL, NULL, FALSE);
  5351.                     _TheaterModeLayout(TRUE);
  5352.                     // theater has its own brand, so needs to know whether we're in shell or web view so it can show the right brand
  5353.                     IUnknown_Exec(_ptbsite, &CGID_Theater, THID_ONINTERNET, _fShellView ? CITE_SHELL : CITE_INTERNET, NULL, NULL);
  5354.  
  5355.                     // pass back _fAutoHide
  5356.                     pvarargOut->vt = VT_I4;
  5357.                     pvarargOut->lVal = _fAutoHide;
  5358.  
  5359.                     goto notify_bands;
  5360.  
  5361.  
  5362.                 case THF_OFF:
  5363.                     _fTheater = FALSE;
  5364.                     ResizeBorderDW(NULL, NULL, FALSE);
  5365.                     _TheaterModeLayout(FALSE);
  5366.  
  5367.                     // position everything properly (needed after reparenting)
  5368.                     SendMessage(_hwnd, RB_PRIV_RESIZE, 0, 0);
  5369.                     goto notify_bands;
  5370.  
  5371. notify_bands:
  5372.                     {
  5373.                         int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
  5374.                         for (int i = 0; i < icBands; i++)
  5375.                         {
  5376.                             REBARBANDINFO rbbi;
  5377.                             rbbi.cbSize = sizeof(REBARBANDINFO);
  5378.                             rbbi.fMask = RBBIM_ID;
  5379.  
  5380.                             if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  5381.                             {
  5382.                                 LPBANDITEMDATA pbid = (LPBANDITEMDATA)_bs._GetBandItemDataStructByID(rbbi.wID);
  5383.                                 if (pbid)
  5384.                                     IUnknown_Exec(pbid->pdb, pguidCmdGroup, CITIDM_THEATER, nCmdexecopt, NULL, NULL);
  5385.                             }
  5386.                         }
  5387.                     }
  5388.                     break;
  5389.  
  5390.                 case THF_UNHIDE:
  5391.                     // position everything properly (needed after reparenting)
  5392.                     SendMessage(_hwnd, RB_PRIV_RESIZE, 0, 0);
  5393.                     break;
  5394.                 }
  5395.  
  5396.                 // IF YOU SEE HTIS ASSERT, TRY TO REMEMBER WHAT YOU DID AND CALL CHEE
  5397.                 ASSERT(_fTheater || _nVisibleBands & VBF_MENU);
  5398.             }
  5399.  
  5400.             break;
  5401.         case CITIDM_VIEWEXTERNALBAND_BYCLASSID:
  5402.             if ((pvarargIn->vt == VT_BSTR) && pvarargIn->bstrVal) {
  5403.                 CLSID clsid;
  5404.                 if (GUIDFromString( pvarargIn->bstrVal, &clsid )) {
  5405.                     hr = E_FAIL;
  5406.                     for (DWORD i = 0; i < MAXEXTERNALBANDS; i++) {
  5407.                         if (clsid == _rgebi[i].clsid) {
  5408.                             DWORD dw = _nVisibleBands;
  5409.                             DWORD dwBit = EXTERNALBAND_VBF_BIT( i );
  5410.                             dw = (nCmdexecopt) ? dw | dwBit : dw & ~dwBit;
  5411.                             if ( !( dw & ~VBF_BRAND)) {
  5412.                                 _pdie->put_ToolBar( FALSE );
  5413.                             }
  5414.                             _ShowVisible(dw, TRUE);
  5415.                             _fUsingDefaultBands = FALSE;
  5416.                             hr = S_OK;
  5417.                             break;
  5418.                         }
  5419.                     }
  5420.                 }
  5421.             }
  5422.             break;
  5423.         default:
  5424.             if (InRange( nCmdID, CITIDM_VIEWEXTERNALBAND_FIRST, CITIDM_VIEWEXTERNALBAND_LAST )) {
  5425.                 _OnCommand(GET_WM_COMMAND_MPS( nCmdID - CITIDM_VIEWEXTERNALBAND_FIRST + FCIDM_EXTERNALBANDS_FIRST, _hwnd, 0));
  5426.                 break;
  5427.             }
  5428.             ASSERT(0);
  5429.             break;
  5430.         }
  5431.     }
  5432.     else
  5433.     {
  5434. Lother:
  5435.         LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  5436.         if (pbid)
  5437.         {
  5438.             hr = IUnknown_Exec(pbid->pdb, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  5439.         }
  5440.     }
  5441.  
  5442.     return hr;
  5443. }
  5444.  
  5445. BOOL _GetSearchHKEY(REFGUID guidSearch, HKEY *phkey)
  5446. {
  5447.     HKEY hkey;
  5448.     BOOL bRet = FALSE;
  5449.  
  5450.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_SZ_STATIC, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  5451.     {
  5452.         TCHAR szExt[MAX_PATH];//extension key name
  5453.         DWORD cchExt = ARRAYSIZE(szExt);
  5454.         int  iExt;
  5455.         BOOL bNoUrl = FALSE; // true iff guidSearch is found and there is no Url subkey
  5456.  
  5457.         for (iExt=0;
  5458.              !bRet && RegEnumKeyEx(hkey, iExt, szExt, &cchExt, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
  5459.              cchExt = ARRAYSIZE(szExt), iExt++)
  5460.         {
  5461.             HKEY hkeyExt; // static extension key
  5462.  
  5463.             if (RegOpenKeyEx(hkey, szExt, 0, KEY_READ, &hkeyExt) == ERROR_SUCCESS)
  5464.             {
  5465.                 int i;
  5466.                 TCHAR szSubKey[32];
  5467.                 HKEY  hkeySub;
  5468.  
  5469.                 for (i = 0; !bRet && (wnsprintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), i),
  5470.                             RegOpenKey(hkeyExt, szSubKey, &hkeySub) == ERROR_SUCCESS);
  5471.                      i++)
  5472.                 {
  5473.                     TCHAR szSearchGuid[GUIDSTR_MAX];
  5474.                     DWORD cb;
  5475.                     DWORD dwType;
  5476.  
  5477.                     cb = SIZEOF(szSearchGuid);
  5478.                     if (SHGetValue(hkeySub, REG_SZ_SEARCH_GUID, NULL, &dwType, (BYTE*)szSearchGuid, &cb) == ERROR_SUCCESS)
  5479.                     {
  5480.                         GUID guid;
  5481.  
  5482.                         if (GUIDFromString(szSearchGuid, &guid) &&
  5483.                             IsEqualGUID(guid, guidSearch))
  5484.                         {
  5485.                             HKEY hkeyTmp;
  5486.  
  5487.                             if (RegOpenKey(hkeySub, REG_SZ_SEARCH_URL, &hkeyTmp) == ERROR_SUCCESS)
  5488.                                 RegCloseKey(hkeyTmp);
  5489.                             else
  5490.                                 bNoUrl = TRUE;
  5491.  
  5492.                             bRet = TRUE;
  5493.                         }
  5494.                     }
  5495.                     if (!bRet || bNoUrl)
  5496.                         RegCloseKey(hkeySub);
  5497.                     else
  5498.                         *phkey = hkeySub;
  5499.  
  5500.                 }
  5501.                 if (!bNoUrl)
  5502.                     RegCloseKey(hkeyExt);
  5503.                 else
  5504.                 {
  5505.                     ASSERT(bRet);
  5506.                     *phkey = hkeyExt;
  5507.                 }
  5508.             }
  5509.         }
  5510.         RegCloseKey(hkey);
  5511.     }
  5512.     return bRet;
  5513. }
  5514.  
  5515. HRESULT CInternetToolbar::GetDefaultSearchUrl(LPWSTR pwszUrl, UINT cch)
  5516. {
  5517.     HRESULT hr = E_FAIL;
  5518.  
  5519.     if (GetDefaultInternetSearchUrlW(pwszUrl, cch, TRUE))
  5520.         hr = S_OK;
  5521.     return hr;
  5522. }
  5523.  
  5524. void WINAPI CopyEnumElement(void *pDest, const void *pSource, DWORD dwSize)
  5525. {
  5526.     if (!pDest)
  5527.         return;
  5528.  
  5529.     memcpy(pDest, pSource, dwSize);
  5530. }
  5531.  
  5532. class CFolderSearches : public IFolderSearches
  5533. {
  5534. public:
  5535.     // *** IUnknown ***
  5536.     STDMETHODIMP QueryInterface(REFIID riid, void ** ppvObj);
  5537.     STDMETHODIMP_(ULONG) AddRef(void);
  5538.     STDMETHODIMP_(ULONG) Release(void);
  5539.     // *** IFolderSearches ***
  5540.     STDMETHODIMP EnumSearches(IEnumUrlSearch **ppenum);
  5541.     STDMETHODIMP DefaultSearch(GUID *pguid);
  5542.  
  5543.     CFolderSearches(GUID *pguid, int iCount, URLSEARCH *pUrlSearch);
  5544.     ~CFolderSearches();
  5545. private:
  5546.     LONG _cRef;
  5547.     int  _iCount;
  5548.     GUID _guidDefault;
  5549.     URLSEARCH *_pUrlSearch;
  5550. };
  5551.  
  5552. CFolderSearches::CFolderSearches(GUID *pguid, int iCount, URLSEARCH *pUrlSearch)
  5553. {
  5554.     _cRef = 1;
  5555.     _iCount = iCount;
  5556.     _guidDefault = *pguid;
  5557.     _pUrlSearch = pUrlSearch;
  5558. }
  5559.  
  5560. CFolderSearches::~CFolderSearches()
  5561. {
  5562.     if (_pUrlSearch)
  5563.         LocalFree(_pUrlSearch);
  5564. }
  5565.  
  5566. HRESULT CFolderSearches::QueryInterface(REFIID riid, void **ppvObj)
  5567. {
  5568.     static const QITAB qit[] =
  5569.     {
  5570.         QITABENT(CFolderSearches, IFolderSearches),
  5571.         { 0 },
  5572.     };
  5573.  
  5574.     return QISearch(this, qit, riid, ppvObj);
  5575. }
  5576.  
  5577. ULONG CFolderSearches::AddRef()
  5578. {
  5579.     return ++_cRef;
  5580. }
  5581.  
  5582. ULONG CFolderSearches::Release()
  5583. {
  5584.     if (--_cRef > 0)
  5585.         return _cRef;
  5586.  
  5587.     delete this;
  5588.     return 0;
  5589. }
  5590.  
  5591. HRESULT CFolderSearches::EnumSearches(IEnumUrlSearch **ppenum)
  5592. {
  5593.     HRESULT hres = E_OUTOFMEMORY;
  5594.  
  5595.     *ppenum = (IEnumUrlSearch *)new CStandardEnum(IID_IEnumUrlSearch, FALSE,
  5596.                 _iCount, sizeof(URLSEARCH), _pUrlSearch, CopyEnumElement);
  5597.     if (*ppenum)
  5598.     {
  5599.         _pUrlSearch = NULL;
  5600.         _iCount = 0;
  5601.         hres = S_OK;
  5602.     }
  5603.     return hres;
  5604. }
  5605.  
  5606. HRESULT CFolderSearches::DefaultSearch(GUID *pguid)
  5607. {
  5608.     *pguid = _guidDefault;
  5609.     return S_OK;
  5610. }
  5611.  
  5612. HRESULT CInternetToolbar::_GetFolderSearches(IFolderSearches **ppfs)
  5613. {
  5614.     HRESULT hres = E_FAIL;
  5615.  
  5616.     *ppfs = NULL;
  5617.     if (_hdpaFSI)
  5618.     {
  5619.         LPURLSEARCH pUrlSearch = NULL;
  5620.         int iCount = 0;
  5621.         int cFSIs = DPA_GetPtrCount(_hdpaFSI);
  5622.  
  5623.         hres = E_OUTOFMEMORY;
  5624.         if (cFSIs > 0
  5625.             && ((pUrlSearch = (LPURLSEARCH)LocalAlloc(LPTR, SIZEOF(URLSEARCH)*cFSIs)) != NULL))
  5626.         {
  5627.             LPFOLDERSEARCHITEM pfsi;
  5628.             int i;
  5629.  
  5630.             // insert per folder items
  5631.             for (i = 0; i < cFSIs && (pfsi = (LPFOLDERSEARCHITEM)DPA_GetPtr(_hdpaFSI, i)) != NULL; i++)
  5632.             {
  5633.                 CLSID  clsid;
  5634.  
  5635.                 // check if Url is actually a GUID. if yes we cannot enumerate it because
  5636.                 // we need Title/Url pair.
  5637.                 if (!GUIDFromStringW(pfsi->wszUrl, &clsid))
  5638.                 {
  5639.                     lstrcpynW(pUrlSearch[iCount].wszName, pfsi->wszName, ARRAYSIZE(pUrlSearch[iCount].wszName));
  5640.                     lstrcpynW(pUrlSearch[iCount].wszUrl,  pfsi->wszUrl,  ARRAYSIZE(pUrlSearch[iCount].wszUrl));
  5641.                     iCount++;
  5642.                 }
  5643.             }
  5644.         }
  5645.         *ppfs = new CFolderSearches(&_guidDefaultSearch, iCount, pUrlSearch);
  5646.         if (*ppfs)
  5647.             hres = S_OK;
  5648.         else
  5649.             LocalFree(pUrlSearch);
  5650.     }
  5651.     return hres;
  5652. }
  5653.  
  5654. BOOL CInternetToolbar::_GetSearchUrl(LPWSTR pwszUrl, DWORD cch)
  5655. {
  5656.     BOOL        bRet = FALSE;
  5657.     HKEY        hkey;
  5658.  
  5659.     if (pwszUrl)
  5660.     {
  5661.         pwszUrl[0] = L'\0';
  5662.  
  5663.         // if we are looking for web search url bypass the registry lookup and the
  5664.         // per folder items and go straight to GetDefaultSearchUrl which call
  5665.         // GetSearchAssistantUrlW
  5666.         if (!IsEqualGUID(_guidDefaultSearch, SRCID_SWebSearch))
  5667.         {
  5668.             // _GetSearchHKEY looks in the registry where shell search items are registered
  5669.             // if we have old shell32 then we don't display shell search items so we should
  5670.             // not look in the registry
  5671.             if (GetUIVersion() >= 5 && _GetSearchHKEY(_guidDefaultSearch, &hkey))
  5672.             {
  5673.                 DWORD cb = cch*sizeof(TCHAR);
  5674.                 TCHAR szGuid[GUIDSTR_MAX];
  5675.                 DWORD cbGuid = SIZEOF(szGuid);
  5676.  
  5677.                 // is there a url key
  5678.                 if (SHGetValueW(hkey, REG_SZ_SEARCH_URL, NULL, NULL, pwszUrl, &cb) == ERROR_SUCCESS)
  5679.                     bRet = TRUE;
  5680.                 // no? try the default value, maybe it's the clsid
  5681.                 else if (SHGetValueW(hkey, NULL, NULL, NULL, szGuid, &cbGuid) == ERROR_SUCCESS)
  5682.                 {
  5683.                     GUID guid;
  5684.                     // is it a valid guid string
  5685.                     if (GUIDFromString(szGuid, &guid))
  5686.                     {
  5687.                         StrCpyNW(pwszUrl, szGuid, cch);
  5688.                         bRet = TRUE;
  5689.                     }
  5690.                 }
  5691.  
  5692.                 RegCloseKey(hkey);
  5693.             }
  5694.             // maybe it's one of the per-folder items...
  5695.             else if (_hdpaFSI) //FSI = folder search items
  5696.             {
  5697.                 int i;
  5698.                 LPFOLDERSEARCHITEM pfsi;
  5699.  
  5700.                 for (i=0; (pfsi = (LPFOLDERSEARCHITEM)DPA_GetPtr(_hdpaFSI, i)) != NULL; i++)
  5701.                 {
  5702.                     if (IsEqualGUID(_guidDefaultSearch, pfsi->guidSearch))
  5703.                     {
  5704.                         StrCpyNW(pwszUrl, pfsi->wszUrl, cch);
  5705.                         bRet = TRUE;
  5706.                         break;
  5707.                     }
  5708.                 }
  5709.             }
  5710.         }
  5711.  
  5712.         if (!bRet)
  5713.             bRet = SUCCEEDED(GetDefaultSearchUrl(pwszUrl, cch));
  5714.     }
  5715.  
  5716.     return bRet;
  5717. }
  5718.  
  5719. void CInternetToolbar::_SetSearchStuff()
  5720. {
  5721.     UINT uiState;
  5722.     BOOL bChecked = FALSE;
  5723.  
  5724.     if (SUCCEEDED(GetState(&CLSID_CommonButtons, TBIDM_SEARCH, &uiState)))
  5725.         bChecked = uiState & TBSTATE_CHECKED;
  5726.  
  5727.     if (!_hdpaFSI)
  5728.         _hdpaFSI = DPA_Create(2);
  5729.     else
  5730.     {
  5731.         DPA_EnumCallback(_hdpaFSI, DeleteDPAPtrCB, NULL); // delete all ptrs
  5732.         DPA_DeleteAllPtrs(_hdpaFSI); // now tell hdpa to forget about them
  5733.     }
  5734.  
  5735.     // BUGBUG: this is bogus -- _fShellView is always FALSE when using automation
  5736.     if (_fShellView)
  5737.         _guidDefaultSearch = SRCID_SFileSearch;
  5738.     else
  5739.         _guidDefaultSearch = SRCID_SWebSearch;
  5740.  
  5741.     // get per folder search items and the default search (if any)
  5742.     // and insert them to _himlSrc
  5743.     _GetFolderSearchData();
  5744.  
  5745.     if (!bChecked)
  5746.     {
  5747.         _guidCurrentSearch = _guidDefaultSearch;
  5748.     }
  5749. }
  5750.  
  5751. //
  5752. // CInternetToolbar::SetCommandTarget()
  5753. //
  5754. // This function sets the current command target and button group.  A client calls this
  5755. // before merging in buttons with the AddButtons method.
  5756. //
  5757. // There are a couple of tricky things about this function.
  5758. //
  5759. // One is that the client can pass some flags (dwFlags param) specifying the bands it wants
  5760. // showing by default (menu, links, address, tools, brand, external).  But we don't let them change
  5761. // the state of the menu band.  And, if another client has already set the default bands, we
  5762. // don't let them change the state of any of the bands.
  5763. //
  5764. // The other is that we do some stuff to figure out if the caller is just another instantiation of the same
  5765. // client.  If we think this is a new client (new guidButtonGroup), we flush the toolbar and return S_OK.
  5766. // But if we think this is the same client reincarnated (same guidButtonGroup and non-NULL command target),
  5767. // we return S_FALSE without flushing the toolbar.  This is done for performance.  A new dochost is instantiated
  5768. // on each navigation, but its toolbar buttons never change, so don't bother remerging its toolbar buttons.
  5769. //
  5770. HRESULT CInternetToolbar::SetCommandTarget(IUnknown* punkCmdTarget, const GUID* pguidButtonGroup, DWORD dwFlags)
  5771. {
  5772.     if (!pguidButtonGroup || !punkCmdTarget || IsEqualGUID(CLSID_CommonButtons, *pguidButtonGroup))
  5773.         return E_INVALIDARG;
  5774.  
  5775.     // this should not change the menu bit or external bands.
  5776.     dwFlags |= (_nVisibleBands & (VBF_MENU | VBF_EXTERNALBANDS));
  5777.  
  5778.     _btb._fCustomize = !((dwFlags & VBF_NOCUSTOMIZE) || SHRestricted2(REST_NOTOOLBARCUSTOMIZE, NULL, 0));
  5779.  
  5780.     // if the new button group is the internet button group, then we're
  5781.     // in internet mode; else we're in shell mode
  5782.     _fShellView = !(_IsDocHostGUID(pguidButtonGroup));
  5783.  
  5784.     _SetSearchStuff();
  5785.  
  5786.     HRESULT hr = S_FALSE;
  5787.  
  5788.     BOOL fNewButtonGroup = !IsEqualGUID(*pguidButtonGroup, _btb._guidCurrentButtonGroup);
  5789.     BOOL fNewCommandTarget = !SHIsSameObject(_btb._pctCurrentButtonGroup, punkCmdTarget);
  5790.  
  5791.     // when changing button groups we need to invalidate our cache of buttons for customization
  5792.     // why? well, with browse in separate process not turned on, navigating from shell to web
  5793.     // reuses the toolbar and some buttons may be disabled for shell but not for browser and vice versa.
  5794.     if (fNewButtonGroup)
  5795.         _iButtons = -1;
  5796.        
  5797.     if (fNewButtonGroup || fNewCommandTarget)
  5798.     {
  5799.         if (_btb._pctCurrentButtonGroup)
  5800.             _btb._pctCurrentButtonGroup->Exec(&IID_IExplorerToolbar, ETCMDID_NEWCOMMANDTARGET, 0, NULL, NULL);
  5801.  
  5802.         _btb._guidCurrentButtonGroup = *pguidButtonGroup;
  5803.         ATOMICRELEASE(_btb._pctCurrentButtonGroup);
  5804.         punkCmdTarget->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&_btb._pctCurrentButtonGroup);
  5805.  
  5806.         // A new view can tell us how many rows of text it NEEDs.
  5807.         // if it doesn't specify, we give it the default. (stored in _uiDefaultTBTextRows)
  5808.         if (dwFlags & VBF_ONELINETEXT )
  5809.             _uiTBTextRows = 1;
  5810.         else if (dwFlags & VBF_TWOLINESTEXT)
  5811.             _uiTBTextRows = 2;
  5812.         else
  5813.             _uiTBTextRows = _uiTBDefaultTextRows;
  5814.  
  5815.         _CompressBands(_fCompressed, _uiTBTextRows, FALSE);
  5816.  
  5817.         if (fNewButtonGroup)
  5818.         {
  5819.             // new button group; flush toolbar
  5820.             _btb._RemoveAllButtons();
  5821.             hr = S_OK;
  5822.         }
  5823.  
  5824.         if (_fUsingDefaultBands && !_fTheater)
  5825.             _fUsingDefaultBands = FALSE;
  5826.         else
  5827.             dwFlags = _nVisibleBands;
  5828.  
  5829.         if (dwFlags)
  5830.             _ShowBands(dwFlags);
  5831.     }
  5832.  
  5833.     return hr;
  5834. }
  5835.  
  5836. HRESULT CInternetToolbar::AddStdBrowserButtons()
  5837. {
  5838.     //
  5839.     // code to add browser buttons has moved to CDocObjectHost::_AddButtons
  5840.     //
  5841.     ASSERT(0);
  5842.     return E_NOTIMPL;
  5843. }
  5844.  
  5845. void CInternetToolbar::_ReloadButtons()
  5846. {
  5847.     if (!IsEqualGUID(_btb._guidCurrentButtonGroup, CLSID_CommonButtons) &&
  5848.             _btb._pctCurrentButtonGroup)
  5849.     {
  5850.         HRESULT hres = _btb._pctCurrentButtonGroup->Exec(&IID_IExplorerToolbar, ETCMDID_RELOADBUTTONS, 0, NULL, NULL);
  5851.         if (FAILED(hres))
  5852.             AddButtons(&_btb._guidCurrentButtonGroup, _btb._cBtnsAdded, _btb._pbtnsAdded);
  5853.  
  5854. #ifdef EDIT_HACK
  5855.         _InitEditButtonStyle();
  5856. #endif
  5857.  
  5858.         _UpdateToolbar(TRUE);
  5859.     }
  5860. }
  5861.  
  5862. // The cmdTarget should have already added the Imagelists and the strings.
  5863. HRESULT CInternetToolbar::AddButtons(const GUID* pguidButtonGroup, UINT nNewButtons, const TBBUTTON * lpButtons)
  5864. {
  5865.     if (!pguidButtonGroup || !IsEqualGUID(*pguidButtonGroup, _btb._guidCurrentButtonGroup))
  5866.         return E_INVALIDARG;
  5867.  
  5868.     if (!IsWindow(_btb._hwnd))
  5869.         return E_FAIL;
  5870.  
  5871.     LPTBBUTTON lpTBCopy = (LPTBBUTTON)LocalAlloc(LPTR, nNewButtons * sizeof(TBBUTTON));
  5872.     if (!lpTBCopy)
  5873.         return E_OUTOFMEMORY;
  5874.  
  5875.     _CreateBands();
  5876.     _btb._RemoveAllButtons();
  5877.  
  5878.     memcpy(lpTBCopy, lpButtons, SIZEOF(TBBUTTON) * nNewButtons);
  5879.  
  5880.     nNewButtons = _btb._ProcessExternalButtons(lpTBCopy, nNewButtons);
  5881.  
  5882.     // Free the old button array
  5883.     _btb._FreeBtnsAdded();
  5884.  
  5885.     _btb._pbtnsAdded = lpTBCopy;
  5886.     _btb._cBtnsAdded = nNewButtons;
  5887.  
  5888.     if (_btb._fCustomize && _btb._SaveRestoreToolbar(FALSE))
  5889.     {
  5890.         // Customization mechanism filled the toolbar for us
  5891.  
  5892.         //
  5893.         // The customization mechanism allocated its own set of
  5894.         // cmdmaps for the buttons, which means that we need to
  5895.         // free those hanging off _pbtnsAdded when _pbtnsAdded is
  5896.         // freed.
  5897.         //
  5898.         _btb._fNeedFreeCmdMapsAdded = TRUE;
  5899.        
  5900.         _btb._RecalcButtonWidths();
  5901.  
  5902. #ifdef EDIT_HACK
  5903.         //
  5904.         // If we had a custom edit glyph, reload it so that we
  5905.         // don't momentarily flash the default glyph during
  5906.         // navigation.  We'll update it again when we get a
  5907.         // DISPID_DOCUMENTCOMPLETE event.
  5908.         //
  5909.         _RefreshEditGlyph();
  5910. #endif //EDIT_HACK
  5911.     }
  5912.     else
  5913.     {
  5914.         // No customization found for this button group
  5915.  
  5916.         //
  5917.         // We're adding the button array to toolbar directly,
  5918.         // and the cmdmaps get freed on TBN_DELETINGBUTTON, so
  5919.         // we shouldn't also try to free them when _pbtnsAdded
  5920.         // is freed.
  5921.         //
  5922.         _btb._fNeedFreeCmdMapsAdded = FALSE;
  5923.  
  5924.         _AddCommonButtons();
  5925.         SendMessage(_btb._hwnd, TB_ADDBUTTONS, nNewButtons, (LPARAM)lpTBCopy);
  5926.     }
  5927.  
  5928.     _bs._SetMinDimensions();
  5929.     return S_OK;
  5930. }
  5931.  
  5932. HRESULT CInternetToolbar::AddString(const GUID * pguidButtonGroup, HINSTANCE hInst, UINT_PTR uiResID, LONG_PTR *pOffset)
  5933. {
  5934.     TraceMsg(DM_ITBAR, "CITBar::AddString called");
  5935.  
  5936.     *pOffset = -1;
  5937.  
  5938.     if (!IsWindow(_btb._hwnd))
  5939.     {
  5940.         TraceMsg(DM_ERROR, "CITBar::AddString failed");
  5941.         return E_FAIL;
  5942.     }
  5943.  
  5944.     *pOffset= SendMessage(_btb._hwnd, TB_ADDSTRING, (WPARAM)hInst, (LPARAM)uiResID);
  5945.  
  5946.     if (*pOffset != -1)
  5947.         return S_OK;
  5948.  
  5949.     TraceMsg(DM_ERROR, "CITBar::AddString failed");
  5950.     return E_FAIL;
  5951. }
  5952.  
  5953. HRESULT CInternetToolbar::GetButton(const GUID* pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton)
  5954. {
  5955.     UINT_PTR uiIndex = 0;
  5956.     TraceMsg(DM_ITBAR, "CITBar::GetButton called");
  5957.  
  5958.     if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
  5959.         return E_FAIL;
  5960.  
  5961.     if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
  5962.     {
  5963.         uiIndex = SendMessage(_btb._hwnd, TB_COMMANDTOINDEX, uiCommand, 0L);
  5964.         if (SendMessage(_btb._hwnd, TB_GETBUTTON, uiIndex, (LPARAM)lpButton))
  5965.         {
  5966.             GUID guid;
  5967.             _btb._ConvertCmd(NULL, lpButton->idCommand, &guid, (UINT*)&lpButton->idCommand);
  5968.             return S_OK;
  5969.         }
  5970.     }
  5971.     return E_FAIL;
  5972. }
  5973.  
  5974. HRESULT CInternetToolbar::GetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT * pfState)
  5975. {
  5976.     TraceMsg(DM_ITBAR, "CITBar::GetState called");
  5977.  
  5978.     if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
  5979.         return E_FAIL;
  5980.  
  5981.     if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
  5982.     {
  5983.         *pfState = (UINT)SendMessage(_btb._hwnd, TB_GETSTATE, uiCommand, 0L);
  5984.         return S_OK;
  5985.     }
  5986.  
  5987.     return E_FAIL;
  5988. }
  5989.  
  5990. HRESULT CInternetToolbar::SetState(const GUID* pguidButtonGroup, UINT uiCommand, UINT fState)
  5991. {
  5992.     BOOL bIsSearchBtn;
  5993.  
  5994.     if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
  5995.         return E_FAIL;
  5996.  
  5997.     TraceMsg(DM_ITBAR, "CITBar::SetState called");
  5998.  
  5999.     bIsSearchBtn = uiCommand == TBIDM_SEARCH;
  6000.     if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
  6001.     {
  6002.         UINT_PTR uiState;
  6003.  
  6004.         uiState = SendMessage(_btb._hwnd, TB_GETSTATE, uiCommand, NULL);
  6005.         uiState ^= fState;
  6006.         if (uiState)
  6007.         {
  6008.             // search button is being unchecked, change the icon to the default search's
  6009.             if (bIsSearchBtn && !(fState & TBSTATE_CHECKED) && !IsEqualGUID(_guidCurrentSearch, _guidDefaultSearch))
  6010.             {
  6011.                 _guidCurrentSearch = _guidDefaultSearch;
  6012.             }
  6013.             if (SendMessage(_btb._hwnd, TB_SETSTATE, uiCommand, (LPARAM)fState))
  6014.             {
  6015.                 if (uiState & TBSTATE_HIDDEN)
  6016.                     _bs._SetMinDimensions();
  6017.             }
  6018.         }
  6019.         return S_OK;
  6020.     }
  6021.     return E_FAIL;
  6022. }
  6023.  
  6024. //
  6025. //  A bitmap can be added in two ways:
  6026. //  1.  Send a bitmap in the hBMPNew field. The uiBMPType parameter needs to be a BITMAP_BMP*
  6027. //      The uiCount and the ptb parameters are ignored
  6028. //      The offset is placed in puiOffset
  6029. //
  6030. //  2.  A TBADDBITMAP struct can be sent. The uiCount should have the count
  6031. //      uiBMPType parameter needs to be a BITMAP_TBA* value
  6032. //      The offset is placed in puiOffset
  6033. HRESULT CInternetToolbar::AddBitmap(const GUID * pguidButtonGroup, UINT uiBMPType, UINT uiCount, TBADDBITMAP * ptb, LRESULT * pOffset, COLORREF rgbMask)
  6034. {
  6035.     UINT uiGetMSG, uiSetMSG;
  6036.     TBBMP_LIST tbl = {NULL};
  6037.  
  6038.     TraceMsg(DM_ITBAR, "CITBar::AddBitmaP called");
  6039.     *pOffset = -1;
  6040.  
  6041.     _CreateBands();
  6042.     if ((!pguidButtonGroup) || (!IsWindow(_btb._hwnd)) || !_hdsaTBBMPs)
  6043.     {
  6044.         TraceMsg(DM_ERROR, "CITBar::AddBitmaP failed");
  6045.         return E_FAIL;
  6046.     }
  6047.  
  6048.     // See if we already have the bitmap loaded.
  6049.     TBBMP_LIST * pTBBs = NULL;
  6050.     int nCount = DSA_GetItemCount(_hdsaTBBMPs);
  6051.     for (int nIndex = 0; nIndex < nCount; nIndex++)
  6052.     {
  6053.         pTBBs = (TBBMP_LIST*)DSA_GetItemPtr(_hdsaTBBMPs, nIndex);
  6054.         if ((pTBBs) && (pTBBs->hInst == ptb->hInst) && (pTBBs->uiResID == ptb->nID))
  6055.             break;
  6056.         pTBBs = NULL;
  6057.     }
  6058.  
  6059.     // If it was in the commctrl, then we should already have an entry in the DSA
  6060.     if ((ptb->hInst == HINST_COMMCTRL) && (!pTBBs))
  6061.     {
  6062.         TraceMsg(DM_ERROR, "CITBar::AddBitmap failed - bogus ResID for HINST_COMMCTL");
  6063.         return E_FAIL;
  6064.     }
  6065.  
  6066.     // If the icons being added are from fontsext.dll or from dialup networking
  6067.     // or the briefcase, then we have it. So just send return the offset
  6068.     if (ptb->hInst != HINST_COMMCTRL)
  6069.     {
  6070.         TCHAR szDLLFileName[MAX_PATH], *pszFN;
  6071.         memset(szDLLFileName, 0, ARRAYSIZE(szDLLFileName));
  6072.         if (GetModuleFileName(ptb->hInst, szDLLFileName, ARRAYSIZE(szDLLFileName)))
  6073.         {
  6074.             pszFN = PathFindFileName(szDLLFileName);
  6075.             if(!lstrcmpi(pszFN, TEXT("fontext.dll")))
  6076.                 *pOffset = FONTGLYPH_OFFSET;
  6077.             else if (!lstrcmpi(pszFN, TEXT("shell32.dll"))) {
  6078.                 // 140 and 141 are the glyphs that Shell32.dll uses:
  6079.                 // IDB_BRF_TB_SMALL        140
  6080.                 // IDB_BRF_TB_LARGE        141
  6081.                 if ((ptb->nID == 140) || (ptb->nID == 141))
  6082.                     *pOffset = BRIEFCASEGLYPH_OFFSET;
  6083.             }
  6084.             else if (!lstrcmpi(pszFN, TEXT("rnaui.dll")))
  6085.                 *pOffset = RNAUIGLYPH_OFFSET;
  6086.             else if (!lstrcmpi(pszFN, TEXT("webcheck.dll")))
  6087.                 *pOffset = WEBCHECKGLYPH_OFFSET;
  6088.             if (*pOffset != -1)
  6089.                 return S_OK;
  6090.         }
  6091.     }
  6092.  
  6093.     // So the bitmaps is not from commctrl. And we have never seen this before.
  6094.     // Add an entry into the DSA and then add the bitmap to the himage list.
  6095.     if (!pTBBs)
  6096.     {
  6097.         tbl.hInst = ptb->hInst;
  6098.         tbl.uiResID = ptb->nID;
  6099.         nIndex = DSA_AppendItem(_hdsaTBBMPs, &tbl);
  6100.         if (nIndex  < 0)
  6101.         {
  6102.             TraceMsg(DM_ERROR, "CITBar::AddBitmap failed");
  6103.             return E_FAIL;
  6104.         }
  6105.         pTBBs = (TBBMP_LIST*)DSA_GetItemPtr(_hdsaTBBMPs, nIndex);
  6106.         if (!pTBBs)
  6107.         {
  6108.             TraceMsg(DM_ERROR, "CITBar::AddBitmap failed");
  6109.             return E_FAIL;
  6110.         }
  6111.     }
  6112.  
  6113.  
  6114.     switch(uiBMPType)
  6115.     {
  6116.     case BITMAP_NORMAL:
  6117.         if ((pTBBs) && (pTBBs->fNormal))
  6118.         {
  6119.             *pOffset = pTBBs->uiOffset;
  6120.             return S_OK;
  6121.         }
  6122.         else if (pTBBs)
  6123.             pTBBs->fNormal = TRUE;
  6124.  
  6125.         uiGetMSG = TB_GETIMAGELIST; uiSetMSG = TB_SETIMAGELIST;
  6126.         break;
  6127.  
  6128.     case BITMAP_HOT:
  6129.         if ((pTBBs) && (pTBBs->fHot))
  6130.         {
  6131.             *pOffset = pTBBs->uiOffset;
  6132.             return S_OK;
  6133.         }
  6134.         else if (pTBBs)
  6135.             pTBBs->fHot = TRUE;
  6136.  
  6137.         uiGetMSG = TB_GETHOTIMAGELIST; uiSetMSG = TB_SETHOTIMAGELIST;
  6138.         break;
  6139.  
  6140.     case BITMAP_DISABLED:
  6141.         if ((pTBBs) && (pTBBs->fDisabled))
  6142.         {
  6143.             *pOffset = pTBBs->uiOffset;
  6144.             return S_OK;
  6145.         }
  6146.         else if (pTBBs)
  6147.             pTBBs->fDisabled = TRUE;
  6148.  
  6149.         uiGetMSG = TB_GETDISABLEDIMAGELIST; uiSetMSG = TB_SETDISABLEDIMAGELIST;
  6150.         break;
  6151.  
  6152.     default:
  6153.         ASSERT(FALSE);
  6154.         return E_FAIL;
  6155.     }
  6156.  
  6157.     *pOffset = _AddBitmapFromForeignModule(uiGetMSG, uiSetMSG, uiCount, ptb->hInst, ptb->nID, rgbMask);
  6158.     if (pTBBs)
  6159.         pTBBs->uiOffset = (UINT)*pOffset;
  6160.  
  6161.     return S_OK;
  6162. }
  6163.  
  6164. // the CmdTarget needs to call this to see what size of bmps we are using.
  6165. HRESULT CInternetToolbar::GetBitmapSize(UINT * uiSize)
  6166. {
  6167.     TraceMsg(DM_ITBAR, "CITBar::GetBitmapSize called");
  6168.  
  6169.     *uiSize = g_fSmallIcons ? MAKELONG(TB_SMBMP_CX, TB_SMBMP_CY) : MAKELONG(TB_BMP_CX,TB_BMP_CY);
  6170.     return S_OK;
  6171. }
  6172.  
  6173. HRESULT CInternetToolbar::SetImageList( const GUID* pguidCmdGroup, HIMAGELIST himlNormal, HIMAGELIST himlHot, HIMAGELIST himlDisabled)
  6174. {
  6175.     if (IsEqualGUID(*pguidCmdGroup, _btb._guidCurrentButtonGroup)) {
  6176.         SendMessage(_btb._hwnd, TB_SETIMAGELIST, 1, (LPARAM)himlNormal);
  6177.         SendMessage(_btb._hwnd, TB_SETHOTIMAGELIST, 1, (LPARAM)himlHot);
  6178.         SendMessage(_btb._hwnd, TB_SETDISABLEDIMAGELIST, 1, (LPARAM)himlDisabled);
  6179.     }
  6180.     return S_OK;
  6181. }
  6182.  
  6183. HRESULT CInternetToolbar::ModifyButton( const GUID * pguidButtonGroup, UINT uiCommand, LPTBBUTTON lpButton)
  6184. {
  6185.     UINT uiIndex = 0;
  6186.     TraceMsg(DM_ITBAR, "CITBar::ModifyButton called");
  6187.  
  6188.     if (!pguidButtonGroup || !IsWindow(_btb._hwnd))
  6189.         return E_FAIL;
  6190.  
  6191.     if (SUCCEEDED(_btb._ConvertCmd(pguidButtonGroup, uiCommand, NULL, &uiCommand)))
  6192.     {
  6193.         TBBUTTONINFO tbbi;
  6194.         tbbi.cbSize = SIZEOF(tbbi);
  6195.         tbbi.dwMask = TBIF_STATE | TBIF_IMAGE;
  6196.         tbbi.fsState = lpButton->fsState;
  6197.         tbbi.iImage = lpButton->iBitmap;
  6198.  
  6199.         if (SendMessage(_btb._hwnd, TB_SETBUTTONINFO, uiCommand, (LPARAM)&tbbi))
  6200.         {
  6201.             return S_OK;
  6202.         }
  6203.     }
  6204.     return E_FAIL;
  6205. }
  6206.  
  6207. HRESULT CInternetToolbar::SendToolbarMsg(const GUID* pguidButtonGroup, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT * plRes)
  6208. {
  6209.     LRESULT lRes;
  6210.     if (!IsWindow(_btb._hwnd))
  6211.     {
  6212.         TraceMsg(DM_ERROR, "CITBar::SendToolbar Message failed");
  6213.         return E_FAIL;
  6214.     }
  6215.  
  6216.     if (
  6217.         // this api is only here for back compat, and these messages didn't
  6218.         // exist when the old clients were written
  6219.  
  6220.         uMsg == TB_GETBUTTONINFOA ||
  6221.         uMsg == TB_GETBUTTONINFOW ||
  6222.         uMsg == TB_SETBUTTONINFOA ||
  6223.         uMsg == TB_SETBUTTONINFOW ||
  6224.  
  6225.         // unsupported right now
  6226.         uMsg == TB_ADDBUTTONSA || uMsg == TB_ADDBUTTONSW
  6227.        ) {
  6228.  
  6229.         ASSERT(0);
  6230.         return E_FAIL;
  6231.     }
  6232.  
  6233.  
  6234.  
  6235.     if ((uMsg == TB_ENABLEBUTTON) || (uMsg == TB_HIDEBUTTON) || (uMsg == TB_CHECKBUTTON) ||
  6236.         (uMsg == TB_PRESSBUTTON) || (uMsg == TB_MARKBUTTON))
  6237.     {
  6238.         unsigned int uiTemp;
  6239.         _btb._ConvertCmd(pguidButtonGroup, (UINT)wParam, NULL, &uiTemp);
  6240.         wParam = uiTemp;
  6241.     }
  6242.  
  6243.     if (uMsg == TB_INSERTBUTTON && lParam) {
  6244.         TBBUTTON btn = (*(TBBUTTON*)lParam);
  6245.         _btb._PreProcessExternalTBButton(&btn);
  6246.         lRes = SendMessage(_btb._hwnd, uMsg, wParam, (LPARAM)&btn);
  6247.     } else {
  6248.         lRes = SendMessage(_btb._hwnd, uMsg, wParam, lParam);
  6249.  
  6250.         if (uMsg == TB_GETBUTTON) {
  6251.             TBBUTTON* pbtn = (TBBUTTON*)lParam;
  6252.             if (pbtn && pbtn->dwData) {
  6253.                 CMDMAP* pcm = (CMDMAP*)pbtn->dwData;
  6254.                 pbtn->idCommand = pcm->nCmdID;
  6255.                 pbtn->dwData = pcm->lParam;
  6256.             }
  6257.         }
  6258.     }
  6259.  
  6260.     if (plRes)
  6261.         *plRes = lRes;
  6262.     return S_OK;
  6263. }
  6264.  
  6265. TOOLSBANDCLASS::CBrowserToolsBand() : CToolbarBand()
  6266. {
  6267.     _fCanFocus = TRUE;
  6268. }
  6269.  
  6270. #define DEFAULT_LIST_VALUE()    (GetUIVersion() >= 5)
  6271.  
  6272. void TOOLSBANDCLASS::_FreeBtnsAdded()
  6273. {
  6274.     if (_pbtnsAdded)
  6275.     {
  6276.         if (_fNeedFreeCmdMapsAdded)
  6277.         {
  6278.             for (int i = 0; i < _cBtnsAdded; i++)
  6279.             {
  6280.                 CMDMAP* pcm = (CMDMAP*)_pbtnsAdded[i].dwData;
  6281.                 _FreeCmdMap(pcm);
  6282.             }
  6283.         }
  6284.  
  6285.         LocalFree(_pbtnsAdded);
  6286.  
  6287.         _pbtnsAdded = NULL;
  6288.         _cBtnsAdded = 0;
  6289.     }
  6290. }
  6291.  
  6292. LRESULT TOOLSBANDCLASS::_ToolsCustNotify (LPNMHDR pnmh)
  6293. {
  6294.     LPTBNOTIFY ptbn = (LPTBNOTIFY) pnmh;
  6295.  
  6296.     switch (pnmh->code)
  6297.     {
  6298.  
  6299.     case TBN_SAVE:
  6300.     {
  6301.         NMTBSAVE *pnmtbs = (NMTBSAVE*)pnmh;
  6302.         if (pnmtbs->iItem == -1)
  6303.         {
  6304.             // before the save
  6305.             int nButtons = (int) SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
  6306.             int uSize = pnmtbs->cbData +
  6307.                         SIZEOF(BUTTONSAVEINFO) * nButtons +  // stuff for each button
  6308.                         SIZEOF(TOOLBARSAVEINFO); // stuff for the toolbar
  6309.             pnmtbs->pData = (LPDWORD)LocalAlloc(LPTR, uSize);
  6310.             pnmtbs->pCurrent = pnmtbs->pData;
  6311.             pnmtbs->cbData = uSize;
  6312.  
  6313.             if (pnmtbs->pData)
  6314.             {
  6315.                 TOOLBARSAVEINFO *ptbsi = (TOOLBARSAVEINFO*)pnmtbs->pData;
  6316.                 ptbsi->cVersion = TBSI_VERSION;
  6317.                 pnmtbs->pCurrent = (LPDWORD)(ptbsi+1);
  6318.             }
  6319.         }
  6320.         else
  6321.         {
  6322.             CMDMAP *pcm = (CMDMAP*)pnmtbs->tbButton.dwData;
  6323.             BUTTONSAVEINFO* pbsi = (BUTTONSAVEINFO*)pnmtbs->pCurrent;
  6324.             pnmtbs->pCurrent = (LPDWORD)(pbsi+1);
  6325.             if (pcm)
  6326.             {
  6327.                 pbsi->guid = pcm->guidButtonGroup;
  6328.                 pbsi->nCmdID = pcm->nCmdID;
  6329.                 pbsi->fButtonState = pnmtbs->tbButton.fsState;
  6330. #ifdef DEBUG
  6331.                 TCHAR szGuid[80];
  6332.                 SHStringFromGUID(pcm->guidButtonGroup, szGuid, ARRAYSIZE(szGuid));
  6333.                 TraceMsg(TF_TBCUST, "Saving: %s - %d (%x)", szGuid, pbsi->nCmdID, pbsi->nCmdID);
  6334. #endif
  6335.             }
  6336.             else
  6337.             {
  6338.                 ASSERT(pnmtbs->tbButton.fsStyle & BTNS_SEP);
  6339.                 if (pnmtbs->tbButton.idCommand)
  6340.                 {
  6341.                     TraceMsg(TF_TBCUST, "Saving: a separator w/ id %d (%x)", pnmtbs->tbButton.idCommand, pnmtbs->tbButton.idCommand);
  6342.                     pbsi->guid = CLSID_Separator;
  6343.                     pbsi->nCmdID = pnmtbs->tbButton.idCommand;
  6344.                 }
  6345.                 else
  6346.                     TraceMsg(TF_TBCUST, "Saving: a separator");
  6347.             }
  6348.         }
  6349.         break;
  6350.     }
  6351.  
  6352.     case TBN_RESTORE:
  6353.         {
  6354.             NMTBRESTORE* pnmtbr = (NMTBRESTORE*)pnmh;
  6355.             if (pnmtbr->iItem == -1)
  6356.             {
  6357.                 // before the restore.
  6358.                 // take the data, verify the version,
  6359.                 // fill in the button count, bytes per record
  6360.                 // initialize the pCurrent to the end of the tb header
  6361.                 //
  6362.                 TOOLBARSAVEINFO* ptbsi = (TOOLBARSAVEINFO*)pnmtbr->pCurrent;
  6363.                 if (ptbsi->cVersion != TBSI_VERSION)
  6364.                     return 1; // abort
  6365.  
  6366.  
  6367.                 // we're actually going to do a restore.  initialize our database:
  6368.                 _BuildButtonDSA();
  6369.  
  6370.                 pnmtbr->pCurrent = (LPDWORD)(ptbsi+1);
  6371.                 pnmtbr->cbBytesPerRecord += SIZEOF(BUTTONSAVEINFO);
  6372.                 pnmtbr->cButtons = (pnmtbr->cbData - SIZEOF(TOOLBARSAVEINFO*)) / pnmtbr->cbBytesPerRecord;
  6373.                 // make sure we did the math right and there are no remainders
  6374.                 ASSERT(((pnmtbr->cbData - SIZEOF(TOOLBARSAVEINFO*)) % pnmtbr->cbBytesPerRecord) == 0);
  6375.  
  6376.                 //this is going to clobber all of the buttons in the current toolbar.
  6377.                 // since toolbar control just writes over the dwords, we need to go free them now.
  6378.                 int nButtons = (int) SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
  6379.  
  6380.                 for (int nTemp = 0; nTemp < nButtons; nTemp++)
  6381.                 {
  6382.                     CMDMAP *pcm = _GetCmdMapByIndex(nTemp);
  6383.                     _FreeCmdMap(pcm);
  6384.                     TBBUTTONINFO tbbi;
  6385.                     tbbi.cbSize = SIZEOF(tbbi);
  6386.                     tbbi.lParam = (LPARAM)NULL;
  6387.                     tbbi.dwMask = TBIF_LPARAM | TBIF_BYINDEX;
  6388.                     SendMessage(_hwnd, TB_SETBUTTONINFO, nTemp, (LPARAM)&tbbi);
  6389.                 }
  6390.             }
  6391.             else
  6392.             {
  6393.                 BUTTONSAVEINFO* pbsi = (BUTTONSAVEINFO*)pnmtbr->pCurrent;
  6394.                 pnmtbr->pCurrent = (LPDWORD)(pbsi+1);
  6395.                 pnmtbr->tbButton.dwData = 0;
  6396.                 pnmtbr->tbButton.iString = -1;
  6397.  
  6398.                 if (IsEqualGUID(CLSID_Separator, pbsi->guid))
  6399.                 {
  6400.                     // restore a separator with a command id
  6401.                     pnmtbr->tbButton.fsStyle = BTNS_SEP;
  6402.                     TraceMsg(TF_TBCUST, "Restoring: a separator w/ id %d (%x)", pnmtbr->tbButton.idCommand, pnmtbr->tbButton.idCommand);
  6403.                 }
  6404.                 else if (!(pnmtbr->tbButton.fsStyle & BTNS_SEP))
  6405.                 {
  6406.                     // Make sure that the button exists for this site
  6407.                     CMDMAPCUSTOMIZE* pcmc = _GetCmdMapCustomize(&pbsi->guid, pbsi->nCmdID);
  6408.                     if (pcmc == NULL)
  6409.                     {
  6410.                         // Ignore this button
  6411.                         return 1;
  6412.                     }
  6413.  
  6414.                     CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, SIZEOF(CMDMAP));
  6415.                     if (pcm)
  6416.                     {
  6417.                         pcm->guidButtonGroup = pbsi->guid;
  6418.                         pcm->nCmdID = pbsi->nCmdID;
  6419.  
  6420. #ifdef DEBUG
  6421.                         TCHAR szGuid[80];
  6422.                         SHStringFromGUID(pcm->guidButtonGroup, szGuid, ARRAYSIZE(szGuid));
  6423.                         TraceMsg(TF_TBCUST, "Restoring: %s - %d (%x)", szGuid, pbsi->nCmdID, pbsi->nCmdID);
  6424. #endif
  6425.  
  6426.                         // fill in the rest of the info
  6427.                         pnmtbr->tbButton = pcmc->btn;
  6428.                         pnmtbr->tbButton.fsState = pbsi->fButtonState;
  6429.                         pnmtbr->tbButton.dwData = (DWORD_PTR) pcm;
  6430.  
  6431.                     }
  6432.                 }
  6433.                 else
  6434.                 {
  6435.                     TraceMsg(TF_TBCUST, "Restoring: a separator");
  6436.                 }
  6437.             }
  6438.         }
  6439.         break;
  6440.  
  6441.     case TBN_ENDADJUST:
  6442.         _OnEndCustomize();
  6443.         break;
  6444.  
  6445.     case TBN_TOOLBARCHANGE:
  6446.         _pcinfo->fDirty = TRUE;
  6447.         break;
  6448.  
  6449.     case TBN_INITCUSTOMIZE:
  6450.         _OnBeginCustomize((NMTBCUSTOMIZEDLG*)pnmh);
  6451.         return TBNRF_HIDEHELP;
  6452.  
  6453.     case TBN_RESET:
  6454.         _pcinfo->fDirty = FALSE;
  6455.         if (_pctCurrentButtonGroup)
  6456.         {
  6457.             NMTBCUSTOMIZEDLG *pnm = (NMTBCUSTOMIZEDLG*)pnmh;
  6458.             CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  6459.             TCHAR szGuid[GUIDSTR_MAX];
  6460.             SHStringFromGUID(_guidCurrentButtonGroup, szGuid, ARRAYSIZE(szGuid));
  6461.             SHDeleteValue(HKEY_CURRENT_USER, REGSTR_PATH_TOOLBAR, szGuid);
  6462.  
  6463.             // Default text labels setting should be as follows:
  6464.             //
  6465.             //  If fullscreen mode, any platform -- "No text labels"
  6466.             //  Else if NT5 -- "Selective text on right"
  6467.             //  Else  -- "Show text labels"
  6468.             //
  6469.             int idsDefault;
  6470.  
  6471.             if (pitbar->_fTheater)
  6472.                 idsDefault = IDS_NOTEXTLABELS;
  6473.             else if (DEFAULT_LIST_VALUE())
  6474.                 idsDefault = IDS_PARTIALTEXT;
  6475.             else
  6476.                 idsDefault = IDS_TEXTLABELS;
  6477.  
  6478.             _UpdateTextSettings(idsDefault);
  6479.  
  6480.             HWND hwnd = (HWND) GetProp(pnm->hDlg, SZ_PROP_CUSTDLG);
  6481.             if (hwnd)
  6482.             {
  6483.                 // update our dialog's control selection states
  6484.                 _SetDialogSelections(hwnd, _DefaultToSmallIcons());
  6485.             }
  6486.  
  6487.             _RemoveAllButtons();
  6488.             _OnEndCustomize();
  6489.             if (_pbtnsAdded)
  6490.             {
  6491.                 pitbar->AddButtons(&_guidCurrentButtonGroup, _cBtnsAdded, _pbtnsAdded);
  6492.  
  6493. #ifdef EDIT_HACK
  6494.                 // Restore the edit button
  6495.                 pitbar->_InitEditButtonStyle();
  6496. #endif
  6497.  
  6498.                 pitbar->_UpdateToolbar(TRUE);
  6499.             }
  6500.             else
  6501.             {
  6502.                 return TBNRF_ENDCUSTOMIZE;
  6503.             }
  6504.         }
  6505.         break;
  6506.  
  6507.     case TBN_QUERYINSERT:
  6508.         return TRUE;
  6509.  
  6510.     case TBN_QUERYDELETE:
  6511.         return (SendMessage(_hwnd, TB_ISBUTTONHIDDEN,
  6512.                             (WPARAM) ptbn->tbButton.idCommand,
  6513.                             (LPARAM) 0)) ? FALSE : TRUE;
  6514.  
  6515.     case TBN_GETBUTTONINFO:
  6516.         if (ptbn->iItem < DSA_GetItemCount(_pcinfo->hdsa))
  6517.         {
  6518.             CMDMAPCUSTOMIZE *pcmc;
  6519.             pcmc = (CMDMAPCUSTOMIZE*)DSA_GetItemPtr(_pcinfo->hdsa, ptbn->iItem);
  6520.             ptbn->tbButton = pcmc->btn;
  6521.             ptbn->tbButton.fsState &= ~TBSTATE_HIDDEN;
  6522.             return TRUE;
  6523.         }
  6524.         return FALSE;
  6525.  
  6526.     case TBN_BEGINADJUST:
  6527.         if (!_pcinfo || !_pcinfo->fAdjust)
  6528.             return 1;
  6529.         break;
  6530.  
  6531.     }
  6532.     return FALSE;
  6533. }
  6534.  
  6535. BOOL TOOLSBANDCLASS::_SaveRestoreToolbar(BOOL fSave)
  6536. {
  6537.     TBSAVEPARAMS tbsp;
  6538.     TCHAR szGuid[GUIDSTR_MAX];
  6539.     SHStringFromGUID(_guidCurrentButtonGroup, szGuid, ARRAYSIZE(szGuid));
  6540.  
  6541.     tbsp.hkr = HKEY_CURRENT_USER;
  6542.     tbsp.pszSubKey = REGSTR_PATH_TOOLBAR;
  6543.     tbsp.pszValueName = szGuid;
  6544.     BOOL fRet = BOOLFROMPTR(SendMessage(_hwnd, TB_SAVERESTORE, (WPARAM) fSave, (LPARAM) &tbsp));
  6545.  
  6546.     _FreeCustomizeInfo();
  6547.     return fRet;
  6548. }
  6549.  
  6550. int TOOLSBANDCLASS::_CommandFromIndex(UINT uIndex)
  6551. {
  6552.     TBBUTTONINFO tbbi;
  6553.     tbbi.cbSize = SIZEOF(tbbi);
  6554.     tbbi.dwMask = TBIF_COMMAND | TBIF_BYINDEX;
  6555.     SendMessage(_hwnd, TB_GETBUTTONINFO, uIndex, (LPARAM)&tbbi);
  6556.     return tbbi.idCommand;
  6557. }
  6558.  
  6559. //  _btb._ConvertCmd()
  6560. //  This is used to covert a external Command ID to an internal ID or vice versa
  6561. //  If we are converting to an external ID then
  6562. //      call with pguidButtonGroup == NULL                  (to external:  pguidButtonGroup == NULL)
  6563. //      otherwise call with the external button group GUID  (to internal:  pguidOut == NULL)
  6564. HRESULT TOOLSBANDCLASS::_ConvertCmd(const GUID* pguidButtonGroup, UINT id, GUID* pguidOut, UINT * pid)
  6565. {
  6566.     HRESULT hres = E_FAIL;
  6567.     BOOL fToInternal = (bool) (pguidButtonGroup);
  6568.  
  6569.     ASSERT((pguidButtonGroup == NULL) ^ (pguidOut == NULL));
  6570.  
  6571.     // First look for the command
  6572.     if (fToInternal && _hwnd) {
  6573.         int nCount = (int) SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0);
  6574.         for (int i = 0; i < nCount; i++) {
  6575.             CMDMAP *pcm = _GetCmdMapByIndex(i);
  6576.  
  6577.             if (pcm) {
  6578.                 ASSERT(pcm);
  6579.  
  6580.                 // loop through the command mapping structures until we
  6581.                 // find this guid and id
  6582.                 if (IsEqualGUID(pcm->guidButtonGroup, *pguidButtonGroup) &&
  6583.                     id == pcm->nCmdID) {
  6584.  
  6585.                     *pid = _CommandFromIndex(i);
  6586.                     hres = S_OK;
  6587.                     break;
  6588.                 }
  6589.             }
  6590.         }
  6591.  
  6592.     } else {
  6593.  
  6594.         // going from toolbar id to commandtarget info
  6595.         CMDMAP *pcm = _GetCmdMapByID(id);
  6596.         if (pcm) {
  6597.             *pguidOut = pcm->guidButtonGroup;
  6598.             *pid = pcm->nCmdID;
  6599.             hres = S_OK;
  6600.         }
  6601.     }
  6602.     return hres;
  6603. }
  6604.  
  6605.  
  6606.  
  6607. LRESULT CInternetToolbar::_AddBitmapFromForeignModule(UINT uiGetMSG, UINT uiSetMSG, UINT uiCount, HINSTANCE hinst, UINT_PTR nID, COLORREF rgbMask)
  6608. {
  6609.     HBITMAP hBMPRaw = NULL, hBMPFixedUp = NULL;
  6610.     HBITMAP * phBmp = &hBMPFixedUp;
  6611.     BITMAP bmp;
  6612.     HIMAGELIST himlTemp;
  6613.     LRESULT lRes = 1L;
  6614.     BOOL fOk = TRUE;
  6615.     HDC dc = NULL, dcMemSrc = NULL, dcMemDest = NULL;
  6616.     HBITMAP hbmpOldDest = NULL, hbmpOldSrc = NULL;
  6617.     int cxOrg = 0;
  6618.     int xDest = 0, yDest = 0;
  6619.     RECT rect = {0,0,0,0};
  6620.     HBRUSH hbr = NULL;
  6621.  
  6622.     // BUGBUG What if hinst == NULL?  That means that nID is really an HBITMAP
  6623.  
  6624.     if (!(hBMPRaw = LoadBitmap(hinst, MAKEINTRESOURCE(nID))))
  6625.         return 0L;
  6626.  
  6627.     fOk = (BOOL)(GetObject(hBMPRaw, sizeof(BITMAP), &bmp) != 0);
  6628.  
  6629.     // Check is the size is OK
  6630.     if (fOk && (bmp.bmWidth != (LONG)(TB_BMP_CX * uiCount)) || (bmp.bmHeight != (LONG)TB_BMP_CY) )
  6631.     {
  6632.         int cxBmp;
  6633.         int cyBmp;
  6634.  
  6635.         if (g_fSmallIcons) {
  6636.             cxBmp = TB_SMBMP_CX;
  6637.             cyBmp = TB_SMBMP_CY;
  6638.         } else {
  6639.             cxBmp = TB_BMP_CX;
  6640.             cyBmp = TB_BMP_CY;
  6641.         }
  6642.  
  6643.         // If the height is 15, the we assume that this is one of the old bitmaps therefore
  6644.         // the width is 16. We cannot rely on the (bmp.bmWidth / uiCount) because some apps
  6645.         // like SecureFile give us a bitmap 192 wide and say that there are 10 glyphs in it.
  6646.         if (bmp.bmHeight == 15)
  6647.             cxOrg = 16;
  6648.         else
  6649.             cxOrg = bmp.bmWidth / (uiCount ? uiCount : 1);
  6650.  
  6651.         if (rgbMask)
  6652.             fOk = (BOOL)((hbr = CreateSolidBrush(rgbMask))!= NULL);
  6653.  
  6654.         if (fOk)
  6655.             fOk = (BOOL)((dc = GetDC(_btb._hwnd)) != NULL);
  6656.  
  6657.         if (fOk)
  6658.             fOk = (BOOL)((hBMPFixedUp = CreateCompatibleBitmap(dc, (cxBmp * uiCount), cyBmp)) != NULL);
  6659.  
  6660.         if (fOk)
  6661.             fOk = (BOOL)((dcMemSrc = CreateCompatibleDC(dc)) != NULL);
  6662.  
  6663.         if (fOk)
  6664.             fOk = (BOOL)((dcMemDest = CreateCompatibleDC(dc)) != NULL);
  6665.  
  6666.         if (!fOk)
  6667.             goto Error;
  6668.  
  6669.         hbmpOldSrc = (HBITMAP)SelectObject(dcMemSrc, hBMPRaw);
  6670.         hbmpOldDest = (HBITMAP)SelectObject(dcMemDest, hBMPFixedUp);
  6671.  
  6672.         rect.right = (cxBmp * uiCount);
  6673.         rect.bottom = cyBmp;
  6674.         if (rgbMask)
  6675.             FillRect(dcMemDest, &rect, hbr);
  6676.  
  6677.         for (UINT n = 0; n < uiCount; n++)
  6678.         {
  6679.  
  6680.             int cxCopy;
  6681.             int cyCopy;
  6682.  
  6683.             xDest = (n * cxBmp);
  6684.             if (cxOrg < cxBmp) {
  6685.                 // if the bitmap is too small, we need to center it.
  6686.                 // the amount we copy is the full bitmap
  6687.                 cxCopy = cxOrg;
  6688.                 xDest += ((cxBmp - cxOrg) / 2);
  6689.             } else {
  6690.                 // if the bitmap is big enough, we align it to top left and
  6691.                 // we strecth(shrink) it down to fit
  6692.                 cxCopy = cxBmp;
  6693.             }
  6694.  
  6695.             if (bmp.bmHeight < cyBmp) {
  6696.                 cyCopy = bmp.bmHeight;
  6697.                 yDest = ((cyBmp - bmp.bmHeight) / 2);
  6698.             } else {
  6699.                 cyCopy = cyBmp;
  6700.                 yDest = 0;
  6701.             }
  6702.             StretchBlt(dcMemDest, xDest, yDest, cxOrg, bmp.bmHeight,
  6703.                    dcMemSrc, (cxOrg * n), 0, cxCopy, cyCopy, SRCCOPY);
  6704.  
  6705.         }
  6706.  
  6707.         SelectObject(dcMemDest, hbmpOldDest);
  6708.         SelectObject(dcMemSrc, hbmpOldSrc);
  6709.     }
  6710.     else
  6711.         phBmp = &hBMPRaw;
  6712.  
  6713.     if (!(himlTemp = (HIMAGELIST)SendMessage(_btb._hwnd, uiGetMSG, 0, 0L)))
  6714.     {
  6715.         TraceMsg(DM_ERROR, "CITBar::AddBitmaPFromForeignModulefailed");
  6716.         fOk = FALSE;
  6717.         goto Error;
  6718.     }
  6719.  
  6720.     if (rgbMask)
  6721.         lRes = ImageList_AddMasked(himlTemp, (HBITMAP)*phBmp, rgbMask);
  6722.     else
  6723.         lRes = ImageList_Add(himlTemp, (HBITMAP)*phBmp, NULL);
  6724.  
  6725.     if (lRes == -1)
  6726.     {
  6727.         TraceMsg(DM_ERROR, "CITBar::AddBitmaPFromForeignModulefailed");
  6728.         fOk = FALSE;
  6729.         goto Error;
  6730.     }
  6731.  
  6732.  
  6733.     if (!SendMessage(_btb._hwnd, uiSetMSG, 0, (LPARAM)himlTemp))
  6734.     {
  6735.         TraceMsg(DM_ERROR, "CITBar::AddBitmaPFromForeignModulefailed");
  6736.         fOk = FALSE;
  6737.         goto Error;
  6738.     }
  6739.  
  6740. Error:
  6741.     if (hBMPFixedUp)
  6742.         DeleteObject(hBMPFixedUp);
  6743.  
  6744.     if (hBMPRaw)
  6745.         DeleteObject(hBMPRaw);
  6746.  
  6747.     if (dc)
  6748.         ReleaseDC(_btb._hwnd, dc);
  6749.  
  6750.     if (dcMemSrc)
  6751.         DeleteDC(dcMemSrc);
  6752.  
  6753.     if (dcMemDest)
  6754.         DeleteDC(dcMemDest);
  6755.  
  6756.     if (hbr)
  6757.         DeleteObject(hbr);
  6758.  
  6759.     if (!fOk)
  6760.         lRes = 0L;
  6761.  
  6762.     return lRes;
  6763. }
  6764.  
  6765. #define VERY_HIGH_NUMBER    4000
  6766. HRESULT CInternetToolbar::_LoadDefaultSettings()
  6767. {
  6768.     memset(&_cs, 0, sizeof(COOLBARSAVE));
  6769.     _cs.cbVer       = CBS_VERSION;
  6770.  
  6771.     _cs.bs[0].wID    = CBIDX_MENU;
  6772.     _cs.bs[0].cx     = VERY_HIGH_NUMBER;
  6773.  
  6774.     _cs.bs[1].wID    = CBIDX_BRAND;
  6775.  
  6776.     _cs.bs[2].wID    = CBIDX_TOOLS;
  6777.     _cs.bs[2].cx     = VERY_HIGH_NUMBER;
  6778.     _cs.bs[2].fStyle = RBBS_BREAK;
  6779.  
  6780.     _cs.bs[3].wID    = CBIDX_ADDRESS;
  6781.     _cs.bs[3].cx     = VERY_HIGH_NUMBER;
  6782.     _cs.bs[3].fStyle = RBBS_BREAK;
  6783.  
  6784.     _cs.bs[4].wID    = CBIDX_LINKS;
  6785.  
  6786.     if (!_fInitialPidlIsWeb) {
  6787.         // we're in shell view, or we're rooted.  for perf,
  6788.         // don't bother creating the links band.
  6789.         _cs.uiVisible = (VBF_MENU | VBF_TOOLS | VBF_ADDRESS | VBF_BRAND);
  6790.     } else {
  6791.         // web page
  6792.         _cs.uiVisible = (VBF_MENU | VBF_TOOLS | VBF_ADDRESS | VBF_LINKS | VBF_BRAND);
  6793.     }
  6794.  
  6795.     _cs.clsidVerticalBar = GUID_NULL;
  6796.     _cs.clsidHorizontalBar = GUID_NULL;
  6797.     _cs.fNoText = FALSE;
  6798.     _cs.fList = DEFAULT_LIST_VALUE();
  6799.  
  6800.     _fUsingDefaultBands = TRUE;
  6801.  
  6802.     return(NOERROR);
  6803. }
  6804.  
  6805. typedef struct tagCOOLBARSAVEv12    // IE4
  6806. {
  6807.     UINT        cbVer;
  6808.     UINT        uiMaxTBWidth;
  6809.     UINT        uiMaxQLWidth;
  6810. #ifdef UNIX
  6811.     BITBOOL     fUnUsed : 28;       // unused
  6812. #endif
  6813.     BOOL        fVertical : 1;      // The bar is oriented vertically
  6814.     BOOL        fNoText :1;         // "NoText"
  6815.     BOOL        fAutoHide : 1;      // Auto hide toolbar in theater mode
  6816.     BOOL        fStatusBar : 1;     // Status bar in theater mode
  6817.     BOOL        fSaveInShellIntegrationMode : 1;     // Did we save in shell
  6818.     UINT        uiVisible;          // "Visible bands"
  6819.     UINT        cyRebar;
  6820.     BANDSAVE    bs[5];
  6821. } COOLBARSAVEv12;
  6822.  
  6823. typedef struct tagCOOLBARSAVEv15    // IE5 Beta2
  6824. {
  6825.     UINT        cbVer;
  6826.     UINT        uiMaxTBWidth;
  6827.     UINT        uiMaxQLWidth;
  6828. #ifdef UNIX
  6829.     BITBOOL     fUnUsed : 28;       // unused
  6830. #endif
  6831.     BITBOOL     fVertical : 1;      // The bar is oriented vertically
  6832.     BITBOOL     fNoText :1;         // "NoText"
  6833.     BITBOOL     fList : 1;          // toolbar is TBSTYLE_LIST (text on right) + TBSTYLE_EX_MIXEDBUTTONS
  6834.     BITBOOL     fAutoHide : 1;      // Auto hide toolbar in theater mode
  6835.     BITBOOL     fStatusBar : 1;     // Status bar in theater mode
  6836.     BITBOOL     fSaveInShellIntegrationMode : 1;     // Did we save in shell integration mode?
  6837.     UINT        uiVisible;          // "Visible bands"
  6838.     UINT        cyRebar;
  6839.     BANDSAVE    bs[5];
  6840.     CLSID       clsidVerticalBar;       //clsid of bar persisted within vertical band
  6841.     CLSID       clsidHorizontalBar;
  6842. } COOLBARSAVEv15;
  6843.  
  6844. #define CB_V12  (sizeof(COOLBARSAVEv12))
  6845. #define CB_V13  (sizeof(COOLBARSAVEv15))
  6846. #define CB_V14  CB_V13          // 14: added fList:1 (in middle!)
  6847. #define CB_V15  CB_V14          // 15: new rbbi.fStyle semantics
  6848. #define CB_V17  (sizeof(COOLBARSAVE))
  6849.  
  6850. HRESULT CInternetToolbar::_LoadUpgradeSettings(ULONG cbRead)
  6851. {
  6852.     // If we shipped with the CBS_VERSION you're incrementing, you need
  6853.     // to add upgrade code here for that version, then update this assertion.
  6854.     COMPILETIME_ASSERT(CBS_VERSION == 17);
  6855.  
  6856.     // Double-check our size calculations.
  6857. #ifndef UNIX
  6858.     COMPILETIME_ASSERT(CB_V12 == (6 * sizeof(UINT) + CBIDX_LAST * sizeof(BANDSAVE)));
  6859. #endif
  6860.     COMPILETIME_ASSERT(CB_V12 == (CB_V15 - SIZEOF(CLSID) * 2));
  6861.     COMPILETIME_ASSERT(CB_V13 == (CB_V12 + 2 * sizeof(CLSID)));
  6862.     COMPILETIME_ASSERT(CB_V14 == (CB_V13 + 0));
  6863.     COMPILETIME_ASSERT(CB_V15 == (CB_V14 + 0));
  6864.     COMPILETIME_ASSERT(CB_V17 == (CB_V15 + (MAXEXTERNALBANDS * sizeof(BANDSAVE)) + (MAXEXTERNALBANDS * sizeof(CLSID))));
  6865.  
  6866.     // If the stream was shorter than the version data field, there's nothing we can do.
  6867.     if (cbRead < SIZEOF(_cs.cbVer))
  6868.     {
  6869.         return E_FAIL;
  6870.     }
  6871.  
  6872.     // Check to see if the version is one we know about and that the stream
  6873.     // size is the same as that version's structure size.
  6874.     if (!((_cs.cbVer == 12 && cbRead == CB_V12) ||      // IE4
  6875.           (_cs.cbVer == 13 && cbRead == CB_V13) ||      // ?
  6876.           (_cs.cbVer == 14 && cbRead == CB_V14) ||      // ?
  6877.           (_cs.cbVer == 15 && cbRead == CB_V15)))       // IE5 Beta2
  6878.     {
  6879.         return E_FAIL;
  6880.     }
  6881.  
  6882.     TraceMsg(DM_WARNING, "citb._lus: try upgrade %d->%d", _cs.cbVer, CBS_VERSION);
  6883.  
  6884.     // Make a scratch copy of _cs so we don't worry about overwriting
  6885.     // parts of _cs we need to read later.
  6886.     COOLBARSAVE cs = _cs;
  6887.  
  6888.     if (_cs.cbVer == 12)
  6889.     {
  6890.         // clsidVerticalBar/clsidHorizontalBar weren't a part
  6891.         // of the structure until v13
  6892.         cs.clsidVerticalBar = GUID_NULL;
  6893.         cs.clsidHorizontalBar = GUID_NULL;
  6894.     }
  6895.     else
  6896.     {
  6897.         ASSERT(_cs.cbVer < 16);
  6898.  
  6899.         // Band array (bs) grew in v16 to include external bands, so
  6900.         // clsidVerticalBar/clsidHorizontalBar were at a different offset.
  6901.         COOLBARSAVEv15 *pv15 = (COOLBARSAVEv15 *) &_cs;
  6902.         cs.clsidVerticalBar = pv15->clsidVerticalBar;
  6903.         cs.clsidHorizontalBar = pv15->clsidHorizontalBar;
  6904.         cs.bs[CBIDX_LAST].wID = 0xFFFFFFFF;
  6905.     }
  6906.  
  6907.     if (InRange(_cs.cbVer, 12, 13))
  6908.     {
  6909.         // fList was inserted into the middle of the bitbool list in v14.
  6910.         // Copy the displaced bitbools and initialize fList.
  6911.         COOLBARSAVEv12 *pv12 = (COOLBARSAVEv12 *) &_cs;
  6912.         cs.fAutoHide = pv12->fAutoHide;
  6913.         cs.fStatusBar = pv12->fStatusBar;
  6914.         cs.fSaveInShellIntegrationMode = pv12->fSaveInShellIntegrationMode;
  6915.         cs.fList = DEFAULT_LIST_VALUE();
  6916.     }
  6917.  
  6918.     // Force FALSE as no longer support vertical itbar mode.
  6919.     cs.fVertical = FALSE;
  6920.  
  6921.     // Strip off any invalid visible band bits
  6922.     cs.uiVisible &= VBF_VALID;
  6923.  
  6924.     // Set current version and copy scratch cs back to _cs
  6925.     cs.cbVer = CBS_VERSION;
  6926.     _cs = cs;
  6927.  
  6928.     return S_OK;
  6929. }
  6930.  
  6931. HRESULT CInternetToolbar::_LoadDefaultWidths()
  6932. {
  6933.     // If there was no max width set for the QL bar or the Toolbar, then
  6934.     // before we use the default, check it the localization people wanted to
  6935.     // increase the width. The RC file string range from '0' to '9'
  6936.     TCHAR szScratch[16];
  6937.     UINT uiExtraWidth = 0;
  6938.  
  6939.     if (GetSystemMetrics(SM_CXSCREEN) < 650) {
  6940.         MLLoadString(IDS_TB_WIDTH_EXTRA_LORES, szScratch, ARRAYSIZE(szScratch));
  6941.         _uiMaxTBWidth = MAX_TB_WIDTH_LORES;
  6942.     } else {
  6943.         MLLoadString(IDS_TB_WIDTH_EXTRA_HIRES, szScratch, ARRAYSIZE(szScratch));
  6944.         _uiMaxTBWidth = MAX_TB_WIDTH_HIRES;
  6945.     }
  6946.     _uiMaxTBWidth += StrToInt(szScratch) * WIDTH_FACTOR;
  6947.  
  6948.  
  6949.     return(NOERROR);
  6950. }
  6951.  
  6952. BOOL IsClsidInHKCR(REFGUID pclsid)
  6953. {
  6954.     HKEY hkeyResult;
  6955.  
  6956.     if (SHRegGetCLSIDKeyW(pclsid, NULL, FALSE, FALSE, &hkeyResult) == ERROR_SUCCESS)
  6957.     {
  6958.         RegCloseKey(hkeyResult);
  6959.         return TRUE;
  6960.     }
  6961.     return FALSE;
  6962. }
  6963.  
  6964. typedef struct tagCOOLBARSAVEv2     // IE3
  6965. {
  6966.     UINT        cbVer;
  6967.     UINT        uiMaxTBWidth;
  6968.     UINT        uiMaxQLWidth;
  6969.     BOOL        fVertical;             // The bar is oriented vertically
  6970.     BANDSAVE    bs[4];
  6971. } COOLBARSAVEv2;
  6972.  
  6973. #define VBF_VALIDv2               (VBF_TOOLS | VBF_ADDRESS | VBF_LINKS)
  6974.  
  6975. void CInternetToolbar::_TryLoadIE3Settings()
  6976. {
  6977.     HKEY hKey;
  6978.  
  6979.     if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegKeyCoolbar, 0, KEY_QUERY_VALUE, &hKey))
  6980.     {
  6981.         COOLBARSAVEv2 cbv2;
  6982.         DWORD dwcbData = SIZEOF(cbv2);
  6983.         if (SHQueryValueEx(hKey, TEXT("Layout"), NULL, NULL, (LPBYTE)&cbv2, &dwcbData) == ERROR_SUCCESS)
  6984.         {
  6985.             _cs.uiMaxTBWidth = cbv2.uiMaxTBWidth;
  6986.             _cs.uiMaxQLWidth = cbv2.uiMaxQLWidth;
  6987.             // BUGBUG: todo -- read in bs field too; need to do some conversions as
  6988.             // CBIDX_ numbers were zero-based and there was no menuband in IE3.
  6989.         }
  6990.  
  6991.         BOOL fNoText;
  6992.         dwcbData = SIZEOF(fNoText);
  6993.         if (SHQueryValueEx(hKey, TEXT("NoText"), NULL, NULL, (LPBYTE)&fNoText, &dwcbData) == ERROR_SUCCESS)
  6994.         {
  6995.             // Set the no-text flag.
  6996.             _cs.fNoText = BOOLIFY(fNoText);
  6997.         }
  6998.  
  6999.         UINT uiVisible;
  7000.         dwcbData = SIZEOF(uiVisible);
  7001.         if (SHQueryValueEx(hKey, TEXT("VisibleBands"), NULL, NULL, (LPBYTE)&uiVisible, &dwcbData) == ERROR_SUCCESS)
  7002.         {
  7003.             // Set the visible bands, changing only the ones that IE3 knew about.
  7004.             _cs.uiVisible = (_cs.uiVisible &~ VBF_VALIDv2) | (uiVisible & VBF_VALIDv2);
  7005.         }
  7006.  
  7007.         RegCloseKey(hKey);
  7008.     }
  7009. }
  7010.  
  7011. HRESULT CInternetToolbar::Load(IStream *pstm)
  7012. {
  7013.     ULONG  ulRead;
  7014.  
  7015.     //Read from the given stream and initialize the Toolbar data!
  7016.  
  7017.     _fLoading = TRUE;
  7018.  
  7019.     HRESULT hr = pstm->Read(&_cs, sizeof(COOLBARSAVE), &ulRead);
  7020.  
  7021.     if (SUCCEEDED(hr))
  7022.     {
  7023.         if (ulRead != sizeof(COOLBARSAVE) || _cs.cbVer != CBS_VERSION)
  7024.             hr = _LoadUpgradeSettings(ulRead);
  7025.     }
  7026.  
  7027.     if (FAILED(hr))
  7028.     {
  7029.         _LoadDefaultSettings();
  7030.     }
  7031.  
  7032.     ASSERT(_cs.uiVisible & VBF_MENU);
  7033.     // make sure that the settings include a menu
  7034.     _cs.uiVisible |= VBF_MENU;
  7035.  
  7036.     _LoadDefaultWidths();
  7037.     _CreateBands();
  7038.  
  7039.     //if in web view, show the last visible browser bars too
  7040.     if (!_fShellView)
  7041.     {
  7042.         VARIANT varOut = {0};
  7043.         varOut.vt = VT_I4;
  7044.  
  7045.         if (!IsEqualGUID(_cs.clsidVerticalBar, GUID_NULL) && IsClsidInHKCR(_cs.clsidVerticalBar))
  7046.         {
  7047. #ifdef UNIX
  7048.             // IEUNIX: Donot persist/load MsgBand
  7049.             if (!IsEqualGUID(_cs.clsidVerticalBar, CLSID_MsgBand))
  7050. #endif
  7051.             if (!IsEqualGUID(_cs.clsidVerticalBar, CLSID_SearchBand) &&
  7052.                 !IsEqualGUID(_cs.clsidVerticalBar, CLSID_FileSearchBand))
  7053.             {
  7054.                 WCHAR wsz[GUIDSTR_MAX];
  7055.                 SHStringFromGUID((const CLSID)_cs.clsidVerticalBar, wsz, ARRAYSIZE(wsz));
  7056.  
  7057.                 VARIANT varClsid;
  7058.                 varClsid.vt = VT_BSTR;
  7059.                 varClsid.bstrVal = wsz;
  7060.  
  7061.                 IUnknown_Exec(_pbs2, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR, 1, &varClsid, &varOut);
  7062.             }
  7063.             else
  7064.             {
  7065.                 //if it's the search band, must be shown in this way to get correct search
  7066.                 VARIANTARG var;
  7067.                 var.vt = VT_I4;
  7068.                 var.lVal = -1;
  7069.  
  7070.                 Exec(&CLSID_CommonButtons, TBIDM_SEARCH, 0, NULL, &var);
  7071.             }
  7072.         }
  7073.  
  7074.         if (!IsEqualGUID(_cs.clsidHorizontalBar, GUID_NULL) && IsClsidInHKCR(_cs.clsidHorizontalBar))
  7075.         {
  7076.             WCHAR wsz[GUIDSTR_MAX];
  7077.             SHStringFromGUID((const CLSID)_cs.clsidHorizontalBar, wsz, ARRAYSIZE(wsz));
  7078.  
  7079.             VARIANT varClsid;
  7080.             varClsid.vt = VT_BSTR;
  7081.             varClsid.bstrVal = wsz;
  7082.  
  7083.             IUnknown_Exec(_pbs2, &CGID_ShellDocView, SHDVID_SHOWBROWSERBAR, 1, &varClsid, &varOut);
  7084.         }
  7085.     }
  7086.     _fLoading = FALSE;
  7087.  
  7088.     return(S_OK);
  7089. }
  7090.  
  7091. //see APPHACK note below
  7092. const GUID CLSID_AlexaVert = { 0xBA0B386CL, 0x7143, 0x11d1, 0xba, 0x8c, 0x00, 0x60, 0x08, 0x27, 0x87, 0x8d };
  7093. const GUID CLSID_AlexaHorz = { 0xBA0B386EL, 0x7143, 0x11d1, 0xba, 0x8c, 0x00, 0x60, 0x08, 0x27, 0x87, 0x8d };
  7094.  
  7095. void CInternetToolbar::_GetVisibleBrowserBar(UINT idBar, CLSID *pclsidOut)
  7096. {
  7097.     *pclsidOut = GUID_NULL;
  7098.  
  7099.     ASSERT(idBar == IDBAR_VERTICAL || idBar == IDBAR_HORIZONTAL);
  7100.  
  7101.     IDockingWindowFrame *psb;
  7102.     if (_psp && SUCCEEDED(_psp->QueryService(SID_STopLevelBrowser, IID_IDockingWindowFrame, (void**)&psb)))
  7103.     {
  7104.         IDeskBar* pdb;
  7105.  
  7106.         if ( (IDBAR_VERTICAL   == idBar && (SUCCEEDED(psb->FindToolbar(INFOBAR_TBNAME, IID_IDeskBar, (void **)&pdb)) && pdb)) ||
  7107.              (IDBAR_HORIZONTAL == idBar && (SUCCEEDED(psb->FindToolbar(COMMBAR_TBNAME, IID_IDeskBar, (void **)&pdb)) && pdb)) )
  7108.         {
  7109.             VARIANT varClsid = {0};
  7110.  
  7111.             if (SUCCEEDED(IUnknown_Exec(pdb, &CGID_DeskBarClient, DBCID_CLSIDOFBAR, 1, NULL, &varClsid)))
  7112.             {
  7113.                 if (varClsid.vt == VT_BSTR)
  7114.                 {
  7115.                     GUIDFromString(varClsid.bstrVal, pclsidOut);
  7116.                     VariantClear(&varClsid);
  7117.                 }
  7118.  
  7119. //APPHACK
  7120. // Alexa 3.0 has some code so that their explorer bar persists that works in ie4. however, when ie5
  7121. // persists them, they don't handle the case where the main page has not finished loading yet, which
  7122. // causes them to fault on launch of the browser. see IE5 55895.
  7123.                 if ( (IDBAR_VERTICAL   == idBar && (IsEqualGUID(*pclsidOut, CLSID_AlexaVert))) ||
  7124.                      (IDBAR_HORIZONTAL == idBar && (IsEqualGUID(*pclsidOut, CLSID_AlexaHorz))) )
  7125.                 {
  7126.                     *pclsidOut = GUID_NULL;
  7127.                 }
  7128. //END APPHACK
  7129.             }
  7130.  
  7131.             pdb->Release();
  7132.         }
  7133.         psb->Release();
  7134.     }
  7135. }
  7136.  
  7137. void CInternetToolbar::_BuildSaveStruct(COOLBARSAVE* pcs)
  7138. {
  7139.     REBARBANDINFO   rbbi;
  7140.     RECT rc;
  7141.     static BOOL fBrowserOnly = (WhichPlatform() != PLATFORM_INTEGRATED);
  7142.  
  7143.     //Save into the given stream!
  7144.     memset(pcs, 0, sizeof(COOLBARSAVE));
  7145.     pcs->cbVer = CBS_VERSION;
  7146.  
  7147.     // Browser Only can't load Shell Integrated streams because of the Favorites
  7148.     // shell extension created pidls unreadable by browser only which doesn't have the Favorites ShellExt
  7149.     pcs->fSaveInShellIntegrationMode = !fBrowserOnly;
  7150.  
  7151.     GetWindowRect(_bs._hwnd, &rc);
  7152.     pcs->cyRebar = RECTHEIGHT(rc);
  7153.     //Save the new fields.
  7154.     pcs->fAutoHide = _fAutoHide;
  7155.     pcs->fNoText = _fCompressed;
  7156.     pcs->fList = IS_LIST_STYLE(_btb._hwnd);
  7157.     pcs->uiVisible = _nVisibleBands;
  7158.  
  7159.     //only persist the visible bars for web view
  7160.     if (!_fShellView)
  7161.     {
  7162.         _GetVisibleBrowserBar(IDBAR_VERTICAL, &pcs->clsidVerticalBar);
  7163.         _GetVisibleBrowserBar(IDBAR_HORIZONTAL, &pcs->clsidHorizontalBar);
  7164.     }
  7165.     //else pcs->clsid*Bar nulled out by memset above
  7166.  
  7167.     LRESULT lStyle = GetWindowLong(_bs._hwnd, GWL_STYLE);
  7168.     pcs->fVertical = BOOLIFY(lStyle & CCS_VERT);
  7169.  
  7170.     pcs->uiMaxTBWidth = _uiMaxTBWidth;
  7171.  
  7172.     rbbi.cbSize = sizeof(REBARBANDINFO);
  7173.     rbbi.fMask = RBBIM_STYLE | RBBIM_SIZE | RBBIM_ID;
  7174.     int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
  7175.     for (int i = 0; i < icBands; i++)
  7176.     {
  7177.         pcs->bs[i].wID = 0xFFFFFFFF;
  7178.         if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  7179.         {
  7180.             if (rbbi.wID < CBANDSMAX)
  7181.             {
  7182.                 // desk band objects have the choice of not saving there visibility
  7183.                 // state
  7184.                 BANDITEMDATA *pbid = _bs._GetBandItem( i );
  7185.                 UINT uiMask = rbbi.wID <= CBIDX_LAST ? ( 1 << (rbbi.wID - 1) ) : EXTERNALBAND_VBF_BIT(rbbi.wID - CBIDX_LAST-1);
  7186.                 if (pbid && pbid->pdb && (pcs->uiVisible & uiMask))
  7187.                 {
  7188.                     OLECMD cmd;
  7189.                     cmd.cmdID = CITIDM_DISABLEVISIBILITYSAVE;
  7190.                     cmd.cmdf = 0;
  7191.                     IUnknown_QueryStatus( pbid->pdb, &CGID_PrivCITCommands, 1, &cmd, NULL );
  7192.                     if ( cmd.cmdf &  OLECMDF_ENABLED )
  7193.                     {
  7194.                         pcs->uiVisible &= ~uiMask;
  7195.                         rbbi.fStyle |= RBBS_HIDDEN;
  7196.                     }
  7197.                 }
  7198.                 pcs->bs[i].fStyle = rbbi.fStyle;
  7199.                 pcs->bs[i].cx = rbbi.cx;
  7200.                 pcs->bs[i].wID = rbbi.wID;
  7201.                 if (IS_EXTERNALBAND(rbbi.wID))
  7202.                 {
  7203.                     pcs->aclsidExternalBands[MAP_TO_EXTERNAL(rbbi.wID)] = _rgebi[MAP_TO_EXTERNAL(rbbi.wID)].clsid;
  7204.                 }
  7205.             }
  7206.         }
  7207.     }
  7208.     // Query CShellBrowser for status bar state
  7209.     VARIANTARG v = { 0 };
  7210.     v.vt = VT_I4;
  7211.     IUnknown_Exec(_ptbsite, &CGID_ShellBrowser, FCIDM_GETSTATUSBAR,
  7212.         0, NULL, &v);
  7213.     pcs->fStatusBar = v.lVal;
  7214. }
  7215.  
  7216. typedef struct tagCLSID_BANDTYPE
  7217. {
  7218.     const CLSID * pclsid;
  7219.     DWORD dwBandID;
  7220. } CLSID_BANDTYPE;
  7221.  
  7222. CLSID_BANDTYPE c_CLSIDsToSave[] =
  7223. {
  7224.     {&CLSID_AddressBand, CBIDX_ADDRESS},
  7225.     {&CLSID_QuickLinks, CBIDX_LINKS},
  7226. };
  7227.  
  7228. HRESULT CInternetToolbar::Save(IStream *pstm, BOOL fClearDirty)
  7229. {
  7230.     COOLBARSAVE cs;
  7231.     HRESULT hr = S_FALSE;
  7232.  
  7233.     // avoid the hit of saving when we are still loading.  State will not have
  7234.     // changed, at least not enough to justify saving, until after we are loaded.
  7235.     if (_fLoading)
  7236.         return(S_OK);
  7237.  
  7238.     //Check the dirty bit to see if we need to save.
  7239.     if(!_fDirty)
  7240.         return(S_OK);
  7241.  
  7242.     ASSERT(!_fTheater);
  7243.     _BuildSaveStruct(&cs);
  7244.  
  7245.     if(SUCCEEDED(hr = pstm->Write(&cs, sizeof(COOLBARSAVE), NULL)) && fClearDirty)
  7246.         _fDirty = FALSE;
  7247.  
  7248.     REBARBANDINFO rbbi;
  7249.     rbbi.cbSize = sizeof(REBARBANDINFO);
  7250.     rbbi.fMask = RBBIM_ID;
  7251.  
  7252.     int icBands = (int) SendMessage( _bs._hwnd, RB_GETBANDCOUNT, 0, 0 );
  7253.     for (int i = 0; i < icBands; i++)
  7254.     {
  7255.         if (SendMessage(_bs._hwnd, RB_GETBANDINFO, i, (LPARAM) &rbbi))
  7256.         {
  7257.             if ((rbbi.wID == CBIDX_ADDRESS) || (rbbi.wID == CBIDX_LINKS) || IS_EXTERNALBAND(rbbi.wID))
  7258.             {
  7259.                 BANDITEMDATA *pbid = _bs._GetBandItem( i );
  7260.                 if (pbid && pbid->pdb) {
  7261.                     CLSID clsid;
  7262.                     IPersistStream *pStream;
  7263.                     if (SUCCEEDED(pbid->pdb->QueryInterface( IID_IPersistStream, (LPVOID *) &pStream ))) {
  7264.                         pStream->GetClassID( &clsid );
  7265.                         IStream * pstm;
  7266.                         TCHAR szGUID[MAX_PATH];
  7267.                         SHStringFromGUID( clsid, szGUID, ARRAYSIZE(szGUID) );
  7268.                         pstm = GetRegStream( _fInitialPidlIsWeb, szGUID, STGM_WRITE | STGM_CREATE );
  7269.                         if (pstm)
  7270.                         {
  7271.                             HRESULT hrInternal = _bs.SaveToStreamBS(pbid->pdb, pstm);
  7272.  
  7273.                             // Only return Success values
  7274.                             if (SUCCEEDED(hrInternal))
  7275.                                 hr = S_OK;
  7276.                             pstm->Release();
  7277.                         }
  7278.                         pStream->Release();
  7279.                     }
  7280.                 }
  7281.             }
  7282.         }
  7283.     }
  7284.     return(hr);
  7285. }
  7286.  
  7287. HRESULT CInternetToolbar::InitNew(void)
  7288. {
  7289.     // This shouldn't get called if Load has already been called, so assert
  7290.     // that _cs is uninitialized.
  7291.     ASSERT(_cs.cbVer == 0);
  7292.  
  7293.     _LoadDefaultSettings();
  7294.  
  7295.     // Look for any IE3 settings and override defaults with those.  (IE3
  7296.     // wrote structures directly to registry, rather than via IPersistStream).
  7297.     _TryLoadIE3Settings();
  7298.  
  7299.     _LoadDefaultWidths();
  7300.  
  7301.     return S_OK;
  7302. }
  7303.  
  7304. BOOL CInternetToolbar::_SendToToolband(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plres)
  7305. {
  7306.     return _bs._SendToToolband(hwnd, uMsg, wParam, lParam, plres);
  7307. }
  7308.  
  7309.  
  7310. HRESULT CInternetToolbar::IsDirty(void)
  7311. {
  7312.     if (_fDirty)
  7313.         return S_OK;
  7314.     else
  7315.         return S_FALSE;
  7316. }
  7317.  
  7318.  
  7319. HRESULT CInternetToolbar::QueryService(REFGUID guidService,
  7320.                                        REFIID riid, void **ppvObj)
  7321. {
  7322.     HRESULT hres = E_NOTIMPL;
  7323.  
  7324.     if (IsEqualIID(guidService, SID_IBandProxy))
  7325.     {
  7326.         hres = QueryService_SID_IBandProxy(SAFECAST(_ptbsitect, IUnknown *), riid, &_pbp, ppvObj);
  7327.         if(!_pbp)
  7328.         {
  7329.             // We need to create it ourselves since our parent couldn't help
  7330.             ASSERT(FALSE == _fCreatedBandProxy);
  7331.  
  7332.             hres = CreateIBandProxyAndSetSite(SAFECAST(_ptbsitect, IUnknown *), riid, &_pbp, ppvObj);
  7333.             if(_pbp)
  7334.             {
  7335.                 ASSERT(S_OK == hres);
  7336.                 _fCreatedBandProxy = TRUE;
  7337.             }
  7338.         }
  7339.         return hres;
  7340.     }
  7341.     else if (IsEqualGUID(guidService, IID_IBandSite))
  7342.     {
  7343.         return _bs.QueryInterface(riid, ppvObj);
  7344.     }
  7345.     else if (IsEqualGUID(guidService, IID_IAddressBand))
  7346.     {
  7347.         LPBANDITEMDATA pbid = _bs._GetBandItemDataStructByID(CBIDX_ADDRESS);
  7348.  
  7349.         ASSERT(pbid && pbid->pdb);     // pbid->pdb is a IDeskBand pointer
  7350.         if (pbid && pbid->pdb)
  7351.         {
  7352.             return pbid->pdb->QueryInterface(riid, ppvObj);
  7353.         }
  7354.         else
  7355.         {
  7356.             *ppvObj = NULL;
  7357.             return E_FAIL;
  7358.         }
  7359.     }
  7360.  
  7361.     if (_psp)
  7362.         return _psp->QueryService(guidService, riid, ppvObj);
  7363.  
  7364.  
  7365.     return SUPERCLASS::QueryService(guidService, riid, ppvObj);
  7366. }
  7367.  
  7368. //
  7369. // BUGBUG: Do we really need to implement the following two functions?
  7370. // Currently nobody uses them.
  7371. //
  7372. HRESULT CInternetToolbar::GetClassID(GUID *pguid)
  7373. {
  7374.     *pguid = CLSID_InternetToolbar;
  7375.     return(S_OK);
  7376. }
  7377.  
  7378. HRESULT CInternetToolbar::GetSizeMax(ULARGE_INTEGER *ulMaxSize)
  7379. {
  7380.     ulMaxSize->LowPart = sizeof(COOLBARSAVE);
  7381.     ulMaxSize->HighPart = 0;
  7382.     return(S_OK);
  7383. }
  7384.  
  7385.  
  7386. CInternetToolbar::CITBandSite::CITBandSite() : CBandSite(NULL)
  7387. {
  7388.     // HACKHACK: set the initial band ID to something bigger
  7389.     //           than the number of toolbars that is in this
  7390.     //           object.  Currently those toolbars are not
  7391.     //           individual bands, but we want CBandSite to
  7392.     //           at least be aware of them.
  7393.     //
  7394.     _dwBandIDNext = CBANDSMAX;
  7395. }
  7396.  
  7397. HRESULT CInternetToolbar::CITBandSite::_OnContextMenu(WPARAM wParam, LPARAM lParam)
  7398. {
  7399.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
  7400.     pitbar->_ShowContextMenu((HWND)wParam, lParam, NULL);
  7401.     return S_OK;
  7402. }
  7403.  
  7404. HRESULT CInternetToolbar::CITBandSite::_Initialize(HWND hwndParent)
  7405. {
  7406.     _hwnd = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL,
  7407.                            RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_REGISTERDROP | RBS_DBLCLKTOGGLE |
  7408.                            WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN |
  7409.                            WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NOPARENTALIGN,
  7410.                            0, 0, 100, 36, hwndParent, (HMENU) FCIDM_REBAR, HINST_THISDLL, NULL);
  7411.  
  7412.     if (_hwnd)
  7413.     {
  7414.         SendMessage(_hwnd, RB_SETTEXTCOLOR, 0, CLR_DEFAULT);
  7415.         SendMessage(_hwnd, RB_SETBKCOLOR, 0, CLR_DEFAULT);
  7416.         SendMessage(_hwnd, CCM_SETVERSION, COMCTL32_VERSION, 0);
  7417.     }
  7418.  
  7419.     return CBandSite::_Initialize(hwndParent);
  7420. }
  7421.  
  7422.  
  7423. HRESULT CInternetToolbar::CITBandSite::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
  7424.     DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  7425. {
  7426.     if (!pguidCmdGroup) {
  7427.         /*NOTHING*/
  7428.     } else if (IsEqualGUID(CGID_PrivCITCommands, *pguidCmdGroup)) {
  7429.  
  7430.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
  7431.         return pitbar->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7432.     }
  7433.     else if (IsEqualGUID(CGID_Theater, *pguidCmdGroup))
  7434.     {
  7435.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
  7436.         return IUnknown_Exec(pitbar->_ptbsite, pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7437.     }
  7438.     return CBandSite::Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvarargIn, pvarargOut);
  7439. }
  7440.  
  7441. HRESULT CInternetToolbar::CITBandSite::AddBand(IUnknown *punk)
  7442. {
  7443.     HRESULT hres = CBandSite::AddBand(punk);
  7444.     if (SUCCEEDED(hres)) {
  7445.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
  7446.         pitbar->_SetBackground();
  7447.     }
  7448.     return hres;
  7449. }
  7450.  
  7451. HRESULT CInternetToolbar::CITBandSite::HasFocusIO()
  7452. {
  7453.     HRESULT hres = CBandSite::HasFocusIO();
  7454.     if (hres == S_FALSE) {
  7455.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _bs, this);
  7456.         if (pitbar->_btb._hwnd == GetFocus())
  7457.             hres = S_OK;
  7458.  
  7459.     }
  7460.     return hres;
  7461. }
  7462.  
  7463. // This will remove all the buttons except the first 2
  7464. BOOL TOOLSBANDCLASS::_RemoveAllButtons()
  7465. {
  7466.     INT_PTR nCount = SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
  7467.  
  7468.     if (!nCount)
  7469.         return FALSE;
  7470.  
  7471.     while (nCount-- > 0)
  7472.     {
  7473.         SendMessage(_hwnd, TB_DELETEBUTTON, nCount, 0L);
  7474.     }
  7475.  
  7476.     return S_OK;
  7477. }
  7478.  
  7479.  
  7480. HRESULT TOOLSBANDCLASS::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
  7481.     DWORD nCmdexecopt, VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
  7482. {
  7483.      CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7484.     if (!pguidCmdGroup) {
  7485.         /*NOTHING*/
  7486. #ifdef DEBUG
  7487.     } else if (IsEqualGUID(*pguidCmdGroup, IID_IExplorerToolbar)) {
  7488.         switch(nCmdID) {
  7489.         case ETCMDID_GETBUTTONS:
  7490.             // if this rips call tjgreen
  7491.             ASSERT(0);
  7492.             return E_FAIL;
  7493.         }
  7494. #endif
  7495.     } else if (_IsDocHostGUID(pguidCmdGroup)) {
  7496.         UEMFireEvent(&UEMIID_BROWSER, UEME_UITOOLBAR, UEMF_XEVENT, UIG_INET, nCmdID);
  7497.  
  7498.         if (nCmdexecopt == OLECMDEXECOPT_PROMPTUSER) {
  7499.             // the user hit the drop down
  7500.             if (pitbar->_ptbsitect && pvarargIn && pvarargIn->vt == VT_INT_PTR)
  7501.             {
  7502.                 // v.vt = VT_I4;
  7503.                 POINT pt;
  7504.                 RECT* prc = (RECT*)pvarargIn->byref;
  7505.                 pt.x = prc->left;
  7506.                 pt.y = prc->bottom;
  7507.  
  7508.                 switch (nCmdID)
  7509.                 {
  7510. #ifdef EDIT_HACK
  7511.                 case DVIDM_EDITPAGE:
  7512.                     {
  7513.                         // Show the edit pop-up
  7514.                         BSTR bstrURL;
  7515.                         pitbar->_pdie->get_LocationURL(&bstrURL);
  7516.                         if (bstrURL)
  7517.                         {
  7518.                             USES_CONVERSION;
  7519.                             pitbar->_aEditVerb.ShowEditMenu(pt,  pitbar->_hwnd, W2T(bstrURL));
  7520.                             SysFreeString(bstrURL);
  7521.                         }
  7522.                         break;
  7523.                     }
  7524. #endif
  7525.  
  7526.                 default:
  7527.                     // if this rips find tjgreen
  7528.                     ASSERT(0);
  7529.                     break;
  7530.                 }
  7531.             }
  7532.             return S_OK;
  7533.         }
  7534.  
  7535.         switch(nCmdID) {
  7536.  
  7537.         case DVIDM_EDITPAGE:
  7538.         {
  7539.             BSTR bstrURL;
  7540.             ULONG fMask = 0;
  7541.             TCHAR szCacheFileName[MAX_PATH + MAX_URL_STRING + 2];
  7542.             memset(szCacheFileName, 0, SIZEOF(szCacheFileName));
  7543.  
  7544.             pitbar->_pdie->get_LocationURL(&bstrURL);
  7545.             if (NULL == bstrURL)
  7546.                 break;
  7547.  
  7548.             USES_CONVERSION;
  7549.             LPCTSTR szURL = W2T(bstrURL);
  7550.  
  7551. #ifdef EDIT_HACK
  7552.             // Use the default edit verb
  7553.             pitbar->_aEditVerb.Edit(szURL);
  7554. #else
  7555.             SHELLEXECUTEINFO sei = {0};
  7556.             LPTSTR pszTemp = PathFindExtension(szURL);
  7557.  
  7558.             // If we did not find an extension, we assume it is an .htm or .html
  7559.             if (*pszTemp != TEXT('.'))
  7560.             {
  7561.                 if (SHVerbExists(TEXT(".htm"), TEXT("edit"), NULL))
  7562.                     sei.lpClass = TEXT(".htm");
  7563.                 else
  7564.                     sei.lpClass = TEXT(".html");
  7565.             }
  7566.             else
  7567.             {
  7568.                 sei.lpClass = pszTemp;
  7569.             }
  7570.  
  7571.             if (PathIsURL(szURL))
  7572.             {
  7573.                 // (reinerf)
  7574.                 // Some apps (FrontPad, Office99, etc) want the URL passed to
  7575.                 // them instead of the cache filename. We therefore create a string
  7576.                 // that has the URL name after the null:
  7577.                 //
  7578.                 //  "CacheFileName/0UrlName"
  7579.                 //
  7580.                 // and pass it as the lpFile parameter to shellexecute.
  7581.                 // We also pass SEE_MASK_FILEANDURL, so shellexecute can
  7582.                 // recognize this case.
  7583.                 int iLength;
  7584.  
  7585.                 URLDownloadToCacheFile(NULL, szURL, szCacheFileName, 0, URLOSTRM_USECACHEDCOPY, NULL);
  7586.                 iLength = lstrlen(szCacheFileName);
  7587.  
  7588.                 // copy in the URL name
  7589.                 StrCpy(&szCacheFileName[iLength + 1], szURL);
  7590.  
  7591.                 // add the mask so shellexecute knows to check for the URL, if necessary.
  7592.                 fMask |= SEE_MASK_FILEANDURL;
  7593.             }
  7594.             else
  7595.             {
  7596.                 StrCpy(szCacheFileName, szURL);
  7597.             }
  7598.  
  7599.             sei.cbSize = sizeof(SHELLEXECUTEINFO);
  7600.             sei.fMask = fMask;
  7601.             sei.hwnd = NULL;
  7602.             sei.lpVerb = TEXT("edit");
  7603.             sei.lpFile = szCacheFileName;
  7604.             sei.lpParameters = NULL;
  7605.             sei.lpDirectory = NULL;
  7606.             sei.nShow = SW_SHOWNORMAL;
  7607.             sei.hInstApp = NULL;
  7608.  
  7609.             ShellExecuteEx(&sei);
  7610.  
  7611.             SysFreeString(bstrURL);
  7612. #endif //!EDIT_HACK
  7613.         }
  7614.         break;
  7615.  
  7616.         default:
  7617.             // if this rips call tjgreen
  7618.             ASSERT(0);
  7619.             break;
  7620.         }
  7621.     }
  7622.  
  7623.     return S_OK;
  7624. }
  7625.  
  7626. // *** IInputObject methods ***
  7627. HRESULT TOOLSBANDCLASS::TranslateAcceleratorIO(LPMSG lpMsg)
  7628. {
  7629.     if (SendMessage(_hwnd, TB_TRANSLATEACCELERATOR, 0, (LPARAM)lpMsg))
  7630.         return S_OK;
  7631.  
  7632.     return CToolBand::TranslateAcceleratorIO(lpMsg);
  7633. }
  7634.  
  7635. // *** IUnknown methods ***
  7636. HRESULT TOOLSBANDCLASS::QueryInterface(REFIID riid, LPVOID * ppvObj)
  7637. {
  7638.     static const QITAB qit[] = {
  7639.         QITABENT(TOOLSBANDCLASS, IWinEventHandler),
  7640.         { 0 },
  7641.     };
  7642.  
  7643.     HRESULT hres = QISearch(this, qit, riid, ppvObj);
  7644.     if (FAILED(hres))
  7645.         hres = CToolBand::QueryInterface(riid, ppvObj);
  7646.  
  7647.     return hres;
  7648. }
  7649.  
  7650. // *** IDeskBand methods ***
  7651. HRESULT TOOLSBANDCLASS::GetBandInfo(DWORD dwBandID, DWORD fViewMode, DESKBANDINFO* pdbi)
  7652. {
  7653.  
  7654.     _dwBandID = dwBandID;
  7655.  
  7656.     // set dwModeFlags
  7657.     pdbi->dwModeFlags = DBIMF_FIXEDBMP | DBIMF_USECHEVRON;
  7658.  
  7659.     // set ptMinSize
  7660.     {
  7661.         if (SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0)) {
  7662.             // make our min size just big enough to show the first button
  7663.             RECT rc;
  7664.             SendMessage(_hwnd, TB_GETITEMRECT, 0, (LPARAM)&rc);
  7665.             pdbi->ptMinSize.x = RECTWIDTH(rc);
  7666.             pdbi->ptMinSize.y = RECTHEIGHT(rc);
  7667.         } else {
  7668.             // we don't have any buttons; so use standard button size
  7669.             LONG lButtonSize = (long) SendMessage(_hwnd, TB_GETBUTTONSIZE, 0, 0);
  7670.             pdbi->ptMinSize.x = LOWORD(lButtonSize);
  7671.             pdbi->ptMinSize.y = HIWORD(lButtonSize);
  7672.         }
  7673.  
  7674.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7675.         if (pitbar->_fTheater && (pdbi->ptMinSize.y < (THEATER_CYTOOLBAR - 1)))
  7676.             pdbi->ptMinSize.y = (THEATER_CYTOOLBAR - 1);
  7677.     }
  7678.  
  7679.     // set ptActual
  7680.     {
  7681.         SIZE size;
  7682.         size.cy = pdbi->ptMinSize.y;
  7683.         SendMessage(_hwnd, TB_GETIDEALSIZE, FALSE, (LPARAM)&size);
  7684.         pdbi->ptActual.x = size.cx;
  7685.         pdbi->ptActual.y = size.cy;
  7686.     }
  7687.  
  7688.     // no title
  7689.     pdbi->dwMask &= ~DBIM_TITLE;
  7690.  
  7691.     return S_OK;
  7692. }
  7693.  
  7694. IOleCommandTarget* TOOLSBANDCLASS::_CommandTargetFromCmdMap(CMDMAP* pcm)
  7695. {
  7696.     IOleCommandTarget* pct = NULL;
  7697.  
  7698.     if (pcm) {
  7699.         if (IsEqualGUID(pcm->guidButtonGroup, CLSID_CommonButtons)) {
  7700.             CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7701.             pct = SAFECAST(pitbar, IOleCommandTarget*);
  7702.         } else {
  7703.             // If either of these rip, the button is stale
  7704.             ASSERT(IsEqualGUID(pcm->guidButtonGroup, _guidCurrentButtonGroup));
  7705.             ASSERT(_pctCurrentButtonGroup);
  7706.  
  7707.             pct = _pctCurrentButtonGroup;
  7708.         }
  7709.     }
  7710.  
  7711.     return pct;
  7712. }
  7713.  
  7714. LRESULT TOOLSBANDCLASS::_OnToolbarDropDown(TBNOTIFY *ptbn)
  7715. {
  7716.     UINT uiCmd;
  7717.     if (ptbn->hdr.hwndFrom == _hwnd)
  7718.     {
  7719.         GUID guid;
  7720.         _ConvertCmd(NULL, ptbn->iItem, &guid, &uiCmd);
  7721.         CMDMAP* pcm = _GetCmdMapByID(ptbn->iItem);
  7722.         IOleCommandTarget* pct = _CommandTargetFromCmdMap(pcm);
  7723.  
  7724.         if (pct) {
  7725.             VARIANTARG var;
  7726.             var.vt = VT_I4;
  7727.             var.lVal = ptbn->iItem;
  7728.  
  7729.             // BUGBUG: use VARIANT[TO/FROM]BUFFER here to fix win64 problem
  7730.  
  7731.             VARIANT v = {VT_INT_PTR};
  7732.             v.byref = &ptbn->rcButton;
  7733.  
  7734.             MapWindowRect(_hwnd, HWND_DESKTOP, &ptbn->rcButton);
  7735.  
  7736.             //
  7737.             // If this window is mirrored, then let's take the
  7738.             // other coordinate [samera]
  7739.             //
  7740.             if (IS_WINDOW_RTL_MIRRORED(_hwnd))
  7741.             {
  7742.                 int iTmp = ptbn->rcButton.right;
  7743.                 ptbn->rcButton.right = ptbn->rcButton.left;
  7744.                 ptbn->rcButton.left  = iTmp;
  7745.             }
  7746.  
  7747. #ifdef EDIT_HACK
  7748.             // BUGBUG: temp code -- edit code moving to dochost.cpp
  7749.             if (_IsDocHostGUID(&pcm->guidButtonGroup) && pcm->nCmdID == DVIDM_EDITPAGE)
  7750.                 Exec(&pcm->guidButtonGroup, (DWORD)pcm->nCmdID, OLECMDEXECOPT_PROMPTUSER, &v, &var);
  7751.             else
  7752. #endif
  7753.                 pct->Exec(&pcm->guidButtonGroup, (DWORD)pcm->nCmdID, OLECMDEXECOPT_PROMPTUSER, &v, &var);
  7754.         }
  7755.     }
  7756.  
  7757.     return TBDDRET_DEFAULT;
  7758. }
  7759.  
  7760. LRESULT TOOLSBANDCLASS::_TryShowBackForwardMenu(DWORD dwItemSpec, LPPOINT ppt, LPRECT prcExclude)
  7761. {
  7762.     LRESULT lres = 0;
  7763.  
  7764.     GUID guid;
  7765.     UINT id;
  7766.     _ConvertCmd(NULL, dwItemSpec, &guid, &id);
  7767.  
  7768.     // If the user right clicked on the the back or forward button, show the context menu
  7769.     // On all other buttons show the regular shortcut menu
  7770.     if (IsEqualGUID(guid, CLSID_CommonButtons))
  7771.     {
  7772.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7773.         if (id == TBIDM_BACK) {
  7774.             pitbar->_ShowBackForwardMenu(FALSE, *ppt, prcExclude);
  7775.             lres = 1;
  7776.         } else if (id == TBIDM_FORWARD) {
  7777.             pitbar->_ShowBackForwardMenu(TRUE, *ppt, prcExclude);
  7778.             lres = 1;
  7779.         }
  7780.     }
  7781.     return lres;
  7782. }
  7783.  
  7784. LRESULT TOOLSBANDCLASS::_OnNotify(LPNMHDR pnmh)
  7785. {
  7786.     LRESULT lres = 0;
  7787.  
  7788.     ASSERT(pnmh->idFrom == FCIDM_TOOLBAR);
  7789.  
  7790.     switch (pnmh->code)
  7791.     {
  7792.  
  7793.     case NM_RCLICK:
  7794.         {
  7795.             NMCLICK * pnm = (LPNMCLICK)pnmh;
  7796.  
  7797.             if (!pnm)
  7798.                 break;
  7799.  
  7800.             // Convert to Screen coordinates
  7801.             MapWindowPoints(pnmh->hwndFrom, HWND_DESKTOP, &pnm->pt, 1);
  7802.  
  7803.             if (pnmh->hwndFrom == _hwnd)
  7804.                 lres = _TryShowBackForwardMenu((DWORD)pnm->dwItemSpec, &pnm->pt, NULL);
  7805.         }
  7806.         break;
  7807.  
  7808.     case TBN_DROPDOWN:
  7809.         lres = _OnToolbarDropDown((TBNOTIFY *)pnmh);
  7810.         break;
  7811.  
  7812.     case TBN_DELETINGBUTTON:
  7813.         _OnDeletingButton((TBNOTIFY*)pnmh);
  7814.         break;
  7815.  
  7816.     case TBN_SAVE:
  7817.     case TBN_RESET:
  7818.     case TBN_INITCUSTOMIZE:
  7819.     case TBN_RESTORE:
  7820.     case TBN_BEGINADJUST:
  7821.     case TBN_GETBUTTONINFO:
  7822.     case TBN_ENDADJUST:
  7823.     case TBN_QUERYDELETE:
  7824.     case TBN_QUERYINSERT:
  7825.     case TBN_TOOLBARCHANGE:
  7826.         if (pnmh->hwndFrom == _hwnd)
  7827.             lres = _ToolsCustNotify (pnmh);
  7828.         break;
  7829.  
  7830.     case TBN_GETOBJECT:
  7831.         {
  7832.             NMOBJECTNOTIFY *pnmon = (NMOBJECTNOTIFY *)pnmh;
  7833.             if (IsEqualIID(*pnmon->piid, IID_IDropTarget))
  7834.             {
  7835.                 if (pnmh->hwndFrom == _hwnd)
  7836.                 {
  7837.                     UINT uiCmd;
  7838.                     GUID guid;
  7839.                     _ConvertCmd(NULL, pnmon->iItem, &guid, &uiCmd);
  7840.  
  7841.                     if (IsEqualGUID(guid, CLSID_CommonButtons) &&
  7842.                             (uiCmd == TBIDM_HOME || uiCmd == TBIDM_FAVORITES)) {
  7843.  
  7844.                         CITBarDropTarget *pdtgt = new CITBarDropTarget(_hwnd, uiCmd);
  7845.                         if (pdtgt)
  7846.                         {
  7847.                             pnmon->pObject = SAFECAST(pdtgt, IDropTarget*);
  7848.                             pnmon->hResult = NOERROR;
  7849.                         }
  7850.                     }
  7851.                     else     // pass back CDropDummy to handle basics.
  7852.                     {
  7853.                         CDropDummy *pdtgt = new CDropDummy(_hwnd);
  7854.                         if (pdtgt)
  7855.                         {
  7856.                             pnmon->pObject = SAFECAST(pdtgt, IDropTarget*);
  7857.                             pnmon->hResult = NOERROR;
  7858.                         }
  7859.                     }
  7860.  
  7861.                 }
  7862.                 lres = TRUE;
  7863.             }
  7864.         }
  7865.         break;
  7866.  
  7867.     default:
  7868.         lres = CToolbarBand::_OnNotify(pnmh);
  7869.         break;
  7870.     }
  7871.  
  7872.     return lres;
  7873. }
  7874.  
  7875. LRESULT TOOLSBANDCLASS::_OnContextMenu(LPARAM lParam, WPARAM wParam)
  7876. {
  7877.     LRESULT lres = 0;
  7878.  
  7879.     if (IS_WM_CONTEXTMENU_KEYBOARD(lParam)) {
  7880.  
  7881.         // keyboard context menu.  figure out where to pop up menu and
  7882.         // which context menu to use, and tell itbar to pop it up.
  7883.         RECT rc;
  7884.         BOOL fBackForward = FALSE;
  7885.  
  7886.         // figure out coordinates to use
  7887.         INT_PTR iBtn = SendMessage(_hwnd, TB_GETHOTITEM, 0, 0);
  7888.         if (iBtn != -1) {
  7889.             // use lower left corner of current hot button
  7890.             SendMessage(_hwnd, TB_GETITEMRECT, iBtn, (LPARAM)&rc);
  7891.         } else {
  7892.             // no hot button; use top left corner of tools window
  7893.             SetRect(&rc, 0, 0, 0, 0);
  7894.         }
  7895.         MapWindowPoints(_hwnd, HWND_DESKTOP, (LPPOINT)&rc, 2);
  7896.  
  7897.         if (iBtn != -1) {
  7898.             // get hot button's command
  7899.             TBBUTTONINFO tbbi;
  7900.             tbbi.cbSize = SIZEOF(TBBUTTONINFO);
  7901.             tbbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
  7902.             SendMessage(_hwnd, TB_GETBUTTONINFO, iBtn, (LPARAM)&tbbi);
  7903.  
  7904.             POINT pt = {rc.left, rc.bottom};
  7905.  
  7906.             // try popping up the back/forward context menu
  7907.             if (_TryShowBackForwardMenu(tbbi.idCommand, &pt, &rc))
  7908.                 fBackForward = TRUE;
  7909.         }
  7910.  
  7911.         if (!fBackForward) {
  7912.             // pop up the standard context menu
  7913.             CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7914.             pitbar->_ShowContextMenu((HWND)wParam, MAKELONG(rc.left, rc.bottom), (iBtn == -1 ? NULL : &rc));
  7915.         }
  7916.  
  7917.         lres = 1;
  7918.     }
  7919.     return lres;
  7920. }
  7921.  
  7922. void TOOLSBANDCLASS::_RecalcButtonWidths()
  7923. {
  7924.     // We need the toolbars buttons to use ONLY exactly as much space as is needed.
  7925.     // By setting the size a a really small number like 10, and then setting it to
  7926.     // the real number we can accomplish this.
  7927.     // If we don't use do this, then when we add new buttons after doing this
  7928.     // RemoveAllButtons(), the new buttons will be at least as wide as the widest
  7929.     // button that existed on the last set of buttons (the ones we are just removing)
  7930.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7931.     SendMessage(_hwnd, TB_SETBUTTONWIDTH, 0, (LPARAM)MAKELONG(0, 10));
  7932.     SendMessage(_hwnd, TB_SETBUTTONWIDTH, 0, (LPARAM)(pitbar->_fCompressed ? MAKELONG(0, MAX_TB_COMPRESSED_WIDTH) : MAKELONG(0, pitbar->_uiMaxTBWidth)));
  7933. }
  7934.  
  7935. // *** IWinEventHandler methods ***
  7936. HRESULT TOOLSBANDCLASS::OnWinEvent(HWND hwnd, UINT dwMsg, WPARAM wParam, LPARAM lParam, LRESULT* plres)
  7937. {
  7938.     HRESULT hres = S_OK;
  7939.  
  7940.     switch (dwMsg) {
  7941.     case WM_CONTEXTMENU:
  7942.         *plres = _OnContextMenu(lParam, wParam);
  7943.         break;
  7944.  
  7945.     case WM_NOTIFY:
  7946.         *plres = _OnNotify((LPNMHDR)lParam);
  7947.         break;
  7948.  
  7949.     case WM_WININICHANGE:
  7950.         *plres = SendMessage(_hwnd, dwMsg, wParam, lParam);
  7951.         if (wParam == SPI_SETNONCLIENTMETRICS)
  7952.         {
  7953.             _RecalcButtonWidths();
  7954.             _BandInfoChanged();
  7955.         }
  7956.         break;
  7957.  
  7958.     default:
  7959.         hres = CToolbarBand::OnWinEvent(hwnd, dwMsg, wParam, lParam, plres);
  7960.         break;
  7961.     }
  7962.  
  7963.     return hres;
  7964. }
  7965.  
  7966. CMDMAP* TOOLSBANDCLASS::_GetCmdMap(int i, BOOL fByIndex)
  7967. {
  7968.     TBBUTTONINFO tbbi;
  7969.     tbbi.cbSize = SIZEOF(tbbi);
  7970.     tbbi.dwMask = TBIF_LPARAM;
  7971.     tbbi.lParam = 0;
  7972.     if (fByIndex)
  7973.         tbbi.dwMask |= TBIF_BYINDEX;
  7974.     SendMessage(_hwnd, TB_GETBUTTONINFO, i, (LPARAM)&tbbi);
  7975.     return (CMDMAP*)(LPVOID)tbbi.lParam;
  7976. }
  7977.  
  7978.  
  7979. void TOOLSBANDCLASS::_FreeCmdMap(CMDMAP* pcm)
  7980. {
  7981.     if (pcm)
  7982.         LocalFree(pcm);
  7983. }
  7984.  
  7985. void TOOLSBANDCLASS::_OnDeletingButton(TBNOTIFY* ptbn)
  7986. {
  7987.     CMDMAP *pcm = (CMDMAP*)(LPVOID)ptbn->tbButton.dwData;
  7988.     _FreeCmdMap(pcm);
  7989. }
  7990.  
  7991. LONG_PTR TOOLSBANDCLASS::_AddString(LPWSTR pwstr)
  7992. {
  7993.     LONG_PTR lOffset;
  7994.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  7995.     pitbar->AddString(&_guidCurrentButtonGroup, 0, (UINT_PTR)pwstr, &lOffset);
  7996.  
  7997.     return lOffset;
  7998. }
  7999.  
  8000. #define PPBS_LOOKINTOOLBAR  0x00000001
  8001. #define PPBS_EXTERNALBUTTON 0x00000002
  8002.  
  8003. void TOOLSBANDCLASS::_PreProcessButtonString(TBBUTTON *ptbn, DWORD dwFlags)
  8004. {
  8005.     // Caller should have checked this.
  8006.     ASSERT(!(ptbn->fsStyle & BTNS_SEP));
  8007.  
  8008.     // If we don't have a command target, we shouldn't have any external buttons.
  8009.     ASSERT(_pctCurrentButtonGroup || !(dwFlags & PPBS_EXTERNALBUTTON));
  8010.  
  8011.     if (ptbn->iString < 0 && ptbn->iBitmap <= MAX_SHELLGLYPHINDEX)
  8012.     {
  8013.         // total hack
  8014.         // we're hard coding the strings in to match
  8015.         // the bitmap.  so if anyone uses the shell bitmaps,
  8016.         // they're going to get our text labels
  8017.         // also hacking in that the bitmap array and string array are
  8018.         // matched
  8019.         // who designed reviewed this???
  8020.  
  8021.         ptbn->iString = ptbn->iBitmap;
  8022.     }
  8023.     else if (!ptbn->iString && (dwFlags & PPBS_EXTERNALBUTTON))
  8024.     {
  8025.         // Some Extensions are giving us bogus string ids (Font ext sends 0)
  8026.         ptbn->iString = -1;
  8027.     }
  8028.     else if (ptbn->iString != -1 && !IS_INTRESOURCE(ptbn->iString))
  8029.     {
  8030.         // It's a string pointer.  The customization mechanism requires that all buttons
  8031.         // use strings from the tb string pool.  So add the string to the pool and set
  8032.         // iString to the pool index.
  8033.         ptbn->iString = _AddString((LPWSTR)ptbn->iString);
  8034.     }
  8035.  
  8036.     if (ptbn->iString == -1 && IsFlagSet(dwFlags, PPBS_LOOKINTOOLBAR | PPBS_EXTERNALBUTTON))
  8037.     {
  8038.         // If we're building the customization dsa rather than adding new buttons to the
  8039.         // toolbar, we may already have this button in the toolbar.  If so, use that string.
  8040.  
  8041.         UINT idCommand;
  8042.         if (SUCCEEDED(_ConvertCmd(&_guidCurrentButtonGroup, ptbn->idCommand, NULL, &idCommand)))
  8043.         {
  8044.             TBBUTTON tbb;
  8045.             if (SendMessage(_hwnd, TB_GETBUTTON, idCommand, (LPARAM)&tbb))
  8046.                 ptbn->iString = tbb.iString;
  8047.         }
  8048.     }
  8049.  
  8050.     if (ptbn->iString == -1 && (dwFlags & PPBS_EXTERNALBUTTON))
  8051.     {
  8052.         // Still don't have a string for this puppy.  Last resort is to ask via QueryStatus.
  8053.         OLECMDTEXTV<MAX_TOOLTIP_STRING> cmdtv;
  8054.         OLECMDTEXT *pcmdText = &cmdtv;
  8055.  
  8056.         pcmdText->cwBuf = MAX_TOOLTIP_STRING;
  8057.         pcmdText->cmdtextf = OLECMDTEXTF_NAME;
  8058.         pcmdText->cwActual = 0;
  8059.  
  8060.         OLECMD rgcmd = {ptbn->idCommand, 0};
  8061.  
  8062.         HRESULT hr = _pctCurrentButtonGroup->QueryStatus(&_guidCurrentButtonGroup, 1, &rgcmd, pcmdText);
  8063.         if (SUCCEEDED(hr) && (pcmdText->cwActual))
  8064.             ptbn->iString = _AddString(pcmdText->rgwz);
  8065.     }
  8066.  
  8067.     // If it's an internal button, we'd better have found a string for it.
  8068.     ASSERT(ptbn->iString != -1 || (dwFlags & PPBS_EXTERNALBUTTON));
  8069. }
  8070.  
  8071. void TOOLSBANDCLASS::_PreProcessExternalTBButton(TBBUTTON *ptbn)
  8072. {
  8073.     if (!(ptbn->fsStyle & BTNS_SEP)) {
  8074.         CMDMAP* pcm = (CMDMAP*)LocalAlloc(LPTR, SIZEOF(CMDMAP));
  8075.         if (pcm) {
  8076.             pcm->guidButtonGroup = _guidCurrentButtonGroup;
  8077.             pcm->nCmdID = ptbn->idCommand;
  8078.  
  8079.             _PreProcessButtonString(ptbn, PPBS_EXTERNALBUTTON);
  8080.  
  8081.             _nNextCommandID++;
  8082.             pcm->lParam = ptbn->dwData;
  8083.         }
  8084.  
  8085.         ptbn->dwData = (LPARAM)pcm;
  8086.     } else {
  8087.         ptbn->dwData = 0;
  8088.  
  8089.         // override default toolbar width for separators; iBitmap member of
  8090.         // TBBUTTON struct is a union of bitmap index & separator width
  8091.         ptbn->iBitmap = CX_SEPARATOR;
  8092.     }
  8093. }
  8094.  
  8095. UINT TOOLSBANDCLASS::_ProcessExternalButtons(PTBBUTTON ptbb, UINT cButtons)
  8096. {
  8097.     cButtons = RemoveHiddenButtons(ptbb, cButtons);
  8098.  
  8099.     for (UINT i = 0; i < cButtons; i++)
  8100.         _PreProcessExternalTBButton(&ptbb[i]);
  8101.  
  8102.     return cButtons;
  8103. }
  8104.  
  8105. void TOOLSBANDCLASS::_GetButtons(IOleCommandTarget* pct, const GUID* pguid, HDSA hdsa)
  8106. {
  8107.     LONG lCount;
  8108.     VARIANTARG v1;
  8109.     VariantInit(&v1);
  8110.     v1.vt = VT_BYREF | VT_I4;
  8111.     v1.plVal = &lCount;
  8112.  
  8113.     VARIANTARG v2;
  8114.     VariantInit(&v2);
  8115.     if (SUCCEEDED(pct->Exec(&IID_IExplorerToolbar, ETCMDID_GETBUTTONS, 0, &v1, &v2)) && v2.vt == VT_BYREF) {
  8116.         CMDMAPCUSTOMIZE cmc;
  8117.         TBBUTTON* pbtn = (TBBUTTON*)v2.byref;
  8118.  
  8119.         cmc.cm.guidButtonGroup = *pguid;
  8120.  
  8121.         DWORD dwFlags = PPBS_LOOKINTOOLBAR;
  8122.  
  8123.         if (!IsEqualGUID(*pguid, CLSID_CommonButtons))
  8124.             dwFlags |= PPBS_EXTERNALBUTTON;
  8125.  
  8126.         for (long l = 0; l < lCount; l++) {
  8127.  
  8128.             cmc.btn = pbtn[l];
  8129.             if (!(cmc.btn.fsStyle & BTNS_SEP)) {
  8130.                 cmc.cm.nCmdID = pbtn[l].idCommand;
  8131.  
  8132.                 _PreProcessButtonString(&cmc.btn, dwFlags);
  8133.  
  8134.                 if (FAILED(_ConvertCmd(pguid, cmc.cm.nCmdID, NULL, (UINT*)&cmc.btn.idCommand))) {
  8135.                     // not already in the toolbar, generate a new id
  8136.                     cmc.btn.idCommand = _nNextCommandID++;
  8137.                 }
  8138.  
  8139.                 DSA_AppendItem(hdsa, &cmc);
  8140.             } else {
  8141.                 cmc.btn.dwData = 0;
  8142.             }
  8143.         }
  8144.     }
  8145. }
  8146.  
  8147. void TOOLSBANDCLASS::_OnEndCustomize()
  8148. {
  8149.  
  8150.     if (_pcinfo) {
  8151.         // loop through and make sure that any items added have the appropriate cmdmap
  8152.         int i;
  8153.         INT_PTR nCount = SendMessage(_hwnd, TB_BUTTONCOUNT, 0, 0L);
  8154.         _pcinfo->fAdjust = FALSE;
  8155.         for(i = 0; i < nCount; i++) {
  8156.             CMDMAP* pcm = _GetCmdMapByIndex(i);
  8157.             if (!pcm) {
  8158.                 // no command map for this item
  8159.                 // find the corresponding CMDMAP in our hdsa, clone it and give it to this button.
  8160.  
  8161.                 // the command id's are the same, so get the toolbar command id, find the corresponding
  8162.                 // one in the hdsa and clone away.
  8163.                 TBBUTTONINFO tbbi;
  8164.                 tbbi.cbSize = SIZEOF(tbbi);
  8165.                 tbbi.dwMask = TBIF_COMMAND | TBIF_BYINDEX;
  8166.                 SendMessage(_hwnd, TB_GETBUTTONINFO, i, (LPARAM)&tbbi);
  8167.  
  8168.                 int j;
  8169.                 for (j = 0; j < DSA_GetItemCount(_pcinfo->hdsa); j++) {
  8170.                     CMDMAPCUSTOMIZE* pcmc = (CMDMAPCUSTOMIZE*)DSA_GetItemPtr(_pcinfo->hdsa, j);
  8171.                     ASSERT(pcmc);
  8172.                     if (pcmc->btn.idCommand == tbbi.idCommand) {
  8173.                         // found it!
  8174.  
  8175.                         // clone the cmdmap
  8176.                         CMDMAP *pcm = (CMDMAP*)LocalAlloc(LPTR, SIZEOF(CMDMAP));
  8177.                         if (pcm) {
  8178.                             *pcm = pcmc->cm;
  8179.                             tbbi.lParam = (LPARAM)pcm;
  8180.                             tbbi.dwMask = TBIF_LPARAM | TBIF_BYINDEX;
  8181.                             SendMessage(_hwnd, TB_SETBUTTONINFO, i, (LPARAM)&tbbi);
  8182.                         }
  8183.                     }
  8184.                 }
  8185.             }
  8186.         }
  8187.  
  8188.         if (_pcinfo->fDirty)
  8189.             _SaveRestoreToolbar(TRUE);
  8190.  
  8191.         _FreeCustomizeInfo();
  8192.  
  8193.         _RecalcButtonWidths();
  8194.         CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  8195.  
  8196. #ifdef EDIT_HACK
  8197.         pitbar->_InitEditButtonStyle();
  8198. #endif
  8199.         if (g_fSmallIcons != _UseSmallIcons())
  8200.             SendShellIEBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)SZ_REGKEY_SMALLICONS, 3000);
  8201.  
  8202.         pitbar->_UpdateToolbar(TRUE);
  8203.     }
  8204. }
  8205.  
  8206. void TOOLSBANDCLASS::_FreeCustomizeInfo()
  8207. {
  8208.     if (_pcinfo) {
  8209.         DSA_Destroy(_pcinfo->hdsa);
  8210.         LocalFree(_pcinfo);
  8211.         _pcinfo = NULL;
  8212.     }
  8213. }
  8214.  
  8215. CMDMAPCUSTOMIZE* TOOLSBANDCLASS::_GetCmdMapCustomize(GUID* pguid, UINT nCmdID)
  8216. {
  8217.     int j;
  8218.     for (j = 0; j < DSA_GetItemCount(_pcinfo->hdsa); j++) {
  8219.         CMDMAPCUSTOMIZE* pcmc = (CMDMAPCUSTOMIZE*)DSA_GetItemPtr(_pcinfo->hdsa, j);
  8220.  
  8221.         if (pcmc->cm.nCmdID == nCmdID &&
  8222.             IsEqualGUID(*pguid, pcmc->cm.guidButtonGroup)) {
  8223.  
  8224.             return pcmc;
  8225.         }
  8226.     }
  8227.  
  8228.     return NULL;
  8229. }
  8230.  
  8231. BOOL TOOLSBANDCLASS::_BuildButtonDSA()
  8232. {
  8233.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  8234.  
  8235.     ASSERT(!_pcinfo);
  8236.     _pcinfo = (CUSTOMIZEINFO*)LocalAlloc(LPTR, SIZEOF(CUSTOMIZEINFO));
  8237.  
  8238.     if (_pcinfo) {
  8239.         // build a CMDMAP array of all the buttons available
  8240.         _pcinfo->hdsa = DSA_Create(SIZEOF(CMDMAPCUSTOMIZE), 4);
  8241.  
  8242.         // add the common set (back,forward, stop, refresh, home and search
  8243.         _GetButtons(pitbar, &CLSID_CommonButtons, _pcinfo->hdsa);
  8244.  
  8245.         _GetButtons(_pctCurrentButtonGroup, &_guidCurrentButtonGroup, _pcinfo->hdsa);
  8246.  
  8247.         return TRUE;
  8248.     }
  8249.     return FALSE;
  8250. }
  8251.  
  8252. void TOOLSBANDCLASS::_UpdateTextSettings(INT_PTR ids)
  8253. {
  8254.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  8255.  
  8256.     BOOL fText, fList;
  8257.  
  8258.     switch (ids) {
  8259.     case IDS_TEXTLABELS:
  8260.         fList = FALSE;
  8261.         fText = TRUE;
  8262.         break;
  8263.  
  8264.     case IDS_PARTIALTEXT:
  8265.         fList = TRUE;
  8266.         fText = TRUE;
  8267.         break;
  8268.  
  8269.     case IDS_NOTEXTLABELS:
  8270.         fList = FALSE;  // (but we really don't care)
  8271.         fText = FALSE;
  8272.         break;
  8273.     }
  8274.  
  8275.     pitbar->_UpdateToolsStyle(fList);
  8276.  
  8277.     // (_fCompressed == TRUE means no text labels)
  8278.     pitbar->_UpdateToolbarDisplay(UTD_TEXTLABEL, 0, !fText, TRUE);
  8279. }
  8280.  
  8281. const static DWORD c_aBtnAttrHelpIDs[] = {
  8282.     IDC_SHOWTEXT,       IDH_BROWSEUI_TB_TEXTOPTNS,
  8283.     IDC_SMALLICONS,     IDH_BROWSEUI_TB_ICONOPTNS,
  8284.     0, 0
  8285. };
  8286.  
  8287. BOOL_PTR CALLBACK TOOLSBANDCLASS::_BtnAttrDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  8288. {
  8289.     CInternetToolbar* pitbar = (CInternetToolbar*)GetWindowPtr(hDlg, DWLP_USER);
  8290.  
  8291.     switch (uMsg) {
  8292.     case WM_INITDIALOG:
  8293.         SetWindowLongPtr(hDlg, DWLP_USER, lParam);  /* LPADJUSTDLGDATA pointer */
  8294.         return TRUE;
  8295.  
  8296.     case WM_COMMAND:
  8297.         if (GET_WM_COMMAND_ID(wParam, lParam) == IDC_SHOWTEXT)
  8298.         {
  8299.             if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELENDOK ||
  8300.                 GET_WM_COMMAND_CMD(wParam, lParam) == CBN_CLOSEUP)
  8301.             {
  8302.                 // what'd they pick?
  8303.                 HWND hwndText = GET_WM_COMMAND_HWND(wParam, lParam);
  8304.                 INT_PTR iSel = SendMessage(hwndText, CB_GETCURSEL, 0, 0);
  8305.                 INT_PTR idsSel = SendMessage(hwndText, CB_GETITEMDATA, iSel, 0);
  8306.  
  8307.                 pitbar->_btb._UpdateTextSettings(idsSel);
  8308.  
  8309.                 return TRUE;
  8310.             }
  8311.         }
  8312.         break;
  8313.  
  8314.     case WM_CONTEXTMENU:
  8315.         SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile,
  8316.             HELP_CONTEXTMENU, (DWORD_PTR)(LPTSTR) c_aBtnAttrHelpIDs);
  8317.         return TRUE;
  8318.  
  8319.     case WM_HELP:
  8320.         SHWinHelpOnDemandWrap((HWND) ((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
  8321.             HELP_WM_HELP, (DWORD_PTR)(LPTSTR) c_aBtnAttrHelpIDs);
  8322.         return TRUE;
  8323.  
  8324.     case WM_DESTROY:
  8325.         {
  8326. #define SZ_YES  TEXT("yes")
  8327. #define SZ_NO   TEXT("no")
  8328.  
  8329.             HWND hwndIcons = GetDlgItem(hDlg, IDC_SMALLICONS);
  8330.             if (TPTR(hwndIcons)) {
  8331.  
  8332.                 INT_PTR iSel = SendMessage(hwndIcons, CB_GETCURSEL, 0, 0);
  8333.                 BOOL fSmallIcons = (SendMessage(hwndIcons, CB_GETITEMDATA, iSel, 0) == IDS_SMALLICONS);
  8334.  
  8335.                 LPCTSTR szData;
  8336.                 DWORD cbData;
  8337.  
  8338.                 if (fSmallIcons) {
  8339.                     szData = SZ_YES;
  8340.                     cbData = SIZEOF(SZ_YES);
  8341.                 } else {
  8342.                     szData = SZ_NO;
  8343.                     cbData = SIZEOF(SZ_NO);
  8344.                 }
  8345.                 SHRegSetUSValue(SZ_REGKEY_SMALLICONS, SZ_REGVALUE_SMALLICONS, REG_SZ, (LPVOID)szData, cbData, SHREGSET_FORCE_HKCU);
  8346.             }
  8347.         }
  8348.         return TRUE;
  8349.     }
  8350.  
  8351.     return FALSE;
  8352. }
  8353.  
  8354. void TOOLSBANDCLASS::_PopulateComboBox(HWND hwnd, const int iResource[], UINT cResources)
  8355. {
  8356.     TCHAR sz[256];
  8357.  
  8358.     // loop through iResource[], load each string resource and insert into combobox
  8359.     for (UINT i = 0; i < cResources; i++) {
  8360.         if (MLLoadString(iResource[i], sz, ARRAYSIZE(sz))) {
  8361.             INT_PTR iIndex = SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)sz);
  8362.             SendMessage(hwnd, CB_SETITEMDATA, iIndex, iResource[i]);
  8363.         }
  8364.     }
  8365. }
  8366.  
  8367. void TOOLSBANDCLASS::_SetComboSelection(HWND hwnd, int iCurOption)
  8368. {
  8369.     INT_PTR cItems = SendMessage(hwnd, CB_GETCOUNT, 0, 0);
  8370.  
  8371.     while (cItems--) {
  8372.  
  8373.         INT_PTR iItemData = SendMessage(hwnd, CB_GETITEMDATA, cItems, 0);
  8374.  
  8375.         if (iItemData == iCurOption) {
  8376.             SendMessage(hwnd, CB_SETCURSEL, cItems, 0);
  8377.             break;
  8378.         }
  8379.         else {
  8380.             // iCurOption should be in list somewhere;
  8381.             // assert that we're not done looking
  8382.             ASSERT(cItems);
  8383.         }
  8384.     }
  8385. }
  8386.  
  8387. void TOOLSBANDCLASS::_SetDialogSelections(HWND hDlg, BOOL fSmallIcons)
  8388. {
  8389.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  8390.  
  8391.     int iCurOption;
  8392.     HWND hwnd;
  8393.  
  8394.     hwnd = GetDlgItem(hDlg, IDC_SHOWTEXT);
  8395.  
  8396.     if (pitbar->_fCompressed)
  8397.         iCurOption = IDS_NOTEXTLABELS;
  8398.     else if (IS_LIST_STYLE(_hwnd))
  8399.         iCurOption = IDS_PARTIALTEXT;
  8400.     else
  8401.         iCurOption = IDS_TEXTLABELS;
  8402.  
  8403.     _SetComboSelection(hwnd, iCurOption);
  8404.     if (pitbar->_fTheater)
  8405.         SHSetWindowBits(hwnd, GWL_STYLE, WS_DISABLED, WS_DISABLED);
  8406.  
  8407.     hwnd = GetDlgItem(hDlg, IDC_SMALLICONS);
  8408.     iCurOption = (fSmallIcons ? IDS_SMALLICONS : IDS_LARGEICONS);
  8409.     _SetComboSelection(hwnd, iCurOption);
  8410. }
  8411.  
  8412. static const int c_iTextOptions[] = {
  8413.     IDS_TEXTLABELS,
  8414.     IDS_PARTIALTEXT,
  8415.     IDS_NOTEXTLABELS,
  8416. };
  8417.  
  8418. static const int c_iIconOptions[] = {
  8419.     IDS_SMALLICONS,
  8420.     IDS_LARGEICONS,
  8421. };
  8422.  
  8423. void TOOLSBANDCLASS::_PopulateDialog(HWND hDlg)
  8424. {
  8425.     HWND hwnd;
  8426.  
  8427.     hwnd = GetDlgItem(hDlg, IDC_SHOWTEXT);
  8428.     _PopulateComboBox(hwnd, c_iTextOptions, ARRAYSIZE(c_iTextOptions));
  8429.  
  8430.     hwnd = GetDlgItem(hDlg, IDC_SMALLICONS);
  8431.     _PopulateComboBox(hwnd, c_iIconOptions, ARRAYSIZE(c_iIconOptions));
  8432. }
  8433.  
  8434. void TOOLSBANDCLASS::_OnBeginCustomize(LPNMTBCUSTOMIZEDLG pnm)
  8435. {
  8436.     CInternetToolbar* pitbar = IToClass(CInternetToolbar, _btb, this);
  8437.     HWND hwnd = (HWND) GetProp(pnm->hDlg, SZ_PROP_CUSTDLG);
  8438.  
  8439.     if (!hwnd) {
  8440.         //
  8441.         // hasn't been initialized.
  8442.         //
  8443.         // we need to check this because this init will be called
  8444.         // when the user hits reset as well
  8445.  
  8446.         hwnd = CreateDialogParam(MLGetHinst(), MAKEINTRESOURCE(DLG_TEXTICONOPTIONS), pnm->hDlg, _BtnAttrDlgProc, (LPARAM)pitbar);
  8447.         if (hwnd) {
  8448.             // store hwnd of our dialog as property on tb cust dialog
  8449.             SetProp(pnm->hDlg, SZ_PROP_CUSTDLG, hwnd);
  8450.  
  8451.             // populate dialog controls
  8452.             _PopulateDialog(hwnd);
  8453.  
  8454.             // initialize dialog control selection states
  8455.             _SetDialogSelections(hwnd, g_fSmallIcons);
  8456.  
  8457.             RECT rc, rcWnd, rcClient;
  8458.             GetWindowRect(pnm->hDlg, &rcWnd);
  8459.             GetClientRect(pnm->hDlg, &rcClient);
  8460.             GetWindowRect(hwnd, &rc);
  8461.  
  8462.             // enlarge tb dialog to make room for our dialog
  8463.             SetWindowPos(pnm->hDlg, NULL, rcWnd.left, rcWnd.top + 64, RECTWIDTH(rcWnd), RECTHEIGHT(rcWnd) + RECTHEIGHT(rc), SWP_NOZORDER);
  8464.  
  8465.             // position our dialog at the bottom of the tb dialog
  8466.             SetWindowPos(hwnd, HWND_TOP, rcClient.left, rcClient.bottom, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW);
  8467.         }
  8468.     }
  8469.  
  8470.     if (_BuildButtonDSA()) {
  8471.         _pcinfo->fAdjust = TRUE;
  8472.     }
  8473. }
  8474.  
  8475. class CBitmapPreload : public IRunnableTask
  8476. {
  8477.     public:
  8478.         STDMETHOD ( QueryInterface ) ( REFIID riid, LPVOID * ppvObj );
  8479.         STDMETHOD_( ULONG, AddRef ) ();
  8480.         STDMETHOD_( ULONG, Release ) ();
  8481.  
  8482.         STDMETHOD (Run)( void );
  8483.         STDMETHOD (Kill)( BOOL fWait );
  8484.         STDMETHOD (Suspend)( );
  8485.         STDMETHOD (Resume)( );
  8486.         STDMETHOD_( ULONG, IsRunning )( void );
  8487.  
  8488.     protected:
  8489.         friend HRESULT CBitmapPreload_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi);
  8490.  
  8491.         CBitmapPreload();
  8492.         ~CBitmapPreload();
  8493.  
  8494.         LONG            m_cRef;
  8495.         LONG            m_lState;
  8496. };
  8497.  
  8498. STDAPI CBitmapPreload_CreateInstance(IUnknown* pUnkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  8499. {
  8500.     // aggregation checking and *ppunk zeroing are handled in class factory
  8501.     ASSERT(pUnkOuter == NULL);
  8502.  
  8503.     CBitmapPreload* pbp = new CBitmapPreload();
  8504.  
  8505.     if (pbp)
  8506.     {
  8507.         *ppunk = SAFECAST(pbp, IRunnableTask*);
  8508.         return S_OK;
  8509.     }
  8510.     else
  8511.     {
  8512.         *ppunk = NULL; // redundant but doesn't hurt
  8513.         return E_OUTOFMEMORY;
  8514.     }
  8515. }
  8516.  
  8517. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8518. CBitmapPreload::CBitmapPreload() : m_cRef(1)
  8519. {
  8520.     m_lState = IRTIR_TASK_NOT_RUNNING;
  8521. }
  8522.  
  8523. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8524. CBitmapPreload::~CBitmapPreload()
  8525. {
  8526. }
  8527.  
  8528. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8529. STDMETHODIMP CBitmapPreload::QueryInterface ( REFIID riid, LPVOID * ppvObj )
  8530. {
  8531.     *ppvObj = NULL;
  8532.  
  8533.     if ( riid == IID_IRunnableTask || riid == IID_IUnknown )
  8534.     {
  8535.         *ppvObj = SAFECAST( this, IRunnableTask *);
  8536.         AddRef();
  8537.     }
  8538.     else
  8539.     {
  8540.         return E_NOINTERFACE;
  8541.     }
  8542.  
  8543.     return NOERROR;
  8544. }
  8545.  
  8546. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8547. STDMETHODIMP_( ULONG ) CBitmapPreload:: AddRef ()
  8548. {
  8549.     InterlockedIncrement( &m_cRef );
  8550.     return m_cRef;
  8551. }
  8552.  
  8553. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8554. STDMETHODIMP_( ULONG ) CBitmapPreload:: Release ()
  8555. {
  8556.     if (InterlockedDecrement( &m_cRef ) == 0 )
  8557.     {
  8558.         delete this;
  8559.         return 0;
  8560.     }
  8561.  
  8562.     return m_cRef;
  8563. }
  8564.  
  8565.  
  8566. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8567. STDMETHODIMP CBitmapPreload::Run ( void )
  8568. {
  8569.     if ( m_lState != IRTIR_TASK_NOT_RUNNING )
  8570.     {
  8571.         return E_FAIL;
  8572.     }
  8573.  
  8574.     InterlockedExchange( &m_lState, IRTIR_TASK_RUNNING );
  8575.  
  8576.     CInternetToolbar_Preload( );
  8577.  
  8578.     InterlockedExchange( &m_lState, IRTIR_TASK_FINISHED );
  8579.  
  8580.     return NOERROR;
  8581. }
  8582.  
  8583. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8584. STDMETHODIMP CBitmapPreload::Kill ( BOOL fWait )
  8585. {
  8586.     return E_NOTIMPL;
  8587. }
  8588.  
  8589. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8590. STDMETHODIMP CBitmapPreload::Suspend ( )
  8591. {
  8592.     return E_NOTIMPL;
  8593. }
  8594.  
  8595. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8596. STDMETHODIMP CBitmapPreload::Resume ( )
  8597. {
  8598.     return E_NOTIMPL;
  8599. }
  8600.  
  8601. /////////////////////////////////////////////////////////////////////////////////////////////////////
  8602. STDMETHODIMP_( ULONG ) CBitmapPreload:: IsRunning ( void )
  8603. {
  8604.     return m_lState;
  8605. }
  8606.  
  8607.  
  8608.  
  8609. #ifdef EDIT_HACK
  8610.  
  8611. //+-------------------------------------------------------------------------
  8612. //  Constructor
  8613. //--------------------------------------------------------------------------
  8614. CInternetToolbar::CEditVerb::CEditVerb()
  8615. {
  8616.     ASSERT(_nElements == 0);
  8617.     ASSERT(_nDefault == 0);
  8618.     ASSERT(_pVerb == NULL);
  8619.     ASSERT(_lpfnOldWndProc == NULL);
  8620.     ASSERT(_pszDefaultEditor == NULL);
  8621.     ASSERT(_fInitEditor == FALSE);
  8622. }
  8623.  
  8624. //+-------------------------------------------------------------------------
  8625. //  Destructor
  8626. //--------------------------------------------------------------------------
  8627. CInternetToolbar::CEditVerb::~CEditVerb()
  8628. {
  8629.     if (_pVerb) RemoveAll();
  8630.     SetStr(&_pszDefaultEditor, NULL);
  8631. }
  8632.  
  8633. //+-------------------------------------------------------------------------
  8634. // Removes all cached edit verbs and associated memory
  8635. //--------------------------------------------------------------------------
  8636. void CInternetToolbar::CEditVerb::RemoveAll()
  8637. {
  8638.     if (_nElements > 0)
  8639.     {
  8640.         for (UINT i=0; i < _nElements; ++i)
  8641.         {
  8642.             EDITVERB& rVerb = _pVerb[i];
  8643.  
  8644.             SetStr(&rVerb.pszDesc, NULL);
  8645.             SetStr(&rVerb.pszMenuText, NULL);
  8646.             SetStr(&rVerb.pszExe, NULL);
  8647.             if (rVerb.hkeyProgID)
  8648.             {
  8649.                 RegCloseKey(rVerb.hkeyProgID);
  8650.             }
  8651.             _ClearMSAAMenuInfo(rVerb);
  8652.         }
  8653.  
  8654.         LocalFree(_pVerb);
  8655.  
  8656.         _pVerb = NULL;
  8657.         _nElements = 0;
  8658.         _nDefault = 0;
  8659.     }
  8660. }
  8661.  
  8662. //+-------------------------------------------------------------------------
  8663. // Check registry for the friendly name of the default html editor.  This
  8664. // editor is configured by inetcpl or by office 2000.  If necessary, the
  8665. // associated verb is moved to the OpenWithList for .htm files.
  8666. //--------------------------------------------------------------------------
  8667. void CInternetToolbar::CEditVerb::InitDefaultEditor(HKEY hkey)
  8668. {
  8669.     //
  8670.     // First see if the default editor is in HKCU
  8671.     //
  8672.     HKEY hkeyEdit = hkey;
  8673.     if (hkey ||
  8674.         ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR,
  8675.                                       0, KEY_READ | KEY_WRITE, &hkeyEdit))
  8676.     {
  8677.         //
  8678.         // See if we have a default editor selected
  8679.         //
  8680.         WCHAR szBuf[MAX_PATH];
  8681.         DWORD cbBuf = sizeof(szBuf);
  8682.         if (ERROR_SUCCESS == SHGetValue(hkeyEdit, NULL, L"Description", NULL, szBuf, &cbBuf))
  8683.         {
  8684.             // We got it!  Save the friendly name.
  8685.             PathRemoveBlanks(szBuf);
  8686.             SetStr(&_pszDefaultEditor, szBuf);
  8687.         }
  8688.         else
  8689.         {
  8690.             IQueryAssociations *pqa;
  8691.  
  8692.             if (SUCCEEDED(AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (LPVOID *)&pqa)))
  8693.             {
  8694.                 //  need to release
  8695.                 if (SUCCEEDED(pqa->Init(0, NULL, hkeyEdit, NULL)) &&
  8696.                 ( SUCCEEDED(pqa->GetString(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, L"edit", szBuf, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szBuf))))
  8697.                 || SUCCEEDED(pqa->GetString(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, NULL, szBuf, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szBuf))))))
  8698.                 {
  8699.                     PathRemoveBlanks(szBuf);
  8700.  
  8701. #ifdef COPY_DEFAULT_TO_OPENWITHLIST
  8702.                     //
  8703.                     // Add this verb to our OpenWithList if it isn't already there.  We add using
  8704.                     // the following format:
  8705.                     //
  8706.                     // .htm\OpenWithList\<friendly name>\shell\<verb>\command
  8707.                     //
  8708.                     HKEY hkeyDest;
  8709.                     WCHAR szKey[MAX_PATH];
  8710.                     wnsprintf(szKey, SIZECHARS(szKey), L".htm\\OpenWithList\\%s", szBuf);
  8711.  
  8712.                     if (ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, szKey, NULL) &&
  8713.  
  8714.                         // Doesn't exist so create it!
  8715.                         ERROR_SUCCESS == RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkeyDest))
  8716.                     {
  8717.                         // Copy the verb to the OpenWithList
  8718.                         SHCopyKey(hkeyEdit, NULL, hkeyDest, 0);
  8719.                         RegCloseKey(hkeyDest);
  8720.                     }
  8721. /*
  8722.                     // Copy to the OpenWithList for .html too
  8723.                     wnsprintf(szKey, SIZECHARS(szKey), L"%s\\OpenWithList\\%s", L".html", szBuf);
  8724.  
  8725.                     if (ERROR_SUCCESS != RegOpenKey(HKEY_CLASSES_ROOT, szKey, NULL) &&
  8726.  
  8727.                         // Doesn't exist so create it!
  8728.                         ERROR_SUCCESS == RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkeyDest))
  8729.                     {
  8730.                         // Copy the verb to the OpenWithList
  8731.                         SHCopyKey(hkeyEdit, NULL, hkeyDest, 0);
  8732.                         RegCloseKey(hkeyDest);
  8733.                     }
  8734. */
  8735. #endif // COPY_DEFAULT_TO_OPENWITHLIST
  8736.  
  8737.                     // Save the name of the default editor
  8738.                     SetStr(&_pszDefaultEditor, szBuf);
  8739.  
  8740.                     SHSetValue(hkeyEdit, NULL, L"Description", REG_SZ, szBuf, CbFromCch(lstrlen(szBuf) +1));
  8741.                 }
  8742.  
  8743.                 pqa->Release();
  8744.             }
  8745.         }
  8746.  
  8747.         // Close the key if it wasn't passed in
  8748.         if (hkeyEdit && NULL == hkey)
  8749.         {
  8750.             RegCloseKey(hkeyEdit);
  8751.         }
  8752.     }
  8753.  
  8754.     // During setup, Office places the orginial edit verb in HKLM. We need to copy this to HKCU.
  8755.     else if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, KEY_READ, &hkeyEdit))
  8756.     {
  8757.         // Migrate this key into HKCU
  8758.         HKEY hkeyDest;
  8759.         if (ERROR_SUCCESS == RegCreateKey(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR, &hkeyDest))
  8760.         {
  8761.             SHCopyKey(hkeyEdit, NULL, hkeyDest, 0);
  8762.  
  8763.             // Try again
  8764.             InitDefaultEditor(hkeyDest);
  8765.             RegCloseKey(hkeyDest);
  8766.         }
  8767.         RegCloseKey(hkeyEdit);
  8768.     }
  8769. }
  8770.  
  8771. //+-------------------------------------------------------------------------
  8772. // Make sure that notepad is registered in the OpenWithList for .htm files.
  8773. // This is called when this dll is registered (at setup time)
  8774. //--------------------------------------------------------------------------
  8775. void AddNotepadToOpenWithList()
  8776. {
  8777.     TCHAR szPath[MAX_PATH];
  8778.     GetWindowsDirectory(szPath, ARRAYSIZE(szPath));
  8779.     PathAddBackslash(szPath);
  8780.     StrCatBuff(szPath, L"Notepad.exe", ARRAYSIZE(szPath));
  8781.     TCHAR szNotepadFriendly[MAX_PATH];
  8782.     HKEY hkeyOpenWith;
  8783.  
  8784.     if (SUCCEEDED(AssocQueryString(ASSOCF_INIT_BYEXENAME | ASSOCF_VERIFY,
  8785.         ASSOCSTR_FRIENDLYAPPNAME, szPath, NULL, szNotepadFriendly, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szNotepadFriendly)))))
  8786.     {
  8787.         // If not already in the OpenWithList, add it
  8788.         WCHAR szKey[MAX_PATH];
  8789.         wnsprintf(szKey, SIZECHARS(szKey), L".htm\\OpenWithList\\%s", szNotepadFriendly);
  8790.  
  8791.         if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_READ, &hkeyOpenWith))
  8792.         {
  8793.             // Compose command for the verb "c:\windows\notepad.exe %1"
  8794.             StrCatBuff(szPath, L" %1", ARRAYSIZE(szPath));
  8795.  
  8796.             // The verb goes under the friendly name
  8797.             StrCatBuff(szKey, L"\\shell\\edit\\command", ARRAYSIZE(szKey));
  8798.             SHSetValue(HKEY_CLASSES_ROOT, szKey, NULL, REG_SZ, szPath, CbFromCch(lstrlen(szPath) + 1));
  8799.         }
  8800.         else
  8801.         {
  8802.             RegCloseKey(hkeyOpenWith);
  8803.         }
  8804.     }
  8805. }
  8806.  
  8807. //+-------------------------------------------------------------------------
  8808. // Returns the friendly name of the default HTML editor
  8809. //--------------------------------------------------------------------------
  8810. LPCTSTR CInternetToolbar::CEditVerb::_GetDefaultEditor()
  8811. {
  8812.     // Do a lazy init of the default editor
  8813.     if (!_fInitEditor)
  8814.     {
  8815.         InitDefaultEditor();
  8816.         _fInitEditor = TRUE;
  8817.     }
  8818.     return _pszDefaultEditor;
  8819. }
  8820.  
  8821. //+-------------------------------------------------------------------------
  8822. // Gets the path of the exe associated with the verb and stores the
  8823. // result in rVerb.  The caller is responsible for freeing the string
  8824. // returned.
  8825. //--------------------------------------------------------------------------
  8826. LPCTSTR CInternetToolbar::CEditVerb::_GetExePath(EDITVERB& rVerb)
  8827. {
  8828.     // If we already have the path, simply return it
  8829.     if (NULL == rVerb.pszExe)
  8830.     {
  8831.         ASSERT(rVerb.hkeyProgID);
  8832.         TCHAR sz[MAX_PATH];
  8833.         if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, rVerb.hkeyProgID,
  8834.             rVerb.fUseOpenVerb ? NULL : L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz)))))
  8835.             rVerb.pszExe = StrDup(sz);
  8836.     }
  8837.  
  8838.     return rVerb.pszExe;
  8839. }
  8840.  
  8841. //+-------------------------------------------------------------------------
  8842. // Returns TRUE if path of the exe associated with the verb is not found in
  8843. // any of the existing verbs.
  8844. //--------------------------------------------------------------------------
  8845. BOOL CInternetToolbar::CEditVerb::_IsUnique(EDITVERB& rNewVerb)
  8846. {
  8847.     // Get the friendly name of the new element
  8848.     LPCTSTR pszNewDesc = _GetDescription(rNewVerb);
  8849.     if (NULL == pszNewDesc)
  8850.     {
  8851.         // Executable must not exist
  8852.         return FALSE;
  8853.     }
  8854.  
  8855.     // Scan existing elements for the same executable
  8856.     for (UINT i=0; i < _nElements; ++i)
  8857.     {
  8858.         LPCTSTR pszDesc = _GetDescription(_pVerb[i]);
  8859.         if (pszDesc && (StrCmpI(pszNewDesc, pszDesc) == 0))
  8860.         {
  8861.             // Match found, so free the friendly name for the new verb
  8862.             SetStr(&rNewVerb.pszDesc, NULL);
  8863.  
  8864.             // If the new item shows its icon on the button, make the duplicate
  8865.             // do the same.
  8866.             if (rNewVerb.fShowIcon)
  8867.             {
  8868.                 _pVerb[i].fShowIcon = TRUE;
  8869.                 _nDefault = i;
  8870.             }
  8871.             return FALSE;
  8872.         }
  8873.     }
  8874.  
  8875.     return TRUE;
  8876. }
  8877.  
  8878. //+-------------------------------------------------------------------------
  8879. // Some programs such as msothmed.exe act as stubs that redirect the edit
  8880. // command to the appropriate executable. This function returns true if
  8881. // the path contains the name of a known stub.
  8882. //--------------------------------------------------------------------------
  8883. BOOL CInternetToolbar::CEditVerb::_IsHtmlStub
  8884. (
  8885.     LPCWSTR pszPath
  8886. )
  8887. {
  8888.     BOOL fRet = FALSE;
  8889.  
  8890.     // Get the MULTISZ list of known redirectors
  8891.     TCHAR szRedir[MAX_PATH];
  8892.     ZeroInit(szRedir, ARRAYSIZE(szRedir)); // Protect against non-multisz strings in the reg
  8893.     DWORD dwType;
  8894.     DWORD cb = sizeof(szRedir) - 4;
  8895.     if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_HTML_EDITOR, L"Stubs", &dwType, szRedir, &cb))
  8896.     {
  8897.         // Nothing in registry, so default to ignore the Office redirector
  8898.         StrCpyN(szRedir, L"msohtmed.exe\0", ARRAYSIZE(szRedir));
  8899.     }
  8900.  
  8901.     // See if the path contains the name of a redirectors
  8902.     // Note that PathFindFileName doesn't work well for pathes with parameters so we just
  8903.     // check for the exe name in the path)
  8904.     for (LPTSTR p = szRedir; *p != NULL; p += lstrlen(p) + 1)
  8905.     {
  8906.         if (StrStrI(pszPath, p))
  8907.         {
  8908.             fRet = TRUE;
  8909.             break;
  8910.         }
  8911.     }
  8912.     return fRet;
  8913. }
  8914.  
  8915. //+-------------------------------------------------------------------------
  8916. //  Adds a new edit verb.  Returns a pointer to the new verb if it
  8917. //  successfully added.
  8918. //--------------------------------------------------------------------------
  8919. CInternetToolbar::CEditVerb::EDITVERB* CInternetToolbar::CEditVerb::_Add
  8920. (
  8921.     HKEY hkeyProgID,        // location of of verb
  8922.     BOOL fPermitOpenVerb,   // permit open as well as edit verb
  8923.     BOOL fCheckForOfficeApp,// redirect to office app
  8924.     BOOL fShowIcon          // if button face icon should be customized
  8925. )
  8926. {
  8927.     EDITVERB* pNewVerb = NULL;
  8928.  
  8929.     if (hkeyProgID)
  8930.     {
  8931.         BOOL fUseOpenVerb = FALSE;
  8932.  
  8933.         //
  8934.         // See if an appropriate verb exists.
  8935.         //
  8936.         TCHAR szCommand[MAX_PATH];
  8937.         HRESULT hr = AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProgID, L"edit", szCommand, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szCommand)));
  8938.         if (FAILED(hr) && fPermitOpenVerb)
  8939.         {
  8940.             hr = AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProgID, NULL, szCommand, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szCommand)));
  8941.             if (SUCCEEDED(hr))
  8942.             {
  8943.                 fUseOpenVerb = TRUE;
  8944.             }
  8945.         }
  8946.  
  8947.         // If no verb or if this is the office redirector, ignore this progid
  8948.         // Otherwise we can get two entries that do the same thing.
  8949.         if (FAILED(hr) || _IsHtmlStub(szCommand))
  8950.         {
  8951.             RegCloseKey(hkeyProgID);
  8952.             return NULL;
  8953.         }
  8954.  
  8955.         if (fCheckForOfficeApp)
  8956.         {
  8957.             ASSERT(*szCommand);
  8958.  
  8959.             //
  8960.             // HACK: Office2000 needs us to call a special proxy to get around thier DDE bugs and
  8961.             // to check the HTML document for the name of the original document.  These problems
  8962.             // should be fixed in the apps themselves.  Morons!
  8963.             //
  8964.             // So if this is an office app, we will redirect to the appropriate progid. Note that
  8965.             // we don't need to do this if a progid was from the html meta tag because this progid
  8966.             // already supports the proxy.
  8967.             //
  8968.             struct OfficeHackery {LPCWSTR pszApp; LPCWSTR pszProgID;};
  8969.  
  8970.             // Must not have been a progid passed in.
  8971.             static const OfficeHackery exeToProgID[] =
  8972.             {
  8973.                 {L"winword",   L"Word.Document"},
  8974.                 {L"excel",     L"Excel.Sheet"},
  8975.                 {L"powerpnt",  L"PowerPoint.Slide"},
  8976.                 {L"msaccess",  L"Access.Application"},
  8977.                 {L"frontpg",   L"FrontPage.Editor.Document"},
  8978.             };
  8979.  
  8980.             for (int i=0; i < ARRAYSIZE(exeToProgID); ++i)
  8981.             {
  8982.                 if (StrStrI(szCommand, exeToProgID[i].pszApp))
  8983.                 {
  8984.                     // Match found!
  8985.                     HKEY hkeyOffice = NULL;
  8986.                     if (SUCCEEDED(AssocQueryKey(0, ASSOCKEY_SHELLEXECCLASS, exeToProgID[i].pszProgID, NULL, &hkeyOffice)))
  8987.                     {
  8988.                         // Redirect to the office progid
  8989.                         RegCloseKey(hkeyProgID);
  8990.                         hkeyProgID = hkeyOffice;
  8991.  
  8992.                         // The office apps always use the open verb
  8993.                         fUseOpenVerb = TRUE;
  8994.  
  8995.                         // The icon is shown on the button face for office apps
  8996.                         fShowIcon = TRUE;
  8997.                     }
  8998.                     break;
  8999.                 }
  9000.             }
  9001.         }
  9002.  
  9003.         EDITVERB newVerb = {0};
  9004.         newVerb.hkeyProgID = hkeyProgID;
  9005.         newVerb.fUseOpenVerb = fUseOpenVerb;
  9006.         newVerb.fShowIcon = fShowIcon;
  9007.  
  9008.         // Ignore it if we have another verb to the same exe.
  9009.         if (!_IsUnique(newVerb))
  9010.         {
  9011.             RegCloseKey(hkeyProgID);
  9012.         }
  9013.         else
  9014.         {
  9015.             EDITVERB* pVerbsNew;
  9016.             if (_pVerb == NULL)
  9017.             {
  9018.                 pVerbsNew = (EDITVERB*)LocalAlloc(LPTR, sizeof(EDITVERB));
  9019.             }
  9020.             else
  9021.             {
  9022.                 pVerbsNew = (EDITVERB*)LocalReAlloc(_pVerb, (_nElements+1) * sizeof(EDITVERB), LMEM_MOVEABLE | LMEM_ZEROINIT);
  9023.             }
  9024.  
  9025.             if (pVerbsNew == NULL)
  9026.             {
  9027.                 RegCloseKey(hkeyProgID);
  9028.             }
  9029.             else
  9030.             {
  9031.                 _pVerb = pVerbsNew;
  9032.                 pNewVerb = &_pVerb[_nElements];
  9033.                 *pNewVerb = newVerb;
  9034.  
  9035.                 //
  9036.                 // If the description of the executable matches that of the default editor, make
  9037.                 // it our default edit verb.  If we are not checking for the office app, we
  9038.                 // can assume that this verb was from a progid in an html file and we will also
  9039.                 // make it our default.
  9040.                 //
  9041.                 LPCWSTR pszDefDesc = _GetDefaultEditor();
  9042.                 LPCWSTR pszNewDesc = _GetDescription(*pNewVerb);
  9043.  
  9044.                 if (!fCheckForOfficeApp ||
  9045.                     (pszDefDesc && pszNewDesc && StrCmp(pszDefDesc, pNewVerb->pszDesc) == 0))
  9046.                 {
  9047.                     _nDefault = _nElements;
  9048.                 }
  9049.  
  9050.                 ++_nElements;
  9051.             }
  9052.         }
  9053.     }
  9054.  
  9055.     return pNewVerb;
  9056. }
  9057.  
  9058. //+-------------------------------------------------------------------------
  9059. //  Adds a new edit verb.  Returns TRUE if a verb was successfully added.
  9060. //--------------------------------------------------------------------------
  9061. BOOL CInternetToolbar::CEditVerb::Add
  9062. (
  9063.     LPTSTR pszProgID    // program id or file extension associated with verb
  9064. )
  9065. {
  9066.     ASSERT(pszProgID);
  9067.  
  9068.     BOOL fRet = FALSE;
  9069.     BOOL fFileExt = (pszProgID[0] == TEXT('.'));
  9070.  
  9071.     //
  9072.     // Open the associated reg key and try to add it to our list of verbs
  9073.     //
  9074.     BOOL fUseOpenVerb = FALSE;
  9075.     HKEY hkeyProgID = NULL;
  9076.     BOOL fPermitOpenVerb = !fFileExt;
  9077.     BOOL fShowIcon = !fFileExt;    // If a progid was passed in, we will show the icon on the button face
  9078.  
  9079.     if (SUCCEEDED(AssocQueryKey(0, ASSOCKEY_SHELLEXECCLASS, pszProgID, NULL, &hkeyProgID)))
  9080.     {
  9081.         EDITVERB* pNewVerb = _Add(hkeyProgID, fPermitOpenVerb, fFileExt, fShowIcon);
  9082.         if (pNewVerb)
  9083.         {
  9084.             fRet = TRUE;
  9085.         }
  9086.     }
  9087.  
  9088.     //
  9089.     // If a file extension was passed in, we also add the alternative editors from the
  9090.     // OpenWithList
  9091.     //
  9092.     if (fFileExt)
  9093.     {
  9094.         WCHAR szOpenWith[MAX_PATH];
  9095.         StrCpyN(szOpenWith, pszProgID, ARRAYSIZE(szOpenWith));
  9096.         StrCatBuff(szOpenWith, L"\\OpenWithList", ARRAYSIZE(szOpenWith));
  9097.  
  9098.         HKEY hkeyOpenWithList;
  9099.  
  9100.         // See if there is an OpenWithList
  9101.         if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szOpenWith, 0, KEY_READ, &hkeyOpenWithList))
  9102.         {
  9103.             DWORD dwIndex = 0;
  9104.             DWORD dwSize = ARRAYSIZE(szOpenWith);
  9105.             HKEY hkeyOpenWith = NULL;
  9106.             while (ERROR_SUCCESS == RegEnumKeyEx(hkeyOpenWithList, dwIndex, szOpenWith, &dwSize, NULL, NULL, NULL, NULL))
  9107.             {
  9108.                 if (ERROR_SUCCESS == RegOpenKeyEx(hkeyOpenWithList, szOpenWith, 0, KEY_READ, &hkeyOpenWith))
  9109.                 {
  9110.                     // We only permit the edit verbs from here
  9111.                     EDITVERB* pNewVerb = _Add(hkeyOpenWith, FALSE, TRUE, FALSE);
  9112.                     if (pNewVerb)
  9113.                     {
  9114.                         // The key name is the friendly name!
  9115.                         PathRemoveBlanks(szOpenWith);
  9116.                         SetStr(&pNewVerb->pszDesc, szOpenWith);
  9117.                         fRet = TRUE;
  9118.                     }
  9119.  
  9120.                     // Note that we don't close hkeyOpenWith here.  It is either closed if it was not added, or
  9121.                     // it will be closed later.
  9122.                 }
  9123.                 ++dwIndex;
  9124.                 dwSize = ARRAYSIZE(szOpenWith);
  9125.             }
  9126.  
  9127.             RegCloseKey(hkeyOpenWithList);
  9128.         }
  9129.  
  9130.         //
  9131.         // If a ".htm" or ".html" was passed in, add our default html editor
  9132.         //
  9133.         if ((StrCmpI(pszProgID, L".htm") == 0 || StrCmpI(pszProgID, L".html") == 0) &&
  9134.             _GetDefaultEditor())
  9135.         {
  9136.             HKEY hkeyDefault;
  9137.             if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, KEY_READ, &hkeyDefault))
  9138.             {
  9139.                 if (_Add(hkeyDefault, TRUE, TRUE, FALSE))
  9140.                 {
  9141.                     fRet = TRUE;
  9142.                 }
  9143.             }
  9144.         }
  9145.     }
  9146.  
  9147.     return fRet;
  9148. }
  9149.  
  9150. //+-------------------------------------------------------------------------
  9151. // Returns the tooltip for the default edit verb
  9152. //--------------------------------------------------------------------------
  9153. BOOL CInternetToolbar::CEditVerb::GetToolTip
  9154. (
  9155.     LPTSTR pszToolTip,
  9156.     UINT cchMax,
  9157.     BOOL fStripAmpersands
  9158. )
  9159. {
  9160.     if (_nElements == 0)
  9161.     {
  9162.         return FALSE;
  9163.     }
  9164.  
  9165.     // Use the menu text for the tooltip.
  9166.     _FormatMenuText(_nDefault);
  9167.  
  9168.     // Copy text stripping out any ampersands
  9169.     LPWSTR pszDest = pszToolTip;
  9170.     LPWSTR pszSrc = _GetVerb(_nDefault).pszMenuText;
  9171.     if (0 < cchMax)
  9172.     {
  9173.         // Leave room for the null terminator
  9174.         while (0 < --cchMax)
  9175.         {
  9176.             // strip out '&'
  9177.             if (fStripAmpersands)
  9178.             {
  9179.                 while (*pszSrc == L'&')
  9180.                 {
  9181.                     ++pszSrc;
  9182.                 }
  9183.             }
  9184.  
  9185.             if ( !(*pszDest++ = *pszSrc++) )
  9186.             {
  9187.                 --pszDest;
  9188.                 break;
  9189.             }
  9190.         }
  9191.  
  9192.         if (0 == cchMax)
  9193.             *pszDest = L'\0';
  9194.  
  9195.         ASSERT(*pszDest == 0);
  9196.  
  9197.         //
  9198.         // In some locals, the accelerator is identified in brackets at the
  9199.         // end of the string, so if we strip ampersands, we strip these too.
  9200.         //
  9201.         if (fStripAmpersands && --pszDest >= pszToolTip && *pszDest == L')')
  9202.         {
  9203.             while (--pszDest >= pszToolTip)
  9204.             {
  9205.                 if (*pszDest == L'(')
  9206.                 {
  9207.                     *pszDest = L'\0';
  9208.                     break;
  9209.                 }
  9210.             }
  9211.         }
  9212.     }
  9213.  
  9214.     return TRUE;
  9215. }
  9216.  
  9217. //+-------------------------------------------------------------------------
  9218. // "Lazy-fetches" the verb info, and returns the desired info.
  9219. //--------------------------------------------------------------------------
  9220. CInternetToolbar::CEditVerb::EDITVERB& CInternetToolbar::CEditVerb::_GetVerb(UINT nIndex)
  9221. {
  9222.     ASSERT(nIndex < _nElements);
  9223.  
  9224.     // We fetch the info when first asked for it.
  9225.     if (!_pVerb[nIndex].fInit)
  9226.     {
  9227.         _FetchInfo(nIndex);
  9228.         _pVerb[nIndex].fInit = TRUE;
  9229.     }
  9230.     return _pVerb[nIndex];
  9231. }
  9232.  
  9233. //+-------------------------------------------------------------------------
  9234. // Gets the name of the app associated with the verb.
  9235. //--------------------------------------------------------------------------
  9236. LPCTSTR CInternetToolbar::CEditVerb::_GetDescription(EDITVERB& rVerb)
  9237. {
  9238.     // If we already have a description, we are done
  9239.     if (NULL == rVerb.pszDesc)
  9240.     {
  9241.         ASSERT(rVerb.hkeyProgID);
  9242.  
  9243.         TCHAR sz[MAX_PATH];
  9244.         if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, rVerb.hkeyProgID,
  9245.             rVerb.fUseOpenVerb ? NULL : L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz)))))
  9246.         {
  9247.             rVerb.pszDesc = StrDup(sz);
  9248.             if (rVerb.pszDesc)
  9249.             {
  9250.                 // Remove preceeding and trailing blanks
  9251.                 PathRemoveBlanks(rVerb.pszDesc);
  9252.             }
  9253.         }
  9254.     }
  9255.  
  9256.     return rVerb.pszDesc;
  9257. }
  9258.  
  9259. //+-------------------------------------------------------------------------
  9260. // Reads the info associated with the progid at the given index.  This
  9261. // function allows us to do a lazy fetch of the info when requested.
  9262. //--------------------------------------------------------------------------
  9263. void CInternetToolbar::CEditVerb::_FetchInfo(UINT nIndex)
  9264. {
  9265.     ASSERT(nIndex < _nElements);
  9266.     ASSERT(_pVerb[nIndex].hkeyProgID != NULL);
  9267.  
  9268.     EDITVERB& rVerb = _pVerb[nIndex];
  9269.  
  9270.     //
  9271.     // Get the path to the edit verb's exe
  9272.     //
  9273.     if (_GetExePath(rVerb))
  9274.     {
  9275.         ASSERT(rVerb.pszExe);
  9276.  
  9277.         // Note that we fetched the friendly name earlier
  9278.         ASSERT(rVerb.pszDesc);
  9279.  
  9280.         // Now get the icon
  9281.         rVerb.iIcon = Shell_GetCachedImageIndex(rVerb.pszExe, 0, 0);
  9282.     }
  9283.     else
  9284.     {
  9285.         rVerb.iIcon = -1;
  9286.     }
  9287. }
  9288.  
  9289. //+-------------------------------------------------------------------------
  9290. // SetMSAAMenuInfo()
  9291. //
  9292. // Fills in MSAAMenuInfo part of EDITVERB from the other fields of the rVerb
  9293. //--------------------------------------------------------------------------
  9294.  
  9295. void CInternetToolbar::CEditVerb::_SetMSAAMenuInfo( EDITVERB& rVerb )
  9296. {
  9297.  
  9298. #ifdef UNICODE
  9299.  
  9300.     // If we're UNICODE, we can just refer to the m_pName of the MenuEntry itself...
  9301.     rVerb.m_MSAA.m_CharLen = lstrlen( rVerb.pszMenuText );
  9302.     rVerb.m_MSAA.m_pWStr = rVerb.pszMenuText;
  9303.  
  9304. #else // UNICODE
  9305.  
  9306.     // If we're ANSI, need to create a UNICODE string for the MSAA text...
  9307.  
  9308.     // Call MultiByteToWideChar first with 0 to get the size needed. (Assumes
  9309.     // m_pName is ASCII NUL terminated - cChars will include the terminating NUL)
  9310.     int cChars = MultiByteToWideChar( CP_ACP, 0, rVerb.pszMenuText, -1, NULL, 0 );
  9311.  
  9312.     // Don't want to include NUL in character length, so subtract one...
  9313.     rVerb.m_MSAA.m_CharLen = cChars - 1;
  9314.  
  9315.     // Now call MultiByteToWideChar to do the conversion.
  9316.     // MultiByteToWideChar adds the terminating WIDE-NUL for us, so we don't have to
  9317.     // add it explicitly...
  9318.     rVerb.m_MSAA.m_pWStr = new WCHAR [ cChars ];
  9319.     if (rVerb.m_MSAA.m_pWStr)
  9320.     {
  9321.         // Note - we don't delete[] the above allocated memory in this sample
  9322.         // code because we know that in this case it will be reclaimed by the system on
  9323.         // exit and won't give a leak.
  9324.         MultiByteToWideChar( CP_ACP, 0, rVerb.pszMenuText, -1, rVerb.m_MSAA.m_pWStr, cChars );
  9325.     }
  9326.  
  9327. #endif // UNICODE
  9328.  
  9329.     // Finally, add MSAAINFO signature...
  9330.     rVerb.m_MSAA.m_MSAASig = MSAA_MENU_SIG;
  9331. }
  9332.  
  9333.  
  9334. //+-------------------------------------------------------------------------
  9335. // ClearMSAAMenuInfo()
  9336. //
  9337. // Clean up MSAAMenuInfo - specifically, release the allocated
  9338. // UNICODE string, if appropriate...
  9339. //--------------------------------------------------------------------------
  9340.  
  9341. void CInternetToolbar::CEditVerb::_ClearMSAAMenuInfo( EDITVERB& rVerb )
  9342. {
  9343.     // Paranoia - clear signature...
  9344.     rVerb.m_MSAA.m_MSAASig = 0;
  9345.  
  9346. #ifdef UNICODE
  9347.  
  9348.     // We're unicode - nothing to do, since we didn't allocate anything.
  9349.  
  9350. #else // UNICODE
  9351.  
  9352.     // We're ANSI - release allocated UNICODE string...
  9353.     delete [] rVerb.m_MSAA.m_pWStr;
  9354.  
  9355. #endif // UNICODE
  9356. }
  9357.  
  9358.  
  9359. //+-------------------------------------------------------------------------
  9360. // Shows the edit pop-up menu.
  9361. //--------------------------------------------------------------------------
  9362. BOOL CInternetToolbar::CEditVerb::ShowEditMenu(POINT pt, HWND hwnd, LPTSTR pszURL)
  9363. {
  9364.     BOOL  bRet  = FALSE;
  9365.     HMENU hmEdit = CreatePopupMenu();
  9366.  
  9367.     if (hmEdit)
  9368.     {
  9369.         UINT idCmd = FCIDM_EDITFIRST;
  9370.         UINT nMax = FCIDM_EDITLAST - FCIDM_EDITFIRST;
  9371.  
  9372.         // Add each verb to the menu
  9373.         for (UINT i=0; i<_nElements && i < nMax; ++i)
  9374.         {
  9375.             EDITVERB& rVerb = _GetVerb(i);
  9376.             _FormatMenuText(i);
  9377.             rVerb.idCmd = idCmd;
  9378.             AppendMenu(hmEdit, MF_OWNERDRAW, idCmd, (LPCTSTR) &rVerb );
  9379.  
  9380.             // Fix up MSAAMenuInfo part...
  9381.             _SetMSAAMenuInfo( rVerb );
  9382.  
  9383.             ++idCmd;
  9384.         }
  9385.  
  9386.         // Temporarily subclass the hwnd to intercept the owner-draw messages
  9387.         if (SetProp(hwnd, SZ_EDITVERB_PROP, this))
  9388.         {
  9389.             ASSERT(!_lpfnOldWndProc);
  9390.             _lpfnOldWndProc = (WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) _WndProc);
  9391.  
  9392.             idCmd = ITBar_TrackPopupMenuEx(hmEdit, TPM_RETURNCMD, pt.x, pt.y, hwnd, NULL);
  9393.  
  9394.             SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)_lpfnOldWndProc);
  9395.             _lpfnOldWndProc = NULL;
  9396.             RemoveProp(hwnd, SZ_EDITVERB_PROP);
  9397.  
  9398.             if (InRange(idCmd, FCIDM_EDITFIRST, FCIDM_EDITLAST))
  9399.             {
  9400.                 // Execute the selected edit verb
  9401.                 _Edit(pszURL, idCmd - FCIDM_EDITFIRST);
  9402.             }
  9403.         }
  9404.  
  9405.         DestroyMenu(hmEdit);
  9406.     }
  9407.  
  9408.     return bRet;
  9409. }
  9410.  
  9411. //+-------------------------------------------------------------------------
  9412. // Creates a menu string from the progid's description
  9413. //--------------------------------------------------------------------------
  9414. void CInternetToolbar::CEditVerb::_FormatMenuText(UINT nIndex)
  9415. {
  9416.     ASSERT(nIndex < _nElements);
  9417.  
  9418.     EDITVERB& rVerb = _GetVerb(nIndex);
  9419.     if (rVerb.pszMenuText == NULL)
  9420.     {
  9421.         if (_GetDescription(rVerb))
  9422.         {
  9423.             TCHAR szFormat[100];
  9424.             TCHAR szMenuText[200];
  9425.  
  9426.             MLLoadString(IDS_EDITWITH, szFormat, ARRAYSIZE(szFormat));
  9427.             wnsprintf(szMenuText, ARRAYSIZE(szMenuText), szFormat, rVerb.pszDesc);
  9428.             SetStr(&((EDITVERB&)rVerb).pszMenuText, szMenuText);
  9429.         }
  9430.         else
  9431.         {
  9432.             // Things are really screwed up
  9433.             ASSERT(FALSE);
  9434.             SetStr(&((EDITVERB&)rVerb).pszMenuText, TEXT(""));
  9435.         }
  9436.     }
  9437. }
  9438.  
  9439.  
  9440. //+-------------------------------------------------------------------------
  9441. // Executes the edit verb indicated by nIndex.
  9442. //--------------------------------------------------------------------------
  9443. void CInternetToolbar::CEditVerb::_Edit
  9444. (
  9445.     LPCTSTR pszURL,     // url assocated with the verb
  9446.     UINT nIndex         // verb to execute
  9447. )
  9448. {
  9449.     ASSERT(pszURL);
  9450.  
  9451.     if (nIndex >= _nElements)
  9452.     {
  9453.         return;
  9454.     }
  9455.  
  9456.     EDITVERB& rVerb = _pVerb[nIndex];
  9457.     int fMask = SEE_MASK_CLASSKEY;
  9458.  
  9459.     SHELLEXECUTEINFO sei = {0};
  9460.  
  9461.     TCHAR szCacheFileName[MAX_PATH + MAX_URL_STRING + 2];
  9462.     memset(szCacheFileName, 0, SIZEOF(szCacheFileName));
  9463.  
  9464.     if (PathIsURL(pszURL))
  9465.     {
  9466.         // We pass the url if the app has register that it wants this
  9467.         if ((WhichPlatform() == PLATFORM_BROWSERONLY) && DoesAppWantUrl(rVerb.pszExe))
  9468.         {
  9469.             //
  9470.             // Old versions of shell32 (PLATFORM_BROWSERONLY) ignore the SEE_MASK_FILEANDURL
  9471.             // flag, so on these platforms we check ourselves to see if the app
  9472.             // wants the url instead of the cache file name.
  9473.             //
  9474.             StrCpyN(szCacheFileName, pszURL, ARRAYSIZE(szCacheFileName));
  9475.             sei.lpFile = szCacheFileName;
  9476.         }
  9477.         else
  9478.         {
  9479.             // (reinerf)
  9480.             // Some apps (FrontPad, Office99, etc) want the URL passed to
  9481.             // them instead of the cache filename. We therefore create a string
  9482.             // that has the URL name after the null:
  9483.             //
  9484.             //  "CacheFileName/0UrlName"
  9485.             //
  9486.             // and pass it as the lpFile parameter to shellexecute.
  9487.             // We also pass SEE_MASK_FILEANDURL, so shellexecute can
  9488.             // recognize this case.
  9489.             //
  9490.             int iLength;
  9491.  
  9492.             if (FAILED(URLToCacheFile(pszURL, szCacheFileName, ARRAYSIZE(szCacheFileName))))
  9493.             {
  9494.                 // Frontpage express crashes if we pass a null file name, so if the app doesn't
  9495.                 // prefer the url instead, we bail.
  9496.                 if (!DoesAppWantUrl(rVerb.pszExe))
  9497.                 {
  9498.                     return;
  9499.                 }
  9500.             }
  9501.             iLength = lstrlen(szCacheFileName);
  9502.  
  9503.             // copy in the URL name
  9504.             StrCpyN(&szCacheFileName[iLength + 1], pszURL, ARRAYSIZE(szCacheFileName) - (iLength + 1));
  9505.  
  9506.             // add the mask so shellexecute knows to check for the URL, if necessary.
  9507.             fMask |= SEE_MASK_FILEANDURL;
  9508.             sei.lpFile = szCacheFileName;
  9509.         }
  9510.     }
  9511.     else
  9512.     {
  9513.         // Not a URL, so pass the filename
  9514.         StrCpyN(szCacheFileName, pszURL, ARRAYSIZE(szCacheFileName));
  9515.         sei.lpFile = szCacheFileName;
  9516.     }
  9517.  
  9518.     // Hack for IE5 bug 50033 - Can remove when fpxpress fixes mru buffer overrun
  9519.     _GetExePath(rVerb);
  9520.     if(StrStr(rVerb.pszExe, TEXT("fpxpress.exe")) != NULL)
  9521.         szCacheFileName[256] = TEXT('\0');
  9522.  
  9523.     sei.cbSize = sizeof(SHELLEXECUTEINFO);
  9524.     sei.fMask = fMask;
  9525.     sei.hwnd = NULL;
  9526.     sei.lpVerb = rVerb.fUseOpenVerb ? NULL : TEXT("edit");
  9527. //    sei.lpFile = szCacheFileName;
  9528. //    sei.lpParameters = NULL;
  9529.     sei.lpDirectory = NULL;
  9530.     sei.nShow = SW_SHOWNORMAL;
  9531.     sei.hInstApp = NULL;
  9532.     sei.hkeyClass= rVerb.hkeyProgID;
  9533.  
  9534.     //
  9535.     // The office guys want us to call a special proxy to get around some DDE problems
  9536.     // and to sniff the html file for the original document name. Hackers! So let's
  9537.     // see if it is registered.
  9538.     //
  9539.     HKEY hkeyProxy = NULL;
  9540.     if (ERROR_SUCCESS == RegOpenKeyEx(rVerb.hkeyProgID, TEXT("HTML Handler"), 0, KEY_READ, &hkeyProxy))
  9541.     {
  9542.         DWORD cch;
  9543.         if (SUCCEEDED(AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProxy, L"edit", NULL, &cch)))
  9544.         {
  9545.             sei.lpVerb = L"edit";
  9546.             sei.hkeyClass = hkeyProxy;
  9547.         }
  9548.         else if (SUCCEEDED(AssocQueryStringByKey(0, ASSOCSTR_COMMAND, hkeyProxy, NULL, NULL, &cch)))
  9549.         {
  9550.             sei.lpVerb = NULL;
  9551.             sei.hkeyClass = hkeyProxy;
  9552.         }
  9553.     }
  9554.  
  9555.     ShellExecuteEx(&sei);
  9556.  
  9557.     if (hkeyProxy)
  9558.     {
  9559.         RegCloseKey(hkeyProxy);
  9560.     }
  9561. }
  9562.  
  9563. //+-------------------------------------------------------------------------
  9564. // This window procedure intercepts owner-draw menu messages when the edit
  9565. // pop-up menu is displayed.
  9566. //--------------------------------------------------------------------------
  9567. LRESULT CALLBACK CInternetToolbar::CEditVerb::_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  9568. {
  9569.     CEditVerb* pThis = (CEditVerb*)GetProp(hwnd, SZ_EDITVERB_PROP);
  9570.  
  9571.     if (!pThis)
  9572.         return DefWindowProcWrap(hwnd, uMsg, wParam, lParam);
  9573.  
  9574.     switch(uMsg)
  9575.     {
  9576.         case WM_DRAWITEM:
  9577.         case WM_MEASUREITEM:
  9578.         {
  9579.             UINT idCmd;
  9580.  
  9581.             switch (uMsg)
  9582.             {
  9583.                 case WM_DRAWITEM:
  9584.                     idCmd = ((EDITVERB*)((DRAWITEMSTRUCT*)lParam)->itemData)->idCmd;
  9585.                     break;
  9586.                 case WM_MEASUREITEM:
  9587.                     idCmd = ((EDITVERB*)((MEASUREITEMSTRUCT*)lParam)->itemData)->idCmd;
  9588.                     break;
  9589.             }
  9590.  
  9591.             if (InRange(idCmd, FCIDM_EDITFIRST, FCIDM_EDITLAST))
  9592.             {
  9593.                 // do our own measuring
  9594.                 UINT index  = idCmd - FCIDM_EDITFIRST;
  9595.                 const EDITVERB& rVerb = pThis->_GetVerb(index);
  9596.  
  9597.                 // We don't want the same accelerator on all items,
  9598.                 // so remove underlines
  9599.                 WCHAR wzBuf[MAX_PATH];
  9600.                 UINT cchMax = ARRAYSIZE(wzBuf);
  9601.                 LPWSTR pszTo = wzBuf;
  9602.                 LPWSTR pszFrom = rVerb.pszMenuText;
  9603.                 if (pszFrom)
  9604.                 {
  9605.                     while (0 < --cchMax)
  9606.                     {
  9607.                         if (*pszFrom == L'&')
  9608.                         {
  9609.                             pszFrom++;
  9610.                             continue;
  9611.                         }
  9612.  
  9613.                         if ( !(*pszTo++ = *pszFrom++) )
  9614.                         {
  9615.                             --pszTo;
  9616.                             break;
  9617.                         }
  9618.                     }
  9619.  
  9620.                     if (0 == cchMax)
  9621.                         *pszTo = L'\0';
  9622.  
  9623.                     //
  9624.                     // In some locals, the accelerator is identified in brackets at the
  9625.                     // end of the string, so if we strip ampersands, we strip these too.
  9626.                     //
  9627.                     if (--pszTo >= wzBuf && *pszTo == L')')
  9628.                     {
  9629.                         while (--pszTo >= wzBuf)
  9630.                         {
  9631.                             if (*pszTo == L'(')
  9632.                             {
  9633.                                 *pszTo = L'\0';
  9634.                                 break;
  9635.                             }
  9636.                         }
  9637.                     }
  9638.                 }
  9639.                 else
  9640.                 {
  9641.                     wzBuf[0] = 0;
  9642.                 }
  9643.  
  9644.                 switch (uMsg)
  9645.                 {
  9646.                     case WM_MEASUREITEM:
  9647.                         MeasureMenuItem((MEASUREITEMSTRUCT *)lParam, wzBuf);
  9648.                         break;
  9649.                     case WM_DRAWITEM:
  9650.                         int iIcon = (rVerb.iIcon != -1) ? rVerb.iIcon : 0;
  9651.                         DrawMenuItem((LPDRAWITEMSTRUCT)lParam, wzBuf, iIcon);
  9652.                         break;
  9653.                 }
  9654.             }
  9655.         }
  9656.         default:
  9657.            return CallWindowProc(pThis->_lpfnOldWndProc, hwnd, uMsg, wParam, lParam);
  9658.     }
  9659.     return 0L;
  9660. }
  9661.  
  9662. #endif // EDIT_HACK
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement