searchns.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 31k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. #include "shellprv.h"
  2. #include "searchns.h"
  3. #include "unicppsdspatch.h"
  4. #include "exdispid.h"
  5. #include <winuser.h>
  6. #define SZ_REGKEY_CTL_SEARCHNAMESPACE  TEXT("Software\Microsoft\Windows\CurrentVersion\Explorer\Controls\SearchNameSpace")
  7. #define CSIDL_DEFAULT_PIDL             CSIDL_RECENT
  8. #define IDS_SEARCH_DEFAULT_LOC         IDS_CSIDL_RECENT
  9. #define COMBO_SUBCLASS_COOKIE          2895
  10. #define EDIT_SUBCLASS_COOKIE           52895
  11. #define LIST_SIZE                      20
  12. // Some stuff added to do timings of populating the list...
  13. #ifdef DEBUG
  14. //#define TIME_POPULATE
  15. #endif
  16. CSearchNameSpaceOC::CSearchNameSpaceOC() : CComboBoxExOC(SZ_REGKEY_CTL_SEARCHNAMESPACE, CSIDL_DEFAULT_PIDL),
  17.         _iDeferPathList(CB_ERR), _iLocalDisk(CB_ERR)
  18. {
  19.     DllAddRef();
  20.     // This allocator should have zero inited the memory, so assert the member variables are empty.
  21.     ASSERT(!_fPopulated);
  22.     ASSERT(!_pidlStart);
  23.     _fFileSysAutoComp = TRUE;
  24.     // ATL needs these to make our window resize automatically.
  25.     m_bWindowOnly = TRUE;
  26.     m_bEnabled = TRUE;
  27.     m_bRecomposeOnResize = TRUE;
  28.     m_bResizeNatural = TRUE;
  29. }
  30. CSearchNameSpaceOC::~CSearchNameSpaceOC()
  31. {
  32.     ILFree(_pidlStart); // should long be gone, but...
  33.     // Get rid of connection point as well...
  34.     if (_dwCookie) {
  35.         _pcpBrowser->Unadvise(_dwCookie);
  36.         ATOMICRELEASE(_pcpBrowser);
  37.         _dwCookie = 0;
  38.     }
  39.     DllRelease();
  40. }
  41. LRESULT CSearchNameSpaceOC::_OnDeleteItemMessage(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
  42. {
  43.     // HACKHACK: combobox (comctl32comboex.c) will pass a LPNMHDR, but it's really
  44.     //          a PNMCOMBOBOXEX (which has a first element of LPNMHDR).  This function
  45.     //          can use this type cast iff it's guaranteed that this will only come from
  46.     //           a function that behaves in this perverse way.
  47.     LRESULT lRet = _DeleteNamespaceComboItem( pnmh ) ;
  48.     bHandled = FALSE;
  49.     return lRet ;
  50. }
  51. LRESULT CSearchNameSpaceOC::_OnFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & bHandled)
  52. {
  53.     // CComControlBase::InPlaceActivate() will call us back recursively, so ignore the second call. 
  54.     TraceMsg(TF_CUSTOM1, "in CSearchNameSpaceOC::_OnFocus(), _fInRecursion=%d", _fInRecursion);
  55.     if (_fInRecursion)
  56.         return 1;       // We already did the set focus.
  57.     _fInRecursion = TRUE;
  58.     _PrivateActivate();
  59.     LRESULT lResult = ::SendMessage(_hwndComboBox, uMsg, wParam, lParam);
  60.     bHandled = FALSE;
  61.     _fInRecursion = FALSE;
  62.     return 1;
  63. }
  64. HRESULT CSearchNameSpaceOC::_PrivateActivate(void)
  65. {
  66.     TraceMsg(TF_CUSTOM1, "in CSearchNameSpaceOC::_PrivateActivate(), _fInRecursion=%d", _fInRecursion);
  67.     if (!m_bUIActive)
  68.         CComControlBase::InPlaceActivate(OLEIVERB_UIACTIVATE);
  69.     return S_OK;
  70. }
  71. // in unicppcpymovto.cpp
  72. extern int BrowseCallback(HWND hwnd, UINT msg, LPARAM lParam, LPARAM lpData);
  73. HRESULT CSearchNameSpaceOC::_BrowseForDirectory(LPTSTR pszPath, DWORD cchSize)
  74. {
  75.     HRESULT hr = E_FAIL;
  76.     LPITEMIDLIST pidlRoot = SHCloneSpecialIDList(NULL, CSIDL_DRIVES, TRUE);
  77.     if (EVAL(pidlRoot))
  78.     {
  79.         LPITEMIDLIST pidlDefault = SHCloneSpecialIDList(NULL, CSIDL_PERSONAL, TRUE);
  80.         
  81.         if (EVAL(pidlDefault))
  82.         {
  83.             TCHAR szTitle[MAX_PATH];
  84.             if (EVAL(LoadString(HINST_THISDLL, IDS_SNS_BROWSERFORDIR_TITLE, szTitle, ARRAYSIZE(szTitle))))
  85.             {
  86.                 // Yes, so display the dialog and replace the display text with the path
  87.                 // if something was selected.
  88.                 BROWSEINFO bi = {0};
  89.                 LPITEMIDLIST pidl;
  90.                 bi.hwndOwner        = _hwndComboBox;
  91.                 // bi.pszDisplayName   = pszPath; - // If we want to display a friendly name then set this value
  92.                 bi.pidlRoot         = pidlRoot;
  93.                 bi.lpszTitle        = szTitle;
  94.                 bi.ulFlags          = (BIF_EDITBOX | BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS | BIF_USENEWUI);
  95.                 bi.lpfn             = BrowseCallback;
  96.                 bi.lParam           = (LPARAM) &pidlDefault;
  97.                 ASSERT(MAX_PATH <= cchSize);    // bi.pszDisplayName requires this
  98.                 // Display Dialog and see if they cancelled or not.
  99.                 hr = S_FALSE;
  100.                 pidl = SHBrowseForFolder(&bi);
  101.                 if (pidl)
  102.                 {
  103.                     SHGetPathFromIDList(pidl, pszPath);
  104.                     ILFree(pidl);
  105.                     hr = S_OK;
  106.                 }
  107.             }
  108.             ILFree(pidlDefault);
  109.         }
  110.         ILFree(pidlRoot);
  111.     }
  112.     return hr;
  113. }
  114. LRESULT CSearchNameSpaceOC::_OnSelectChangeMessage(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
  115. {
  116.     LONG nSelected = (LONG) ::SendMessage(_hwndComboBox, CB_GETCURSEL, 0, 0);
  117.     LPCVOID pvData = (LPCVOID)::SendMessage(_hwndComboBox, CB_GETITEMDATA, nSelected, 0);
  118.     // Was this the "Browse..." item?
  119.     if ((-1 != nSelected) && (INVALID_HANDLE_VALUE == pvData))
  120.     {
  121.         TCHAR szPath[MAX_PATH];
  122.         if (S_OK == _BrowseForDirectory(szPath, ARRAYSIZE(szPath)))
  123.         {
  124.             // They didn't cancel so grab the directory path.
  125.             ::SetWindowText(_hwndComboBox, szPath);
  126.         }
  127.         else
  128.             ::SetWindowText(_hwndComboBox, TEXT(""));   // Do this so we don't leave "Browse..."
  129.     }
  130.     bHandled = FALSE;
  131.     return 1;
  132. }
  133. LRESULT CSearchNameSpaceOC::SubClassWndProc(HWND hwnd, UINT uMessage, WPARAM wParam, LPARAM lParam, WPARAM uIdSubclass, ULONG_PTR dwRefData)
  134. {
  135.     if ((COMBO_SUBCLASS_COOKIE == uIdSubclass) ||
  136.         (EDIT_SUBCLASS_COOKIE == uIdSubclass))
  137.     {
  138.         switch (uMessage)
  139.         {
  140.         case WM_SETFOCUS:
  141.             {
  142.                 CSearchNameSpaceOC * pdtp = (CSearchNameSpaceOC *) dwRefData;
  143.                 if (EVAL(pdtp))
  144.                     pdtp->_PrivateActivate();
  145.             }
  146.             break;
  147.         case WM_DESTROY:
  148.             RemoveWindowSubclass(hwnd, CSearchNameSpaceOC::SubClassWndProc, uIdSubclass);
  149.             break;
  150.         }
  151.     }
  152.     return DefSubclassProc(hwnd, uMessage, wParam, lParam);
  153. }
  154. HWND CSearchNameSpaceOC::Create(HWND hWndParent, RECT& rcPos, LPCTSTR pszWindowName, DWORD dwStyle, DWORD dwExStyle, UINT_PTR nID)
  155. {
  156.     m_hWnd = _CreateComboBoxEx(m_spClientSite, m_hWnd, hWndParent, rcPos, pszWindowName, dwStyle, dwExStyle, nID);
  157.     if (EVAL(_hwndComboBox))
  158.     {
  159.         BOOL fSucceeded;
  160.         HWND hwndComboBox = (HWND)::SendMessage(_hwndComboBox, CBEM_GETCOMBOCONTROL, 0, 0);
  161.         if (EVAL(hwndComboBox))
  162.         {
  163.             fSucceeded = SetWindowSubclass(hwndComboBox, CSearchNameSpaceOC::SubClassWndProc, COMBO_SUBCLASS_COOKIE, (ULONG_PTR) this);
  164.             ASSERT(fSucceeded);
  165.         }
  166.         if (_hwndEdit)  // User may not want combobox to be editable.
  167.         {
  168.             fSucceeded = SetWindowSubclass(_hwndEdit, CSearchNameSpaceOC::SubClassWndProc, EDIT_SUBCLASS_COOKIE, (ULONG_PTR) this);
  169.             ASSERT(fSucceeded);
  170.         }
  171.     }
  172.     if (EVAL(_hwndEdit) && _fFileSysAutoComp)
  173.         SHAutoComplete(_hwndEdit, NULL);
  174.     return m_hWnd;
  175. }
  176. /*
  177. LRESULT CSearchNameSpaceOC::_DisableIconMessage(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
  178. {
  179. //    ::SendMessage(_hwndComboBox, CBEM_SETEXTENDEDSTYLE, CBES_EX_NOEDITIMAGE, 0);    // Disable Icon
  180.     bHandled = FALSE;
  181.     return 1;
  182. }
  183. LRESULT CSearchNameSpaceOC::_EnableIconMessage(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
  184. {
  185. //    ::SendMessage(_hwndComboBox, CBEM_SETEXTENDEDSTYLE, CBES_EX_NOEDITIMAGE, CBES_EX_NOEDITIMAGE);    // Enable Icon
  186.     bHandled = FALSE;  // BUGBUG
  187.     return 1;
  188. }
  189. */
  190. // IPersistPropertyBag
  191. HRESULT CSearchNameSpaceOC::Load(IPropertyBag * pPropBag, IErrorLog * pErrorLog)
  192. {
  193.     HRESULT hr = S_FALSE;
  194.     VARIANT var;
  195.     TraceMsg(TF_CUSTOM1, "in CSearchNameSpaceOC::Load()");
  196.     // TODO: Load in SearchNameSpace specific settings.
  197.     var.vt = VT_UI4;
  198.     var.ulVal = NULL;
  199.     hr = pPropBag->Read(L"AutoComplete In File System", &var, NULL);
  200.     if (SUCCEEDED(hr) && var.vt==VT_UI4)
  201.         _fFileSysAutoComp = var.ulVal;
  202.     hr = CComboBoxExOC::_Load(pPropBag, pErrorLog);
  203.     return S_OK;
  204. }
  205. HRESULT CSearchNameSpaceOC::_GetSelectText(LPTSTR pszSelectText, DWORD cchSize, BOOL fDisplayName)
  206. {
  207.     LPITEMIDLIST pidl = SHCloneSpecialIDList(NULL, CSIDL_DEFAULT_PIDL, TRUE);
  208.     if (EVAL(pidl))
  209.     {
  210.         UINT shgdnf = (fDisplayName ? SHGDN_NORMAL : SHGDN_FORPARSING | SHGDN_FORADDRESSBAR);
  211.         SHGetNameAndFlags(pidl, shgdnf, pszSelectText, cchSize, NULL);
  212.         ILFree(pidl);
  213.     }
  214.     return S_OK;
  215. }
  216. HRESULT CSearchNameSpaceOC::IOleInPlaceObject_InPlaceDeactivate(void)
  217. {
  218.     // Take this time to persist out selection.
  219.     TCHAR szRegValue[MAX_PATH];
  220.     // sortof gross, but save room for ! at start to say that this is user input...
  221.     TCHAR szDisplayName[MAX_URL_STRING+1];
  222.     LPTSTR pszDisplayName = &szDisplayName[1];
  223.     LPCTSTR pszPath = NULL;
  224.     LRESULT nIndex = _GetCurItemTextAndIndex( FALSE, pszDisplayName, ARRAYSIZE(szDisplayName)-1);
  225.     TraceMsg(TF_CUSTOM1, "in CSearchNameSpaceOC::CSearchNameSpaceOC::IOleInPlaceObject_InPlaceDeactivate(), _fInRecursion=%d", _fInRecursion);
  226.     _fPopulated = FALSE;    // This call will destroy the window.
  227.     if (nIndex == -1)
  228.     {
  229.         // we are adding a speed hack to the control that allows us to know the next time we load this control
  230.         // that this was user input data.  We detect if it had an ! at the start (not a valid start for a path) and if so
  231.         // simply restore the path.
  232.         szDisplayName[0] = TEXT('!');
  233.         pszDisplayName = szDisplayName;
  234.     }
  235.     else
  236.         pszPath = (LPCTSTR)::SendMessage(_hwndComboBox, CB_GETITEMDATA, (WPARAM)nIndex, (LPARAM)0);
  237.     SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CTL_SEARCHNAMESPACE, 
  238.             (_pszPersistString ? _pszPersistString : SZ_REGVALUE_LAST_SELECTION), REG_SZ, 
  239.             (LPVOID)pszDisplayName, (lstrlen(pszDisplayName) + 1) * sizeof(TCHAR));
  240.     wnsprintf(szRegValue, ARRAYSIZE(szRegValue), TEXT("%s_Path"), (_pszPersistString ? _pszPersistString : SZ_REGVALUE_LAST_SELECTION));
  241.     SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CTL_SEARCHNAMESPACE, szRegValue, REG_SZ, 
  242.             (LPVOID)(pszPath ? pszPath : pszDisplayName), 
  243.             (lstrlen(pszPath ? pszPath : pszDisplayName) + 1) * sizeof(TCHAR));
  244.     return CComControlBase::IOleInPlaceObject_InPlaceDeactivate();
  245. }
  246. HRESULT CSearchNameSpaceOC::_Populate(void)
  247. {
  248. //    if (_fPopulated)
  249. //        return S_OK;        // Done.
  250. #ifdef TIME_POPULATE
  251. #define ENDTIME(x) DWORD x = GetTickCount()
  252.     DWORD dwStart = GetTickCount();
  253. #else 
  254. #define ENDTIME(x)
  255. #endif
  256.     _fPopulated = TRUE;
  257.     ASSERT(_hwndComboBox);
  258.     ::SendMessage(_hwndComboBox, CB_RESETCONTENT, 0, 0L);
  259.     _iLocalDisk = CB_ERR;   // reset to default value...
  260.     _iDeferPathList = CB_ERR;
  261.     // Document Folders
  262.     _AddResourceAndCsidlStr(IDS_CSIDL_PERSONAL, CSIDL_PERSONAL, CSIDL_PERSONAL, LISTINSERT_LAST, NO_ITEM_INDEX);       //  My Documents (IDS_CSIDL_PERSONAL)
  263.     _AddCsidlItemStr(CSIDL_DESKTOPDIRECTORY, CSIDL_DESKTOP, LISTINSERT_LAST, NO_ITEM_INDEX);                                    //  Desktop
  264.     ENDTIME(dwPer);
  265.     // My Computer
  266.     _AddMyComputer();                                                                                               // My Computer Drives
  267.     ENDTIME(dwMyComp);
  268.     _AddLocalHardDrives();                                                                                          //  Local HardDrives (C:, D:, E:)
  269.     ENDTIME(dwLocDrives);
  270.     _AddDrives();                                                                                                   //  each drive
  271.     ENDTIME(dwDrives);
  272.     // My Network Places
  273.     _AddMyNetworkPlaces();                                                                                          // My Network Places
  274.     ENDTIME(dwMyNet);
  275.     _AddMyNetworkPlacesItems();                                                                                     //  Nethood and maybe PubPlaces
  276.     ENDTIME(dwMyNetI);
  277.     // Recent Folder
  278.     _AddRecentFolderAndEntries(TRUE);                                                                               // Recent Folder
  279.     ENDTIME(dwRecent);
  280.     // Browse...
  281.     _AddBrowseItem();                                                                                             // Recent Folder
  282.     _SetDefaultSelect();
  283. #ifdef TIME_POPULATE
  284.     TraceMsg(TF_GENERAL, "Populate Total Time=%d", (GetTickCount()-dwStart));
  285. DWORD dwLast = dwStart;
  286. #define PDELTA(x, y)  TraceMsg(TF_GENERAL, "        %s=%d", TEXT(x), (y-dwLast)); dwLast = y;
  287.     PDELTA("My Computer", dwMyComp);
  288.     PDELTA("Local Drives", dwLocDrives);
  289.     PDELTA("All Drives", dwDrives);
  290.     PDELTA("My Network", dwMyNet);
  291.     PDELTA("My Network Items", dwMyNetI);
  292.     PDELTA("Recent and Items", dwRecent);
  293. #endif
  294.     return S_OK;
  295. }
  296. HRESULT CSearchNameSpaceOC::_AddMyComputer(void)
  297. {
  298.     CBXITEM item ;
  299.     HRESULT hr = _MakeMyComputerCbxItem( &item ) ;
  300.     if( SUCCEEDED( hr ) )
  301.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, NULL ) ;
  302.     return hr;
  303. }
  304. HRESULT CSearchNameSpaceOC::_AddLocalHardDrives(void)
  305. {
  306.     CBXITEM item ;
  307.     HRESULT hr = _MakeLocalHardDrivesCbxItem( &item ) ;
  308.     if( SUCCEEDED( hr ) )
  309.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, &_iLocalDisk ) ;
  310.     return hr;
  311. }
  312. HRESULT CSearchNameSpaceOC::_CustomizeName(UINT idString, LPTSTR szDisplayName, DWORD cchSize)
  313. {
  314.     if (IDS_SNS_LOCALHARDDRIVES == idString)
  315.     {
  316.         TCHAR szDriveList[MAX_PATH];    // Needs to be 'Z'-'A' (26) * 3 + 1 = 79.
  317.         TCHAR szTemp[MAX_PATH];
  318.         TCHAR szDrive[3] = TEXT("A:");
  319.         int nSlot = 0;
  320.         TCHAR chDriveLetter;
  321.         for (chDriveLetter = TEXT('A'); chDriveLetter <= TEXT('Z'); chDriveLetter++)
  322.         {
  323.             szDrive[0] = chDriveLetter;
  324.             if (DRIVE_FIXED == GetDriveType(szDrive))
  325.             {
  326.                 if (nSlot) // Do we need to add a separator before we add the next item?
  327.                     szDriveList[nSlot++] = TEXT(','); // terminate list.  
  328.                 szDriveList[nSlot++] = chDriveLetter; // terminate list.  
  329.                 szDriveList[nSlot++] = TEXT(':'); // terminate list.  
  330.             }
  331.         }
  332.         szDriveList[nSlot] = 0; // terminate list.  
  333.         wsprintf(szTemp, szDisplayName, szDriveList);
  334.         StrCpyN(szDisplayName, szTemp, cchwSize);     // Put back into the final location.
  335.     }
  336.     return S_OK;
  337. }
  338. HRESULT CSearchNameSpaceOC::_AddMappedDrives(LPITEMIDLIST pidl)
  339. {
  340.     CBXITEM item ;
  341.     HRESULT hr = _MakeMappedDrivesCbxItem( &item, pidl) ;
  342.     if( SUCCEEDED( hr ) )
  343.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, NULL ) ;
  344.     return hr ;
  345. }
  346. HRESULT CSearchNameSpaceOC::_AddNethoodDirs(LPITEMIDLIST pidl)
  347. {
  348.     CBXITEM item ;
  349.     HRESULT hr = _MakeNethoodDirsCbxItem( &item, pidl ) ;
  350.     if( SUCCEEDED( hr ) )
  351.     {
  352.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, NULL ) ;
  353.         if( SUCCEEDED( hr ) )
  354.             EVAL(_AddPath( item.szText )) ;  // TODO: Use something larger than MAX_PATH.
  355.     }
  356.     return hr ;
  357. }
  358. HRESULT CSearchNameSpaceOC::_AddRecentFolderAndEntries(BOOL fAddEntries)
  359. {
  360.     CBXITEM item ;
  361.     HRESULT hr = _MakeRecentFolderCbxItem( &item ) ;
  362.     if( SUCCEEDED( hr ) )
  363.     {
  364.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, &_iDeferPathList ) ;
  365.     
  366.         if (fAddEntries)
  367.             _ReallyEnumRecentFolderAndEntries(fAddEntries);
  368.     }
  369.     return S_OK;
  370. }
  371. // Ok we now need to do the work to get the paths contained in recent...
  372. HRESULT CSearchNameSpaceOC::_ReallyEnumRecentFolderAndEntries(BOOL fAddEntries)
  373. {
  374.         LPTSTR pszPath = NULL;
  375.         // Now build the list and optional the entries
  376.         _EnumRecentAndGeneratePath( fAddEntries, _EnumRecentAndGenPathCB, this );
  377.         if (!_pszPathList || !*_pszPathList)
  378.         {
  379.             // Recent is empty, for now assume local hard disks...
  380.             if (_iLocalDisk != CB_ERR)
  381.             {
  382.                 LPTSTR pszString;
  383.                 pszString = (LPTSTR)::SendMessage(_hwndComboBox, CB_GETITEMDATA, _iLocalDisk, 0);
  384.                 Str_SetPtr(&_pszPathList, pszString);
  385.             }
  386.             else
  387.             {
  388.                 // handle case where we may not have enum the list...
  389.                 TCHAR szPath[MAX_PATH];
  390.                 _BuildDrivesList(DRIVE_FIXED, TEXT(";"), TEXT(":\"), szPath, ARRAYSIZE(szPath));
  391.                 Str_SetPtr(&_pszPathList, szPath);
  392.             }
  393.         }
  394.         // Now update the path for the item to the calculated path.
  395.         _UpdateDeferredPathFromPathList();
  396.     return S_OK;
  397. }
  398. HRESULT CSearchNameSpaceOC::_EnumRecentAndGenPathCB( LPCTSTR pszPath, BOOL fAddEntries, LPVOID pvParam )
  399. {
  400.     CSearchNameSpaceOC* pThis = (CSearchNameSpaceOC*)pvParam ;
  401.     ASSERT( pThis ) ;
  402.     EVAL(pThis->_AddPath(pszPath));
  403.     if (fAddEntries)
  404.     {
  405.         LPTSTR psz = NULL;
  406.         Str_SetPtr(&psz, pszPath);
  407.         CBXITEM item ;
  408.         if( SUCCEEDED( _MakeCbxItemKnownImage( &item, pszPath, (LPVOID)psz,
  409.                                                3, 3, LISTINSERT_LAST, ITEM_INDEX ) ) )
  410.             _AddCbxItemToComboBox( pThis->_hwndComboBox, &item, NULL ) ;
  411.     }
  412.     return S_OK ;
  413. }
  414. HRESULT CSearchNameSpaceOC::_AddBrowseItem(void)
  415. {
  416.     CBXITEM item ;
  417.     HRESULT hr = _MakeBrowseForCbxItem( &item ) ;
  418.     if( SUCCEEDED( hr ) )
  419.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, NULL ) ;
  420.     return hr;
  421. }
  422. BOOL CSearchNameSpaceOC::_AddPath(LPCTSTR pszPath)
  423. {
  424.     BOOL fSuccess;
  425.     TCHAR szPathList[MAX_PATH * LIST_SIZE];
  426.     szPathList[0] = 0;
  427.     if (_pszPathList)
  428.         StrCpyN(szPathList, _pszPathList, ARRAYSIZE(szPathList));
  429.     fSuccess = SafePathListAppend(szPathList, ARRAYSIZE(szPathList), pszPath);
  430.     Str_SetPtr(&_pszPathList, szPathList);
  431.     return fSuccess;
  432. }
  433. HRESULT CSearchNameSpaceOC::_AddMyNetworkPlaces(void)
  434. {
  435.     CBXITEM item ;
  436.     LPTSTR pszPath = NULL;
  437.     Str_SetPtr(&pszPath, (_pszPathList ? _pszPathList : TEXT("")));
  438.     HRESULT hr = _MakeNetworkPlacesCbxItem( &item, pszPath ) ;
  439.     if( SUCCEEDED( hr ) )
  440.     {
  441.         hr = _AddCbxItemToComboBox( _hwndComboBox, &item, &_iDeferPathList ) ;
  442.         if( SUCCEEDED( hr ) )
  443.             Str_SetPtr(&_pszPathList, NULL);
  444.     }
  445.     return hr ;
  446. }
  447. HRESULT CSearchNameSpaceOC::_AddMyNetworkPlacesItems(void) 
  448.     HRESULT hr = _EnumSpecialItemIDs(CSIDL_NETHOOD, (SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN), 
  449.             _AddNethoodDirsCB, this); 
  450.     if (SUCCEEDED(hr))
  451.         _UpdateDeferredPathFromPathList();
  452.     return hr;
  453. };
  454. void CSearchNameSpaceOC::_UpdateDeferredPathFromPathList(void) 
  455.     if (_iDeferPathList != CB_ERR)
  456.     {
  457.         LPTSTR pszString = (LPTSTR)::SendMessage(_hwndComboBox, CB_GETITEMDATA, _iDeferPathList, 0);
  458.         Str_SetPtr(&pszString, NULL);
  459.         pszString = (LPTSTR)::SendMessage(_hwndComboBox, CB_SETITEMDATA, _iDeferPathList, (LPARAM)_pszPathList);
  460.         _pszPathList = NULL;
  461.         _iDeferPathList = CB_ERR;
  462.     }
  463. };
  464. HRESULT CSearchNameSpaceOC::_IsDefaultSelection(LPCTSTR pszLastSelection)
  465. {
  466.     BOOL fIsDefault = FALSE;
  467.     TCHAR szDefault[MAX_PATH];
  468.     // if there is a pidl start say no here...
  469.     if (_FGetStartingPidl())
  470.         return FALSE;
  471.     if (EVAL(LoadString(HINST_THISDLL, IDS_SEARCH_DEFAULT_LOC, szDefault, ARRAYSIZE(szDefault))) &&
  472.         !StrCmp(szDefault, pszLastSelection))
  473.     {
  474.         fIsDefault = TRUE;
  475.     }
  476.     return fIsDefault;
  477. }
  478. BOOL CSearchNameSpaceOC::_SetupBrowserCP()
  479. {
  480.     HRESULT hr;
  481.     if (!_dwCookie) {
  482.         _cwbe.SetOwner(this);   // make sure our owner is set...
  483.         IServiceProvider *pspTLB;
  484.         IConnectionPointContainer *pcpc;
  485.         // OK now lets register ourself with the Defview to get any events that they may generate...
  486.         if (SUCCEEDED(hr = IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, 
  487.                 IID_IServiceProvider, (void**)&pspTLB))) {
  488.             if (SUCCEEDED(hr = pspTLB->QueryService(IID_IExpDispSupport, IID_IConnectionPointContainer, (void **)&pcpc))) {
  489.                 hr = ConnectToConnectionPoint(SAFECAST(&_cwbe,IDispatch*), DIID_DWebBrowserEvents2,
  490.                                               TRUE, pcpc, &_dwCookie, &_pcpBrowser);
  491.                 pcpc->Release();
  492.             }
  493.             pspTLB->Release();
  494.         }
  495.     }
  496.     if (_dwCookie) {
  497.         _cwbe.SetWaiting(TRUE);
  498.         return TRUE;
  499.     }
  500.     return FALSE;
  501. }
  502. HRESULT CSearchNameSpaceOC::_RestoreIfUserInputValue(LPCTSTR pszLastSelection)
  503. {
  504.     if (_pidlStart)
  505.     {
  506.         // BUGBUG only works if file system path...
  507.         // Should check to see if get path fails and try to select item by different
  508.         // way...
  509.         TCHAR szPath[ MAX_PATH ];
  510.         BOOL fOk = SHGetPathFromIDList(_pidlStart, szPath);
  511.         ILFree(_pidlStart);
  512.         _pidlStart = NULL;
  513.         if (fOk)
  514.         {
  515.             ::SetWindowText(_hwndComboBox, szPath);
  516.             return S_OK;
  517.         }
  518.     }
  519.     if (*pszLastSelection == TEXT('!'))
  520.     {
  521.         // user input...
  522.         ::SetWindowText(_hwndComboBox, pszLastSelection+1);
  523.         return S_OK;
  524.     }
  525.     return S_FALSE; // say nope we did not handle this.
  526. }
  527. LRESULT CSearchNameSpaceOC::_GetCurItemTextAndIndex( BOOL fPath, LPTSTR psz, int cch)
  528. {
  529.     //  Devnote: Keep logic synched with external version
  530.     //  _GetNamespaceComboItemText(), _GetNamespaceComboSelItemText()
  531.     // Share code with get_String and the save user input code.
  532.     TCHAR szItemName[MAX_PATH];
  533.     LRESULT nSelected = ::SendMessage(_hwndComboBox, CB_GETCURSEL, 0, 0);
  534.     // We don't trust the comboex to handle the edit text properly so try to compensate...
  535.     ::GetWindowText(_hwndComboBox, psz, cch);
  536.     if (-1 != nSelected)
  537.     {
  538.         if (::SendMessage(_hwndComboBox, CB_GETLBTEXT, (WPARAM)nSelected, (LPARAM)szItemName) == CB_ERR)
  539.             szItemName[0]=0;
  540.         LPCTSTR pszString = (LPCTSTR)::SendMessage(_hwndComboBox, CB_GETITEMDATA, nSelected, 0);
  541.         // We doule check that the text of the control is equal to the text of the item.  If not the control
  542.         // probably screwed up and we will use the text...  Also check for error conditions returned from GetItemData...
  543.         // Why would this happen? (Did once during stress...)
  544.         if (pszString && (lstrcmp(pszString, NAMESPACECOMBO_RECENT_PARAM) == 0))
  545.         {
  546.             // oops this is the default case and we have not calculated the default yet, do it now...
  547.             _iDeferPathList = nSelected;
  548.             _ReallyEnumRecentFolderAndEntries(FALSE);
  549.             // Try again...
  550.             pszString = (LPCTSTR)::SendMessage(_hwndComboBox, CB_GETITEMDATA, nSelected, 0);
  551.         }
  552.         
  553.         if (EVAL(!pszString) || EVAL(pszString == (LPCTSTR)CB_ERR) || (lstrcmp(psz, szItemName) != 0))
  554.             nSelected = -1;
  555.         else
  556.             StrCpyN(psz, fPath? pszString : szItemName, cch);
  557.     }
  558.     return nSelected;
  559. }
  560. // IComboBoxExOC
  561. HRESULT CSearchNameSpaceOC::get_String(OUT BSTR *pbs)
  562. {
  563.     if (EVAL(pbs && _hwndComboBox))
  564.     {
  565.         TCHAR szPath[MAX_PATH];
  566.         _GetCurItemTextAndIndex( TRUE, szPath, ARRAYSIZE(szPath));
  567. #ifdef UNICODE
  568.         *pbs = SysAllocString(szPath);
  569. #else // UNICODE
  570.         WCHAR wzString[MAX_URL_STRING];
  571.         SHAnsiToUnicode(szPath, wzString, ARRAYSIZE(wzString));
  572.         *pbs = SysAllocString(wzString);
  573. #endif // UNICODE
  574.     }
  575.     return S_OK;
  576. }
  577. HRESULT CSearchNameSpaceOC::put_String(IN BSTR bs)
  578. {    
  579.     HRESULT hr = S_FALSE;
  580.     if (EVAL(bs))
  581.     {
  582.         CHAR szNewString[MAX_URL_STRING];
  583.         SHUnicodeToAnsi(bs, szNewString, ARRAYSIZE(szNewString));
  584.         hr = CComboBoxExOC::_putString(szNewString);
  585.     }
  586.     return hr;
  587. }
  588. // *** ISearchNameSpaceOC ***
  589. HRESULT CSearchNameSpaceOC::get_IsValidSearch(OUT VARIANT_BOOL * pfValid)
  590. {
  591.     if (!pfValid)
  592.         return S_FALSE;
  593.     // we start by assuming the search is valid
  594.     *pfValid = VARIANT_TRUE;
  595.     // Get the selected item index;
  596.     LRESULT nIndex = ::SendMessage(_hwndComboBox, CB_GETCURSEL, 0, 0);
  597.     // If any item is selected then we are valid because we only have valid items in the combo box.
  598.     if (-1 == nIndex)
  599.     {
  600.         // If no item is selected the user might have entered a path.  Any string is considered
  601.         // valid so we simply need to check if the path is empty.  If the path is empty then
  602.         // this is an invalid search.  Note that an empty path is a valid search if the index
  603.         // does not equal -1.
  604.         TCHAR szPath[3];
  605.         ::GetWindowText(_hwndComboBox, szPath, ARRAYSIZE(szPath));
  606.         if ( !szPath[0] )
  607.         {
  608.             // So basically the only invalid case is when nIndex == -1 and the path is NULL
  609.             *pfValid = VARIANT_FALSE;
  610.         }
  611.     }
  612.     return S_OK;
  613. }
  614. HRESULT CSearchNameSpaceOC::SetClientSite(IOleClientSite * pClientSite)
  615. {
  616.     if (!pClientSite && _dwCookie) 
  617.     {
  618.         _pcpBrowser->Unadvise(_dwCookie);
  619.         ATOMICRELEASE(_pcpBrowser);
  620.         _dwCookie = 0;
  621.     }
  622.     return CComControlBase::IOleObject_SetClientSite(pClientSite);
  623. }
  624. HRESULT CSearchNameSpaceOC::_SetDefaultSelect(void)
  625. {
  626.     TCHAR szDefaultDisplayName[MAX_URL_STRING];
  627.     TCHAR szDefaultPath[MAX_URL_STRING];
  628.     if (EVAL(SUCCEEDED(_GetSelectText(szDefaultDisplayName, ARRAYSIZE(szDefaultDisplayName), TRUE))) &&
  629.         EVAL(SUCCEEDED(_GetSelectText(szDefaultPath, ARRAYSIZE(szDefaultPath), FALSE))))
  630.     {
  631.         _SetSelect(szDefaultDisplayName, szDefaultPath);
  632.     }
  633.     return S_OK;
  634. }
  635. #define SZ_WEB_SEARCHTEMPLATE_PATH      TEXT("Web\fsearch.htm")
  636. HRESULT CSearchNameSpaceOC::_GetSearchUrlW(LPWSTR pwzUrl, DWORD cchSize)
  637. {
  638.     TCHAR szUrlPath[MAX_PATH];
  639.     if (EVAL(GetWindowsDirectory(szUrlPath, ARRAYSIZE(szUrlPath))))
  640.     {
  641.         DWORD cchTempSize;
  642.         PathAppend(szUrlPath, SZ_WEB_SEARCHTEMPLATE_PATH);
  643.         EVAL(SUCCEEDED(UrlCreateFromPath(szUrlPath, szUrlPath, &cchTempSize, 0)));
  644.         SHTCharToUnicode(szUrlPath, pwzUrl, cchSize);
  645.     }
  646.     return S_OK;
  647. }
  648. BOOL CSearchNameSpaceOC::_IsSecure(void)
  649. {    
  650.     BOOL fSecure = FALSE;
  651.     if (EVAL(m_spClientSite))
  652.     {
  653.         if (S_OK == LocalZoneCheck((IUnknown *) m_spClientSite))
  654.             fSecure = TRUE;
  655.     }
  656.     else
  657.         TraceMsg(TF_CUSTOM1, "in CSearchNameSpaceOC::_GetEditboxBuddy() We don't have a parent yet.");
  658.     return fSecure;
  659. }
  660. BOOL CSearchNameSpaceOC::_FGetStartingPidl(void)
  661. {    
  662.     if (EVAL(m_spClientSite))
  663.     {
  664.         IShellBrowser  *psb;
  665.         IShellView     *psv;
  666.         IWebBrowser2* pwb = NULL;
  667.         if (SUCCEEDED(IUnknown_QueryService(m_spClientSite, SID_STopLevelBrowser, 
  668.                 IID_IShellBrowser, (void **) &psb)))
  669.         {
  670.             
  671.             // Warning:: We check for shell view simply to see how the search pane was
  672.             // loaded.  If this fails it is because we were loaded on the CoCreateInstance
  673.             // of the browser window and as such it is a race condition to know if the
  674.             // properties were set or not.  So in this case wait until we get a 
  675.             // navigate complete.  This lets us know for sure if a save file was passed
  676.             // in or not.
  677.             if (SUCCEEDED(psb->QueryActiveShellView(&psv))) 
  678.             {
  679.                 if (SUCCEEDED(IUnknown_QueryService(psb, SID_SWebBrowserApp, 
  680.                         IID_IWebBrowser2, (void **) &pwb)))
  681.                 {
  682.                     SA_BSTR bstr;
  683.                     VARIANT var;       
  684.                     VariantInit(&var);
  685.                     lstrcpyW(bstr.wsz, L"Search_PidlFolder");
  686.                     bstr.cb = lstrlenW(bstr.wsz) * sizeof(WCHAR);
  687.                     pwb->GetProperty(bstr.wsz, &var);
  688.         
  689.                     if (var.vt != VT_EMPTY)
  690.                     {
  691.                         _pidlStart = VariantToIDList(&var);
  692.                         VariantClear(&var);
  693.                         pwb->PutProperty(bstr.wsz, var);  // clear it out so only use once
  694.                     }
  695.                     pwb->Release();
  696.                 }
  697.                 psv->Release();
  698.             }
  699.             else
  700.             {
  701.                 // appears to be race condition to load
  702.                 if (!_fDeferPidlStartTried)
  703.                 {
  704.                     TraceMsg(TF_WARNING, "CDFCommand::MaybeRestoreSearch - QueryActiveShellView failed...");
  705.                     _fDeferPidlStart = TRUE;
  706.                     if (!_SetupBrowserCP())
  707.                         _fDeferPidlStart = FALSE;
  708.                 }
  709.             }
  710.             psb->Release();
  711.         }
  712.     }
  713.     return _pidlStart != NULL;
  714. }
  715. HRESULT CSearchNameSpaceOC::_AddDefaultItem(void)
  716. {    
  717.     _AddRecentFolderAndEntries(FALSE);
  718.     ::SendMessage(_hwndComboBox, CB_SETCURSEL, (WPARAM)0, 0);     // Select "Recent"
  719.     return S_OK;
  720. }
  721. // Implemention of our IDispatch to hookup to the top level browsers connnection point...
  722. ULONG CSearchNameSpaceOC::CWBEvents2::AddRef(void)        
  723. {
  724.     return (SAFECAST(_pcsns, IComboBoxExOC *))->AddRef();
  725. }
  726. ULONG CSearchNameSpaceOC::CWBEvents2::Release(void)        
  727. {
  728.     return (SAFECAST(_pcsns, IComboBoxExOC *))->Release();
  729. }
  730. STDMETHODIMP CSearchNameSpaceOC::CWBEvents2::QueryInterface(REFIID riid, LPVOID *ppvObj)
  731. {
  732.     if ( riid == IID_IUnknown || riid == IID_IDispatch || riid == DIID_DWebBrowserEvents2
  733.          || riid == DIID_DWebBrowserEvents){
  734.         *ppvObj = (LPVOID)this;
  735.         AddRef();
  736.     }
  737.     else
  738.     {
  739.         return E_NOINTERFACE;
  740.     }
  741.     return NOERROR;
  742. }
  743. STDMETHODIMP CSearchNameSpaceOC::CWBEvents2::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo, UINT * puArgErr)
  744. {
  745.     if (_fWaitingForNavigate) {
  746.         TraceMsg(TF_WARNING, "CSearchNameSpaceOC::CWBEvents2::Invoke dispid=%d.",dispidMember);
  747.         if ((dispidMember == DISPID_NAVIGATECOMPLETE) || (dispidMember == DISPID_DOCUMENTCOMPLETE)) {
  748.             // Assume this is ours... Should maybe check parameters...
  749.             _fWaitingForNavigate = FALSE;
  750.             // Now see if it is a case where we are to restore the search...
  751.             if (_pcsns->_fDeferPidlStart)
  752.             {
  753.                 _pcsns->_fDeferPidlStart = FALSE;
  754.                 _pcsns->_fDeferPidlStartTried = TRUE;
  755.                 if (_pcsns->_FGetStartingPidl())
  756.                 {
  757.                     // Call the restoreuser input function which will
  758.                     // if possible update the combobox...
  759.                     _pcsns->_RestoreIfUserInputValue(TEXT(""));
  760.                 }
  761.             }
  762.         }
  763.     }
  764.     return S_OK;
  765. }