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

4221 lines
139 KiB

  1. #include "pch.h"
  2. #include "uxtheme.h"
  3. #pragma hdrstop
  4. /*-----------------------------------------------------------------------------
  5. / Private data and helper functions
  6. /----------------------------------------------------------------------------*/
  7. //
  8. // ICommonQuery stuff
  9. //
  10. class CCommonQuery : public ICommonQuery, IObjectWithSite
  11. {
  12. private:
  13. LONG _cRef;
  14. IUnknown* _punkSite;
  15. public:
  16. CCommonQuery();
  17. ~CCommonQuery();
  18. // IUnknown
  19. STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  20. STDMETHOD_(ULONG, AddRef)();
  21. STDMETHOD_(ULONG, Release)();
  22. // ICommonQuery
  23. STDMETHOD(OpenQueryWindow)(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject);
  24. // IObjectWithSite
  25. STDMETHODIMP SetSite(IUnknown* punk);
  26. STDMETHODIMP GetSite(REFIID riid, void **ppv);
  27. };
  28. //
  29. // View layout constants used by our dialogs
  30. //
  31. #define VIEWER_DEFAULT_CY 200
  32. #define COMBOEX_IMAGE_CX 16
  33. #define COMBOEX_IMAGE_CY 16
  34. typedef struct
  35. {
  36. HDSA hdsaPages; // DSA containing page entries
  37. DWORD dwFlags; // flags
  38. CLSID clsidForm; // CLSID identifier for this form
  39. LPTSTR pTitle; // title used for drop down / title bar
  40. HICON hIcon; // hIcon passed by caller
  41. INT iImage; // image list index of icon
  42. INT iForm; // visible index of form in control
  43. INT iPage; // currently selected page on form
  44. } QUERYFORM, * LPQUERYFORM;
  45. typedef struct
  46. {
  47. CLSID clsidForm; // CLSID to associate this form with
  48. LPCQPAGE pPage; // CQPAGE structures
  49. LPCQPAGEPROC pPageProc; // PageProc's used by thunking layer
  50. LPARAM lParam; // PAGEPROC lParam
  51. HWND hwndPage; // hWnd of page dialog // = NULL if none
  52. } QUERYFORMPAGE, * LPQUERYFORMPAGE;
  53. typedef struct
  54. {
  55. LPCQSCOPE pScope;
  56. INT iImage;
  57. } QUERYSCOPE, * LPQUERYSCOPE;
  58. class CQueryFrame : public IQueryFrame
  59. {
  60. friend INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
  61. friend INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  62. public:
  63. CQueryFrame(IUnknown* punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject);
  64. ~CQueryFrame();
  65. // IUnknown
  66. STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  67. STDMETHOD_(ULONG, AddRef)();
  68. STDMETHOD_(ULONG, Release)();
  69. // Internal helper functions
  70. STDMETHOD(DoModal)(HWND hwndParent);
  71. // IQueryFrame
  72. STDMETHOD(AddScope)(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect);
  73. STDMETHOD(GetWindow)(THIS_ HWND* phWnd);
  74. STDMETHOD(InsertMenus)(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth);
  75. STDMETHOD(RemoveMenus)(THIS_ HMENU hmenuShared);
  76. STDMETHOD(SetMenu)(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu);
  77. STDMETHOD(SetStatusText)(THIS_ LPCTSTR pszStatusText);
  78. STDMETHOD(StartQuery)(THIS_ BOOL fStarting);
  79. STDMETHOD(LoadQuery)(THIS_ IPersistQuery* pPersistQuery);
  80. STDMETHOD(SaveQuery)(THIS_ IPersistQuery* pPersistQuery);
  81. STDMETHOD(CallForm)(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
  82. STDMETHOD(GetScope)(THIS_ LPCQSCOPE* ppScope);
  83. STDMETHOD(GetHandler)(THIS_ REFIID riid, void **ppv);
  84. protected:
  85. // Helper functions
  86. VOID CloseQueryFrame(HRESULT hres);
  87. INT FrameMessageBox(LPCTSTR pPrompt, UINT uType);
  88. // Message handlers
  89. HRESULT OnInitDialog(HWND hwnd);
  90. VOID DoEnableControls(VOID);
  91. LRESULT OnNotify(INT idCtrl, LPNMHDR pNotify);
  92. VOID OnSize(INT cx, INT cy);
  93. VOID OnGetMinMaxInfo(LPMINMAXINFO lpmmi);
  94. VOID OnCommand(WPARAM wParam, LPARAM lParam);
  95. VOID OnInitMenu(HMENU hMenu);
  96. VOID OnEnterMenuLoop(BOOL fEntering);
  97. VOID OnMenuSelect(HMENU hMenu, UINT uID);
  98. HRESULT OnFindNow(VOID);
  99. BOOL OnNewQuery(BOOL fAlwaysPrompt);
  100. HRESULT OnBrowse(VOID);
  101. HRESULT OnHelp(LPHELPINFO pHelpInfo);
  102. // Form/Scope helper fucntions
  103. HRESULT InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl);
  104. HRESULT AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i);
  105. HRESULT PopulateScopeControl(VOID);
  106. HRESULT GetSelectedScope(LPQUERYSCOPE* ppQueryScope);
  107. HRESULT AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hkeyForm);
  108. HRESULT GatherForms(VOID);
  109. HRESULT GetForms(HKEY hKeyForms, LPTSTR pName);
  110. HRESULT PopulateFormControl(BOOL fIncludeHidden);
  111. HRESULT SelectForm(REFCLSID clsidForm);
  112. VOID SelectFormPage(LPQUERYFORM pQueryForm, INT iPage);
  113. HRESULT CallFormPages(LPQUERYFORM pQueryForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
  114. LPQUERYFORM FindQueryForm(REFCLSID clsidForm);
  115. private:
  116. LONG _cRef; // reference count for the object
  117. IUnknown* _punkSite; // site object we need to pass through
  118. IQueryHandler* _pQueryHandler; // IQueryHandler object we need to interact with
  119. LPOPENQUERYWINDOW _pOpenQueryWnd; // copy of initial parameters provided by caller
  120. IDataObject** _ppDataObject; // receives the resulting data object from handler
  121. DWORD _dwHandlerViewFlags; // flags from the handler
  122. BOOL _fQueryRunning:1; // = 1 => query has been started, via IQueryFrame::StartQuery(TRUE)
  123. BOOL _fExitModalLoop:1; // = 1 => must leave modal loop
  124. BOOL _fScopesPopulated:1; // = 1 => scope control has been populated
  125. BOOL _fTrackingMenuBar:1; // = 1 => then we are tracking the menu bar, therefore send activates etc
  126. BOOL _fAddScopesNYI:1; // = 1 => did AddScopes return E_NOTIMPL
  127. BOOL _fScopesAddedAsync:1; // = 1 => scopes added async by the handler
  128. BOOL _fScopeImageListSet:1; // = 1 => scope image list has been set
  129. BOOL _fFormFirstEnable:1; // = 1 => enabling controls for first item, so ensure we set focus
  130. HRESULT _hResult; // result value stored by CloseQueryFrame
  131. HKEY _hkHandler; // registry key for the handler
  132. HWND _hwnd; // main window handle
  133. HWND _hwndResults; // result viewer
  134. HWND _hwndStatus; // status bar
  135. HWND _hwndFrame; // Query Pages tab control
  136. HWND _hwndLookForLabel; // "Find:"
  137. HWND _hwndLookFor; // Form combo
  138. HWND _hwndLookInLabel; // "In:"
  139. HWND _hwndLookIn; // Scope combo
  140. HWND _hwndBrowse; // "Browse"
  141. HWND _hwndFindNow; // "Find now"
  142. HWND _hwndStop; // "Stop"
  143. HWND _hwndNewQuery; // "New Query"
  144. HWND _hwndOK; // "OK"
  145. HWND _hwndCancel; // "Cancel"
  146. HWND _hwndFindAnimation; // Query issued animation
  147. HICON _hiconSmall; // large/small app icons
  148. HICON _hiconLarge;
  149. HMENU _hmenuFile; // handle of the frames menu bar
  150. HIMAGELIST _himlForms; // image list for query form objects
  151. SIZE _szMinTrack; // minimum track size of the window
  152. INT _dxFormAreaLeft; // offset to left edge of form area (from window left)
  153. INT _dxFormAreaRight; // offset to right edge of form area (from window right)
  154. INT _dxButtonsLeft; // offset to left edge of buttons (from window right)
  155. INT _dxAnimationLeft; // offset to left edge of aniimation (from window right)
  156. INT _dyResultsTop; // offset to top of results (from top of window)
  157. INT _dyOKTop; // offset to top of "OK" buttom (from results top)
  158. INT _dxGap; // gap between OK + Cancel / LookIn + Browse
  159. INT _dyGap; // gap between bottom of OK,Cancel and the frame.
  160. INT _cyStatus; // height of the status bar
  161. HDSA _hdsaForms; // forms DSA
  162. HDSA _hdsaPages; // pages DSA
  163. SIZE _szForm; // size of the (current form we are displaying)
  164. HDSA _hdsaScopes; // scopes DSA
  165. INT _iDefaultScope; // index of the defualt scope to select (into DSA)
  166. LPQUERYFORM _pCurrentForm; // == NULL if none / else -> form structure
  167. LPQUERYFORMPAGE _pCurrentFormPage; // == NULL if none / else -> page structure
  168. };
  169. //
  170. // Helper functions
  171. //
  172. INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  173. INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
  174. HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid);
  175. INT _FreeScope(LPQUERYSCOPE pQueryScope);
  176. INT _FreeScopeCB(LPVOID pItem, LPVOID pData);
  177. HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam);
  178. INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData);
  179. INT _FreeQueryForm(LPQUERYFORM pQueryForm);
  180. INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData);
  181. INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage);
  182. HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM pForm);
  183. HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE pPage);
  184. //
  185. // Help stuff
  186. //
  187. #define HELP_FILE (NULL)
  188. static DWORD const aHelpIDs[] =
  189. {
  190. 0, 0
  191. };
  192. //
  193. // constant strings
  194. //
  195. TCHAR const c_szCLSID[] = TEXT("CLSID");
  196. TCHAR const c_szForms[] = TEXT("Forms");
  197. TCHAR const c_szFlags[] = TEXT("Flags");
  198. TCHAR const c_szCommonQuery[] = TEXT("CommonQuery");
  199. TCHAR const c_szHandlerIs[] = TEXT("Handler");
  200. TCHAR const c_szFormIs[] = TEXT("Form");
  201. TCHAR const c_szSearchPaneHidden[] = TEXT("SearchPaneHidden");
  202. /*-----------------------------------------------------------------------------
  203. / CCommonQuery
  204. /----------------------------------------------------------------------------*/
  205. CCommonQuery::CCommonQuery() :
  206. _punkSite(NULL), _cRef(1)
  207. {
  208. DllAddRef();
  209. }
  210. CCommonQuery::~CCommonQuery()
  211. {
  212. DoRelease(_punkSite);
  213. DllRelease();
  214. }
  215. // QI handling
  216. ULONG CCommonQuery::AddRef()
  217. {
  218. return InterlockedIncrement(&_cRef);
  219. }
  220. ULONG CCommonQuery::Release()
  221. {
  222. TraceAssert( 0 != _cRef );
  223. ULONG cRef = InterlockedDecrement(&_cRef);
  224. if ( 0 == cRef )
  225. {
  226. delete this;
  227. }
  228. return cRef;
  229. }
  230. HRESULT CCommonQuery::QueryInterface(REFIID riid, void **ppv)
  231. {
  232. static const QITAB qit[] =
  233. {
  234. QITABENT(CCommonQuery, ICommonQuery), // IID_ICommonQuery
  235. QITABENT(CCommonQuery, IObjectWithSite), // IID_IObjectWithSite
  236. {0, 0 },
  237. };
  238. return QISearch(this, qit, riid, ppv);
  239. }
  240. STDAPI CCommonQuery_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  241. {
  242. CCommonQuery *pcq = new CCommonQuery;
  243. if (!pcq)
  244. return E_OUTOFMEMORY;
  245. HRESULT hres = pcq->QueryInterface(IID_IUnknown, (void **)ppunk);
  246. pcq->Release();
  247. return hres;
  248. }
  249. // ICommonQuery methods
  250. STDMETHODIMP CCommonQuery::OpenQueryWindow(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject)
  251. {
  252. HRESULT hres;
  253. CQueryFrame* pQueryFrame = NULL;
  254. TraceEnter(TRACE_QUERY, "CCommonQuery::OpenQueryWindow");
  255. if (!pOpenQueryWnd || (hwndParent && !IsWindow(hwndParent)))
  256. ExitGracefully(hres, E_INVALIDARG, "Bad parameters");
  257. if (ppDataObject)
  258. *(ppDataObject) = NULL;
  259. pQueryFrame = new CQueryFrame(_punkSite, pOpenQueryWnd, ppDataObject);
  260. TraceAssert(pQueryFrame);
  261. if (!pQueryFrame)
  262. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to construct the query window object");
  263. hres = pQueryFrame->DoModal(hwndParent); // don't bother fail gracefully etc
  264. FailGracefully(hres, "Failed on calling DoModal");
  265. exit_gracefully:
  266. DoRelease(pQueryFrame);
  267. TraceLeaveResult(hres);
  268. }
  269. // IObjectWithSite
  270. STDMETHODIMP CCommonQuery::SetSite(IUnknown* punk)
  271. {
  272. HRESULT hres = S_OK;
  273. TraceEnter(TRACE_QUERY, "CCommonQuery::SetSite");
  274. DoRelease(_punkSite);
  275. if (punk)
  276. {
  277. TraceMsg("QIing for IUnknown from the site object");
  278. hres = punk->QueryInterface(IID_IUnknown, (void **)&_punkSite);
  279. FailGracefully(hres, "Failed to get IUnknown from the site object");
  280. }
  281. exit_gracefully:
  282. TraceLeaveResult(hres);
  283. }
  284. STDMETHODIMP CCommonQuery::GetSite(REFIID riid, void **ppv)
  285. {
  286. HRESULT hres;
  287. TraceEnter(TRACE_QUERY, "CCommonQuery::GetSite");
  288. if (!_punkSite)
  289. ExitGracefully(hres, E_NOINTERFACE, "No site to QI from");
  290. hres = _punkSite->QueryInterface(riid, ppv);
  291. FailGracefully(hres, "QI failed on the site unknown object");
  292. exit_gracefully:
  293. TraceLeaveResult(hres);
  294. }
  295. // IQueryFrame stuff
  296. CQueryFrame::CQueryFrame(IUnknown *punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject) :
  297. _cRef(1), _punkSite(punkSite), _pOpenQueryWnd(pOpenQueryWindow),
  298. _ppDataObject(ppDataObject), _hiconLarge(NULL), _hiconSmall(NULL)
  299. {
  300. if (_punkSite)
  301. _punkSite->AddRef();
  302. DllAddRef();
  303. }
  304. CQueryFrame::~CQueryFrame()
  305. {
  306. DoRelease(_punkSite);
  307. if (_hiconLarge)
  308. DestroyIcon(_hiconLarge);
  309. if (_hiconSmall)
  310. DestroyIcon(_hiconSmall);
  311. if (_hkHandler)
  312. RegCloseKey(_hkHandler);
  313. if (_hmenuFile)
  314. DestroyMenu(_hmenuFile);
  315. if (_himlForms)
  316. ImageList_Destroy(_himlForms);
  317. if (_hdsaForms)
  318. {
  319. Trace(TEXT("Destroying QUERYFORM DSA (%d)"), DSA_GetItemCount(_hdsaForms));
  320. DSA_DestroyCallback(_hdsaForms, _FreeQueryFormCB, NULL);
  321. _hdsaForms = NULL;
  322. }
  323. if (_hdsaPages)
  324. {
  325. Trace(TEXT("Destroying QUERYFORMPAGE DSA (%d)"), DSA_GetItemCount(_hdsaPages));
  326. DSA_DestroyCallback(_hdsaPages, _FreeQueryFormPageCB, NULL);
  327. _hdsaPages = NULL;
  328. }
  329. if (_hdsaScopes)
  330. {
  331. Trace(TEXT("Destroying QUERYSCOPE DSA (%d)"), DSA_GetItemCount(_hdsaScopes));
  332. DSA_DestroyCallback(_hdsaScopes, _FreeScopeCB, NULL);
  333. _hdsaScopes = NULL;
  334. }
  335. _pCurrentForm = NULL;
  336. _pCurrentFormPage = NULL;
  337. // Now discard the handler and its window (if we have one), if
  338. // we don't do this they will never kill their objects
  339. if (_hwndResults)
  340. {
  341. DestroyWindow(_hwndResults);
  342. _hwndResults = NULL;
  343. }
  344. DllRelease();
  345. }
  346. // QI handling
  347. ULONG CQueryFrame::AddRef()
  348. {
  349. return InterlockedIncrement(&_cRef);
  350. }
  351. ULONG CQueryFrame::Release()
  352. {
  353. TraceAssert( 0 != _cRef );
  354. ULONG cRef = InterlockedDecrement(&_cRef);
  355. if ( 0 == cRef )
  356. {
  357. delete this;
  358. }
  359. return cRef;
  360. }
  361. HRESULT CQueryFrame::QueryInterface(REFIID riid, void **ppv)
  362. {
  363. static const QITAB qit[] =
  364. {
  365. QITABENT(CQueryFrame, IQueryFrame), // IID_IQueryFrame
  366. {0, 0 },
  367. };
  368. return QISearch(this, qit, riid, ppv);
  369. }
  370. /*-----------------------------------------------------------------------------
  371. / IQueryFrame
  372. /----------------------------------------------------------------------------*/
  373. STDMETHODIMP CQueryFrame::DoModal(HWND hwndParent)
  374. {
  375. HRESULT hres;
  376. HWND hwndFrame = NULL;
  377. HWND hwndFocus = NULL;
  378. HWND hwndTopOwner = hwndParent;
  379. MSG msg;
  380. INITCOMMONCONTROLSEX iccex;
  381. TraceEnter(TRACE_FRAME, "CQueryFrame::DoModal");
  382. // initialize with the query handler we need
  383. //REVIEWED-2002-02-25-lucios.
  384. hres = CoCreateInstance(_pOpenQueryWnd->clsidHandler, NULL, CLSCTX_INPROC_SERVER, IID_IQueryHandler, (LPVOID*)&_pQueryHandler);
  385. FailGracefully(hres, "Failed to get IQueryHandler for the given CLSID");
  386. hres = _pQueryHandler->Initialize(this, _pOpenQueryWnd->dwFlags, _pOpenQueryWnd->pHandlerParameters);
  387. FailGracefully(hres, "Failed to initialize the handler");
  388. // mimic the behaviour of DialogBox by working out which control previously
  389. // had focus, which window to disable and then running a message
  390. // pump for our dialog. Having done this we can then restore the state
  391. // back to something sensible.
  392. _fExitModalLoop = FALSE; // can be changed from hear down
  393. iccex.dwSize = SIZEOF(iccex);
  394. iccex.dwICC = ICC_USEREX_CLASSES;
  395. InitCommonControlsEx(&iccex);
  396. if (_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI)
  397. {
  398. hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FILTER),
  399. hwndParent,
  400. QueryWnd_DlgProc, (LPARAM)this);
  401. }
  402. else
  403. {
  404. hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FIND),
  405. hwndParent,
  406. QueryWnd_DlgProc, (LPARAM)this);
  407. }
  408. if (!hwndFrame)
  409. ExitGracefully(hres, E_FAIL, "Failed to create the dialog");
  410. hwndFocus = GetFocus();
  411. if (hwndTopOwner)
  412. {
  413. // walk up the window stack looking for the window to be disabled, this must
  414. // be the top-most non-child window. If the resulting window is either
  415. // the desktop or is already disabled then don't bother.
  416. while (GetWindowLong(hwndTopOwner, GWL_STYLE) & WS_CHILD)
  417. hwndTopOwner = GetParent(hwndTopOwner);
  418. TraceAssert(hwndTopOwner);
  419. if ((hwndTopOwner == GetDesktopWindow())
  420. || EnableWindow(hwndTopOwner, FALSE))
  421. {
  422. TraceMsg("Parent is disabled or the desktop window, therefore setting to NULL");
  423. hwndTopOwner = NULL;
  424. }
  425. }
  426. ShowWindow(hwndFrame, SW_SHOW); // show the query window
  427. while (!_fExitModalLoop && GetMessage(&msg, NULL, 0, 0) > 0)
  428. {
  429. if (!QueryWnd_MessageProc(hwndFrame, &msg) && !IsDialogMessage(hwndFrame, &msg))
  430. {
  431. TranslateMessage(&msg);
  432. DispatchMessage(&msg);
  433. }
  434. }
  435. // Now tidy up, make the parent the active window, enable the top most
  436. // window if there is one and restore focus as required.
  437. if (hwndTopOwner)
  438. EnableWindow(hwndTopOwner, TRUE);
  439. if (hwndParent && (GetActiveWindow() == hwndFrame))
  440. {
  441. TraceMsg("Passing activation to parent");
  442. SetActiveWindow(hwndParent);
  443. }
  444. if (IsWindow(hwndFocus))
  445. SetFocus(hwndFocus);
  446. DestroyWindow(hwndFrame); // discard the current frame window
  447. exit_gracefully:
  448. DoRelease(_pQueryHandler);
  449. TraceLeaveResult(_hResult);
  450. }
  451. /*---------------------------------------------------------------------------*/
  452. STDMETHODIMP CQueryFrame::AddScope(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect)
  453. {
  454. HRESULT hres;
  455. TraceEnter(TRACE_FRAME, "CQueryFrame::AddScope");
  456. if (!pScope)
  457. ExitGracefully(hres, E_INVALIDARG, "No scope to add to the list");
  458. // Add the scope to the control and then ensure that we either have
  459. // its index stored (for default selection) or we select the
  460. // item.
  461. if (!_hdsaScopes || !DSA_GetItemCount(_hdsaScopes))
  462. {
  463. TraceMsg("First scope being added, thefore selecting");
  464. fSelect = TRUE;
  465. }
  466. hres = InsertScopeIntoList(pScope, i, _fScopesPopulated);
  467. FailGracefully(hres, "Failed to add scope to control");
  468. if (fSelect)
  469. {
  470. if (!_fScopesPopulated)
  471. {
  472. Trace(TEXT("Storing default scope index %d"), ShortFromResult(hres));
  473. _iDefaultScope = ShortFromResult(hres);
  474. }
  475. else
  476. {
  477. Trace(TEXT("Selecting scope index %d"), ShortFromResult(hres));
  478. ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
  479. }
  480. }
  481. // hres = S_OK;
  482. exit_gracefully:
  483. TraceLeaveResult(hres);
  484. }
  485. /*---------------------------------------------------------------------------*/
  486. STDMETHODIMP CQueryFrame::GetWindow(THIS_ HWND* phWnd)
  487. {
  488. TraceEnter(TRACE_FRAME, "CQueryFrame::GetWindow");
  489. TraceAssert(phWnd);
  490. *phWnd = _hwnd;
  491. TraceLeaveResult(S_OK);
  492. }
  493. /*---------------------------------------------------------------------------*/
  494. // Add a menu group to the given menu bar, updating the width index accordingly
  495. // so that other people can merge in accordingly
  496. VOID _DoInsertMenu(HMENU hMenu, INT iIndexTo, HMENU hMenuToInsert, INT iIndexFrom)
  497. {
  498. TCHAR szBuffer[MAX_PATH];
  499. HMENU hPopupMenu = NULL;
  500. TraceEnter(TRACE_FRAME, "_DoInsertMenu");
  501. hPopupMenu = CreatePopupMenu();
  502. if (hPopupMenu)
  503. {
  504. Shell_MergeMenus(hPopupMenu, GetSubMenu(hMenuToInsert, iIndexFrom), 0x0, 0x0, 0x7fff, 0);
  505. //REVIEWED-2002-02-25-lucios.
  506. GetMenuString(hMenuToInsert, iIndexFrom, szBuffer, ARRAYSIZE(szBuffer), MF_BYPOSITION);
  507. InsertMenu(hMenu, iIndexTo, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hPopupMenu, szBuffer);
  508. }
  509. TraceLeave();
  510. }
  511. VOID _AddMenuGroup(HMENU hMenuShared, HMENU hMenuGroup, LONG iInsertAt, LPLONG pWidth)
  512. {
  513. HRESULT hres;
  514. TCHAR szBuffer[MAX_PATH];
  515. HMENU hMenu;
  516. INT i;
  517. TraceEnter(TRACE_FRAME, "_AddMenuGroup");
  518. TraceAssert(hMenuShared);
  519. TraceAssert(hMenuGroup);
  520. TraceAssert(pWidth);
  521. for (i = 0 ; i < GetMenuItemCount(hMenuGroup) ; i++)
  522. {
  523. _DoInsertMenu(hMenuShared, iInsertAt+i, hMenuGroup, i);
  524. *pWidth += 1;
  525. }
  526. TraceLeave();
  527. }
  528. STDMETHODIMP CQueryFrame::InsertMenus(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth)
  529. {
  530. HRESULT hres;
  531. TraceEnter(TRACE_FRAME, "CQueryFrame::InsertMenus");
  532. if (!hmenuShared || !lpMenuWidth)
  533. ExitGracefully(hres, E_INVALIDARG, "Unable to insert menus");
  534. // if we don't have the menu bar already loaded then lets load it,
  535. // having done that we can then add our menu to the bar (we only
  536. // provide entries for the file menu).
  537. if (!_hmenuFile)
  538. {
  539. _hmenuFile = LoadMenu(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDR_FILEMENUGROUP));
  540. if (!_hmenuFile)
  541. ExitGracefully(hres, E_FAIL, "Failed to load base menu defn");
  542. }
  543. _AddMenuGroup(hmenuShared, _hmenuFile, 0, &lpMenuWidth->width[0]);
  544. hres = S_OK; // success
  545. exit_gracefully:
  546. TraceLeaveResult(hres);
  547. }
  548. /*---------------------------------------------------------------------------*/
  549. STDMETHODIMP CQueryFrame::RemoveMenus(THIS_ HMENU hmenuShared)
  550. {
  551. TraceEnter(TRACE_FRAME, "CQueryFrame::RemoveMenus");
  552. // We don't need to implement this as we copy or menus into the
  553. // menu that the handler supplies - fix DSQUERY if this ever
  554. // changes.
  555. TraceLeaveResult(S_OK);
  556. }
  557. /*---------------------------------------------------------------------------*/
  558. STDMETHODIMP CQueryFrame::SetMenu(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu)
  559. {
  560. TraceEnter(TRACE_FRAME, "CQueryFrame::SetMenu");
  561. if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
  562. {
  563. HMENU hmenuOld = ::GetMenu(_hwnd);
  564. if (!hmenuShared)
  565. hmenuShared = _hmenuFile;
  566. ::SetMenu(_hwnd, hmenuShared);
  567. DoEnableControls(); // ensure the menu state is valid
  568. ::DrawMenuBar(_hwnd);
  569. if (hmenuOld && (hmenuOld != _hmenuFile) && (hmenuOld != hmenuShared))
  570. {
  571. TraceMsg("Destroying old menu");
  572. DestroyMenu(hmenuOld);
  573. }
  574. }
  575. TraceLeaveResult(S_OK);
  576. }
  577. /*---------------------------------------------------------------------------*/
  578. STDMETHODIMP CQueryFrame::SetStatusText(THIS_ LPCTSTR pszStatusText)
  579. {
  580. TraceEnter(TRACE_FRAME, "CQueryFrame::SetStatusText");
  581. Trace(TEXT("Setting status text to: %s"), pszStatusText);
  582. if (_hwndStatus)
  583. SendMessage(_hwndStatus, SB_SETTEXT, 0, (LPARAM)pszStatusText);
  584. TraceLeaveResult(S_OK);
  585. }
  586. /*---------------------------------------------------------------------------*/
  587. STDMETHODIMP CQueryFrame::StartQuery(THIS_ BOOL fStarting)
  588. {
  589. TraceEnter(TRACE_FRAME, "CQueryFrame::StartQuery");
  590. if (fStarting)
  591. {
  592. Animate_Play(_hwndFindAnimation, 0, -1, -1);
  593. }
  594. else
  595. {
  596. Animate_Stop(_hwndFindAnimation);
  597. Animate_Seek(_hwndFindAnimation, 0); // go to start
  598. }
  599. if (_pQueryHandler)
  600. _pQueryHandler->ActivateView(CQRVA_STARTQUERY, (WPARAM)fStarting, 0);
  601. // now set the controls into a sensble state
  602. _fQueryRunning = fStarting;
  603. DoEnableControls();
  604. TraceLeaveResult(S_OK);
  605. }
  606. /*---------------------------------------------------------------------------*/
  607. STDMETHODIMP CQueryFrame::LoadQuery(THIS_ IPersistQuery* pPersistQuery)
  608. {
  609. HRESULT hres;
  610. TCHAR szGUID[GUIDSTR_MAX+1];
  611. LPQUERYFORM pQueryForm = NULL;
  612. GUID guid;
  613. TraceEnter(TRACE_FRAME, "CQueryFrame::LoadQuery");
  614. _pQueryHandler->StopQuery(); // ensure that the handler stops its processing
  615. // Attempt to read the handler GUID from the query stream, first try reading it as
  616. // as string then parsing it into something that we can use, if that fails then
  617. // try again, but this time read it as a structure.
  618. //
  619. // having aquired the GUID for the handler make sure that we have the correct handler
  620. // selected.
  621. if (FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szHandlerIs, szGUID, ARRAYSIZE(szGUID))) ||
  622. !GetGUIDFromString(szGUID, &guid))
  623. {
  624. TraceMsg("Trying new style handler GUID as struct");
  625. hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szHandlerIs, &guid, SIZEOF(guid));
  626. FailGracefully(hres, "Failed to read handler GUID as struct");
  627. }
  628. if (guid != _pOpenQueryWnd->clsidHandler)
  629. ExitGracefully(hres, E_FAIL, "Persisted handler GUID and specified handler GUID don't match");
  630. hres = _pQueryHandler->LoadQuery(pPersistQuery);
  631. FailGracefully(hres, "Handler failed to load its query data");
  632. // Get the form ID, then look up the form to see if we have one that matches,
  633. // if not then we cannot load any thing else. If we do haved that form then
  634. // ensure that we clear it and then load away.
  635. if (FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szFormIs, szGUID, ARRAYSIZE(szGUID))) ||
  636. !GetGUIDFromString(szGUID, &guid))
  637. {
  638. TraceMsg("Trying new style form GUID as struct");
  639. hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szFormIs, &guid, SIZEOF(guid));
  640. FailGracefully(hres, "Failed to read handler GUID as struct");
  641. }
  642. hres = SelectForm(guid);
  643. FailGracefully(hres, "Failed to select the query form");
  644. if (hres == S_FALSE)
  645. ExitGracefully(hres, E_FAIL, "Failed to select the query form to read the query info");
  646. hres = CallFormPages(_pCurrentForm, CQPM_CLEARFORM, 0, 0);
  647. FailGracefully(hres, "Failed to clear form before loading");
  648. // Load the persisted query from the stream, coping correctly with the
  649. // UNICODE / ANSI issue. We will be passed an IPersistQuery object which
  650. // we must then thunk accordingly if we are UNICODE for the pages we
  651. // are going to talk to.
  652. hres = CallFormPages(_pCurrentForm, CQPM_PERSIST, TRUE, (LPARAM)pPersistQuery);
  653. FailGracefully(hres, "Failed to load page data (UNICODE)");
  654. hres = S_OK; // success
  655. exit_gracefully:
  656. if (SUCCEEDED(hres))
  657. {
  658. TraceMsg("Query loaded successfully, select form query");
  659. SelectForm(guid);
  660. }
  661. TraceLeaveResult(hres);
  662. }
  663. /*---------------------------------------------------------------------------*/
  664. STDMETHODIMP CQueryFrame::SaveQuery(THIS_ IPersistQuery* pPersistQuery)
  665. {
  666. HRESULT hres;
  667. LPQUERYSCOPE pQueryScope;
  668. TCHAR szBuffer[MAX_PATH];
  669. TraceEnter(TRACE_FRAME, "CQueryFrame::SaveQuery");
  670. if (!pPersistQuery)
  671. ExitGracefully(hres, E_INVALIDARG, "No pPersistQuery object to write into");
  672. pPersistQuery->Clear(); // flush the contents
  673. hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szHandlerIs,
  674. &_pOpenQueryWnd->clsidHandler,
  675. SIZEOF(_pOpenQueryWnd->clsidHandler));
  676. FailGracefully(hres, "Failed to write handler GUID");
  677. hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szFormIs,
  678. &_pCurrentForm->clsidForm,
  679. SIZEOF(_pCurrentForm->clsidForm));
  680. FailGracefully(hres, "Failed to write form GUID");
  681. // Allow the handler to persist itself into the the stream, this includes
  682. // giving it the current scope to store.
  683. hres = GetSelectedScope(&pQueryScope);
  684. FailGracefully(hres, "Failed to get the scope from the LookIn control");
  685. hres = _pQueryHandler->SaveQuery(pPersistQuery, pQueryScope->pScope);
  686. FailGracefully(hres, "Failed when calling handler to persist itself");
  687. // Save the query into the stream, coping correctly with the
  688. // UNICODE / ANSI issue. We will be passed an IPersistQuery object which
  689. // we must then thunk accordingly if we are UNICODE for the pages we
  690. // are going to talk to.
  691. hres = CallFormPages(_pCurrentForm, CQPM_PERSIST, FALSE, (LPARAM)pPersistQuery);
  692. FailGracefully(hres, "Failed to load page data (UNICODE)");
  693. hres = S_OK;
  694. exit_gracefully:
  695. TraceLeaveResult(hres);
  696. }
  697. /*---------------------------------------------------------------------------*/
  698. STDMETHODIMP CQueryFrame::CallForm(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
  699. {
  700. HRESULT hres;
  701. LPQUERYFORM pQueryForm = _pCurrentForm;
  702. TraceEnter(TRACE_FRAME, "CQueryFrame::CallForm");
  703. if (pclsidForm)
  704. {
  705. pQueryForm = FindQueryForm(*pclsidForm);
  706. TraceAssert(pQueryForm);
  707. }
  708. if (!pQueryForm)
  709. ExitGracefully(hres, E_FAIL, "Failed to find query form for given CLSID");
  710. hres = CallFormPages(pQueryForm, uMsg, wParam, lParam);
  711. FailGracefully(hres, "Failed when calling CallFormPages");
  712. // hres = S_OK;
  713. exit_gracefully:
  714. TraceLeaveResult(hres);
  715. }
  716. /*---------------------------------------------------------------------------*/
  717. STDMETHODIMP CQueryFrame::GetScope(THIS_ LPCQSCOPE* ppScope)
  718. {
  719. HRESULT hres;
  720. LPQUERYSCOPE pQueryScope;
  721. TraceEnter(TRACE_FRAME, "CQueryFrame::GetScope");
  722. if (!ppScope)
  723. ExitGracefully(hres, E_INVALIDARG, "ppScope == NULL, thats bad");
  724. hres = GetSelectedScope(&pQueryScope);
  725. FailGracefully(hres, "Failed to get the current scope");
  726. *ppScope = (LPCQSCOPE)CoTaskMemAlloc(pQueryScope->pScope->cbStruct);
  727. TraceAssert(*ppScope);
  728. if (!*ppScope)
  729. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope block");
  730. //REVIEWED-2002-02-25-lucios.
  731. memcpy(*ppScope, pQueryScope->pScope, pQueryScope->pScope->cbStruct);
  732. hres = S_OK;
  733. exit_gracefully:
  734. TraceLeaveResult(hres);
  735. }
  736. /*---------------------------------------------------------------------------*/
  737. STDMETHODIMP CQueryFrame::GetHandler(THIS_ REFIID riid, void **ppv)
  738. {
  739. HRESULT hres;
  740. TraceEnter(TRACE_FRAME, "CQueryFrame::GetHandler");
  741. if (!_pQueryHandler)
  742. ExitGracefully(hres, E_UNEXPECTED, "_pQueryHandler is NULL");
  743. hres = _pQueryHandler->QueryInterface(riid, ppv);
  744. exit_gracefully:
  745. TraceLeaveResult(hres);
  746. }
  747. /*-----------------------------------------------------------------------------
  748. / Dialog box handler functions (core guts)
  749. /----------------------------------------------------------------------------*/
  750. #define REAL_WINDOW(hwnd) \
  751. (hwnd && \
  752. IsWindowVisible(hwnd) && \
  753. IsWindowEnabled(hwnd) && \
  754. (GetWindowLong(hwnd, GWL_STYLE) & WS_TABSTOP))
  755. HWND _NextTabStop(HWND hwndSearch, BOOL fShift)
  756. {
  757. HWND hwnd;
  758. Trace(TEXT("hwndSearch %08x, fShift %d"), hwndSearch, fShift);
  759. // do we have a window to search into?
  760. while (hwndSearch)
  761. {
  762. // if we have a window then lets check to see if it has any children?
  763. hwnd = GetWindow(hwndSearch, GW_CHILD);
  764. Trace(TEXT("Child of %08x is %08x"), hwndSearch, hwnd);
  765. if (hwnd)
  766. {
  767. // it has a child therefore lets to go its first/last
  768. // and continue the search there for a window that
  769. // matches the criteria we are looking for.
  770. hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
  771. if (!REAL_WINDOW(hwnd))
  772. {
  773. Trace(TEXT("Trying to recurse into %08x"), hwnd);
  774. hwnd = _NextTabStop(hwnd, fShift);
  775. }
  776. Trace(TEXT("Tabstop child of %08x is %08x"), hwndSearch, hwnd);
  777. }
  778. // after all that is hwnd a valid window? if so then pass
  779. // that back out to the caller.
  780. if (REAL_WINDOW(hwnd))
  781. {
  782. Trace(TEXT("Child tab stop was %08x"), hwnd);
  783. return hwnd;
  784. }
  785. // do we have a sibling? if so then lets return that otherwise
  786. // lets just continue to search until we either run out of windows
  787. // or hit something interesting
  788. hwndSearch = GetWindow(hwndSearch, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
  789. if (REAL_WINDOW(hwndSearch))
  790. {
  791. Trace(TEXT("Next tab stop was %08x"), hwndSearch);
  792. return hwndSearch;
  793. }
  794. }
  795. return hwndSearch;
  796. }
  797. INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg)
  798. {
  799. LRESULT lResult = 0;
  800. CQueryFrame* pQueryFrame = NULL;
  801. NMHDR nmhdr;
  802. pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
  803. if (!pQueryFrame)
  804. return 0;
  805. if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB))
  806. {
  807. BOOL fCtrl = GetAsyncKeyState(VK_CONTROL) < 0;
  808. BOOL fShift = GetAsyncKeyState(VK_SHIFT) < 0;
  809. // ensure that the focus rectangles are shown
  810. #if (_WIN32_WINNT >= 0x0500)
  811. SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
  812. #endif
  813. if (fCtrl)
  814. {
  815. // if this is a key press within the parent then lets ensure that we
  816. // allow the tab control to change the page correctly. otherwise lets
  817. // just hack around the problem of the result view not handling tabs
  818. // properly.
  819. INT iCur = TabCtrl_GetCurSel(pQueryFrame->_hwndFrame);
  820. INT nPages = TabCtrl_GetItemCount(pQueryFrame->_hwndFrame);
  821. if (fShift)
  822. iCur += (nPages-1);
  823. else
  824. iCur++;
  825. pQueryFrame->SelectFormPage(pQueryFrame->_pCurrentForm, iCur % nPages);
  826. return 1; // we processed it
  827. }
  828. else
  829. {
  830. // is the window that has the focus a child of the result view, if
  831. // so then we must attempt to pass focus to its 1st child and hope
  832. // that is can do the rest.
  833. HWND hwndNext, hwndFocus = GetFocus();
  834. Trace(TEXT("Current focus window %08x"), hwndFocus);
  835. while (hwndFocus && GetWindowLong(hwndFocus, GWL_STYLE) & WS_CHILD)
  836. {
  837. hwndNext = _NextTabStop(hwndFocus, fShift);
  838. Trace(TEXT("_NextTabStop yeilds %08x from %08x"), hwndNext, hwndFocus);
  839. if (hwndNext)
  840. {
  841. Trace(TEXT("SetFocus on child %08x"), hwndNext);
  842. SendMessage(GetParent(hwndNext),WM_NEXTDLGCTL,(WPARAM)hwndNext,TRUE);
  843. SetFocus(hwndNext);
  844. return 1;
  845. }
  846. while (TRUE)
  847. {
  848. // look up the parent list trying to find a window that we can
  849. // tab back into. We must watch that when we walk out of the
  850. // child list we loop correctly at the top of the list.
  851. hwndNext = GetParent(hwndFocus);
  852. Trace(TEXT("Parent hwnd %08x"), hwndNext);
  853. if (GetWindowLong(hwndNext, GWL_STYLE) & WS_CHILD)
  854. {
  855. // the parent window is a child, therefore we can check
  856. // to see if has any siblings.
  857. Trace(TEXT("hwndNext is a child, therefore hwndNext of it is %08x"),
  858. GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT));
  859. if (GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT))
  860. {
  861. hwndFocus = GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
  862. Trace(TEXT("Silbing window found %08x"), hwndFocus);
  863. break;
  864. }
  865. else
  866. {
  867. TraceMsg("There was no sibling, therefore continuing parent loop");
  868. hwndFocus = hwndNext;
  869. }
  870. }
  871. else
  872. {
  873. // we have hit the parent window of it all (the overlapped one)
  874. // therefore we must attempt to go to its first child. Walk forward
  875. // in the stack looking for a window that matches the
  876. // "REAL_WINDOW" conditions.
  877. hwndFocus = GetWindow(hwndFocus, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
  878. Trace(TEXT("First child is %08x"), hwndFocus);
  879. break; // continue the sibling search etc
  880. }
  881. }
  882. if (REAL_WINDOW(hwndFocus))
  883. {
  884. SendMessage(GetParent(hwndFocus),WM_NEXTDLGCTL,(WPARAM)hwndFocus,TRUE);
  885. SetFocus(hwndFocus);
  886. return 1;
  887. }
  888. }
  889. }
  890. }
  891. return 0;
  892. }
  893. //
  894. // Main DLGPROC
  895. //
  896. INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  897. {
  898. CQueryFrame* pQueryFrame;
  899. if (uMsg == WM_INITDIALOG)
  900. {
  901. HRESULT hres;
  902. pQueryFrame = (CQueryFrame*)lParam;
  903. SetWindowLongPtr(hwnd, DWLP_USER, (LRESULT)pQueryFrame);
  904. hres = pQueryFrame->OnInitDialog(hwnd);
  905. Trace(TEXT("OnInitDialog returns %08x"), hres);
  906. if (FAILED(hres))
  907. {
  908. TraceMsg("Failed to initialize the dialog, Destroying the window");
  909. pQueryFrame->CloseQueryFrame(hres);
  910. DestroyWindow(hwnd);
  911. }
  912. }
  913. else
  914. {
  915. pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
  916. if (!pQueryFrame)
  917. goto exit_gracefully;
  918. switch (uMsg)
  919. {
  920. case WM_ERASEBKGND:
  921. {
  922. HDC hdc = (HDC)wParam;
  923. RECT rc;
  924. // if we have a DC then lets fill it, and if we have a
  925. // query form then lets paint the divider between the menu bar and
  926. // this area.
  927. if (hdc)
  928. {
  929. GetClientRect(hwnd, &rc);
  930. FillRect(hdc, &rc, (HBRUSH)(COLOR_3DFACE+1));
  931. if (!(pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
  932. DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP);
  933. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  934. }
  935. return 1;
  936. }
  937. case WM_NOTIFY:
  938. return pQueryFrame->OnNotify((int)wParam, (LPNMHDR)lParam);
  939. case WM_SIZE:
  940. pQueryFrame->OnSize(LOWORD(lParam), HIWORD(lParam));
  941. return(1);
  942. case WM_GETMINMAXINFO:
  943. pQueryFrame->OnGetMinMaxInfo((LPMINMAXINFO)lParam);
  944. return(1);
  945. case WM_COMMAND:
  946. pQueryFrame->OnCommand(wParam, lParam);
  947. return(1);
  948. case WM_ACTIVATE:
  949. pQueryFrame->_pQueryHandler->ActivateView(wParam ? CQRVA_ACTIVATE : CQRVA_DEACTIVATE, 0, 0);
  950. // NTRAID#NTBUG9-411693-2001/10/24-lucios
  951. // We return 0 so that we don't call DefWndProc and therefore the
  952. // focus is not set to the first child control
  953. return(0);
  954. case WM_INITMENU:
  955. pQueryFrame->OnInitMenu((HMENU)wParam);
  956. return(1);
  957. case WM_SETCURSOR:
  958. {
  959. // do we have any scopes? if not then let us display the wait
  960. // cursor for the user. if we have a query running then lets
  961. // display the app start cursor.
  962. if (!pQueryFrame->_fAddScopesNYI &&
  963. !ComboBox_GetCount(pQueryFrame->_hwndLookIn))
  964. {
  965. if (LOWORD(lParam) == HTCLIENT)
  966. {
  967. SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));
  968. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  969. return 1;
  970. }
  971. }
  972. break;
  973. }
  974. case WM_INITMENUPOPUP:
  975. {
  976. // only send sub-menu activates if the menu bar is being tracked, this is
  977. // handled within OnInitMenu, if we are not tracking the menu then we
  978. // assume that the client has already primed the menu and that they are
  979. // using some kind of popup menu.
  980. if (pQueryFrame->_fTrackingMenuBar)
  981. pQueryFrame->_pQueryHandler->ActivateView(CQRVA_INITMENUBARPOPUP, wParam, lParam);
  982. return(1);
  983. }
  984. case WM_ENTERMENULOOP:
  985. pQueryFrame->OnEnterMenuLoop(TRUE);
  986. return(1);
  987. case WM_EXITMENULOOP:
  988. pQueryFrame->OnEnterMenuLoop(FALSE);
  989. return(1);
  990. case WM_MENUSELECT:
  991. {
  992. UINT uID = LOWORD(wParam);
  993. UINT uFlags = HIWORD(wParam);
  994. HMENU hMenu = (HMENU)lParam;
  995. // the command opens a popup menu the the uID is actually
  996. // the index into the menu, so lets ensure that we pick
  997. // up the correct ID by calling GetMenuItemInfo, note that
  998. // GetMenuItemID returns -1 in this case which is totally
  999. // useless.
  1000. if (uFlags & MF_POPUP)
  1001. {
  1002. MENUITEMINFO mii;
  1003. ZeroMemory(&mii, SIZEOF(mii));
  1004. mii.cbSize = SIZEOF(mii);
  1005. mii.fMask = MIIM_ID;
  1006. if (GetMenuItemInfo(hMenu, uID, TRUE, &mii))
  1007. uID = mii.wID;
  1008. }
  1009. pQueryFrame->OnMenuSelect(hMenu, uID);
  1010. return(1);
  1011. }
  1012. case WM_SYSCOMMAND:
  1013. if (wParam == SC_CLOSE)
  1014. {
  1015. pQueryFrame->CloseQueryFrame(S_FALSE);
  1016. return(1);
  1017. }
  1018. break;
  1019. case WM_CONTEXTMENU:
  1020. {
  1021. // there are a couple of controls we don't care about for the
  1022. // frame, so lets ignore those when passing the CQRVA_CONTEXTMENU
  1023. // through to the handler.
  1024. POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  1025. ScreenToClient((HWND)wParam, &pt);
  1026. switch (GetDlgCtrlID(ChildWindowFromPoint((HWND)wParam, pt)))
  1027. {
  1028. case IDC_FORMAREA:
  1029. case IDC_FINDANIMATION:
  1030. case IDC_STATUS:
  1031. return TRUE; // handled
  1032. default:
  1033. pQueryFrame->_pQueryHandler->ActivateView(CQRVA_CONTEXTMENU, wParam, lParam);
  1034. return TRUE;
  1035. }
  1036. return FALSE;
  1037. }
  1038. case WM_HELP:
  1039. {
  1040. LPHELPINFO phi = (LPHELPINFO)lParam;
  1041. // filter out those controls we are not interested in (they make no sense)
  1042. // to bother the user with
  1043. switch (GetDlgCtrlID((HWND)phi->hItemHandle))
  1044. {
  1045. case IDC_FORMAREA:
  1046. case IDC_FINDANIMATION:
  1047. case IDC_STATUS:
  1048. return TRUE;
  1049. default:
  1050. pQueryFrame->OnHelp(phi);
  1051. return TRUE;
  1052. }
  1053. return FALSE;
  1054. }
  1055. case CQFWM_ADDSCOPE:
  1056. {
  1057. LPCQSCOPE pScope = (LPCQSCOPE)wParam;
  1058. BOOL fSelect = LOWORD(lParam);
  1059. INT iIndex = HIWORD(lParam);
  1060. if (SUCCEEDED(pQueryFrame->AddScope(pScope, iIndex, fSelect)))
  1061. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1062. return 1;
  1063. }
  1064. case CQFWM_GETFRAME:
  1065. {
  1066. IQueryFrame** ppQueryFrame = (IQueryFrame**)lParam;
  1067. if (ppQueryFrame)
  1068. {
  1069. pQueryFrame->AddRef();
  1070. *ppQueryFrame = pQueryFrame;
  1071. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1072. }
  1073. return 1;
  1074. }
  1075. case CQFWM_ALLSCOPESADDED:
  1076. {
  1077. // there is an async scope collector, it has added all the scopes
  1078. // so we must now attempt to issue the query if the we are in the
  1079. // holding pattern waiting for the scopes to be collected.
  1080. pQueryFrame->_fScopesAddedAsync = FALSE; // all scopes have been added
  1081. if (pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN)
  1082. PostMessage(pQueryFrame->_hwnd, CQFWM_STARTQUERY, 0, 0);
  1083. return 1;
  1084. }
  1085. case CQFWM_STARTQUERY:
  1086. pQueryFrame->OnFindNow();
  1087. return 1;
  1088. case CQFWM_SETDEFAULTFOCUS:
  1089. {
  1090. HWND hwndNextTab = _NextTabStop(pQueryFrame->_pCurrentFormPage->hwndPage, FALSE);
  1091. SendMessage(pQueryFrame->_pCurrentFormPage->hwndPage, WM_NEXTDLGCTL, (WPARAM)hwndNextTab, 1);
  1092. break;
  1093. }
  1094. default:
  1095. break;
  1096. }
  1097. }
  1098. exit_gracefully:
  1099. return(0);
  1100. }
  1101. /*-----------------------------------------------------------------------------
  1102. / CQueryFrame::CloseQueryFrame
  1103. / ----------------------------
  1104. / Close the query window passing back the data object if required, and ensuring
  1105. / that our result code indicates what is going on.
  1106. /
  1107. / In:
  1108. / hResult = result code to pass to the caller
  1109. /
  1110. / Out:
  1111. / -
  1112. /----------------------------------------------------------------------------*/
  1113. VOID CQueryFrame::CloseQueryFrame(HRESULT hres)
  1114. {
  1115. TraceEnter(TRACE_FRAME, "CQueryFrame::CloseQueryFrame");
  1116. Trace(TEXT("hResult %08x"), hres);
  1117. // If we succeeded then attempt to collect the IDataObject and pass it
  1118. // back to the caller.
  1119. if (hres == S_OK)
  1120. {
  1121. if (_ppDataObject)
  1122. {
  1123. hres = _pQueryHandler->GetViewObject(CQRVS_SELECTION, IID_IDataObject, (LPVOID*)_ppDataObject);
  1124. FailGracefully(hres, "Failed when collecting the data object");
  1125. }
  1126. if ((_pOpenQueryWnd->dwFlags & OQWF_SAVEQUERYONOK) && _pOpenQueryWnd->pPersistQuery)
  1127. {
  1128. hres = SaveQuery(_pOpenQueryWnd->pPersistQuery);
  1129. FailGracefully(hres, "Failed when persisting query to IPersistQuery blob");
  1130. }
  1131. hres = S_OK; // success
  1132. }
  1133. exit_gracefully:
  1134. _hResult = hres;
  1135. _fExitModalLoop = TRUE; // bomb out of the modal loop
  1136. TraceLeave();
  1137. }
  1138. /*-----------------------------------------------------------------------------
  1139. / CQueryFrame::FrameMessageBox
  1140. / ----------------------------
  1141. / Our message box for putting up prompts that relate to the current
  1142. / query. We handle getting the view information and displaying
  1143. / the prompt, returning the result from MessageBox.
  1144. /
  1145. / In:
  1146. / pPrompt = text displayed as a prompt
  1147. / uType = message box type
  1148. /
  1149. / Out:
  1150. / INT
  1151. /----------------------------------------------------------------------------*/
  1152. INT CQueryFrame::FrameMessageBox(LPCTSTR pPrompt, UINT uType)
  1153. {
  1154. TCHAR szTitle[MAX_PATH];
  1155. CQVIEWINFO vi;
  1156. TraceEnter(TRACE_FRAME, "CQueryFrame::FrameMessageBox");
  1157. ZeroMemory(&vi, SIZEOF(vi));
  1158. //vi. dwFlags = 0; // display attributes
  1159. if (SUCCEEDED(_pQueryHandler->GetViewInfo(&vi)) && vi.hInstance && vi.idTitle)
  1160. LoadString(vi.hInstance, vi.idTitle, szTitle, ARRAYSIZE(szTitle));
  1161. else
  1162. GetWindowText(_hwnd, szTitle, ARRAYSIZE(szTitle));
  1163. TraceLeaveValue(MessageBox(_hwnd, pPrompt, szTitle, uType));
  1164. }
  1165. /*-----------------------------------------------------------------------------
  1166. / CQueryFrame::OnInitDlg
  1167. / ----------------------
  1168. / Handle a WM_INITDAILOG message, this is sent as the first thing the
  1169. / dialog receives, therefore we must handle our initialization that
  1170. / was not handled in the constructor.
  1171. /
  1172. / In:
  1173. / hwnd = handle of dialog we are initializing
  1174. /
  1175. / Out:
  1176. / HRESULT
  1177. /----------------------------------------------------------------------------*/
  1178. HRESULT CQueryFrame::OnInitDialog(HWND hwnd)
  1179. {
  1180. HRESULT hres;
  1181. HICON hIcon = NULL;
  1182. TCHAR szGUID[GUIDSTR_MAX+1];
  1183. TCHAR szBuffer[MAX_PATH];
  1184. CQVIEWINFO vi;
  1185. INT dyControls = 0;
  1186. RECT rect, rect2;
  1187. SIZE size;
  1188. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitDialog");
  1189. // get the HKEY for the handler we are using
  1190. hres = GetKeyForCLSID(_pOpenQueryWnd->clsidHandler, NULL, &_hkHandler);
  1191. FailGracefully(hres, "Failed to open handlers HKEY");
  1192. // pick up the control handles and store them, saves picking them up later
  1193. _hwnd = hwnd;
  1194. _hwndFrame = GetDlgItem(hwnd, IDC_FORMAREA);
  1195. _hwndLookForLabel = GetDlgItem(hwnd, CQID_LOOKFORLABEL);
  1196. _hwndLookFor = GetDlgItem(hwnd, CQID_LOOKFOR);
  1197. _hwndLookInLabel = GetDlgItem(hwnd, CQID_LOOKINLABEL);
  1198. _hwndLookIn = GetDlgItem(hwnd, CQID_LOOKIN);
  1199. _hwndBrowse = GetDlgItem(hwnd, CQID_BROWSE);
  1200. _hwndFindNow = GetDlgItem(hwnd, CQID_FINDNOW);
  1201. _hwndStop = GetDlgItem(hwnd, CQID_STOP);
  1202. _hwndNewQuery = GetDlgItem(hwnd, CQID_CLEARALL);
  1203. _hwndFindAnimation = GetDlgItem(hwnd, IDC_FINDANIMATION);
  1204. _hwndOK = GetDlgItem(hwnd, IDOK);
  1205. _hwndCancel = GetDlgItem(hwnd, IDCANCEL);
  1206. // when enable is called this will be the first
  1207. _fFormFirstEnable = TRUE;
  1208. // call the IQueryHandler interface and get its display attributes,
  1209. // then reflect these into the dialog we are about to display to the
  1210. // outside world.
  1211. vi.dwFlags = 0;
  1212. vi.hInstance = NULL;
  1213. vi.idLargeIcon = 0;
  1214. vi.idSmallIcon = 0;
  1215. vi.idTitle = 0;
  1216. vi.idAnimation = 0;
  1217. hres = _pQueryHandler->GetViewInfo(&vi);
  1218. FailGracefully(hres, "Failed when getting the view info from the handler");
  1219. _dwHandlerViewFlags = vi.dwFlags;
  1220. if (vi.hInstance)
  1221. {
  1222. HICON hiTemp = NULL;
  1223. if (vi.idLargeIcon)
  1224. {
  1225. _hiconLarge = (HICON)LoadImage(vi.hInstance,
  1226. MAKEINTRESOURCE(vi.idLargeIcon),
  1227. IMAGE_ICON,
  1228. 0, 0,
  1229. LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
  1230. if (_hiconLarge)
  1231. SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)_hiconLarge);
  1232. }
  1233. if (vi.idSmallIcon)
  1234. {
  1235. _hiconSmall = (HICON)LoadImage(vi.hInstance,
  1236. MAKEINTRESOURCE(vi.idLargeIcon),
  1237. IMAGE_ICON,
  1238. GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
  1239. LR_DEFAULTCOLOR);
  1240. if (_hiconSmall)
  1241. SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)_hiconSmall);
  1242. }
  1243. if (vi.idTitle)
  1244. {
  1245. LoadString(vi.hInstance, vi.idTitle, szBuffer, ARRAYSIZE(szBuffer));
  1246. SetWindowText(hwnd, szBuffer);
  1247. }
  1248. }
  1249. if (vi.hInstance && vi.idAnimation)
  1250. {
  1251. SetWindowLongPtr(_hwndFindAnimation, GWLP_HINSTANCE, (LRESULT)vi.hInstance);
  1252. Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(vi.idAnimation));
  1253. }
  1254. else
  1255. {
  1256. Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(IDR_FINDANIMATION));
  1257. }
  1258. // now adjust the positions and hide the controls we are not interested in
  1259. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS)
  1260. {
  1261. // NTRAID#NTBUG9-619016-2002/05/21-lucios
  1262. EnableWindow(_hwndLookForLabel,FALSE);
  1263. ShowWindow(_hwndLookForLabel, SW_HIDE);
  1264. ShowWindow(_hwndLookFor, SW_HIDE);
  1265. }
  1266. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES)
  1267. {
  1268. // NTRAID#NTBUG9-619016-2002/05/21-lucios
  1269. EnableWindow(_hwndLookInLabel,FALSE);
  1270. ShowWindow(_hwndLookInLabel, SW_HIDE);
  1271. ShowWindow(_hwndLookIn, SW_HIDE);
  1272. ShowWindow(_hwndBrowse, SW_HIDE);
  1273. }
  1274. // hiding both the scopes and the forms control causes us to
  1275. // move all the controls up by so many units.
  1276. if ((_pOpenQueryWnd->dwFlags & (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES))
  1277. == (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES))
  1278. {
  1279. GetRealWindowInfo(_hwndLookForLabel, &rect, NULL);
  1280. GetRealWindowInfo(_hwndFrame, &rect2, NULL);
  1281. dyControls += rect2.top - rect.top;
  1282. Trace(TEXT("Moving all controls up by %d units"), dyControls);
  1283. OffsetWindow(_hwndFrame, 0, -dyControls);
  1284. OffsetWindow(_hwndFindNow, 0, -dyControls);
  1285. OffsetWindow(_hwndStop, 0, -dyControls);
  1286. OffsetWindow(_hwndNewQuery, 0, -dyControls);
  1287. OffsetWindow(_hwndFindAnimation, 0, -dyControls);
  1288. OffsetWindow(_hwndOK, 0, -dyControls);
  1289. if (_hwndCancel)
  1290. OffsetWindow(_hwndCancel, 0, -dyControls);
  1291. }
  1292. // hiding OK/Cancel so lets adjust the size here to include the
  1293. // OK/Cancel buttons disappearing, note that we update dyControls
  1294. // to include this delta
  1295. if (!(_pOpenQueryWnd->dwFlags & OQWF_OKCANCEL))
  1296. {
  1297. ShowWindow(_hwndOK, SW_HIDE);
  1298. if (_hwndCancel)
  1299. ShowWindow(_hwndCancel, SW_HIDE);
  1300. // if this is the filter dialog then lets ensure that
  1301. // we trim the OK/Cancel buttons from the size by adjusting the
  1302. // dyControls further.
  1303. GetRealWindowInfo(_hwndOK, &rect, NULL);
  1304. GetRealWindowInfo(_hwndFrame, &rect2, NULL);
  1305. dyControls += rect.bottom - rect2.bottom;
  1306. }
  1307. // having performed that extra bit of initialization lets cache the
  1308. // positions of the various controls, to make sizing more fun...
  1309. GetClientRect(hwnd, &rect2);
  1310. rect2.bottom -= dyControls;
  1311. _dyResultsTop = rect2.bottom;
  1312. GetRealWindowInfo(hwnd, NULL, &size);
  1313. GetRealWindowInfo(_hwndFrame, &rect, &_szForm);
  1314. Trace(TEXT("dyControls %d"), dyControls);
  1315. size.cy -= dyControls;
  1316. _dxFormAreaLeft = rect.left;
  1317. _dxFormAreaRight = rect2.right - rect.right;
  1318. _szMinTrack.cx = size.cx - _szForm.cx;
  1319. _szMinTrack.cy = size.cy - _szForm.cy;
  1320. if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS))
  1321. {
  1322. TraceMsg("Adjusting _szMinTrack.cy to account for menu bar");
  1323. _szMinTrack.cy += GetSystemMetrics(SM_CYMENU);
  1324. }
  1325. GetRealWindowInfo(_hwndBrowse, &rect, NULL);
  1326. _dxButtonsLeft = rect2.right - rect.left;
  1327. GetRealWindowInfo(_hwndLookIn, &rect, NULL);
  1328. _dxGap = (rect2.right - rect.right) - _dxButtonsLeft;
  1329. GetRealWindowInfo(_hwndFindAnimation, &rect, NULL);
  1330. _dxAnimationLeft = rect2.right - rect.left;
  1331. GetRealWindowInfo(_hwndOK, &rect, NULL);
  1332. _dyOKTop = rect2.bottom - rect.top;
  1333. _dyGap = size.cy - rect.bottom;
  1334. // Now collect the forms and pages, then walk them building the size
  1335. // information that we need.
  1336. hres = GatherForms();
  1337. FailGracefully(hres, "Failed to init form list");
  1338. _szMinTrack.cx += _szForm.cx;
  1339. _szMinTrack.cy += _szForm.cy;
  1340. // Populate the scope control by querying the handler for them,
  1341. // if there are none then we display a suitable message box and
  1342. // let the user know that something went wrong.
  1343. hres = PopulateScopeControl();
  1344. FailGracefully(hres, "Failed to init scope list");
  1345. _fScopesPopulated = TRUE; // scope control now populated
  1346. // perform final fix up of the window, ensure that we size it so that
  1347. // the entire form and buttons are visible. Then set ourselves into the
  1348. // no query state and reset the animation.
  1349. SetWindowPos(hwnd,
  1350. NULL,
  1351. 0, 0,
  1352. _szMinTrack.cx, _szMinTrack.cy,
  1353. SWP_NOMOVE|SWP_NOZORDER);
  1354. if (_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS)
  1355. ::SetMenu(hwnd, NULL);
  1356. hres = PopulateFormControl(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL);
  1357. FailGracefully(hres, "Failed to populate form control");
  1358. // Now load the query which inturn selects the form that we should be using,
  1359. // if there is no query to load then either use the default form or
  1360. // the first in the list.
  1361. if ((_pOpenQueryWnd->dwFlags & OQWF_LOADQUERY) && _pOpenQueryWnd->pPersistQuery)
  1362. {
  1363. // NTRAID#NTBUG9-627056-2002/06/11-artm
  1364. // If unable to load query, still show the window but w/out values filled in.
  1365. HRESULT hResLoad = LoadQuery(_pOpenQueryWnd->pPersistQuery);
  1366. if (FAILED(hResLoad))
  1367. {
  1368. Trace(TEXT("Failed when trying to load query from supplied IPersistQuery with error %x"), hResLoad);
  1369. }
  1370. }
  1371. else
  1372. {
  1373. if (_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM)
  1374. {
  1375. SelectForm(_pOpenQueryWnd->clsidDefaultForm);
  1376. if (!_pCurrentForm)
  1377. ExitGracefully(hres, E_FAIL, "Failed to select the query form");
  1378. }
  1379. else
  1380. {
  1381. INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, 0);
  1382. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  1383. TraceAssert(pQueryForm);
  1384. SelectForm(pQueryForm->clsidForm);
  1385. }
  1386. }
  1387. StartQuery(FALSE);
  1388. // issue on open, therefore lets get the query going, if there is async
  1389. // scope collection then the query will be issued by the bg thread.
  1390. if (_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN)
  1391. PostMessage(_hwnd, CQFWM_STARTQUERY, 0, 0);
  1392. SetForegroundWindow(hwnd);
  1393. hres = S_OK; // success
  1394. exit_gracefully:
  1395. TraceLeaveResult(hres);
  1396. }
  1397. /*-----------------------------------------------------------------------------
  1398. / CQueryFrame::EnableControls
  1399. / ---------------------------
  1400. / Set the controls into their enabled/disabled state based on the
  1401. / state of the dialog.
  1402. /
  1403. / In:
  1404. / -
  1405. /
  1406. / Out:
  1407. / HRESULT
  1408. /----------------------------------------------------------------------------*/
  1409. VOID CQueryFrame::DoEnableControls(VOID)
  1410. {
  1411. BOOL fScopes = (_fAddScopesNYI || ComboBox_GetCount(_hwndLookIn));
  1412. BOOL fEnable = fScopes;
  1413. UINT uEnable = fScopes ? MF_ENABLED:MF_GRAYED;
  1414. HMENU hMenu = GetMenu(_hwnd);
  1415. INT i;
  1416. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::DoEnableControls");
  1417. EnableWindow(_hwndFindNow, !_fQueryRunning && fEnable);
  1418. EnableWindow(_hwndStop, _fQueryRunning && fEnable);
  1419. EnableWindow(_hwndNewQuery, fEnable);
  1420. EnableWindow(_hwndLookFor, !_fQueryRunning && fEnable);
  1421. EnableWindow(_hwndLookIn, !_fQueryRunning && fEnable);
  1422. EnableWindow(_hwndBrowse, !_fQueryRunning && fEnable);
  1423. if (_pCurrentForm)
  1424. {
  1425. CallFormPages(_pCurrentForm, CQPM_ENABLE, (BOOL)(!_fQueryRunning && fEnable), 0);
  1426. if (_fFormFirstEnable)
  1427. {
  1428. PostMessage(_hwnd, CQFWM_SETDEFAULTFOCUS, 0, 0);
  1429. _fFormFirstEnable = FALSE;
  1430. }
  1431. }
  1432. if (_hwndOK)
  1433. EnableWindow(_hwndOK, !_fQueryRunning && fEnable);
  1434. if (_hwndCancel)
  1435. EnableWindow(_hwndCancel, !_fQueryRunning && fEnable);
  1436. for (i = 0 ; i < GetMenuItemCount(hMenu) ; i++)
  1437. EnableMenuItem(hMenu, i, MF_BYPOSITION|uEnable);
  1438. DrawMenuBar(_hwnd);
  1439. TraceLeave();
  1440. }
  1441. /*-----------------------------------------------------------------------------
  1442. / CQueryFrame::OnNotify
  1443. / ---------------------
  1444. / Notify event received, decode it and handle accordingly
  1445. /
  1446. / In:
  1447. / idCtrl = ID of control issuing notify
  1448. / pNotify -> LPNMHDR structure
  1449. /
  1450. / Out:
  1451. / LRESULT
  1452. /----------------------------------------------------------------------------*/
  1453. LRESULT CQueryFrame::OnNotify(INT idCtrl, LPNMHDR pNotify)
  1454. {
  1455. LRESULT lr = 0;
  1456. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNotify");
  1457. // TCN_SELCHANGE used to indicate that the currently active
  1458. // tab has been changed
  1459. if (pNotify->code == TCN_SELCHANGE)
  1460. {
  1461. INT iPage = TabCtrl_GetCurSel(_hwndFrame);
  1462. TraceAssert(iPage >= 0);
  1463. if (iPage >= 0)
  1464. {
  1465. SelectFormPage(_pCurrentForm, iPage);
  1466. lr = 0;
  1467. }
  1468. }
  1469. TraceLeaveResult((HRESULT)lr);
  1470. }
  1471. /*-----------------------------------------------------------------------------
  1472. / CQueryFrame::OnSize
  1473. / -------------------
  1474. / The window is being sized and we received a WM_SIZE, therefore move
  1475. / the content of the window about.
  1476. /
  1477. / In:
  1478. / cx = new width
  1479. / cy = new height
  1480. /
  1481. / Out:
  1482. / -
  1483. /----------------------------------------------------------------------------*/
  1484. VOID CQueryFrame::OnSize(INT cx, INT cy)
  1485. {
  1486. HDWP hdwp;
  1487. RECT rect, rect2;
  1488. SIZE sz, sz2;
  1489. INT x, cxForm, cyForm;
  1490. INT dyResultsTop = 0;
  1491. INT frameBottom = 0;
  1492. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnSize");
  1493. // do as much as we can within a DefWindowPos to aVOID too
  1494. // much flicker.
  1495. hdwp = BeginDeferWindowPos(16);
  1496. if (hdwp)
  1497. {
  1498. {
  1499. // adjust the look for controls, if there is no scope then
  1500. // stretch the look for control over the entire client area
  1501. // of the window.
  1502. if (!(_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS))
  1503. {
  1504. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES)
  1505. {
  1506. GetRealWindowInfo(_hwndLookFor, &rect, &sz);
  1507. if (hdwp)
  1508. {
  1509. hdwp = DeferWindowPos(hdwp, _hwndLookFor, NULL,
  1510. 0, 0,
  1511. (cx - _dxFormAreaRight) - rect.left, sz.cy,
  1512. SWP_NOZORDER|SWP_NOMOVE);
  1513. }
  1514. }
  1515. }
  1516. // adjust the "look in" controls, if there is a form control
  1517. // then stretch across the remaining space, otherwise move the
  1518. // label and stretch the scope over the remaining space.
  1519. if (!(_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES))
  1520. {
  1521. INT xScopeRight;
  1522. GetRealWindowInfo(_hwndLookIn, &rect, &sz);
  1523. xScopeRight = cx - _dxFormAreaRight - _dxGap;
  1524. if (_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI)
  1525. {
  1526. //
  1527. // when hiding the search UI, then adjust the button position to account for the
  1528. // right edge of the dialog not having buttons.
  1529. //
  1530. xScopeRight -= (_dxButtonsLeft - _dxFormAreaRight) + _dxGap;
  1531. }
  1532. if (_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS)
  1533. {
  1534. GetRealWindowInfo(_hwndLookInLabel, &rect2, &sz2);
  1535. if (hdwp)
  1536. {
  1537. hdwp = DeferWindowPos(hdwp, _hwndLookInLabel, NULL,
  1538. _dxFormAreaLeft, rect2.top,
  1539. 0, 0,
  1540. SWP_NOSIZE|SWP_NOZORDER);
  1541. }
  1542. if(hdwp)
  1543. {
  1544. hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,
  1545. _dxFormAreaLeft+sz2.cx, rect.top,
  1546. xScopeRight - (_dxFormAreaLeft + sz2.cx), sz.cy,
  1547. SWP_NOZORDER);
  1548. }
  1549. }
  1550. else
  1551. {
  1552. if(hdwp)
  1553. {
  1554. hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,
  1555. 0, 0,
  1556. xScopeRight - rect.left, sz.cy,
  1557. SWP_NOZORDER|SWP_NOMOVE);
  1558. }
  1559. }
  1560. // browse control is displayed always if we are showing the
  1561. // scopes.
  1562. GetRealWindowInfo(_hwndBrowse, &rect, NULL);
  1563. if(hdwp)
  1564. {
  1565. hdwp = DeferWindowPos(hdwp, _hwndBrowse, NULL,
  1566. xScopeRight+_dxGap, rect.top,
  1567. 0, 0,
  1568. SWP_NOZORDER|SWP_NOSIZE);
  1569. }
  1570. }
  1571. // all the buttons have a fixed offset from the right edege
  1572. // of the dialog, so just handle that as we can.
  1573. if (!(_pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI))
  1574. {
  1575. GetRealWindowInfo(_hwndFindNow, &rect, NULL);
  1576. if(hdwp)
  1577. {
  1578. hdwp = DeferWindowPos(hdwp, _hwndFindNow, NULL,
  1579. (cx - _dxButtonsLeft), rect.top,
  1580. 0, 0,
  1581. SWP_NOZORDER|SWP_NOSIZE);
  1582. }
  1583. GetRealWindowInfo(_hwndStop, &rect, &sz);
  1584. if(hdwp)
  1585. {
  1586. hdwp = DeferWindowPos(hdwp, _hwndStop, NULL,
  1587. (cx - _dxButtonsLeft), rect.top,
  1588. 0, 0,
  1589. SWP_NOZORDER|SWP_NOSIZE);
  1590. }
  1591. GetRealWindowInfo(_hwndNewQuery, &rect, NULL);
  1592. if(hdwp)
  1593. {
  1594. hdwp = DeferWindowPos(hdwp, _hwndNewQuery, NULL,
  1595. (cx - _dxButtonsLeft), rect.top,
  1596. 0, 0,
  1597. SWP_NOZORDER|SWP_NOSIZE);
  1598. }
  1599. GetRealWindowInfo(_hwndFindAnimation, &rect2, &sz2);
  1600. if(hdwp)
  1601. {
  1602. hdwp = DeferWindowPos(hdwp, _hwndFindAnimation, NULL,
  1603. (cx - _dxAnimationLeft), rect2.top,
  1604. 0, 0,
  1605. SWP_NOZORDER|SWP_NOSIZE);
  1606. }
  1607. }
  1608. // position the form "frame" control
  1609. GetRealWindowInfo(_hwndFrame, &rect, &sz);
  1610. cxForm = (cx - _dxFormAreaRight) - rect.left;
  1611. if(hdwp)
  1612. {
  1613. hdwp = DeferWindowPos(hdwp, _hwndFrame, NULL,
  1614. 0, 0,
  1615. cxForm, _szForm.cy,
  1616. SWP_NOZORDER|SWP_NOMOVE);
  1617. }
  1618. dyResultsTop = _dyResultsTop;
  1619. // NOTICE-NTRAID#NTBUG9-577850-2002/05/21-artm
  1620. // Layout did not give enough vertical room to the result label.
  1621. // In FE localized builds it was clipped when the window was
  1622. // repainted. _dyResultsTop does not take into account space
  1623. // needed between frame bottom and the top of the result label.
  1624. // Store the bottom of the frame for later calculation.
  1625. frameBottom = rect.bottom;
  1626. // when we have a cancel button then ensure that it is to the right
  1627. // of the OK button.
  1628. if (_hwndCancel)
  1629. {
  1630. GetRealWindowInfo(_hwndCancel, &rect, &sz);
  1631. if(hdwp)
  1632. {
  1633. hdwp = DeferWindowPos(hdwp, _hwndCancel, NULL,
  1634. (cx - _dxButtonsLeft), dyResultsTop - _dyOKTop,
  1635. 0, 0,
  1636. SWP_NOZORDER|SWP_NOSIZE);
  1637. }
  1638. GetRealWindowInfo(_hwndOK, &rect, &sz);
  1639. if(hdwp)
  1640. {
  1641. hdwp = DeferWindowPos(hdwp, _hwndOK, NULL,
  1642. (cx - _dxButtonsLeft - _dxGap - sz.cx), dyResultsTop - _dyOKTop,
  1643. 0, 0,
  1644. SWP_NOZORDER|SWP_NOSIZE);
  1645. }
  1646. }
  1647. else
  1648. {
  1649. GetRealWindowInfo(_hwndOK, &rect, &sz);
  1650. if(hdwp)
  1651. {
  1652. hdwp = DeferWindowPos(hdwp, _hwndOK, NULL,
  1653. (cx - _dxButtonsLeft), dyResultsTop - _dyOKTop,
  1654. 0, 0,
  1655. SWP_NOZORDER|SWP_NOSIZE);
  1656. }
  1657. }
  1658. }
  1659. // move the results and status bar as required
  1660. if (_hwndResults)
  1661. {
  1662. if(hdwp)
  1663. {
  1664. hdwp = DeferWindowPos(hdwp, _hwndStatus, NULL,
  1665. 0, cy - _cyStatus,
  1666. cx, _cyStatus,
  1667. SWP_SHOWWINDOW|SWP_NOZORDER);
  1668. }
  1669. // NTRAID#NTBUG9-406927-2001/10/24-lucios
  1670. HWND resultsLabel=GetDlgItem(_hwnd,CQID_RESULTSLABEL);
  1671. if(resultsLabel)
  1672. {
  1673. // NOTICE-NTRAID#NTBUG9-577850-2002/05/15-artm Label showing on FE builds.
  1674. // Make sure that the label is enabled now that we want to show it.
  1675. EnableWindow(resultsLabel, TRUE);
  1676. RECT rec;
  1677. GetClientRect(resultsLabel,&rec);
  1678. INT height=rect.bottom-rect.top;
  1679. // Include blank space above label proportional to height of label.
  1680. dyResultsTop = frameBottom + (height / 4);
  1681. if(hdwp)
  1682. {
  1683. hdwp = DeferWindowPos(hdwp, resultsLabel, NULL,
  1684. 0, dyResultsTop,
  1685. cx, height,
  1686. SWP_SHOWWINDOW|SWP_NOZORDER);
  1687. }
  1688. dyResultsTop+=height;
  1689. }
  1690. if(hdwp)
  1691. {
  1692. hdwp = DeferWindowPos(hdwp, _hwndResults, NULL,
  1693. 0, dyResultsTop,
  1694. cx, max(0, cy - (dyResultsTop + _cyStatus)),
  1695. SWP_SHOWWINDOW|SWP_NOZORDER);
  1696. }
  1697. }
  1698. // NTRAID#NTBUG9-670595-2002/08/08-artm
  1699. // Need to call EndDeferWindowPos() whether or not results and status bar moved.
  1700. if(hdwp)
  1701. {
  1702. EndDeferWindowPos(hdwp);
  1703. }
  1704. // here is the strange bit, by this point we have moved & sized all the
  1705. // controls on the dialog except the current page, as this is a child window
  1706. // and not a control which in turn has controls doing this would break
  1707. // the DefWindowPos path, therefore having updated everybody, lets update
  1708. // the page.
  1709. if (_pCurrentFormPage && _pCurrentFormPage->hwndPage)
  1710. {
  1711. GetRealWindowInfo(_hwndFrame, &rect, NULL);
  1712. TabCtrl_AdjustRect(_hwndFrame, FALSE, &rect);
  1713. cxForm = rect.right - rect.left;
  1714. cyForm = rect.bottom - rect.top;
  1715. SetWindowPos(_pCurrentFormPage->hwndPage, NULL,
  1716. rect.left, rect.top, cxForm, cyForm,
  1717. SWP_NOZORDER);
  1718. }
  1719. }
  1720. TraceLeave();
  1721. }
  1722. /*-----------------------------------------------------------------------------
  1723. / CQueryFrame::OnGetMinMaxInfo
  1724. / ----------------------------
  1725. / The window is being sized and we received a WM_SIZE, therefore move
  1726. / the content of the window about.
  1727. /
  1728. / In:
  1729. / lpmmin -> MINMAXINFO structure
  1730. /
  1731. / Out:
  1732. / -
  1733. /----------------------------------------------------------------------------*/
  1734. VOID CQueryFrame::OnGetMinMaxInfo(LPMINMAXINFO lpmmi)
  1735. {
  1736. RECT rect = {0, 0, 0, 0};
  1737. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnGetMinMaxInfo");
  1738. #if 0
  1739. if (!_fHideSearchPane)
  1740. #endif
  1741. {
  1742. lpmmi->ptMinTrackSize.x = _szMinTrack.cx;
  1743. lpmmi->ptMinTrackSize.y = _szMinTrack.cy;
  1744. if (!_hwndResults)
  1745. {
  1746. lpmmi->ptMaxSize.y = lpmmi->ptMinTrackSize.y;
  1747. lpmmi->ptMaxTrackSize.y = lpmmi->ptMinTrackSize.y;
  1748. }
  1749. }
  1750. #if 0
  1751. else
  1752. {
  1753. AdjustWindowRect(&rect, GetWindowLong(_hwnd, GWL_STYLE), (NULL != GetMenu(_hwnd)));
  1754. lpmmi->ptMinTrackSize.y = rect.bottom - rect.top;
  1755. }
  1756. #endif
  1757. if (_hwndResults && _hwndStatus)
  1758. lpmmi->ptMinTrackSize.y += _cyStatus;
  1759. TraceLeave();
  1760. }
  1761. /*-----------------------------------------------------------------------------
  1762. / CQueryFrame::OnCommand
  1763. / ----------------------
  1764. / We have recieved a WM_COMMAND so process it accordingly.
  1765. /
  1766. / In:
  1767. / wParam, lParam = parameters from the message
  1768. /
  1769. / Out:
  1770. / -
  1771. /----------------------------------------------------------------------------*/
  1772. VOID CQueryFrame::OnCommand(WPARAM wParam, LPARAM lParam)
  1773. {
  1774. HRESULT hres;
  1775. UINT uID = LOWORD(wParam);
  1776. UINT uNotify = HIWORD(wParam);
  1777. HWND hwndControl = (HWND)lParam;
  1778. INT i;
  1779. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnCommand");
  1780. Trace(TEXT("uID %08x, uNotify %d, hwndControl %08x"), uID, uNotify, hwndControl);
  1781. switch (uID)
  1782. {
  1783. case IDOK:
  1784. TraceMsg("IDOK received");
  1785. CloseQueryFrame(S_OK);
  1786. break;
  1787. case IDCANCEL:
  1788. TraceMsg("IDCANCEL received");
  1789. CloseQueryFrame(S_FALSE);
  1790. break;
  1791. case CQID_LOOKFOR:
  1792. {
  1793. if (uNotify == CBN_SELCHANGE)
  1794. {
  1795. INT iSel = ComboBox_GetCurSel(_hwndLookFor);
  1796. INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, iSel);
  1797. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  1798. TraceAssert(pQueryForm);
  1799. if (S_FALSE == SelectForm(pQueryForm->clsidForm))
  1800. {
  1801. TraceMsg("SelectForm return S_FALSE, so the user doesn't want the new form");
  1802. PostMessage(_hwndLookFor, CB_SETCURSEL, (WPARAM)_pCurrentForm->iForm, 0);
  1803. }
  1804. }
  1805. break;
  1806. }
  1807. case CQID_BROWSE:
  1808. OnBrowse();
  1809. break;
  1810. case CQID_FINDNOW:
  1811. OnFindNow();
  1812. break;
  1813. case CQID_STOP:
  1814. {
  1815. LONG style;
  1816. _pQueryHandler->StopQuery();
  1817. // For some reason, the standard method of getting the old
  1818. // def button used in SetDefButton() below isn't working,
  1819. // so we have to forcibly remove the BS_DEFPUSHBUTTON style
  1820. // from the CQID_STOP button.
  1821. style = GetWindowLong(_hwndStop, GWL_STYLE) & ~BS_DEFPUSHBUTTON;
  1822. SendMessage(_hwndStop,
  1823. BM_SETSTYLE,
  1824. MAKEWPARAM(style, 0),
  1825. MAKELPARAM(TRUE, 0));
  1826. SetDefButton(_hwnd, CQID_FINDNOW);
  1827. SendMessage(GetParent(_hwndFindNow),WM_NEXTDLGCTL,(WPARAM)_hwndFindNow,TRUE);
  1828. SetFocus(_hwndFindNow);
  1829. break;
  1830. }
  1831. case CQID_CLEARALL:
  1832. OnNewQuery(TRUE); // discard the current query
  1833. break;
  1834. case CQID_FILE_CLOSE:
  1835. TraceMsg("CQID_FILE_CLOSE received");
  1836. CloseQueryFrame(S_FALSE);
  1837. break;
  1838. default:
  1839. _pQueryHandler->InvokeCommand(_hwnd, uID);
  1840. break;
  1841. }
  1842. TraceLeave();
  1843. }
  1844. /*-----------------------------------------------------------------------------
  1845. / CQueryFrame::OnInitMenu
  1846. / -----------------------
  1847. / Handle telling the handler that the menu is being initialised, however
  1848. / this should only happen if the menu being activated is the
  1849. / menu bar, otherwise we assume that the caller is tracking a popup
  1850. / menu and has performed the required initalization.
  1851. /
  1852. / In:
  1853. / wParam, lParam = parameters from the WM_INITMENU
  1854. /
  1855. / Out:
  1856. / -
  1857. /----------------------------------------------------------------------------*/
  1858. VOID CQueryFrame::OnInitMenu(HMENU hMenu)
  1859. {
  1860. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitMenu");
  1861. _fTrackingMenuBar = (GetMenu(_hwnd) == hMenu);
  1862. if (_fTrackingMenuBar)
  1863. {
  1864. TraceMsg("Tracking the menu bar, sending activate");
  1865. _pQueryHandler->ActivateView(CQRVA_INITMENUBAR, (WPARAM)hMenu, 0L);
  1866. // NTRAID#NTBUG9-630248-2002/06/12-artm
  1867. // Only enable View menu if the results list box is displayed.
  1868. EnableMenuItem(
  1869. hMenu,
  1870. CQID_VIEW_SEARCHPANE,
  1871. MF_BYCOMMAND| ((_hwndResults != NULL) ? MF_ENABLED:MF_GRAYED) );
  1872. }
  1873. TraceLeave();
  1874. }
  1875. /*-----------------------------------------------------------------------------
  1876. / CQueryFrame::OnEnterMenuLoop
  1877. / ----------------------------
  1878. / When the user displays a menu we must reflect this into the status bar
  1879. / so that we can give the user help text relating to the commands they
  1880. / select.
  1881. /
  1882. / In:
  1883. / fEntering = entering the menu loop, or leaving.
  1884. /
  1885. / Out:
  1886. / -
  1887. /----------------------------------------------------------------------------*/
  1888. VOID CQueryFrame::OnEnterMenuLoop(BOOL fEntering)
  1889. {
  1890. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnEnterMenuLoop");
  1891. if (_hwndStatus)
  1892. {
  1893. if (fEntering)
  1894. {
  1895. SendMessage(_hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0L);
  1896. SendMessage(_hwndStatus, SB_SETTEXT, (WPARAM)SBT_NOBORDERS|255, 0L);
  1897. }
  1898. else
  1899. {
  1900. SendMessage(_hwndStatus, SB_SIMPLE, (WPARAM)FALSE, 0L);
  1901. }
  1902. }
  1903. TraceLeave();
  1904. }
  1905. /*-----------------------------------------------------------------------------
  1906. / CQueryFrame::OnMenuSelect
  1907. / -------------------------
  1908. / Get the status text for this menu item and display it to the user,
  1909. / if this doesn't map to any particular command then NULL out
  1910. / the string. At this point we also trap our commands.
  1911. /
  1912. / In:
  1913. / hMenu = menu the user is on
  1914. / uID = command ID for that item
  1915. /
  1916. / Out:
  1917. / -
  1918. /----------------------------------------------------------------------------*/
  1919. VOID CQueryFrame::OnMenuSelect(HMENU hMenu, UINT uID)
  1920. {
  1921. TCHAR szBuffer[MAX_PATH] = { TEXT('\0') };
  1922. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnMenuSelect");
  1923. Trace(TEXT("hMenu %08x, uID %08x"), hMenu, uID);
  1924. if (_hwndStatus)
  1925. {
  1926. switch (uID)
  1927. {
  1928. case CQID_FILE_CLOSE:
  1929. case CQID_VIEW_SEARCHPANE:
  1930. LoadString(GLOBAL_HINSTANCE, uID, szBuffer, ARRAYSIZE(szBuffer));
  1931. break;
  1932. default:
  1933. _pQueryHandler->GetCommandString(uID, 0x0, szBuffer, ARRAYSIZE(szBuffer));
  1934. break;
  1935. }
  1936. Trace(TEXT("Setting status bar to: %s"), szBuffer);
  1937. SendMessage(_hwndStatus, SB_SETTEXT, (WPARAM)SBT_NOBORDERS|255, (LPARAM)szBuffer);
  1938. }
  1939. TraceLeave();
  1940. }
  1941. /*-----------------------------------------------------------------------------
  1942. / CQueryFrame::OnFindNow
  1943. / ----------------------
  1944. // Issue the query, resulting in a view window being created and then issuing
  1945. // the parameter block to the query client.
  1946. /
  1947. / In:
  1948. / Out:
  1949. / HRESULT
  1950. /----------------------------------------------------------------------------*/
  1951. HRESULT CQueryFrame::OnFindNow(VOID)
  1952. {
  1953. HRESULT hres;
  1954. CQPARAMS qp = { 0 };
  1955. LPQUERYSCOPE pQueryScope = NULL;
  1956. TCHAR szBuffer[MAX_PATH];
  1957. BOOL fFixSize = TRUE;
  1958. RECT rc;
  1959. DECLAREWAITCURSOR;
  1960. BOOL fSetCursor = FALSE;
  1961. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnFindNow");
  1962. TraceAssert(_pCurrentForm != NULL);
  1963. if (_fQueryRunning)
  1964. ExitGracefully(hres, E_FAIL, "Quyery is already running");
  1965. SetWaitCursor();
  1966. fSetCursor = TRUE;
  1967. // If we have not created the viewer before now lets do so, also at the
  1968. // same time we attempt to fix the window size to ensure that enough
  1969. // of the view is visible.
  1970. if (!_hwndResults)
  1971. {
  1972. if (!_hwndStatus)
  1973. {
  1974. _hwndStatus = CreateStatusWindow(WS_CHILD, NULL, _hwnd, IDC_STATUS);
  1975. GetClientRect(_hwndStatus, &rc);
  1976. _cyStatus = rc.bottom - rc.top;
  1977. }
  1978. // Now construct the result viewer for us to use
  1979. hres = _pQueryHandler->CreateResultView(_hwnd, &_hwndResults);
  1980. FailGracefully(hres, "Failed when creating the view object");
  1981. GetWindowRect(_hwnd, &rc);
  1982. SetWindowPos(_hwnd, NULL,
  1983. 0, 0,
  1984. rc.right - rc.left,
  1985. _szMinTrack.cy + VIEWER_DEFAULT_CY,
  1986. SWP_NOZORDER|SWP_NOMOVE);
  1987. }
  1988. // are we still collecting the scopes async? If so then lets wait until
  1989. // they have all arrived before we set the UI running.
  1990. if (_hdsaScopes && DSA_GetItemCount(_hdsaScopes))
  1991. {
  1992. // Collect the parameters ready for starting the query, if this fails then
  1993. // there is no point us continuing.
  1994. ZeroMemory(&qp, SIZEOF(qp));
  1995. qp.cbStruct = SIZEOF(qp);
  1996. //qp.dwFlags = 0x0;
  1997. qp.clsidForm = _pCurrentForm->clsidForm; // new NT5 beta 2
  1998. hres = GetSelectedScope(&pQueryScope);
  1999. FailGracefully(hres, "Failed to get the scope from the LookIn control");
  2000. if (pQueryScope)
  2001. {
  2002. Trace(TEXT("pQueryScope %08x"), pQueryScope);
  2003. qp.pQueryScope = pQueryScope->pScope;
  2004. }
  2005. hres = CallFormPages(_pCurrentForm, CQPM_GETPARAMETERS, 0, (LPARAM)&qp.pQueryParameters);
  2006. FailGracefully(hres, "Failed when collecting parameters from form");
  2007. if (!qp.pQueryParameters)
  2008. {
  2009. LoadString(GLOBAL_HINSTANCE, IDS_ERR_NOPARAMS, szBuffer, ARRAYSIZE(szBuffer));
  2010. FrameMessageBox(szBuffer, MB_ICONERROR|MB_OK);
  2011. ExitGracefully(hres, E_FAIL, "Failed to issue the query, no parameters");
  2012. }
  2013. // We either already had a view, or have just created one. Either way
  2014. // we must now prepare the query for sending.
  2015. Trace(TEXT("qp.cbStruct %08x"), qp.cbStruct);
  2016. Trace(TEXT("qp.dwFlags %08x"), qp.dwFlags);
  2017. Trace(TEXT("qp.pQueryScope %08x"), qp.pQueryScope);
  2018. Trace(TEXT("qp.pQueryParameters %08x"), qp.pQueryParameters);
  2019. TraceGUID("qp.clsidForm: ", qp.clsidForm);
  2020. hres = _pQueryHandler->IssueQuery(&qp);
  2021. FailGracefully(hres, "Failed in IssueQuery");
  2022. }
  2023. else
  2024. {
  2025. // set the status text to reflect that we are initializng, otherwise it is
  2026. // left empty and looks like we have crashed.
  2027. if (LoadString(GLOBAL_HINSTANCE, IDS_INITIALIZING, szBuffer, ARRAYSIZE(szBuffer)))
  2028. {
  2029. SetStatusText(szBuffer);
  2030. }
  2031. }
  2032. hres = S_OK; // success
  2033. exit_gracefully:
  2034. if (qp.pQueryParameters)
  2035. CoTaskMemFree(qp.pQueryParameters);
  2036. if (fSetCursor)
  2037. ResetWaitCursor();
  2038. TraceLeaveResult(hres);
  2039. }
  2040. /*-----------------------------------------------------------------------------
  2041. / CQueryFrame::OnNewQuery
  2042. / -----------------------
  2043. / Discard the current query, prompting the user as requierd.
  2044. /
  2045. / In:
  2046. / fAlwaysPrompt = TRUE if we force prompting of the user
  2047. /
  2048. / Out:
  2049. / BOOL
  2050. /----------------------------------------------------------------------------*/
  2051. BOOL CQueryFrame::OnNewQuery(BOOL fAlwaysPrompt)
  2052. {
  2053. BOOL fQueryCleared = TRUE;
  2054. TCHAR szBuffer[MAX_PATH];
  2055. RECT rc;
  2056. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNewQuery");
  2057. if (_hwndResults || fAlwaysPrompt)
  2058. {
  2059. LoadString(GLOBAL_HINSTANCE, IDS_CLEARCURRENT, szBuffer, ARRAYSIZE(szBuffer));
  2060. if (IDOK != FrameMessageBox(szBuffer, MB_ICONINFORMATION|MB_OKCANCEL))
  2061. ExitGracefully(fQueryCleared, FALSE, "Used cancled new query");
  2062. if (_pQueryHandler)
  2063. _pQueryHandler->StopQuery();
  2064. CallFormPages(_pCurrentForm, CQPM_CLEARFORM, 0, 0);
  2065. if (_hwndResults)
  2066. {
  2067. DestroyWindow(_hwndResults); // no result view now
  2068. _hwndResults = NULL;
  2069. // NOTICE-NTRAID#NTBUG9-577850-2002/05/15-artm Label showing in FE builds.
  2070. // Hide the label so there is no chance of seeing it when result view not
  2071. // visible.
  2072. HWND resultsLabel = GetDlgItem(_hwnd, CQID_RESULTSLABEL);
  2073. if (resultsLabel)
  2074. {
  2075. EnableWindow(resultsLabel, FALSE);
  2076. ShowWindow(resultsLabel, SW_HIDE);
  2077. }
  2078. DestroyWindow(_hwndStatus); // no status bar
  2079. _hwndStatus = NULL;
  2080. GetWindowRect(_hwnd, &rc); // shrink the window
  2081. SetWindowPos(_hwnd, NULL,
  2082. 0, 0, rc.right - rc.left, _szMinTrack.cy,
  2083. SWP_NOZORDER|SWP_NOMOVE);
  2084. }
  2085. }
  2086. exit_gracefully:
  2087. TraceLeaveValue(fQueryCleared);
  2088. }
  2089. /*-----------------------------------------------------------------------------
  2090. / CQueryFrame::OnBrowse
  2091. / ---------------------
  2092. / Browse for a new scope, adding it to the list if not already present,
  2093. / or selecting the previous scope.
  2094. /
  2095. / In:
  2096. / Out:
  2097. / HRESULT
  2098. /----------------------------------------------------------------------------*/
  2099. HRESULT CQueryFrame::OnBrowse(VOID)
  2100. {
  2101. HRESULT hres;
  2102. LPQUERYSCOPE pQueryScope = NULL;
  2103. LPCQSCOPE pScope = NULL;
  2104. TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnBrowse");
  2105. // Call the handler and get a scope allocation back, then add it to the list
  2106. // of scopes to be displayed.
  2107. hres = GetSelectedScope(&pQueryScope);
  2108. FailGracefully(hres, "Failed to get the scope from the LookIn control");
  2109. Trace(TEXT("Calling BrowseForScope _hwnd %08x, pQueryScope %08x (%08x)"),
  2110. _hwnd, pQueryScope, pQueryScope->pScope);
  2111. hres = _pQueryHandler->BrowseForScope(_hwnd, pQueryScope ? pQueryScope->pScope:NULL, &pScope);
  2112. FailGracefully(hres, "Failed when calling BrowseForScope");
  2113. if ((hres != S_FALSE) && pScope)
  2114. {
  2115. hres = InsertScopeIntoList(pScope, DA_LAST, TRUE);
  2116. FailGracefully(hres, "Failed when adding the scope to the control");
  2117. ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
  2118. }
  2119. hres = S_OK;
  2120. exit_gracefully:
  2121. if (pScope)
  2122. CoTaskMemFree(pScope);
  2123. TraceLeaveResult(hres);
  2124. }
  2125. /*-----------------------------------------------------------------------------
  2126. / CQueryFrame::OnHelp
  2127. / -------------------
  2128. / Invoke the context sensitive help for the window, catch the
  2129. / handler specific and page specific stuff and pass those help
  2130. / requests down to the relevant objects.
  2131. /
  2132. / In:
  2133. / pHelpInfo -> help info structure
  2134. /
  2135. / Out:
  2136. / HRESULT
  2137. /----------------------------------------------------------------------------*/
  2138. HRESULT CQueryFrame::OnHelp(LPHELPINFO pHelpInfo)
  2139. {
  2140. HRESULT hres;
  2141. RECT rc;
  2142. HWND hwnd = (HWND)pHelpInfo->hItemHandle;
  2143. TraceEnter(TRACE_FRAME, "CQueryFrame::OnHelp");
  2144. // We are invoking help, theroefore we need ot check to see where element
  2145. // of the window we are being invoked for. If it is the
  2146. // result view then route the message to that, if its the form then
  2147. // likewise.
  2148. //
  2149. // If we don't hit any of the extension controls then lets pass the
  2150. // help onto WinHelp and get it to display the topics we have.
  2151. if (pHelpInfo->iContextType != HELPINFO_WINDOW)
  2152. ExitGracefully(hres, E_FAIL, "WM_HELP handler only copes with WINDOW objects");
  2153. if (_pCurrentFormPage->hwndPage && IsChild(_pCurrentFormPage->hwndPage, hwnd))
  2154. {
  2155. // it was on the query form page, therefore let it go there, that way
  2156. // they can provide topics specific to them
  2157. TraceMsg("Invoking help on the form pane");
  2158. hres = _CallPageProc(_pCurrentFormPage, CQPM_HELP, 0, (LPARAM)pHelpInfo);
  2159. FailGracefully(hres, "Failed when calling page proc to get help");
  2160. }
  2161. else
  2162. {
  2163. // pass the help information through to the handler as an activation,
  2164. // this should really just be a new method, but this works.
  2165. TraceMsg("Invoking help on the results pane");
  2166. TraceAssert(_pQueryHandler);
  2167. hres = _pQueryHandler->ActivateView(CQRVA_HELP, 0, (LPARAM)pHelpInfo);
  2168. FailGracefully(hres, "Handler WndProc returned FALSE");
  2169. }
  2170. hres = S_OK;
  2171. exit_gracefully:
  2172. TraceLeaveResult(hres);
  2173. }
  2174. /*-----------------------------------------------------------------------------
  2175. / Scope helper functions
  2176. /----------------------------------------------------------------------------*/
  2177. /*-----------------------------------------------------------------------------
  2178. / _CallScopeProc
  2179. / --------------
  2180. / Releae the given scope object, freeing the object that is referenced
  2181. / and passing a CQSM_RELEASE message to it.
  2182. /
  2183. / In:
  2184. / pQueryScope -> scope object to be called
  2185. / uMsg, pVoid -> parameters for the scope
  2186. /
  2187. / Out:
  2188. / HRESULT
  2189. /----------------------------------------------------------------------------*/
  2190. HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid)
  2191. {
  2192. HRESULT hres;
  2193. TraceEnter(TRACE_SCOPES, "_CallScopeProc");
  2194. Trace(TEXT("pQueryScope %08x, uMsg %d, pVoid %08x"), pQueryScope, uMsg, pVoid);
  2195. Trace(TEXT("(cbStruct %d, pScopeProc %08x, lParam %08x)"),
  2196. pQueryScope->pScope->cbStruct,
  2197. pQueryScope->pScope->pScopeProc,
  2198. pQueryScope->pScope->lParam);
  2199. if (!pQueryScope)
  2200. ExitGracefully(hres, S_OK, "pQueryScope == NULL");
  2201. hres = (pQueryScope->pScope->pScopeProc)(pQueryScope->pScope, uMsg, pVoid);
  2202. FailGracefully(hres, "Failed calling ScopeProc");
  2203. exit_gracefully:
  2204. TraceLeaveResult(hres);
  2205. }
  2206. /*-----------------------------------------------------------------------------
  2207. / _FreeScope
  2208. / ----------
  2209. / Releae the given scope object, freeing the object that is referenced
  2210. / and passing a CQSM_RELEASE message to it.
  2211. /
  2212. / In:
  2213. / pQueryScope -> scope object to be released
  2214. /
  2215. / Out:
  2216. / INT == 1 always
  2217. /----------------------------------------------------------------------------*/
  2218. INT _FreeScopeCB(LPVOID pItem, LPVOID pData)
  2219. {
  2220. return _FreeScope((LPQUERYSCOPE)pItem);
  2221. }
  2222. INT _FreeScope(LPQUERYSCOPE pQueryScope)
  2223. {
  2224. TraceEnter(TRACE_SCOPES, "_FreeScope");
  2225. Trace(TEXT("pQueryScope %08x, pQueryScope->pScope %08x"), pQueryScope, pQueryScope->pScope);
  2226. if (pQueryScope)
  2227. {
  2228. _CallScopeProc(pQueryScope, CQSM_RELEASE, NULL);
  2229. if (pQueryScope->pScope)
  2230. {
  2231. LocalFree((HLOCAL)pQueryScope->pScope);
  2232. pQueryScope->pScope = NULL;
  2233. }
  2234. }
  2235. TraceLeaveValue(TRUE);
  2236. }
  2237. /*-----------------------------------------------------------------------------
  2238. / CQueryFrame::InsertScopeIntoList
  2239. / --------------------------------
  2240. / Adds the given scope to the scope picker.
  2241. /
  2242. / In:
  2243. / pQueryScope -> zcope object to be added to the view
  2244. / i = index to insert the scope at
  2245. / fAddToControl = add the scope the picker control
  2246. / ppQueryScope -> recieves the new query scope object / = NULL
  2247. /
  2248. / Out:
  2249. / HRESULT
  2250. /----------------------------------------------------------------------------*/
  2251. HRESULT CQueryFrame::InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl)
  2252. {
  2253. HRESULT hres;
  2254. QUERYSCOPE qs;
  2255. INT iScope;
  2256. TraceEnter(TRACE_SCOPES, "CQueryFrame::InsertScopeIntoList");
  2257. Trace(TEXT("pScope %08x, i %d, fAddToControl %d"), pScope, i, fAddToControl);
  2258. if (!pScope)
  2259. ExitGracefully(hres, E_INVALIDARG, "pScope == NULL, not allowed");
  2260. // if we don't have any scopes then allocate the DSA
  2261. if (!_hdsaScopes)
  2262. {
  2263. _hdsaScopes = DSA_Create(SIZEOF(QUERYSCOPE), 4);
  2264. TraceAssert(_hdsaScopes);
  2265. if (!_hdsaScopes)
  2266. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope DPA");
  2267. }
  2268. // Walk the list of scopes checking to see if this one is already in
  2269. // there, if not then we can add it.
  2270. for (iScope = 0 ; iScope < DSA_GetItemCount(_hdsaScopes) ; iScope++)
  2271. {
  2272. LPQUERYSCOPE pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
  2273. TraceAssert(pQueryScope);
  2274. if (S_OK == _CallScopeProc(pQueryScope, CQSM_SCOPEEQUAL, pScope))
  2275. {
  2276. hres = ResultFromShort(iScope);
  2277. goto exit_gracefully;
  2278. }
  2279. }
  2280. // Take a copy of the scope blob passed by the caller. We copy the entire
  2281. // structure who's size is defined by cbStruct into a LocalAlloc block,
  2282. // once we have this we can then build the QUERYSCOPE structure that references
  2283. // it.
  2284. Trace(TEXT("pScope->cbStruct == %d"), pScope->cbStruct);
  2285. qs.pScope = (LPCQSCOPE)LocalAlloc(LPTR, pScope->cbStruct);
  2286. if (!qs.pScope)
  2287. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate query scope");
  2288. Trace(TEXT("Copying structure qs.pScope %08x, pScope %08x"), qs.pScope, pScope);
  2289. //REVIEWED-2002-02-25-lucios.
  2290. CopyMemory(qs.pScope, pScope, pScope->cbStruct);
  2291. //qs.pScope = NULL;
  2292. qs.iImage = -1; // no image
  2293. // We have a QUERYSCOPE, so initialize it, if that works then append it to the
  2294. // DSA before either setting the return value or appending it to the control.
  2295. _CallScopeProc(&qs, CQSM_INITIALIZE, NULL);
  2296. iScope = DSA_InsertItem(_hdsaScopes, i, &qs);
  2297. Trace(TEXT("iScope = %d"), iScope);
  2298. if (iScope == -1)
  2299. {
  2300. _FreeScope(&qs);
  2301. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to add scope to DSA");
  2302. }
  2303. if (fAddToControl)
  2304. {
  2305. LPQUERYSCOPE pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
  2306. TraceAssert(pQueryScope);
  2307. Trace(TEXT("Calling AddScopeToControl with %08x (%d)"), pQueryScope, iScope);
  2308. hres = AddScopeToControl(pQueryScope, iScope);
  2309. }
  2310. else
  2311. {
  2312. hres = ResultFromShort(iScope);
  2313. }
  2314. exit_gracefully:
  2315. TraceLeaveResult(hres);
  2316. }
  2317. /*-----------------------------------------------------------------------------
  2318. / CQueryFrame::AddScopeToControl
  2319. / ------------------------------
  2320. / Adds the given scope to the scope picker.
  2321. /
  2322. / In:
  2323. / pQueryScope -> zcope object to be added to the view
  2324. / i = index into view where to insert the scope
  2325. /
  2326. / Out:
  2327. / HRESULT (== index of item added)
  2328. /----------------------------------------------------------------------------*/
  2329. HRESULT CQueryFrame::AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i)
  2330. {
  2331. HRESULT hres;
  2332. CQSCOPEDISPLAYINFO cqsdi;
  2333. COMBOBOXEXITEM cbi;
  2334. TCHAR szBuffer[MAX_PATH];
  2335. TCHAR szIconLocation[MAX_PATH] = { 0 };
  2336. INT item;
  2337. TraceEnter(TRACE_SCOPES, "CQueryFrame::AddScopeToControl");
  2338. if (!pQueryScope)
  2339. ExitGracefully(hres, E_INVALIDARG, "No scope specified");
  2340. // Call the scope to get the display information about this
  2341. // scope before we attempt to add it.
  2342. cqsdi.cbStruct = SIZEOF(cqsdi);
  2343. cqsdi.dwFlags = 0;
  2344. cqsdi.pDisplayName = szBuffer;
  2345. cqsdi.cchDisplayName = ARRAYSIZE(szBuffer);
  2346. cqsdi.pIconLocation = szIconLocation;
  2347. cqsdi.cchIconLocation = ARRAYSIZE(szIconLocation);
  2348. cqsdi.iIconResID = 0;
  2349. cqsdi.iIndent = 0;
  2350. hres = _CallScopeProc(pQueryScope, CQSM_GETDISPLAYINFO, &cqsdi);
  2351. FailGracefully(hres, "Failed to get display info for the scope");
  2352. // Now add the item to the control, if they gave as an image then
  2353. // add that to the image list (and tweak the INSERTITEM structure
  2354. // accordingly).
  2355. cbi.mask = CBEIF_TEXT|CBEIF_INDENT;
  2356. cbi.iItem = i;
  2357. cbi.pszText = cqsdi.pDisplayName;
  2358. cbi.iIndent = cqsdi.iIndent;
  2359. Trace(TEXT("Indent is %d"), cqsdi.iIndent);
  2360. if (szIconLocation[0] && cqsdi.iIconResID)
  2361. {
  2362. INT iImage;
  2363. if (!_fScopeImageListSet)
  2364. {
  2365. HIMAGELIST himlSmall;
  2366. Shell_GetImageLists(NULL, &himlSmall);
  2367. SendMessage(_hwndLookIn, CBEM_SETIMAGELIST, 0, (LPARAM)himlSmall);
  2368. _fScopeImageListSet = TRUE;
  2369. }
  2370. cbi.mask |= CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
  2371. cbi.iImage = Shell_GetCachedImageIndex(szIconLocation, cqsdi.iIconResID, 0x0);;
  2372. cbi.iSelectedImage = cbi.iImage;
  2373. Trace(TEXT("Image index set to: %d"), cbi.iImage);
  2374. }
  2375. item = (INT)SendMessage(_hwndLookIn, CBEM_INSERTITEM, 0, (LPARAM)&cbi);
  2376. if (item == -1)
  2377. ExitGracefully(hres, E_FAIL, "Failed when inserting the scope to the list");
  2378. DoEnableControls(); // reflect button changes into UI
  2379. hres = ResultFromShort(item);
  2380. exit_gracefully:
  2381. TraceLeaveResult(hres);
  2382. }
  2383. /*-----------------------------------------------------------------------------
  2384. / CQueryFrame::PopulateScopeControl
  2385. / ---------------------------------
  2386. / Collect the scopes that we want to display in the scope control and
  2387. / then populate it. If the handler doesn't return any scopes then
  2388. / we remove the control and assume that know what to do when they
  2389. / don't receive a scope pointer.
  2390. /
  2391. / In:
  2392. / -
  2393. /
  2394. / Out:
  2395. / HRESULT
  2396. /----------------------------------------------------------------------------*/
  2397. HRESULT CQueryFrame::PopulateScopeControl(VOID)
  2398. {
  2399. HRESULT hres;
  2400. LPQUERYSCOPE pQueryScope;
  2401. INT i;
  2402. TraceEnter(TRACE_SCOPES, "CQueryFrame::PopulateScopeControl");
  2403. // Collect the scopes that we should be showing in the view, if we don't
  2404. // get any back then we disable the scope control, if we do get some then
  2405. // populate the scope control with them.
  2406. hres = _pQueryHandler->AddScopes();
  2407. _fAddScopesNYI = (hres == E_NOTIMPL);
  2408. if (hres != E_NOTIMPL)
  2409. FailGracefully(hres, "Failed when calling handler to add scopes");
  2410. if (_hdsaScopes)
  2411. {
  2412. // We have some scopes, so now we create the image list that we can use
  2413. // for icons with scopes. Then walk through the DPA getting the scope
  2414. // to give us some display information about itself that we can
  2415. // add to the combo box.
  2416. ComboBox_SetExtendedUI(_hwndLookIn, TRUE);
  2417. for (i = 0 ; i < DSA_GetItemCount(_hdsaScopes); i++)
  2418. {
  2419. pQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, i);
  2420. TraceAssert(pQueryScope);
  2421. AddScopeToControl(pQueryScope, i);
  2422. }
  2423. }
  2424. else
  2425. {
  2426. // we don't have any scopes after calling AddScopes, this is either
  2427. // because the ::AddScopes method is not implemented, or the
  2428. // scopes are being added async. If IssueQuery returned a success
  2429. // we assume they are coming in async and flag as such in our
  2430. // state.
  2431. if (!_fAddScopesNYI)
  2432. {
  2433. TraceMsg("Handler adding scopes async, so marking so");
  2434. _fScopesAddedAsync = TRUE;
  2435. }
  2436. }
  2437. hres = S_OK; // success
  2438. exit_gracefully:
  2439. Trace(TEXT("Default scope is index %d"), _iDefaultScope);
  2440. ComboBox_SetCurSel(_hwndLookIn, _iDefaultScope);
  2441. TraceLeaveResult(hres);
  2442. }
  2443. /*-----------------------------------------------------------------------------
  2444. / CQueryFrame::GetSelectedScope
  2445. / -----------------------------
  2446. / Get the selected from the the scope ComboBox, this is a reference into the
  2447. / scope DSA.
  2448. /
  2449. / In:
  2450. / ppQueryScope = receives a pointer to the new scope
  2451. /
  2452. / Out:
  2453. / HRESULT
  2454. /----------------------------------------------------------------------------*/
  2455. HRESULT CQueryFrame::GetSelectedScope(LPQUERYSCOPE* ppQueryScope)
  2456. {
  2457. HRESULT hres;
  2458. COMBOBOXEXITEM cbi;
  2459. INT iScope;
  2460. TraceEnter(TRACE_SCOPES, "CQueryFrame::GetSelectedScope");
  2461. *ppQueryScope = NULL;
  2462. if (_hdsaScopes)
  2463. {
  2464. // Get the index for the current scope, if it doesn't give a real
  2465. // index to a item in our view then barf! Otherwise look up the
  2466. // associated scope.
  2467. iScope = ComboBox_GetCurSel(_hwndLookIn);
  2468. Trace(TEXT("iScope %d"), iScope);
  2469. if (iScope == -1)
  2470. ExitGracefully(hres, E_FAIL, "User entered scopes not supported yet");
  2471. *ppQueryScope = (LPQUERYSCOPE)DSA_GetItemPtr(_hdsaScopes, iScope);
  2472. TraceAssert(*ppQueryScope);
  2473. }
  2474. hres = *ppQueryScope ? S_OK : E_FAIL;
  2475. exit_gracefully:
  2476. Trace(TEXT("Returning LPQUERYSCOPE %08x"), *ppQueryScope);
  2477. TraceLeaveResult(hres);
  2478. }
  2479. /*-----------------------------------------------------------------------------
  2480. / Form handling functions
  2481. /----------------------------------------------------------------------------*/
  2482. /*-----------------------------------------------------------------------------
  2483. / _FreeQueryForm
  2484. / ---------------
  2485. / Destroy the QUERYFORM allocation being used to describe the form in
  2486. / our DPA. We ensure that we issue a CQPM_RELEASE before doing anything
  2487. /
  2488. / In:
  2489. / pQueryForm -> query form to be destroyed
  2490. /
  2491. / Out:
  2492. / INT == 1 always
  2493. /----------------------------------------------------------------------------*/
  2494. INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData)
  2495. {
  2496. return _FreeQueryForm((LPQUERYFORM)pItem);
  2497. }
  2498. INT _FreeQueryForm(LPQUERYFORM pQueryForm)
  2499. {
  2500. TraceEnter(TRACE_FORMS, "_FreeQueryForm");
  2501. if (pQueryForm)
  2502. {
  2503. if (pQueryForm->hdsaPages)
  2504. {
  2505. DSA_DestroyCallback(pQueryForm->hdsaPages, _FreeQueryFormPageCB, NULL);
  2506. pQueryForm->hdsaPages = NULL;
  2507. }
  2508. Str_SetPtr(&pQueryForm->pTitle, NULL);
  2509. if (pQueryForm->hIcon)
  2510. {
  2511. DestroyIcon(pQueryForm->hIcon);
  2512. }
  2513. }
  2514. TraceLeaveValue(TRUE);
  2515. }
  2516. /*-----------------------------------------------------------------------------
  2517. / _FreeQueryFormPage
  2518. / ------------------
  2519. / Given a pointer to a query form page structure release the members that
  2520. // are of interest, including calling the PAGEPROC to releasee the underlying
  2521. / object.
  2522. /
  2523. / In:
  2524. / pQueryFormPage -> page to be removed
  2525. /
  2526. / Out:
  2527. / INT == 1 always
  2528. /----------------------------------------------------------------------------*/
  2529. INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData)
  2530. {
  2531. return _FreeQueryFormPage((LPQUERYFORMPAGE)pItem);
  2532. }
  2533. INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage)
  2534. {
  2535. TraceEnter(TRACE_FORMS, "_FreeQueryFormPage");
  2536. if (pQueryFormPage)
  2537. {
  2538. _CallPageProc(pQueryFormPage, CQPM_RELEASE, 0, 0); // NB: ignore return code
  2539. if (pQueryFormPage->hwndPage)
  2540. {
  2541. EnableThemeDialogTexture(pQueryFormPage->hwndPage, ETDT_DISABLE);
  2542. DestroyWindow(pQueryFormPage->hwndPage);
  2543. pQueryFormPage->hwndPage = NULL;
  2544. }
  2545. if (pQueryFormPage->pPage)
  2546. {
  2547. LocalFree(pQueryFormPage->pPage);
  2548. pQueryFormPage->pPage = NULL;
  2549. }
  2550. }
  2551. TraceLeaveValue(TRUE);
  2552. }
  2553. /*-----------------------------------------------------------------------------
  2554. / _CallPageProc
  2555. / -------------
  2556. / Call the given page object thunking the arguments as required if the
  2557. / page object is non-UNICODE (only if building UNICODE).
  2558. /
  2559. / In:
  2560. / pQueryFormPage -> page object to be called
  2561. / uMsg, wParam, lParam = parameters for message
  2562. /
  2563. / Out:
  2564. / HRESULT
  2565. /----------------------------------------------------------------------------*/
  2566. HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2567. {
  2568. HRESULT hres;
  2569. TraceEnter(TRACE_FORMS, "_CallPageProc");
  2570. Trace(TEXT("pQueryFormPage %08x, pPage %08x, uMsg %d, wParam %08x, lParam %08x"),
  2571. pQueryFormPage, pQueryFormPage->pPage, uMsg, wParam, lParam);
  2572. if (!pQueryFormPage)
  2573. ExitGracefully(hres, S_OK, "pQueryFormPage == NULL");
  2574. hres = (pQueryFormPage->pPage->pPageProc)(pQueryFormPage->pPage, pQueryFormPage->hwndPage, uMsg, wParam, lParam);
  2575. FailGracefully(hres, "Failed calling PageProc");
  2576. // hres = S_OK;
  2577. exit_gracefully:
  2578. TraceLeaveResult(hres);
  2579. }
  2580. /*-----------------------------------------------------------------------------
  2581. / Functions for adding query forms/pages
  2582. /----------------------------------------------------------------------------*/
  2583. // CB to add forms to the form DSA.
  2584. HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM pForm)
  2585. {
  2586. HRESULT hres;
  2587. QUERYFORM qf = {0};
  2588. HDSA hdsaForms = (HDSA)lParam;
  2589. TraceEnter(TRACE_FORMS, "_AddFormsProc");
  2590. if (!pForm || !hdsaForms)
  2591. ExitGracefully(hres, E_INVALIDARG, "Failed to add page pForm == NULL");
  2592. // Allocate and thunk as required
  2593. qf.hdsaPages = NULL; // DSA of pages
  2594. qf.dwFlags = pForm->dwFlags; // flags
  2595. qf.clsidForm = pForm->clsid; // CLSID identifier for this form
  2596. qf.pTitle = NULL; // title used for drop down / title bar
  2597. qf.hIcon = pForm->hIcon; // hIcon passed by caller
  2598. qf.iImage = -1; // image list index of icon
  2599. qf.iForm = 0; // visible index of form in control
  2600. qf.iPage = 0; // currently selected page on form
  2601. if (!Str_SetPtr(&qf.pTitle, pForm->pszTitle))
  2602. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to copy form title string");
  2603. // Allocate the DSA if one doesn't exist yet, then add in the form
  2604. // structure as required.
  2605. if (-1 == DSA_AppendItem(hdsaForms, &qf))
  2606. ExitGracefully(hres, E_FAIL, "Failed to add form to the form DSA");
  2607. hres = S_OK; // success
  2608. exit_gracefully:
  2609. if (FAILED(hres))
  2610. _FreeQueryForm(&qf);
  2611. TraceLeaveResult(hres);
  2612. }
  2613. // CB to add pages to the page DSA.
  2614. HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE pPage)
  2615. {
  2616. HRESULT hres;
  2617. QUERYFORMPAGE qfp = {0};
  2618. HDSA hdsaPages = (HDSA)lParam;
  2619. TraceEnter(TRACE_FORMS, "_AddPagesProc");
  2620. if (!pPage || !hdsaPages)
  2621. ExitGracefully(hres, E_INVALIDARG, "Failed to add page pPage == NULL");
  2622. // copy the pPage structure for us to pass to the PAGEPROC later, nb: we
  2623. // use the cbStruct field to indicate the size of blob we must copy.
  2624. Trace(TEXT("pPage->cbStruct == %d"), pPage->cbStruct);
  2625. qfp.pPage = (LPCQPAGE)LocalAlloc(LPTR, pPage->cbStruct);
  2626. if (!qfp.pPage)
  2627. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate copy of page structure");
  2628. Trace(TEXT("Copying structure qfp.pPage %08x, pPage %08x"), qfp.pPage, pPage);
  2629. //REVIEWED-2002-02-25-lucios.
  2630. CopyMemory(qfp.pPage, pPage, pPage->cbStruct); // copy the page structure
  2631. //qfp.pPage = NULL;
  2632. qfp.clsidForm = clsidForm;
  2633. qfp.pPageProc = pPage->pPageProc;
  2634. qfp.lParam = pPage->lParam;
  2635. qfp.hwndPage = NULL;
  2636. _CallPageProc(&qfp, CQPM_INITIALIZE, 0, 0);
  2637. if (-1 == DSA_AppendItem(hdsaPages, &qfp))
  2638. ExitGracefully(hres, E_FAIL, "Failed to add the form to the DSA");
  2639. hres = S_OK; // succcess
  2640. exit_gracefully:
  2641. if (FAILED(hres))
  2642. _FreeQueryFormPage(&qfp);
  2643. TraceLeaveResult(hres);
  2644. }
  2645. // Add forms/pages from a UNICODE IQueryForm iface
  2646. HRESULT CQueryFrame::AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hKeyForm)
  2647. {
  2648. HRESULT hres;
  2649. TraceEnter(TRACE_FORMS, "CQueryFrame::AddFromIQueryForm");
  2650. if (!pQueryForm)
  2651. ExitGracefully(hres, E_FAIL, "pQueryForm == NULL, failing");
  2652. hres = pQueryForm->Initialize(hKeyForm);
  2653. FailGracefully(hres, "Failed in IQueryFormW::Initialize");
  2654. // Call the form object to add its form and then its pages
  2655. hres = pQueryForm->AddForms(_AddFormsProc, (LPARAM)_hdsaForms);
  2656. if (SUCCEEDED(hres) || (hres == E_NOTIMPL))
  2657. {
  2658. hres = pQueryForm->AddPages(_AddPagesProc, (LPARAM)_hdsaPages);
  2659. FailGracefully(hres, "Failed in IQueryForm::AddPages");
  2660. }
  2661. else
  2662. {
  2663. FailGracefully(hres, "Failed when calling IQueryForm::AddForms");
  2664. }
  2665. hres = S_OK; // success
  2666. exit_gracefully:
  2667. TraceLeaveResult(hres);
  2668. }
  2669. #ifdef UNICODE
  2670. #define ADD_FROM_IQUERYFORM AddFromIQueryFormW
  2671. #else
  2672. #define ADD_FROM_IQUERYFORM AddFromIQueryFormA
  2673. #endif
  2674. /*-----------------------------------------------------------------------------
  2675. / CQueryFrame::GatherForms
  2676. / ------------------------
  2677. / Enumerate all the query forms for the given query handler and build
  2678. / the DPA containing the list of them. Once we have done this we
  2679. / can then populate the control at some more convientent moment.
  2680. /
  2681. / When gathering we first hit the "handler", then the "Forms" sub-key
  2682. / trying to load all the InProc servers that provide forms. We build
  2683. / list of hidden, never shown etc.
  2684. /
  2685. / In:
  2686. / -
  2687. / Out:
  2688. / HRESULT
  2689. /----------------------------------------------------------------------------*/
  2690. HRESULT _AddPageToForm(LPQUERYFORM pQueryForm, LPQUERYFORMPAGE pQueryFormPage, BOOL fClone)
  2691. {
  2692. HRESULT hres;
  2693. QUERYFORMPAGE qfp;
  2694. TraceEnter(TRACE_FORMS, "_AddPageToForm");
  2695. TraceAssert(pQueryForm);
  2696. TraceAssert(pQueryFormPage);
  2697. // ensure that we have a page DSA for this form object
  2698. if (!pQueryForm->hdsaPages)
  2699. {
  2700. TraceMsg("Creating a new page DSA for form");
  2701. pQueryForm->hdsaPages = DSA_Create(SIZEOF(QUERYFORMPAGE), 4);
  2702. if (!pQueryForm->hdsaPages)
  2703. ExitGracefully(hres, E_OUTOFMEMORY, "*** No page DSA on form object ***");
  2704. }
  2705. if (!fClone)
  2706. {
  2707. // Moving this page structure to the one associated with the query form,
  2708. // therefore just ensure that the form has a DSA for pages and just
  2709. // insert an item at the header (yes, we add the pages in reverse).
  2710. Trace(TEXT("Adding page %08x to form %s"), pQueryFormPage, pQueryForm->pTitle);
  2711. if (-1 == DSA_InsertItem(pQueryForm->hdsaPages, 0, pQueryFormPage))
  2712. ExitGracefully(hres, E_FAIL, "Failed to copy page to form page DSA");
  2713. }
  2714. else
  2715. {
  2716. LPCQPAGE pPage = pQueryFormPage->pPage;
  2717. // Copying the page structure (it must be global), therefore clone
  2718. // the QUERYFORMPAGE strucutre and the CQPAGE into a new allocation
  2719. // and insert that into the page DSA.
  2720. Trace(TEXT("Cloning page %08x to form %s"), pQueryFormPage, pQueryForm->pTitle);
  2721. CopyMemory(&qfp, pQueryFormPage, SIZEOF(QUERYFORMPAGE));
  2722. qfp.pPage = (LPCQPAGE)LocalAlloc(LPTR, pPage->cbStruct);
  2723. if (!qfp.pPage)
  2724. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate copy of page structure");
  2725. Trace(TEXT("Copying structure qfp.pPage %08x, pPage %08x"), qfp.pPage, pPage);
  2726. //REVIEWED-2002-02-25-lucios.
  2727. CopyMemory(qfp.pPage, pPage, pPage->cbStruct); // copy the page structure
  2728. _CallPageProc(&qfp, CQPM_INITIALIZE, 0, 0);
  2729. if (-1 == DSA_AppendItem(pQueryForm->hdsaPages, &qfp))
  2730. {
  2731. _FreeQueryFormPage(&qfp);
  2732. ExitGracefully(hres, E_FAIL, "Failed to copy page to form DSA");
  2733. }
  2734. }
  2735. hres = S_OK; // success
  2736. exit_gracefully:
  2737. TraceLeaveResult(hres);
  2738. }
  2739. HRESULT CQueryFrame::GatherForms(VOID)
  2740. {
  2741. HRESULT hres;
  2742. IQueryForm* pQueryFormA = NULL;
  2743. HKEY hKeyForms = NULL;
  2744. TCHAR szBuffer[MAX_PATH];
  2745. INT i, iPage, iForm;
  2746. RECT rect;
  2747. TC_ITEM tci;
  2748. TraceEnter(TRACE_FORMS, "CQueryFrame::GatherForms");
  2749. // Construct DSA's so we can store the forms and pages as required.
  2750. _hdsaForms = DSA_Create(SIZEOF(QUERYFORM), 4);
  2751. _hdsaPages = DSA_Create(SIZEOF(QUERYFORMPAGE), 4);
  2752. if (!_hdsaForms || !_hdsaPages)
  2753. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to create DSA's for storing pages/forms");
  2754. // First check the IQueryHandler to see if it supports IQueryForm, if it does
  2755. // then call it to add its objects. Note that we don't bother with ANSI/UNICODE
  2756. // at this point as the handler is assumed to be built the same the
  2757. // the query framework.
  2758. if (SUCCEEDED(_pQueryHandler->QueryInterface(IID_IQueryForm, (LPVOID*)&pQueryFormA)))
  2759. {
  2760. hres = AddFromIQueryForm(pQueryFormA, NULL);
  2761. FailGracefully(hres, "Failed when calling AddFromIQueryForm on handlers IQueryForm iface)");
  2762. }
  2763. // now attempt to build the list of forms and pages from the registered form
  2764. // extensions. These are declared under the handlers CLSID in the registry,
  2765. // under the sub-key "Forms".
  2766. if (ERROR_SUCCESS != RegOpenKeyEx(_hkHandler, c_szForms, NULL, KEY_READ, &hKeyForms))
  2767. {
  2768. TraceMsg("No 'Forms' sub-key found, therefore skipping");
  2769. }
  2770. else
  2771. {
  2772. // Enumerate all the keys in the "Forms" key, these are assumed to be a list of
  2773. // the form handlers.
  2774. for (i = 0 ; TRUE ; i++)
  2775. {
  2776. DWORD cchStruct = ARRAYSIZE(szBuffer);
  2777. if (ERROR_SUCCESS != RegEnumKeyEx(hKeyForms, i, szBuffer, &cchStruct, NULL, NULL, NULL, NULL))
  2778. {
  2779. TraceMsg("RegEnumKeyEx return's false, therefore stopping eunmeration");
  2780. break;
  2781. }
  2782. GetForms(hKeyForms, szBuffer);
  2783. }
  2784. }
  2785. // Now tally the form/page information together and remove duplicates and attach the pages
  2786. // to forms, take special note of the global pages. As all forms will now be in the
  2787. // DSA we can check for a zero count and we don't have to worry about the order
  2788. // in which the the forms and pages were added.
  2789. if (!DSA_GetItemCount(_hdsaForms) || !DSA_GetItemCount(_hdsaPages))
  2790. ExitGracefully(hres, E_FAIL, "Either the forms or pages DSA is empty");
  2791. for (iPage = DSA_GetItemCount(_hdsaPages) ; --iPage >= 0 ;)
  2792. {
  2793. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(_hdsaPages, iPage);
  2794. TraceAssert(pQueryFormPage);
  2795. Trace(TEXT("iPage %d (of %d)"), iPage, DSA_GetItemCount(_hdsaPages));
  2796. if (!(pQueryFormPage->pPage->dwFlags & CQPF_ISGLOBAL))
  2797. {
  2798. LPQUERYFORM pQueryFormB = FindQueryForm(pQueryFormPage->clsidForm);
  2799. TraceAssert(pQueryFormB);
  2800. TraceGUID("Adding page to form:", pQueryFormPage->clsidForm);
  2801. if (pQueryFormB)
  2802. {
  2803. hres = _AddPageToForm(pQueryFormB, pQueryFormPage, FALSE);
  2804. FailGracefully(hres, "Failed when adding page to form");
  2805. if (!DSA_DeleteItem(_hdsaPages, iPage))
  2806. TraceMsg("**** Failed to remove page from global DSA ****");
  2807. }
  2808. }
  2809. }
  2810. for (iPage = DSA_GetItemCount(_hdsaPages) ; --iPage >= 0 ;)
  2811. {
  2812. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(_hdsaPages, iPage);
  2813. TraceAssert(pQueryFormPage);
  2814. if ((pQueryFormPage->pPage->dwFlags & CQPF_ISGLOBAL))
  2815. {
  2816. Trace(TEXT("Adding global page to %d forms"), DSA_GetItemCount(_hdsaForms));
  2817. for (iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
  2818. {
  2819. LPQUERYFORM pQueryFormC = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2820. TraceAssert(pQueryFormC);
  2821. if (!(pQueryFormC->dwFlags & CQFF_NOGLOBALPAGES))
  2822. {
  2823. hres = _AddPageToForm(pQueryFormC, pQueryFormPage, TRUE);
  2824. FailGracefully(hres, "Failed when adding global page to form");
  2825. }
  2826. }
  2827. _FreeQueryFormPage(pQueryFormPage);
  2828. if (!DSA_DeleteItem(_hdsaPages, iPage))
  2829. TraceMsg("**** Failed to remove page from global DSA ****");
  2830. }
  2831. }
  2832. // Walk the list of forms, rmeoving the ones which have no pages assocaited with
  2833. // them, we don't need these around confusing the world around us. Note that
  2834. // we walk backwards through the list removing.
  2835. //
  2836. // Also remove the optional forms we don't want to ehw orld to see
  2837. for (iForm = DSA_GetItemCount(_hdsaForms) ; --iForm >= 0 ;)
  2838. {
  2839. LPQUERYFORM pQueryFormD = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2840. TraceAssert(pQueryFormD);
  2841. Trace(TEXT("pQueryForm %08x (%s), pQueryFormD->hdsaPages %08x (%d)"),
  2842. pQueryFormD,
  2843. pQueryFormD->pTitle,
  2844. pQueryFormD->hdsaPages,
  2845. pQueryFormD->hdsaPages ? DSA_GetItemCount(pQueryFormD->hdsaPages):0);
  2846. if (!pQueryFormD->hdsaPages
  2847. || !DSA_GetItemCount(pQueryFormD->hdsaPages)
  2848. || ((pQueryFormD->dwFlags & CQFF_ISOPTIONAL) && !(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL)))
  2849. {
  2850. TraceGUID("Removing form: ", pQueryFormD->clsidForm);
  2851. _FreeQueryForm(pQueryFormD);
  2852. DSA_DeleteItem(_hdsaForms, iForm);
  2853. }
  2854. }
  2855. if (!DSA_GetItemCount(_hdsaForms))
  2856. ExitGracefully(hres, E_FAIL, "!!!!! No forms registered after page/form fix ups !!!!!");
  2857. // The pages have been attached to the forms so we can now attempt to create the
  2858. // form/page objects.
  2859. _szForm.cx = 0;
  2860. _szForm.cy = 0;
  2861. tci.mask = TCIF_TEXT;
  2862. tci.pszText = TEXT("");
  2863. tci.cchTextMax = 0;
  2864. TabCtrl_InsertItem(_hwndFrame, 0, &tci); // tabctrl needs at least one item so we can compute sizes
  2865. for (iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
  2866. {
  2867. LPQUERYFORM pQueryFormE = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  2868. TraceAssert(pQueryFormE);
  2869. // Create each of the modeless page dialoges that we show to allow the user
  2870. // to edit the search criteria. We also grab the size and modify the
  2871. // form informaiton we have so that the default size of the dialog can be
  2872. // correctly computed.
  2873. for (iPage = 0 ; iPage < DSA_GetItemCount(pQueryFormE->hdsaPages); iPage++)
  2874. {
  2875. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryFormE->hdsaPages, iPage);
  2876. TraceAssert(pQueryFormPage);
  2877. pQueryFormPage->hwndPage = CreateDialogParam(pQueryFormPage->pPage->hInstance,
  2878. MAKEINTRESOURCE(pQueryFormPage->pPage->idPageTemplate),
  2879. _hwnd,
  2880. pQueryFormPage->pPage->pDlgProc,
  2881. (LPARAM)pQueryFormPage->pPage);
  2882. if (!pQueryFormPage->hwndPage)
  2883. ExitGracefully(hres, E_FAIL, "Failed to create query form page");
  2884. EnableThemeDialogTexture(pQueryFormPage->hwndPage, ETDT_ENABLETAB);
  2885. GetRealWindowInfo(pQueryFormPage->hwndPage, &rect, NULL);
  2886. TabCtrl_AdjustRect(_hwndFrame, TRUE, &rect);
  2887. _szForm.cx = max(rect.right-rect.left, _szForm.cx);
  2888. _szForm.cy = max(rect.bottom-rect.top, _szForm.cy);
  2889. // flush the form parameters
  2890. _CallPageProc(pQueryFormPage, CQPM_CLEARFORM, 0, 0);
  2891. // Call the page with CQPM_SETDEFAULTPARAMETERS with the
  2892. // OPENQUERYWINDOW structure. wParam is TRUE/FALSE indiciating if
  2893. // the form is the default one, and therefore if the pFormParam is
  2894. // valid.
  2895. _CallPageProc(pQueryFormPage, CQPM_SETDEFAULTPARAMETERS,
  2896. (WPARAM)((_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM) &&
  2897. IsEqualCLSID(_pOpenQueryWnd->clsidDefaultForm, pQueryFormPage->clsidForm)),
  2898. (LPARAM)_pOpenQueryWnd);
  2899. }
  2900. // If the form has an hIcon then lets ensure that we add that to the form image
  2901. // list, any failure here is non-fatal, in that we will just skip that forms
  2902. // icon in the list (rather than barfing)
  2903. if (pQueryFormE->hIcon)
  2904. {
  2905. if (!_himlForms)
  2906. _himlForms = ImageList_Create(COMBOEX_IMAGE_CX, COMBOEX_IMAGE_CY, 0, 4, 1);
  2907. if (_himlForms)
  2908. {
  2909. pQueryFormE->iImage = ImageList_AddIcon(_himlForms, pQueryFormE->hIcon);
  2910. TraceAssert(pQueryFormE->iImage >= 0);
  2911. }
  2912. DestroyIcon(pQueryFormE->hIcon);
  2913. pQueryFormE->hIcon = NULL;
  2914. }
  2915. }
  2916. hres = S_OK; // success
  2917. exit_gracefully:
  2918. DoRelease(pQueryFormA);
  2919. if (hKeyForms)
  2920. RegCloseKey(hKeyForms);
  2921. TraceLeaveResult(hres);
  2922. }
  2923. /*-----------------------------------------------------------------------------
  2924. / CQueryFrame::GetForms
  2925. / ---------------------
  2926. / Given a HKEY to the forms list and the value name for the form we want
  2927. / to add, query for the form information add add the form objects
  2928. / to the master list.
  2929. /
  2930. / In:
  2931. / hKeyForms = HKEY for the {CLSID provider}\Forms key
  2932. / pName -> key value to query for
  2933. /
  2934. / Out:
  2935. / VOID
  2936. /----------------------------------------------------------------------------*/
  2937. HRESULT CQueryFrame::GetForms(HKEY hKeyForms, LPTSTR pName)
  2938. {
  2939. HRESULT hres;
  2940. HKEY hKeyForm = NULL;
  2941. TCHAR szQueryFormCLSID[GUIDSTR_MAX+1];
  2942. DWORD dwFlags;
  2943. DWORD dwSize;
  2944. IUnknown* pUnknown = NULL;
  2945. IQueryForm* pQueryForm = NULL;
  2946. CLSID clsidForm;
  2947. BOOL fIncludeForms = FALSE;
  2948. TraceEnter(TRACE_FORMS, "CQueryFrame::_GetForms");
  2949. Trace(TEXT("pName %s"), pName);
  2950. if (ERROR_SUCCESS != RegOpenKeyEx(hKeyForms, pName, NULL, KEY_READ, &hKeyForm))
  2951. ExitGracefully(hres, E_UNEXPECTED, "Failed to open the form key");
  2952. // Read the flags and try to determine if we should invoke this form object.
  2953. dwSize = SIZEOF(dwFlags);
  2954. if (ERROR_SUCCESS != RegQueryValueEx(hKeyForm, c_szFlags, NULL, NULL, (LPBYTE)&dwFlags, &dwSize))
  2955. {
  2956. TraceMsg("No flags, defaulting to something sensible");
  2957. dwFlags = QUERYFORM_CHANGESFORMLIST;
  2958. }
  2959. Trace(TEXT("Forms flag is %08x"), dwFlags);
  2960. // should be invoke this form object?
  2961. //
  2962. // - if dwFlags has QUERYFORM_CHANGESFORMSLIST, or
  2963. // - if dwFlags has QUERYFORM_CHANGESOPTFORMLIST and we are showing optional forms, or
  2964. // - neither set and the form object supports the requested form
  2965. if (!(dwFlags & QUERYFORM_CHANGESFORMLIST))
  2966. {
  2967. if ((dwFlags & QUERYFORM_CHANGESOPTFORMLIST) &&
  2968. (_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL))
  2969. {
  2970. TraceMsg("Form is optional, are we are showing optional forms");
  2971. fIncludeForms = TRUE;
  2972. }
  2973. else
  2974. {
  2975. // OK, so it either didn't update the form list, or wasn't marked as optional,
  2976. // so lets check to see if it supports the form the user has requested, if not
  2977. // then don't bother loading this guy.
  2978. if (_pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM)
  2979. {
  2980. TCHAR szBuffer[GUIDSTR_MAX+32];
  2981. HKEY hkFormsSupported;
  2982. TraceMsg("Checking for supported form");
  2983. if (ERROR_SUCCESS == RegOpenKeyEx(hKeyForm, TEXT("Forms Supported"), NULL, KEY_READ, &hkFormsSupported))
  2984. {
  2985. TraceMsg("Form has a 'Supported Forms' sub-key");
  2986. GetStringFromGUID(_pOpenQueryWnd->clsidDefaultForm, szQueryFormCLSID, ARRAYSIZE(szQueryFormCLSID));
  2987. Trace(TEXT("Checking for: %s"), szQueryFormCLSID);
  2988. if (ERROR_SUCCESS == RegQueryValueEx(hkFormsSupported, szQueryFormCLSID, NULL, NULL, NULL, NULL))
  2989. {
  2990. TraceMsg("Query form is in supported list");
  2991. fIncludeForms = TRUE;
  2992. }
  2993. RegCloseKey(hkFormsSupported);
  2994. }
  2995. else
  2996. {
  2997. TraceMsg("No forms supported sub-key, so loading form object anyway");
  2998. fIncludeForms = TRUE;
  2999. }
  3000. }
  3001. }
  3002. }
  3003. else
  3004. {
  3005. TraceMsg("Form updates form list");
  3006. fIncludeForms = TRUE;
  3007. }
  3008. // if fIncludeForms is TRUE, then the checks above succeeded and we are including forms
  3009. // from this object (identified by pName), so we must now get the CLSID of the object
  3010. // we are invoking and use its IQueryForm interface to add the forms that we want.
  3011. if (fIncludeForms)
  3012. {
  3013. // get the form object CLSID, having parse it, then CoCreate it adding the forms.
  3014. dwSize = SIZEOF(szQueryFormCLSID);
  3015. if (ERROR_SUCCESS != RegQueryValueEx(hKeyForm, c_szCLSID, NULL, NULL, (LPBYTE)szQueryFormCLSID, &dwSize))
  3016. ExitGracefully(hres, E_UNEXPECTED, "Failed to read the CLSID of the form");
  3017. Trace(TEXT("szQueryFormCLSID: %s"), szQueryFormCLSID);
  3018. if (!GetGUIDFromString(szQueryFormCLSID, &clsidForm))
  3019. ExitGracefully(hres, E_UNEXPECTED, "Fialed to parse the string as a GUID");
  3020. // we now have the CLISD of the form object, so we must attempt to CoCreate it, we try for
  3021. // the current build type (eg UNICODE) and then fall back to ANSI if thats not supported,
  3022. // so we can support ANSI query form objects on a UNICODE platform.
  3023. hres = CoCreateInstance(clsidForm, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknown);
  3024. FailGracefully(hres, "Failed to CoCreate the form object");
  3025. if (SUCCEEDED(pUnknown->QueryInterface(IID_IQueryForm, (LPVOID*)&pQueryForm)))
  3026. {
  3027. hres = AddFromIQueryForm(pQueryForm, hKeyForm);
  3028. FailGracefully(hres, "Failed when adding forms from specified IQueryForm iface");
  3029. }
  3030. else
  3031. {
  3032. ExitGracefully(hres, E_UNEXPECTED, "Form object doesn't support IQueryForm(A/W)");
  3033. }
  3034. }
  3035. hres = S_OK;
  3036. exit_gracefully:
  3037. if (hKeyForm)
  3038. RegCloseKey(hKeyForm);
  3039. DoRelease(pUnknown);
  3040. DoRelease(pQueryForm);
  3041. TraceLeaveResult(hres);
  3042. }
  3043. /*-----------------------------------------------------------------------------
  3044. / CQueryFrame::PopulateFormControl
  3045. / ---------------------------------
  3046. / Enumerate all the query forms for the given query handler and build
  3047. / the DPA containing the list of them. Once we have done this we
  3048. / can then populate the control at some more convientent moment.
  3049. /
  3050. / When gathering we first hit the "handler", then the "Forms" sub-key
  3051. / trying to load all the InProc servers that provide forms. We build
  3052. / list of hidden, never shown etc.
  3053. /
  3054. / In:
  3055. / fIncludeHidden = list forms marked as hidden in control
  3056. /
  3057. / Out:
  3058. / VOID
  3059. /----------------------------------------------------------------------------*/
  3060. HRESULT CQueryFrame::PopulateFormControl(BOOL fIncludeHidden)
  3061. {
  3062. HRESULT hres;
  3063. COMBOBOXEXITEM cbi;
  3064. INT i, iForm;
  3065. TraceEnter(TRACE_FORMS, "CQueryFrame::PopulateFormControl");
  3066. Trace(TEXT("fIncludeHidden: %d"), fIncludeHidden);
  3067. // list which forms within the control
  3068. if (!_hdsaForms)
  3069. ExitGracefully(hres, E_FAIL, "No forms to list");
  3070. ComboBox_ResetContent(_hwndLookFor); // remove all items from that control
  3071. for (i = 0, iForm = 0 ; iForm < DSA_GetItemCount(_hdsaForms); iForm++)
  3072. {
  3073. LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  3074. TraceAssert(pQueryForm);
  3075. // filter out those forms that are not of interest to this instance of the
  3076. // dialog.
  3077. if (((pQueryForm->dwFlags & CQFF_ISOPTIONAL) && !fIncludeHidden) ||
  3078. (pQueryForm->dwFlags & CQFF_ISNEVERLISTED))
  3079. {
  3080. Trace(TEXT("Hiding form: %s"), pQueryForm->pTitle);
  3081. continue;
  3082. }
  3083. // now add the form to the control, including the image if there is an image
  3084. // specified.
  3085. cbi.mask = CBEIF_TEXT|CBEIF_LPARAM;
  3086. cbi.iItem = i++;
  3087. cbi.pszText = pQueryForm->pTitle;
  3088. cbi.cchTextMax = lstrlen(pQueryForm->pTitle);
  3089. cbi.lParam = iForm;
  3090. if (pQueryForm->iImage >= 0)
  3091. {
  3092. Trace(TEXT("Form has an image %d"), pQueryForm->iImage);
  3093. cbi.mask |= CBEIF_IMAGE|CBEIF_SELECTEDIMAGE;
  3094. cbi.iImage = pQueryForm->iImage;
  3095. cbi.iSelectedImage = pQueryForm->iImage;
  3096. }
  3097. pQueryForm->iForm = (int)SendMessage(_hwndLookFor, CBEM_INSERTITEM, 0, (LPARAM)&cbi);
  3098. if (pQueryForm->iForm < 0)
  3099. {
  3100. Trace(TEXT("Form name: %s"), pQueryForm->pTitle);
  3101. ExitGracefully(hres, E_FAIL, "Failed to add the entry to the combo box");
  3102. }
  3103. }
  3104. hres = S_OK;
  3105. exit_gracefully:
  3106. TraceLeaveValue(hres);
  3107. }
  3108. /*-----------------------------------------------------------------------------
  3109. / CQueryFrame::SelectForm
  3110. / -----------------------
  3111. / Changes the current form to the one specified as an into the DPA.
  3112. /
  3113. / In:
  3114. / iForm = form to be selected
  3115. /
  3116. / Out:
  3117. / -
  3118. /----------------------------------------------------------------------------*/
  3119. HRESULT CQueryFrame::SelectForm(REFCLSID clsidForm)
  3120. {
  3121. HRESULT hres;
  3122. LPQUERYFORM pQueryForm, pOldQueryForm;
  3123. LPQUERYFORMPAGE pQueryFormPage;
  3124. LPCQPAGE pPage;
  3125. INT nCmdShow = SW_SHOW;
  3126. TCHAR szBuffer[64], szTitle[MAX_PATH];;
  3127. TC_ITEM tci;
  3128. INT i;
  3129. TraceEnter(TRACE_FORMS, "CQueryFrame::SelectForm");
  3130. pQueryForm = FindQueryForm(clsidForm);
  3131. TraceAssert(pQueryForm);
  3132. if (!pQueryForm)
  3133. ExitGracefully(hres, S_FALSE, "Failed to find the requested form");
  3134. // Change the currently displayed form and change the displayed
  3135. // tabs to correctly indicate this
  3136. if ((pQueryForm != _pCurrentForm))
  3137. {
  3138. if (!OnNewQuery(FALSE)) // prompt the user
  3139. ExitGracefully(hres, S_FALSE, "Failed to select the new form");
  3140. TabCtrl_DeleteAllItems(_hwndFrame);
  3141. for (i = 0 ; i < DSA_GetItemCount(pQueryForm->hdsaPages) ; i++)
  3142. {
  3143. pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, i);
  3144. pPage = pQueryFormPage->pPage;
  3145. tci.mask = TCIF_TEXT;
  3146. tci.pszText = pQueryForm->pTitle;
  3147. tci.cchTextMax = MAX_PATH;
  3148. if (pPage->idPageName &&
  3149. LoadString(pPage->hInstance, pPage->idPageName, szBuffer, ARRAYSIZE(szBuffer)))
  3150. {
  3151. Trace(TEXT("Loaded page title string %s"), szBuffer);
  3152. tci.pszText = szBuffer;
  3153. }
  3154. TabCtrl_InsertItem(_hwndFrame, i, &tci);
  3155. }
  3156. ComboBox_SetCurSel(_hwndLookFor, pQueryForm->iForm);
  3157. _pCurrentForm = pQueryForm;
  3158. SelectFormPage(pQueryForm, pQueryForm->iPage);
  3159. // Change the dialog title to reflect the new form
  3160. if (LoadString(GLOBAL_HINSTANCE, IDS_FRAMETITLE, szBuffer, ARRAYSIZE(szBuffer)))
  3161. {
  3162. // NTRAID#NTBUG9-554458-2002/02/20-lucios. Pending fix.
  3163. wsprintf(szTitle, szBuffer, pQueryForm->pTitle);
  3164. SetWindowText(_hwnd, szTitle);
  3165. }
  3166. // Tell the handler that we have changed the form, they can then use this
  3167. // new form name to modify their UI.
  3168. _pQueryHandler->ActivateView(CQRVA_FORMCHANGED, (WPARAM)lstrlen(pQueryForm->pTitle), (LPARAM)pQueryForm->pTitle);
  3169. }
  3170. hres = S_OK;
  3171. exit_gracefully:
  3172. TraceLeaveResult(hres);
  3173. }
  3174. /*-----------------------------------------------------------------------------
  3175. / CQueryFrame::SelectFormPage
  3176. / ---------------------------
  3177. / Change the currently active page of a query form to the one specified
  3178. / by the index.
  3179. /
  3180. / In:
  3181. / pQueryForm = query form to be changed
  3182. / iForm = form to be selected
  3183. /
  3184. / Out:
  3185. / -
  3186. /----------------------------------------------------------------------------*/
  3187. VOID CQueryFrame::SelectFormPage(LPQUERYFORM pQueryForm, INT iPage)
  3188. {
  3189. LPQUERYFORMPAGE pQueryFormPage;
  3190. RECT rect;
  3191. TraceEnter(TRACE_FORMS, "CQueryFrame::SelectFormPage");
  3192. pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
  3193. // Have we changed the query form page? If so then display the now dialog
  3194. // hiding the previous one. We call the TabCtrl to find out where we should
  3195. // be placing this new control.
  3196. if (pQueryFormPage != _pCurrentFormPage)
  3197. {
  3198. // Reflect the change into the tab control
  3199. TabCtrl_SetCurSel(_hwndFrame, iPage);
  3200. pQueryForm->iPage = iPage;
  3201. // Fix the size and visability of the new form
  3202. if (_pCurrentFormPage)
  3203. ShowWindow(_pCurrentFormPage->hwndPage, SW_HIDE);
  3204. GetRealWindowInfo(_hwndFrame, &rect, NULL);
  3205. TabCtrl_AdjustRect(_hwndFrame, FALSE, &rect);
  3206. SetWindowPos(pQueryFormPage->hwndPage,
  3207. HWND_TOP,
  3208. rect.left, rect.top,
  3209. rect.right - rect.left,
  3210. rect.bottom - rect.top,
  3211. SWP_SHOWWINDOW);
  3212. _pCurrentFormPage = pQueryFormPage;
  3213. }
  3214. TraceLeave();
  3215. }
  3216. /*-----------------------------------------------------------------------------
  3217. / CQueryFrame::CallFormPages
  3218. / --------------------------
  3219. / Given a query form traverse the array of pages calling each of them
  3220. / with the given message information. If any of the pages return
  3221. / an error code (other than E_NOTIMPL) we bail.
  3222. /
  3223. / In:
  3224. / pQueryForm = query form to call
  3225. / uMsg, wParam, lParam = parameters for the page
  3226. /
  3227. / Out:
  3228. / HRESULT
  3229. /----------------------------------------------------------------------------*/
  3230. HRESULT CQueryFrame::CallFormPages(LPQUERYFORM pQueryForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3231. {
  3232. HRESULT hres = S_OK;
  3233. INT iPage;
  3234. TraceEnter(TRACE_FORMS, "CQueryFrame::CallFormPages");
  3235. if (!pQueryForm || !pQueryForm->hdsaPages)
  3236. ExitGracefully(hres, E_FAIL, "No pQueryForm || pQueryForm->hdsaPages == NULL");
  3237. Trace(TEXT("pQueryForm %08x"), pQueryForm);
  3238. Trace(TEXT("uMsg %08x, wParam %08x, lParam %08x"), uMsg, wParam, lParam);
  3239. Trace(TEXT("%d pages to call"), DSA_GetItemCount(pQueryForm->hdsaPages));
  3240. // Call each page in turn if it matches the filter we have been given for calling
  3241. // down. If a page returns S_FALSE or a FAILURE then we exit the loop. If the
  3242. // failure however is E_NOTIMPL then we ignore.
  3243. for (iPage = 0 ; iPage < DSA_GetItemCount(pQueryForm->hdsaPages); iPage++)
  3244. {
  3245. LPQUERYFORMPAGE pQueryFormPage = (LPQUERYFORMPAGE)DSA_GetItemPtr(pQueryForm->hdsaPages, iPage);
  3246. TraceAssert(pQueryFormPage);
  3247. hres = _CallPageProc(pQueryFormPage, uMsg, wParam, lParam);
  3248. if (FAILED(hres) && (hres != E_NOTIMPL))
  3249. {
  3250. TraceMsg("PageProc returned a FAILURE");
  3251. break;
  3252. }
  3253. else if (hres == S_FALSE)
  3254. {
  3255. TraceMsg("PageProc returned S_FALSE, exiting loop");
  3256. break;
  3257. }
  3258. }
  3259. exit_gracefully:
  3260. TraceLeaveResult(hres);
  3261. }
  3262. /*-----------------------------------------------------------------------------
  3263. / CQueryFrame::FindQueryForm
  3264. / --------------------------
  3265. / Given the CLSID for the form return a pointer to its LPQUERYFORM structure,
  3266. / or NULL if not found.
  3267. /
  3268. / In:
  3269. / clsidForm = ID of the form
  3270. /
  3271. / Out:
  3272. / LPQUERYFORM
  3273. /----------------------------------------------------------------------------*/
  3274. LPQUERYFORM CQueryFrame::FindQueryForm(REFCLSID clsidForm)
  3275. {
  3276. LPQUERYFORM pQueryForm = NULL;
  3277. INT i;
  3278. TraceEnter(TRACE_FORMS, "CQueryFrame::FindQueryForm");
  3279. TraceGUID("Form ID", clsidForm);
  3280. for (i = 0 ; _hdsaForms && (i < DSA_GetItemCount(_hdsaForms)) ; i++)
  3281. {
  3282. pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, i);
  3283. TraceAssert(pQueryForm);
  3284. if (IsEqualCLSID(clsidForm, pQueryForm->clsidForm))
  3285. {
  3286. Trace(TEXT("Form is index %d (%08x)"), i, pQueryForm);
  3287. break;
  3288. }
  3289. }
  3290. if (!_hdsaForms || (i >= DSA_GetItemCount(_hdsaForms)))
  3291. pQueryForm = NULL;
  3292. TraceLeaveValue(pQueryForm);
  3293. }