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

Windows Kernel

Development Platform:

Visual C++

  1. #include "pch.h"
  2. #pragma hdrstop
  3. /*-----------------------------------------------------------------------------
  4. / Private data and helper functions
  5. /----------------------------------------------------------------------------*/
  6. //
  7. // ICommonQuery stuff 
  8. //
  9. #ifdef UNICODE
  10. class CCommonQuery : public ICommonQuery, IObjectWithSite, ICommonQueryA, CUnknown
  11. #else
  12. class CCommonQuery : public ICommonQuery, IObjectWithSite, CUnknown
  13. #endif
  14. {
  15.     private:
  16.         IUnknown* _punkSite;
  17.     public:
  18.         CCommonQuery();
  19.         ~CCommonQuery();
  20.         // IUnknown
  21.         STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  22.         STDMETHOD_(ULONG, AddRef)();
  23.         STDMETHOD_(ULONG, Release)();
  24.         // ICommonQuery
  25.         STDMETHOD(OpenQueryWindow)(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject);
  26. #ifdef UNICODE        
  27.         // ICommonQueryA
  28.         STDMETHOD(OpenQueryWindow)(THIS_ HWND hwndParent, LPOPENQUERYWINDOW_A pOpenQueryWnd, IDataObject** ppDataObject);
  29. #endif
  30.         // IObjectWithSite
  31.         STDMETHODIMP SetSite(IUnknown* punk);
  32.         STDMETHODIMP GetSite(REFIID riid, void **ppv);
  33. };
  34. //
  35. // View layout constants used by our dialogs
  36. //
  37. #define VIEWER_DEFAULT_CY   200
  38. #define COMBOEX_IMAGE_CX    16
  39. #define COMBOEX_IMAGE_CY    16
  40. //
  41. // Internal reference to a form and page
  42. //
  43. typedef struct
  44. {
  45.     HDSA   hdsaPages;                   // DSA containing page entries
  46.     DWORD  dwFlags;                     // flags
  47.     CLSID  clsidForm;                   // CLSID identifier for this form
  48.     LPTSTR pTitle;                      // title used for drop down / title bar
  49.     HICON  hIcon;                       // hIcon passed by caller
  50.     INT    iImage;                      // image list index of icon
  51.     INT    iForm;                       // visible index of form in control
  52.     INT    iPage;                       // currently selected page on form
  53. } QUERYFORM, * LPQUERYFORM;
  54. typedef struct
  55. {
  56.     CLSID    clsidForm;                 // CLSID to associate this form with
  57.     BOOL     fPageIsANSI : 1;           // page was declared ANSI
  58.     union
  59.     {
  60.         LPCQPAGE pPage;                 // CQPAGE structures
  61. #ifdef UNICODE
  62.         LPCQPAGE_A pPageA;              
  63. #endif
  64.     };
  65.     union
  66.     {
  67.         LPCQPAGEPROC pPageProc;         // PageProc's used by thunking layer
  68. #ifdef UNICODE
  69.         LPCQPAGEPROC_A pPageProcA;
  70. #endif
  71.     };
  72.     LPARAM   lParam;                    // PAGEPROC lParam
  73.     HWND     hwndPage;                  // hWnd of page dialog // = NULL if none
  74. } QUERYFORMPAGE, * LPQUERYFORMPAGE;
  75. //
  76. // Internal reference of a scope
  77. //
  78. typedef struct
  79. {
  80.     LPCQSCOPE pScope;
  81.     INT iImage;
  82. } QUERYSCOPE, * LPQUERYSCOPE;
  83. //
  84. // CQueryFrame, our implementation of IQueryFrame
  85. //
  86. #define CALLFORMPAGES_ANSI    0x0001    // call only ANSI query form pages
  87. #define CALLFORMPAGES_UNICODE 0x0002    // call only UNICODE query form pages
  88. #define CALLFORMPAGES_ALL     0x0003
  89. class CQueryFrame : public IQueryFrame, CUnknown
  90. {
  91.     friend INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
  92.     friend INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  93.     public:
  94.         CQueryFrame(IUnknown* punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject);
  95.         ~CQueryFrame();
  96.         // IUnknown
  97.         STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  98.         STDMETHOD_(ULONG, AddRef)();
  99.         STDMETHOD_(ULONG, Release)();
  100.         // Internal helper functions
  101.         STDMETHOD(DoModal)(HWND hwndParent);
  102.         // IQueryFrame
  103.         STDMETHOD(AddScope)(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect);
  104.         STDMETHOD(GetWindow)(THIS_ HWND* phWnd);
  105.         STDMETHOD(InsertMenus)(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth);
  106.         STDMETHOD(RemoveMenus)(THIS_ HMENU hmenuShared);
  107.         STDMETHOD(SetMenu)(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu);
  108.         STDMETHOD(SetStatusText)(THIS_ LPCTSTR pszStatusText);
  109.         STDMETHOD(StartQuery)(THIS_ BOOL fStarting);
  110.         STDMETHOD(LoadQuery)(THIS_ IPersistQuery* pPersistQuery);
  111.         STDMETHOD(SaveQuery)(THIS_ IPersistQuery* pPersistQuery);
  112.         STDMETHOD(CallForm)(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam);
  113.         STDMETHOD(GetScope)(THIS_ LPCQSCOPE* ppScope);
  114.         STDMETHOD(GetHandler)(THIS_ REFIID riid, void **ppv);
  115.     protected:
  116.         // Helper functions
  117.         VOID CloseQueryFrame(HRESULT hres);
  118. #if HIDE_SEARCH_PANE
  119.         VOID HideSearchPane(BOOL fHide);        
  120. #endif
  121.         INT FrameMessageBox(LPCTSTR pPrompt, UINT uType);
  122.         // Message handlers
  123.         HRESULT OnInitDialog(HWND hwnd);
  124.         VOID DoEnableControls(VOID);
  125.         LRESULT OnNotify(INT idCtrl, LPNMHDR pNotify);
  126.         VOID OnSize(INT cx, INT cy);
  127.         VOID OnGetMinMaxInfo(LPMINMAXINFO lpmmi);    
  128.         VOID OnCommand(WPARAM wParam, LPARAM lParam);
  129.         VOID OnInitMenu(HMENU hMenu);
  130.         VOID OnEnterMenuLoop(BOOL fEntering);
  131.         VOID OnMenuSelect(HMENU hMenu, UINT uID);
  132.         HRESULT OnFindNow(VOID);
  133.         BOOL OnNewQuery(BOOL fAlwaysPrompt);
  134.         HRESULT OnBrowse(VOID);    
  135.         HRESULT OnHelp(LPHELPINFO pHelpInfo);
  136.         
  137.         // Form/Scope helper fucntions
  138.         HRESULT InsertScopeIntoList(LPCQSCOPE pScope, INT i, BOOL fAddToControl);
  139.         HRESULT AddScopeToControl(LPQUERYSCOPE pQueryScope, INT i);
  140.         HRESULT PopulateScopeControl(VOID);
  141.         HRESULT GetSelectedScope(LPQUERYSCOPE* ppQueryScope);
  142.         HRESULT AddFromIQueryForm(IQueryForm* pQueryForm, HKEY hkeyForm);
  143. #ifdef UNICODE
  144.         HRESULT AddFromIQueryFormA(IQueryFormA* pQueryForm, HKEY hkeyForm);
  145. #endif
  146.         HRESULT GatherForms(VOID);
  147.         HRESULT GetForms(HKEY hKeyForms, LPTSTR pName);
  148.         HRESULT PopulateFormControl(BOOL fIncludeHidden);
  149.         HRESULT SelectForm(REFCLSID clsidForm);
  150.         VOID SelectFormPage(LPQUERYFORM pQueryForm, INT iPage);
  151.         HRESULT CallFormPages(LPQUERYFORM pQueryForm, DWORD dwFlags, UINT uMsg, WPARAM wParam, LPARAM lParam);
  152.         LPQUERYFORM FindQueryForm(REFCLSID clsidForm);
  153.     private:
  154.         IUnknown* _punkSite;                    // site object we need to pass through
  155.         IQueryHandler* _pQueryHandler;         // IQueryHandler object we need to interact with
  156.         LPOPENQUERYWINDOW _pOpenQueryWnd;      // copy of initial parameters provided by caller
  157.         IDataObject** _ppDataObject;           // receives the resulting data object from handler
  158.         DWORD      _dwHandlerViewFlags;        // flags from the handler
  159.         BOOL       _fQueryRunning:1;           // = 1 => query has been started, via IQueryFrame::StartQuery(TRUE)
  160.         BOOL       _fExitModalLoop:1;          // = 1 => must leave modal loop
  161.         BOOL       _fScopesPopulated:1;        // = 1 => scope control has been populated
  162.         BOOL       _fTrackingMenuBar:1;        // = 1 => then we are tracking the menu bar, therefore send activates etc
  163. #if HIDE_SEARCH_PANE
  164.         BOOL       _fHideSearchPane:1;         // = 1 => form area is currently hidden
  165. #endif
  166.         BOOL       _fAddScopesNYI:1;           // = 1 => did AddScopes return E_NOTIMPL
  167.         BOOL       _fScopesAddedAsync:1;       // = 1 => scopes added async by the handler
  168.         BOOL       _fScopeImageListSet:1;      // = 1 => scope image list has been set
  169.         HRESULT    _hResult;                   // result value stored by CloseQueryFrame
  170.         HKEY       _hkHandler;                 // registry key for the handler
  171.         HWND       _hwnd;                      // main window handle
  172.         HWND       _hwndResults;               // result viewer
  173.         HWND       _hwndStatus;                // status bar
  174.         HWND       _hwndFrame;                 // Query Pages tab control
  175.         HWND       _hwndLookForLabel;          // "Find:"
  176.         HWND       _hwndLookFor;               // Form combo
  177.         HWND       _hwndLookInLabel;           // "In:"
  178.         HWND       _hwndLookIn;                // Scope combo
  179.         HWND       _hwndBrowse;                // "Browse"
  180.         HWND       _hwndFindNow;               // "Find now"
  181.         HWND       _hwndStop;                  // "Stop"
  182.         HWND       _hwndNewQuery;              // "New Query"
  183.         HWND       _hwndOK;                    // "OK"
  184.         HWND       _hwndCancel;                // "Cancel"
  185.         HWND       _hwndFindAnimation;         // Query issued animation
  186.         HICON      _hiconSmall;                // large/small app icons
  187.         HICON      _hiconLarge;
  188.         HMENU      _hmenuFile;                 // handle of the frames menu bar
  189.         HIMAGELIST _himlForms;                 // image list for query form objects
  190.         SIZE       _szMinTrack;                // minimum track size of the window
  191.         INT        _dxFormAreaLeft;            // offset to left edge of form area (from window left)
  192.         INT        _dxFormAreaRight;           // offset to right edge of form area (from window right)
  193.         INT        _dxButtonsLeft;             // offset to left edge of buttons (from window right)
  194.         INT        _dxAnimationLeft;           // offset to left edge of aniimation (from window right)
  195.         INT        _dyResultsTop;              // offset to top of results (from top of window)
  196.         INT        _dyOKTop;                   // offset to top of "OK" buttom (from results top)
  197.         INT        _dxGap;                     // gap between OK + Cancel / LookIn + Browse
  198.         INT        _dyGap;                     // gap between bottom of OK,Cancel and the frame.
  199.         INT        _cyStatus;                  // height of the status bar
  200.         HDSA       _hdsaForms;                 // forms DSA
  201.         HDSA       _hdsaPages;                 // pages DSA
  202.         SIZE       _szForm;                    // size of the (current form we are displaying)
  203.         HDSA       _hdsaScopes;                // scopes DSA
  204.         INT        _iDefaultScope;             // index of the defualt scope to select (into DSA)
  205.         LPQUERYFORM _pCurrentForm;              // == NULL if none / else -> form structure
  206.         LPQUERYFORMPAGE _pCurrentFormPage;      // == NULL if none / else -> page structure
  207. };
  208. //
  209. // Helper functions
  210. //
  211. INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  212. INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg);
  213. HRESULT _CallScopeProc(LPQUERYSCOPE pQueryScope, UINT uMsg, LPVOID pVoid);
  214. INT _FreeScope(LPQUERYSCOPE pQueryScope);
  215. INT _FreeScopeCB(LPVOID pItem, LPVOID pData);
  216. HRESULT _CallPageProc(LPQUERYFORMPAGE pQueryFormPage, UINT uMsg, WPARAM wParam, LPARAM lParam);
  217. INT _FreeQueryFormCB(LPVOID pItem, LPVOID pData);
  218. INT _FreeQueryForm(LPQUERYFORM pQueryForm);
  219. INT _FreeQueryFormPageCB(LPVOID pItem, LPVOID pData);
  220. INT _FreeQueryFormPage(LPQUERYFORMPAGE pQueryFormPage);
  221. #ifdef UNICODE
  222. HRESULT _AddFormsProcA(LPARAM lParam, LPCQFORM_A pForm);
  223. HRESULT _AddPagesProcA(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE_A pPage);
  224. #endif
  225. HRESULT _AddFormsProc(LPARAM lParam, LPCQFORM_W pForm);
  226. HRESULT _AddPagesProc(LPARAM lParam, REFCLSID clsidForm, LPCQPAGE_W pPage);
  227. //
  228. // Help stuff
  229. //
  230. #define HELP_FILE (NULL)
  231. static DWORD const aHelpIDs[] =
  232. {
  233.     0, 0
  234. };
  235. //
  236. // constant strings
  237. //
  238. TCHAR const c_szCLSID[]             = TEXT("CLSID");
  239. TCHAR const c_szForms[]             = TEXT("Forms");
  240. TCHAR const c_szFlags[]             = TEXT("Flags");
  241. TCHAR const c_szCommonQuery[]       = TEXT("CommonQuery");
  242. TCHAR const c_szHandlerIs[]         = TEXT("Handler");
  243. TCHAR const c_szFormIs[]            = TEXT("Form");
  244. TCHAR const c_szSearchPaneHidden[]  = TEXT("SearchPaneHidden");
  245. /*-----------------------------------------------------------------------------
  246. / CCommonQuery
  247. /----------------------------------------------------------------------------*/
  248. CCommonQuery::CCommonQuery() :
  249.     _punkSite(NULL)
  250. {
  251. }
  252. CCommonQuery::~CCommonQuery()
  253. {
  254.     DoRelease(_punkSite);
  255. }
  256. // IUnknown bits
  257. #undef  CLASS_NAME
  258. #define CLASS_NAME CCommonQuery
  259. #include "unknown.inc"
  260. STDMETHODIMP CCommonQuery::QueryInterface(REFIID riid, LPVOID* ppvObject)
  261. {
  262.     INTERFACES iface[] =
  263.     {
  264.         &IID_ICommonQuery, (ICommonQuery*)this,
  265. #ifdef UNICODE
  266.         &IID_ICommonQueryA, (ICommonQueryA*)this,
  267. #endif
  268.     };
  269.     return HandleQueryInterface(riid, ppvObject, iface, ARRAYSIZE(iface));
  270. }
  271. //
  272. // handle creating a new instance of CLSID_CommonQuery
  273. //
  274. STDAPI CCommonQuery_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi)
  275. {
  276.     CCommonQuery *pcq = new CCommonQuery;
  277.     if ( !pcq )
  278.         return E_OUTOFMEMORY;
  279.     HRESULT hres = pcq->QueryInterface(IID_IUnknown, (void **)ppunk);
  280.     pcq->Release();
  281.     return hres;
  282. }
  283. /*-----------------------------------------------------------------------------
  284. / ICommonQuery methods
  285. /----------------------------------------------------------------------------*/
  286. /*-----------------------------------------------------------------------------
  287. / OpenQueryWindow
  288. / ---------------
  289. /   Display the query window for the given provider, including collecting
  290. /   all the forms etc.
  291. /
  292. / In:
  293. /   hwndParent -> parent window for this dialog
  294. /   pOpenQueryWnd -> structure that defines how the window should be opened
  295. /   ppDataObject -> receives a pointer to the data object
  296. /
  297. / Out:
  298. /   HRESULT
  299. /----------------------------------------------------------------------------*/
  300. STDMETHODIMP CCommonQuery::OpenQueryWindow(THIS_ HWND hwndParent, LPOPENQUERYWINDOW pOpenQueryWnd, IDataObject** ppDataObject)
  301. {
  302.     HRESULT hres;
  303.     CQueryFrame* pQueryFrame = NULL;
  304.     TraceEnter(TRACE_QUERY, "CCommonQuery::OpenQueryWindow");
  305.     if ( !pOpenQueryWnd || (hwndParent && !IsWindow(hwndParent)) )
  306.         ExitGracefully(hres, E_INVALIDARG, "Bad parameters");
  307.    
  308.     if ( ppDataObject )
  309.         *(ppDataObject) = NULL;
  310.     pQueryFrame = new CQueryFrame(_punkSite, pOpenQueryWnd, ppDataObject);
  311.     TraceAssert(pQueryFrame);
  312.     if ( !pQueryFrame )
  313.         ExitGracefully(hres, E_OUTOFMEMORY, "Failed to construct the query window object");
  314.     hres = pQueryFrame->DoModal(hwndParent);                // don't bother fail gracefully etc
  315.     FailGracefully(hres, "Failed on calling DoModal");
  316. exit_gracefully:
  317.     DoRelease(pQueryFrame);
  318.     TraceLeaveResult(hres);
  319. }
  320. /*-----------------------------------------------------------------------------
  321. / OpenQueryWindow - thunking from ANSI
  322. / ---------------
  323. /   Display the query window for the given provider, including collecting
  324. /   all the forms etc.
  325. /
  326. / In:
  327. /   hwndParent -> parent window for this dialog
  328. /   pOpenQueryWnd -> structure that defines how the window should be opened
  329. /   ppDataObject -> receives a pointer to the data object
  330. /
  331. / Out:
  332. /   HRESULT
  333. /----------------------------------------------------------------------------*/
  334. #ifdef UNICODE
  335. STDMETHODIMP CCommonQuery::OpenQueryWindow(THIS_ HWND hwndParent, LPOPENQUERYWINDOW_A pOpenQueryWnd, IDataObject** ppDataObject)
  336. {
  337.     HRESULT hres;
  338.     LPOPENQUERYWINDOW_W pOpenQueryWndW = NULL;
  339.     TraceEnter(TRACE_QUERY, "CCommonQueryA::OpenQueryWindow");
  340.     if ( !pOpenQueryWnd )
  341.         ExitGracefully(hres, E_INVALIDARG, "No pOpenQueryWnd structure");
  342.     // allocate the UNICODE verison of the OPENQUERYWINDOW structure that 
  343.     // we can then passed to the wide versions of this API.
  344.     
  345.     pOpenQueryWndW = (LPOPENQUERYWINDOW_W)LocalAlloc(LPTR, pOpenQueryWnd->cbStruct);
  346.     
  347.     if ( !pOpenQueryWndW )
  348.         ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate OPENQUERYWINDOW structure");
  349.     Trace(TEXT("Copying OPENQUERYWINDOW structure to %08x (from %08x, size %08x)"), 
  350.                                         pOpenQueryWndW, pOpenQueryWnd, pOpenQueryWnd->cbStruct);
  351.     CopyMemory(pOpenQueryWndW, pOpenQueryWnd, pOpenQueryWnd->cbStruct);
  352.     // Thunk the persistance interface, this will be an ANSI assuming of course that
  353.     // the caller has called the ANSI ICommonQuery interface.
  354.     if ( !pOpenQueryWndW->pPersistQuery )
  355.     {
  356.         pOpenQueryWndW->pPersistQuery = new CPersistQueryW2A(pOpenQueryWnd->pPersistQuery);
  357.         Trace(TEXT("pPersistA2W %08x"), pOpenQueryWndW->pPersistQuery);
  358.         if ( !pOpenQueryWndW->pPersistQuery )
  359.             ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate persistance thunk");
  360.     }
  361.     hres = OpenQueryWindow(hwndParent, pOpenQueryWndW, ppDataObject);
  362.     FailGracefully(hres, "Failed when calling UNICODE OpenQueryWindow function");
  363. exit_gracefully:
  364.   
  365.     if ( pOpenQueryWndW )
  366.     {
  367.         DoRelease(pOpenQueryWndW->pPersistQuery);
  368.         LocalFree((HLOCAL)pOpenQueryWndW);
  369.     }
  370.     TraceLeaveResult(hres);
  371. }
  372. #endif
  373. /*----------------------------------------------------------------------------
  374. / IObjectWithSite
  375. /----------------------------------------------------------------------------*/
  376. STDMETHODIMP CCommonQuery::SetSite(IUnknown* punk)
  377. {
  378.     HRESULT hres = S_OK;
  379.     TraceEnter(TRACE_QUERY, "CCommonQuery::SetSite");
  380.     DoRelease(_punkSite);
  381.     if ( punk )
  382.     {
  383.         TraceMsg("QIing for IUnknown from the site object");
  384.         hres = punk->QueryInterface(IID_IUnknown, (void **)&_punkSite);
  385.         FailGracefully(hres, "Failed to get IUnknown from the site object");
  386.     }
  387. exit_gracefully:
  388.     TraceLeaveResult(hres);
  389. }
  390. /*---------------------------------------------------------------------------*/
  391. STDMETHODIMP CCommonQuery::GetSite(REFIID riid, void **ppv)
  392. {
  393.     HRESULT hres;
  394.     
  395.     TraceEnter(TRACE_QUERY, "CCommonQuery::GetSite");
  396.     if ( !_punkSite )
  397.         ExitGracefully(hres, E_NOINTERFACE, "No site to QI from");
  398.     hres = _punkSite->QueryInterface(riid, ppv);
  399.     FailGracefully(hres, "QI failed on the site unknown object");
  400. exit_gracefully:
  401.     TraceLeaveResult(hres);
  402. }
  403. /*-----------------------------------------------------------------------------
  404. / CQueryFrame
  405. /----------------------------------------------------------------------------*/
  406. CQueryFrame::CQueryFrame(IUnknown *punkSite, LPOPENQUERYWINDOW pOpenQueryWindow, IDataObject** ppDataObject) :
  407.     _punkSite(punkSite),
  408.     _pOpenQueryWnd(pOpenQueryWindow),
  409.     _ppDataObject(ppDataObject),
  410.     _hiconLarge(NULL),
  411.     _hiconSmall(NULL)
  412. {
  413.     TraceEnter(TRACE_FRAME, "CQueryFrame::CQueryFrame");
  414.     if ( _punkSite )
  415.         _punkSite->AddRef();
  416.     TraceLeave();
  417. }
  418. CQueryFrame::~CQueryFrame()
  419. {
  420.     TraceEnter(TRACE_FRAME, "CQueryFrame::~CQueryFrame");
  421.     
  422.     DoRelease(_punkSite);
  423.     if ( _hiconLarge )
  424.         DestroyIcon(_hiconLarge);
  425.     if ( _hiconSmall )
  426.         DestroyIcon(_hiconSmall);
  427.     if ( _hkHandler )
  428.         RegCloseKey(_hkHandler);
  429.     if ( _hmenuFile )
  430.         DestroyMenu(_hmenuFile);
  431.     if ( _himlForms )
  432.         ImageList_Destroy(_himlForms);
  433.     if ( _hdsaForms )
  434.     {
  435.         Trace(TEXT("Destroying QUERYFORM DSA (%d)"), DSA_GetItemCount(_hdsaForms));
  436.         DSA_DestroyCallback(_hdsaForms, _FreeQueryFormCB, NULL);
  437.         _hdsaForms = NULL;
  438.     }
  439.     if ( _hdsaPages )
  440.     {
  441.         Trace(TEXT("Destroying QUERYFORMPAGE DSA (%d)"), DSA_GetItemCount(_hdsaPages));
  442.         DSA_DestroyCallback(_hdsaPages, _FreeQueryFormPageCB, NULL);
  443.         _hdsaPages = NULL;
  444.     }
  445.     if ( _hdsaScopes )
  446.     {
  447.         Trace(TEXT("Destroying QUERYSCOPE DSA (%d)"), DSA_GetItemCount(_hdsaScopes));
  448.         DSA_DestroyCallback(_hdsaScopes, _FreeScopeCB, NULL);
  449.         _hdsaScopes = NULL;
  450.     }
  451.     _pCurrentForm = NULL;
  452.     _pCurrentFormPage = NULL;
  453.     // Now discard the handler and its window (if we have one), if
  454.     // we don't do this they will never kill their objects
  455.     if ( _hwndResults )
  456.     {
  457.         DestroyWindow(_hwndResults);
  458.         _hwndResults = NULL;
  459.     }
  460.     TraceLeave();
  461. }
  462. // IUnknown bits
  463. #undef CLASS_NAME
  464. #define CLASS_NAME CQueryFrame
  465. #include "unknown.inc"
  466. STDMETHODIMP CQueryFrame::QueryInterface(REFIID riid, LPVOID* ppvObject)
  467. {
  468.     INTERFACES iface[] =
  469.     {
  470.         &IID_IQueryFrame, (IQueryFrame*)this,
  471.     };
  472.     return HandleQueryInterface(riid, ppvObject, iface, ARRAYSIZE(iface));
  473. }
  474. /*-----------------------------------------------------------------------------
  475. / IQueryFrame
  476. /----------------------------------------------------------------------------*/
  477. STDMETHODIMP CQueryFrame::DoModal(HWND hwndParent)
  478. {
  479.     HRESULT hres;
  480.     HWND hwndFrame = NULL;
  481.     HWND hwndFocus = NULL;
  482.     HWND hwndTopOwner = hwndParent;
  483.     MSG msg;
  484.     INITCOMMONCONTROLSEX iccex;
  485.     TraceEnter(TRACE_FRAME, "CQueryFrame::DoModal");
  486.     // initialize with the query handler we need
  487.     hres = CoCreateInstance(_pOpenQueryWnd->clsidHandler, NULL, CLSCTX_INPROC_SERVER, IID_IQueryHandler, (LPVOID*)&_pQueryHandler);
  488.     FailGracefully(hres, "Failed to get IQueryHandler for the given CLSID");
  489.     hres = _pQueryHandler->Initialize(this, _pOpenQueryWnd->dwFlags, _pOpenQueryWnd->pHandlerParameters);
  490.     FailGracefully(hres, "Failed to initialize the handler");
  491.     // mimic the behaviour of DialogBox by working out which control previously
  492.     // had focus, which window to disable and then running a message
  493.     // pump for our dialog.  Having done this we can then restore the state
  494.     // back to something sensible.
  495.     _fExitModalLoop = FALSE;                   // can be changed from hear down
  496.     iccex.dwSize = SIZEOF(iccex);
  497.     iccex.dwICC = ICC_USEREX_CLASSES;
  498.     InitCommonControlsEx(&iccex);
  499.     if ( _pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI )
  500.     {
  501.         hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FILTER),
  502.                                       hwndParent, 
  503.                                       QueryWnd_DlgProc, (LPARAM)this);
  504.     }
  505.     else
  506.     {
  507.         hwndFrame = CreateDialogParam(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDD_FIND),
  508.                                       hwndParent, 
  509.                                       QueryWnd_DlgProc, (LPARAM)this);
  510.     }
  511.     if ( !hwndFrame )
  512.         ExitGracefully(hres, E_FAIL, "Failed to create the dialog");
  513.     hwndFocus = GetFocus();
  514.     if ( hwndTopOwner )
  515.     {
  516.         // walk up the window stack looking for the window to be disabled, this must
  517.         // be the top-most non-child window.  If the resulting window is either
  518.         // the desktop or is already disabled then don't bother.
  519.         while ( GetWindowLong(hwndTopOwner, GWL_STYLE) & WS_CHILD )
  520.             hwndTopOwner = GetParent(hwndTopOwner);
  521.         TraceAssert(hwndTopOwner);
  522.         if ( (hwndTopOwner == GetDesktopWindow()) 
  523.                                 || EnableWindow(hwndTopOwner, FALSE) )
  524.         { 
  525.             TraceMsg("Parent is disabled or the desktop window, therefore setting to NULL");
  526.             hwndTopOwner = NULL;
  527.         }
  528.     }
  529.     ShowWindow(hwndFrame, SW_SHOW);                     // show the query window
  530.     
  531.     while ( !_fExitModalLoop && GetMessage(&msg, NULL, 0, 0) > 0 ) 
  532.     {
  533.         if ( !QueryWnd_MessageProc(hwndFrame, &msg) && !IsDialogMessage(hwndFrame, &msg) )
  534.         {
  535.             TranslateMessage(&msg);
  536.             DispatchMessage(&msg);
  537.         }
  538.     }
  539.     // Now tidy up, make the parent the active window, enable the top most
  540.     // window if there is one and restore focus as required.
  541.     if ( hwndTopOwner )
  542.         EnableWindow(hwndTopOwner, TRUE);
  543.     if ( hwndParent && (GetActiveWindow() == hwndFrame) )
  544.     {
  545.         TraceMsg("Passing activation to parent");
  546.         SetActiveWindow(hwndParent);
  547.     }
  548.     
  549.     if ( IsWindow(hwndFocus) )
  550.         SetFocus(hwndFocus);
  551.     DestroyWindow(hwndFrame);                   // discard the current frame window
  552. exit_gracefully:
  553.     DoRelease(_pQueryHandler);
  554.     TraceLeaveResult(_hResult);
  555. }
  556. /*---------------------------------------------------------------------------*/
  557. STDMETHODIMP CQueryFrame::AddScope(THIS_ LPCQSCOPE pScope, INT i, BOOL fSelect)
  558. {
  559.     HRESULT hres;
  560.     TraceEnter(TRACE_FRAME, "CQueryFrame::AddScope");
  561.     if ( !pScope )
  562.         ExitGracefully(hres, E_INVALIDARG, "No scope to add to the list");
  563.     // Add the scope to the control and then ensure that we either have
  564.     // its index stored (for default selection) or we select the 
  565.     // item.
  566.     if ( !_hdsaScopes || !DSA_GetItemCount(_hdsaScopes) )
  567.     {
  568.         TraceMsg("First scope being added, thefore selecting");
  569.         fSelect = TRUE;
  570.     }
  571.     hres = InsertScopeIntoList(pScope, i, _fScopesPopulated);
  572.     FailGracefully(hres, "Failed to add scope to control");
  573.     if ( fSelect ) 
  574.     {
  575.         if ( !_fScopesPopulated )
  576.         {
  577.             Trace(TEXT("Storing default scope index %d"), ShortFromResult(hres));
  578.             _iDefaultScope = ShortFromResult(hres);
  579.         }
  580.         else
  581.         {
  582.             Trace(TEXT("Selecting scope index %d"), ShortFromResult(hres));
  583.             ComboBox_SetCurSel(_hwndLookIn, ShortFromResult(hres));
  584.         }   
  585.     }
  586.     // hres = S_OK;
  587. exit_gracefully:
  588.     TraceLeaveResult(hres);
  589. }
  590. /*---------------------------------------------------------------------------*/
  591. STDMETHODIMP CQueryFrame::GetWindow(THIS_ HWND* phWnd)
  592. {
  593.     TraceEnter(TRACE_FRAME, "CQueryFrame::GetWindow");
  594.     TraceAssert(phWnd);
  595.     *phWnd = _hwnd;
  596.     TraceLeaveResult(S_OK);
  597. }
  598. /*---------------------------------------------------------------------------*/
  599. // Add a menu group to the given menu bar, updating the width index accordingly
  600. // so that other people can merge in accordingly
  601. VOID _DoInsertMenu(HMENU hMenu, INT iIndexTo, HMENU hMenuToInsert, INT iIndexFrom)
  602. {
  603.     TCHAR szBuffer[MAX_PATH];
  604.     HMENU hPopupMenu = NULL;
  605.     TraceEnter(TRACE_FRAME, "_DoInsertMenu");
  606.     
  607.     hPopupMenu = CreatePopupMenu();
  608.     
  609.     if ( hPopupMenu )
  610.     {
  611.         Shell_MergeMenus(hPopupMenu, GetSubMenu(hMenuToInsert, iIndexFrom), 0x0, 0x0, 0x7fff, 0);
  612.         GetMenuString(hMenuToInsert, iIndexFrom, szBuffer, ARRAYSIZE(szBuffer), MF_BYPOSITION);
  613.         InsertMenu(hMenu, iIndexTo, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hPopupMenu, szBuffer);
  614.     }
  615.     TraceLeave();
  616. }
  617. VOID _AddMenuGroup(HMENU hMenuShared, HMENU hMenuGroup, LONG iInsertAt, LPLONG pWidth)
  618. {
  619.     HRESULT hres;
  620.     TCHAR szBuffer[MAX_PATH];
  621.     HMENU hMenu;
  622.     INT i;
  623.     TraceEnter(TRACE_FRAME, "_AddMenuGroup");
  624.     TraceAssert(hMenuShared);
  625.     TraceAssert(hMenuGroup);
  626.     TraceAssert(pWidth);
  627.     for ( i = 0 ; i < GetMenuItemCount(hMenuGroup) ; i++ )
  628.     {
  629.         _DoInsertMenu(hMenuShared, iInsertAt+i, hMenuGroup, i);
  630.         *pWidth += 1;
  631.     }
  632.     TraceLeave();
  633. }
  634. STDMETHODIMP CQueryFrame::InsertMenus(THIS_ HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidth)
  635. {
  636.     HRESULT hres;
  637.     TraceEnter(TRACE_FRAME, "CQueryFrame::InsertMenus");
  638.     if ( !hmenuShared || !lpMenuWidth )
  639.         ExitGracefully(hres, E_INVALIDARG, "Unable to insert menus");
  640.     // if we don't have the menu bar already loaded then lets load it,
  641.     // having done that we can then add our menu to the bar (we only
  642.     // provide entries for the file menu).
  643.     
  644.     if ( !_hmenuFile )
  645.     {
  646.         _hmenuFile = LoadMenu(GLOBAL_HINSTANCE, MAKEINTRESOURCE(IDR_FILEMENUGROUP));
  647.         if ( !_hmenuFile )
  648.             ExitGracefully(hres, E_FAIL, "Failed to load base menu defn");
  649.     }
  650.     _AddMenuGroup(hmenuShared, _hmenuFile, 0, &lpMenuWidth->width[0]);
  651.     hres = S_OK;              // success
  652. exit_gracefully:
  653.     TraceLeaveResult(hres);
  654. }
  655. /*---------------------------------------------------------------------------*/
  656. STDMETHODIMP CQueryFrame::RemoveMenus(THIS_ HMENU hmenuShared)
  657. {
  658.     TraceEnter(TRACE_FRAME, "CQueryFrame::RemoveMenus");
  659.     // We don't need to implement this as we copy or menus into the
  660.     // menu that the handler supplies - fix DSQUERY if this ever
  661.     // changes.
  662.     TraceLeaveResult(S_OK);
  663. }
  664. /*---------------------------------------------------------------------------*/
  665. STDMETHODIMP CQueryFrame::SetMenu(THIS_ HMENU hmenuShared, HOLEMENU holereservedMenu)
  666. {
  667.     TraceEnter(TRACE_FRAME, "CQueryFrame::SetMenu");
  668.     if ( !(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS) )
  669.     {
  670.         HMENU hmenuOld = ::GetMenu(_hwnd);
  671.         if ( !hmenuShared )
  672.             hmenuShared = _hmenuFile;
  673.         ::SetMenu(_hwnd, hmenuShared);
  674.         DoEnableControls();             // ensure the menu state is valid    
  675.         ::DrawMenuBar(_hwnd);
  676.         if ( (hmenuOld != _hmenuFile) && (hmenuOld != hmenuShared) )
  677.         {
  678.             TraceMsg("Destroying old menu");
  679.             DestroyMenu(hmenuOld);
  680.         }
  681.     }
  682.     TraceLeaveResult(S_OK);
  683. }
  684. /*---------------------------------------------------------------------------*/
  685. STDMETHODIMP CQueryFrame::SetStatusText(THIS_ LPCTSTR pszStatusText)
  686. {
  687.     TraceEnter(TRACE_FRAME, "CQueryFrame::SetStatusText");
  688.     Trace(TEXT("Setting status text to: %s"), pszStatusText);
  689.     if ( _hwndStatus )
  690.         SendMessage(_hwndStatus, SB_SETTEXT, 0, (LPARAM)pszStatusText); 
  691.     TraceLeaveResult(S_OK);
  692. }
  693. /*---------------------------------------------------------------------------*/
  694. STDMETHODIMP CQueryFrame::StartQuery(THIS_ BOOL fStarting)
  695. {
  696.     TraceEnter(TRACE_FRAME, "CQueryFrame::StartQuery");
  697.     if ( fStarting )
  698.     {
  699.         Animate_Play(_hwndFindAnimation, 0, -1, -1);
  700.     }
  701.     else
  702.     {
  703.         Animate_Stop(_hwndFindAnimation);
  704.         Animate_Seek(_hwndFindAnimation, 0);        // go to start
  705.     }
  706.     if ( _pQueryHandler )
  707.         _pQueryHandler->ActivateView(CQRVA_STARTQUERY, (WPARAM)fStarting, 0);
  708.     
  709.     // now set the controls into a sensble state
  710.     _fQueryRunning = fStarting;
  711.     DoEnableControls();
  712.     TraceLeaveResult(S_OK);
  713. }
  714. /*---------------------------------------------------------------------------*/
  715. STDMETHODIMP CQueryFrame::LoadQuery(THIS_ IPersistQuery* pPersistQuery)
  716. {
  717.     HRESULT hres;
  718.     TCHAR szGUID[GUIDSTR_MAX+1];
  719.     LPQUERYFORM pQueryForm = NULL;
  720. #ifdef UNICODE
  721.     CPersistQueryA2W* pPersistQueryA2W = NULL;
  722. #endif
  723. #if HIDE_SEARCH_PANE
  724.     BOOL fHideSearchPanes = FALSE;
  725. #endif
  726.     GUID guid;
  727.     TraceEnter(TRACE_FRAME, "CQueryFrame::LoadQuery");
  728.     _pQueryHandler->StopQuery();                       // ensure that the handler stops its processing
  729.     // Attempt to read the handler GUID from the query stream, first try reading it as
  730.     // as string then parsing it into something that we can use, if that fails then
  731.     // try again, but this time read it as a structure.
  732.     //
  733.     // having aquired the GUID for the handler make sure that we have the correct handler
  734.     // selected.
  735.     if ( FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szHandlerIs, szGUID, ARRAYSIZE(szGUID))) ||
  736.          !GetGUIDFromString(szGUID, &guid) )
  737.     {
  738.         TraceMsg("Trying new style handler GUID as struct");
  739.         hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szHandlerIs, &guid, SIZEOF(guid));
  740.         FailGracefully(hres, "Failed to read handler GUID as struct");
  741.     }    
  742.     if ( guid != _pOpenQueryWnd->clsidHandler )
  743.         ExitGracefully(hres, E_FAIL, "Persisted handler GUID and specified handler GUID don't match");
  744. #if HIDE_SEARCH_PANE    
  745.     if ( SUCCEEDED(pPersistQuery->ReadInt(c_szCommonQuery, c_szSearchPaneHidden, &fHideSearchPanes)) )
  746.     {
  747.         Trace(TEXT("Hide forms %d form file"), fHideSearchPanes);
  748.         HideSearchPane(fHideSearchPanes);
  749.     }
  750. #endif
  751.     hres = _pQueryHandler->LoadQuery(pPersistQuery);
  752.     FailGracefully(hres, "Handler failed to load its query data");
  753.     // Get the form ID, then look up the form to see if we have one that matches,
  754.     // if not then we cannot load any thing else. If we do haved that form then
  755.     // ensure that we clear it and then load away.
  756.     if ( FAILED(pPersistQuery->ReadString(c_szCommonQuery, c_szFormIs, szGUID, ARRAYSIZE(szGUID))) ||
  757.          !GetGUIDFromString(szGUID, &guid) )
  758.     {
  759.         TraceMsg("Trying new style form GUID as struct");
  760.         hres = pPersistQuery->ReadStruct(c_szCommonQuery, c_szFormIs, &guid, SIZEOF(guid));
  761.         FailGracefully(hres, "Failed to read handler GUID as struct");
  762.     }    
  763.     hres = SelectForm(guid);
  764.     FailGracefully(hres, "Failed to select the query form");
  765.     if ( hres == S_FALSE )
  766.         ExitGracefully(hres, E_FAIL, "Failed to select the query form to read the query info");
  767.     
  768.     hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_ALL, CQPM_CLEARFORM, 0, 0);
  769.     FailGracefully(hres, "Failed to clear form before loading");
  770.     // Load the persisted query from the stream, coping correctly with the 
  771.     // UNICODE / ANSI issue.  We will be passed an IPersistQuery object which
  772.     // we must then thunk accordingly if we are UNICODE for the pages we
  773.     // are going to talk to.
  774. #ifndef UNICODE
  775.     hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_ANSI, CQPM_PERSIST, TRUE, (LPARAM)pPersistQuery);
  776.     FailGracefully(hres, "Failed to load form data");
  777. #else
  778.     hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_UNICODE, CQPM_PERSIST, TRUE, (LPARAM)pPersistQuery);
  779.     FailGracefully(hres, "Failed to load page data (UNICODE)");
  780.     if ( SUCCEEDED(hres) )
  781.     {
  782.         pPersistQueryA2W = new CPersistQueryA2W(pPersistQuery);
  783.         TraceAssert(pPersistQueryA2W);
  784.         if ( !pPersistQueryA2W )
  785.             ExitGracefully(hres, E_OUTOFMEMORY, "Failed to construct persistance thunk object");
  786.         hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_ANSI, CQPM_PERSIST, TRUE, (LPARAM)pPersistQueryA2W);
  787.         FailGracefully(hres, "Failed to load page data (ANSI)");
  788.     }
  789. #endif
  790.     hres = S_OK;          //  success
  791. exit_gracefully:
  792.     if ( SUCCEEDED(hres) )
  793.     {
  794.         TraceMsg("Query loaded successfully, select form query");
  795.         SelectForm(guid);
  796.     }
  797. #ifdef UNICODE
  798.     DoRelease(pPersistQueryA2W);
  799. #endif
  800.     TraceLeaveResult(hres);
  801. }
  802. /*---------------------------------------------------------------------------*/
  803. STDMETHODIMP CQueryFrame::SaveQuery(THIS_ IPersistQuery* pPersistQuery)
  804. {
  805.     HRESULT hres;
  806.     LPQUERYSCOPE pQueryScope;
  807. #ifdef UNICODE
  808.     CPersistQueryA2W* pPersistQueryA2W = NULL;
  809. #endif
  810.     TCHAR szBuffer[MAX_PATH];
  811.     
  812.     TraceEnter(TRACE_FRAME, "CQueryFrame::SaveQuery");
  813.     if ( !pPersistQuery )
  814.         ExitGracefully(hres, E_INVALIDARG, "No pPersistQuery object to write into");
  815.     pPersistQuery->Clear();             // flush the contents
  816.     hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szHandlerIs, 
  817.                                                         &_pOpenQueryWnd->clsidHandler, 
  818.                                                         SIZEOF(_pOpenQueryWnd->clsidHandler));
  819.     FailGracefully(hres, "Failed to write handler GUID");
  820.     hres = pPersistQuery->WriteStruct(c_szCommonQuery, c_szFormIs, 
  821.                                                         &_pCurrentForm->clsidForm, 
  822.                                                         SIZEOF(_pCurrentForm->clsidForm));
  823.     FailGracefully(hres, "Failed to write form GUID");
  824. #if HIDE_SEARCH_PANE
  825.     hres = pPersistQuery->WriteInt(c_szCommonQuery, c_szSearchPaneHidden, _fHideSearchPane);
  826.     FailGracefully(hres, "Failed to write form hide state");
  827. #endif
  828.     // Allow the handler to persist itself into the the stream, this includes
  829.     // giving it the current scope to store.
  830.     hres = GetSelectedScope(&pQueryScope);
  831.     FailGracefully(hres, "Failed to get the scope from the LookIn control");
  832.     hres = _pQueryHandler->SaveQuery(pPersistQuery, pQueryScope->pScope);
  833.     FailGracefully(hres, "Failed when calling handler to persist itself");
  834.     // Save the query into the stream, coping correctly with the 
  835.     // UNICODE / ANSI issue.  We will be passed an IPersistQuery object which
  836.     // we must then thunk accordingly if we are UNICODE for the pages we
  837.     // are going to talk to.
  838. #ifndef UNICODE
  839.     hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_ANSI, CQPM_PERSIST, FALSE, (LPARAM)pPersistQuery);
  840.     FailGracefully(hres, "Failed to load form data");
  841. #else
  842.     hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_UNICODE, CQPM_PERSIST, FALSE, (LPARAM)pPersistQuery);
  843.     FailGracefully(hres, "Failed to load page data (UNICODE)");
  844.     if ( SUCCEEDED(hres) )
  845.     {
  846.         pPersistQueryA2W = new CPersistQueryA2W(pPersistQuery);
  847.         TraceAssert(pPersistQueryA2W);
  848.         if ( !pPersistQueryA2W )
  849.             ExitGracefully(hres, E_OUTOFMEMORY, "Failed to construct persistance thunk object");
  850.         hres = CallFormPages(_pCurrentForm, CALLFORMPAGES_ANSI, CQPM_PERSIST, FALSE, (LPARAM)pPersistQueryA2W);
  851.         FailGracefully(hres, "Failed to load page data (ANSI)");
  852.     }
  853. #endif
  854.     hres = S_OK;
  855. exit_gracefully:
  856. #ifdef UNICODE
  857.     DoRelease(pPersistQueryA2W);
  858. #endif
  859.     TraceLeaveResult(hres);
  860. }
  861. /*---------------------------------------------------------------------------*/
  862. STDMETHODIMP CQueryFrame::CallForm(THIS_ LPCLSID pclsidForm, UINT uMsg, WPARAM wParam, LPARAM lParam)
  863. {
  864.     HRESULT hres;
  865.     LPQUERYFORM pQueryForm = _pCurrentForm;
  866.     TraceEnter(TRACE_FRAME, "CQueryFrame::CallForm");
  867.     
  868.     if ( pclsidForm )
  869.     {
  870.         pQueryForm = FindQueryForm(*pclsidForm);
  871.         TraceAssert(pQueryForm);
  872.     }
  873.     if ( !pQueryForm )
  874.         ExitGracefully(hres, E_FAIL, "Failed to find query form for given CLSID");
  875.     hres = CallFormPages(pQueryForm, CALLFORMPAGES_ALL, uMsg, wParam, lParam);
  876.     FailGracefully(hres, "Failed when calling CallFormPages");
  877.     // hres = S_OK;
  878. exit_gracefully:
  879.     TraceLeaveResult(hres);
  880. }
  881. /*---------------------------------------------------------------------------*/
  882. STDMETHODIMP CQueryFrame::GetScope(THIS_ LPCQSCOPE* ppScope)
  883. {
  884.     HRESULT hres;
  885.     LPQUERYSCOPE pQueryScope;
  886.     TraceEnter(TRACE_FRAME, "CQueryFrame::GetScope");
  887.     if ( !ppScope )
  888.         ExitGracefully(hres, E_INVALIDARG, "ppScope == NULL, thats bad");
  889.     hres = GetSelectedScope(&pQueryScope);
  890.     FailGracefully(hres, "Failed to get the current scope");
  891.     *ppScope = (LPCQSCOPE)CoTaskMemAlloc(pQueryScope->pScope->cbStruct);
  892.     TraceAssert(*ppScope);
  893.     if ( !*ppScope )
  894.         ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate the scope block");
  895.                         
  896.     memcpy(*ppScope, pQueryScope->pScope, pQueryScope->pScope->cbStruct);
  897.     hres = S_OK;
  898. exit_gracefully:
  899.     TraceLeaveResult(hres);
  900. }
  901. /*---------------------------------------------------------------------------*/
  902. STDMETHODIMP CQueryFrame::GetHandler(THIS_ REFIID riid, void **ppv)
  903. {
  904.     HRESULT hres;
  905.     TraceEnter(TRACE_FRAME, "CQueryFrame::GetHandler");
  906.     if ( !_pQueryHandler )
  907.         ExitGracefully(hres, E_UNEXPECTED, "_pQueryHandler is NULL");
  908.     hres = _pQueryHandler->QueryInterface(riid, ppv);
  909. exit_gracefully:
  910.     TraceLeaveResult(hres);
  911. }
  912. /*-----------------------------------------------------------------------------
  913. / Dialog box handler functions (core guts)
  914. /----------------------------------------------------------------------------*/
  915. #define REAL_WINDOW(hwnd)                   
  916.         (hwnd &&                            
  917.             IsWindowVisible(hwnd) &&        
  918.                 IsWindowEnabled(hwnd) &&    
  919.                     (GetWindowLong(hwnd, GWL_STYLE) & WS_TABSTOP))
  920. HWND _NextTabStop(HWND hwndSearch, BOOL fShift)
  921. {
  922.     HWND hwnd;
  923.     Trace(TEXT("hwndSearch %08x, fShift %d"), hwndSearch, fShift);
  924.     // do we have a window to search into?
  925.     
  926.     while ( hwndSearch )
  927.     {
  928.         // if we have a window then lets check to see if it has any children?
  929.         hwnd = GetWindow(hwndSearch, GW_CHILD);
  930.         Trace(TEXT("Child of %08x is %08x"), hwndSearch, hwnd);
  931.         if ( hwnd )
  932.         {
  933.             // it has a child therefore lets to go its first/last
  934.             // and continue the search there for a window that
  935.             // matches the criteria we are looking for.
  936.             hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
  937.             if ( !REAL_WINDOW(hwnd) )
  938.             {
  939.                 Trace(TEXT("Trying to recurse into %08x"), hwnd);
  940.                 hwnd = _NextTabStop(hwnd, fShift);
  941.             }
  942.             Trace(TEXT("Tabstop child of %08x is %08x"), hwndSearch, hwnd);
  943.         }
  944.         // after all that is hwnd a valid window?  if so then pass
  945.         // that back out to the caller.
  946.         if ( REAL_WINDOW(hwnd) )
  947.         {
  948.             Trace(TEXT("Child tab stop was %08x"), hwnd);
  949.             return hwnd;
  950.         }
  951.         // do we have a sibling?  if so then lets return that otherwise
  952.         // lets just continue to search until we either run out of windows
  953.         // or hit something interesting
  954.         hwndSearch = GetWindow(hwndSearch, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
  955.         if ( REAL_WINDOW(hwndSearch) )
  956.         {
  957.             Trace(TEXT("Next tab stop was %08x"), hwndSearch);
  958.             return hwndSearch;
  959.         }
  960.     }
  961.     return hwndSearch;
  962. }
  963. INT QueryWnd_MessageProc(HWND hwnd, LPMSG pMsg)
  964. {
  965.     LRESULT lResult = 0;
  966.     CQueryFrame* pQueryFrame = NULL;
  967.     NMHDR nmhdr;
  968.     pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
  969.     if ( !pQueryFrame )
  970.         return 0;
  971.     if ( (pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_TAB) )
  972.     {
  973.         BOOL fCtrl = GetAsyncKeyState(VK_CONTROL) < 0;
  974.         BOOL fShift = GetAsyncKeyState(VK_SHIFT) < 0;
  975.         // ensure that the focus rectangles are shown
  976. #if (_WIN32_WINNT >= 0x0500)
  977.         SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
  978. #endif
  979.         if ( fCtrl )
  980.         {
  981.             // if this is a key press within the parent then lets ensure that we
  982.             // allow the tab control to change the page correctly.  otherwise lets
  983.             // just hack around the problem of the result view not handling tabs
  984.             // properly.
  985.             INT iCur = TabCtrl_GetCurSel(pQueryFrame->_hwndFrame);
  986.             INT nPages = TabCtrl_GetItemCount(pQueryFrame->_hwndFrame);
  987.             if ( fShift )
  988.                 iCur += (nPages-1);
  989.             else
  990.                 iCur++;
  991.             pQueryFrame->SelectFormPage(pQueryFrame->_pCurrentForm, iCur % nPages);
  992.             return 1;                   // we processed it
  993.         }
  994.         else
  995.         {
  996.             // is the window that has the focus a child of the result view, if
  997.             // so then we must attempt to pass focus to its 1st child and hope
  998.             // that is can do the rest.
  999.             HWND hwndNext, hwnd = GetFocus();
  1000.             Trace(TEXT("Current focus window %08x"), hwnd);
  1001.            
  1002.             while ( hwnd && GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD )
  1003.             {      
  1004.                 hwndNext = _NextTabStop(hwnd, fShift);
  1005.                 Trace(TEXT("_NextTabStop yeilds %08x from %08x"), hwndNext, hwnd);
  1006.         
  1007.                 if ( hwndNext )
  1008.                 {
  1009.                     Trace(TEXT("SetFocus on child %08x"), hwndNext);
  1010.                     SetFocus(hwndNext);
  1011.                     return 1;
  1012.                 }
  1013.                 while ( TRUE )
  1014.                 {
  1015.                     // look up the parent list trying to find a window that we can 
  1016.                     // tab back into.  We must watch that when we walk out of the
  1017.                     // child list we loop correctly at the top of the list.
  1018.                     hwndNext = GetParent(hwnd);
  1019.                     Trace(TEXT("Parent hwnd %08x"), hwndNext);
  1020.                     if ( GetWindowLong(hwndNext, GWL_STYLE) & WS_CHILD )
  1021.                     {
  1022.                         // the parent window is a child, therefore we can check
  1023.                         // to see if has any siblings.
  1024.                         
  1025.                         Trace(TEXT("hwndNext is a child, therefore hwndNext of it is %08x"), 
  1026.                                                         GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT));
  1027.                                                                                 
  1028.                         if ( GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT) )
  1029.                         {
  1030.                             hwnd = GetWindow(hwndNext, fShift ? GW_HWNDPREV:GW_HWNDNEXT);
  1031.                             Trace(TEXT("Silbing window found %08x"), hwnd);
  1032.                             break;
  1033.                         }
  1034.                         else
  1035.                         {
  1036.                             TraceMsg("There was no sibling, therefore continuing parent loop");
  1037.                             hwnd = hwndNext;
  1038.                         }
  1039.                     }
  1040.                     else
  1041.                     {
  1042.                         // we have hit the parent window of it all (the overlapped one)
  1043.                         // therefore we must attempt to go to its first child.  Walk forward
  1044.                         // in the stack looking for a window that matches the
  1045.                         // "REAL_WINDOW" conditions.
  1046.                         hwnd = GetWindow(hwnd, fShift ? GW_HWNDLAST:GW_HWNDFIRST);
  1047.                         Trace(TEXT("First child is %08x"), hwnd);
  1048.                         break;                                  // continue the sibling search etc
  1049.                     }
  1050.                 }
  1051.                 if ( REAL_WINDOW(hwnd) )
  1052.                 {
  1053.                     SetFocus(hwnd);
  1054.                     return 1;
  1055.                 }
  1056.             }
  1057.         }
  1058.     }
  1059.     return 0;
  1060. }
  1061. //
  1062. // Main DLGPROC
  1063. //
  1064. INT_PTR CALLBACK QueryWnd_DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1065. {
  1066.     CQueryFrame* pQueryFrame;
  1067.     if ( uMsg == WM_INITDIALOG )
  1068.     {
  1069.         HRESULT hres;
  1070.         pQueryFrame = (CQueryFrame*)lParam;
  1071.         SetWindowLongPtr(hwnd, DWLP_USER, (LRESULT)pQueryFrame);
  1072.         hres = pQueryFrame->OnInitDialog(hwnd);
  1073.         Trace(TEXT("OnInitDialog returns %08x"), hres);
  1074.         
  1075.         if ( FAILED(hres) )
  1076.         {
  1077.             TraceMsg("Failed to initialize the dialog, Destroying the window");    
  1078.             pQueryFrame->CloseQueryFrame(hres);
  1079.             DestroyWindow(hwnd);
  1080.         }
  1081.     }
  1082.     else
  1083.     {
  1084.         pQueryFrame = (CQueryFrame*)GetWindowLongPtr(hwnd, DWLP_USER);
  1085.         if ( !pQueryFrame )
  1086.             goto exit_gracefully;
  1087.         switch ( uMsg )
  1088.         {
  1089.             case WM_ERASEBKGND:
  1090.             {
  1091.                 HDC hdc = (HDC)wParam;
  1092.                 RECT rc;
  1093.                 // if we have a DC then lets fill it, and if we have a 
  1094.                 // query form then lets paint the divider between the menu bar and
  1095.                 // this area.
  1096.                 if ( hdc  )
  1097.                 {
  1098.                     GetClientRect(hwnd, &rc);
  1099.                     FillRect(hdc, &rc, (HBRUSH)(COLOR_3DFACE+1));
  1100.                     if ( !(pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS) )
  1101.                     {
  1102. #if HIDE_SEARCH_PANE
  1103.                         if ( !pQueryFrame->_fHideSearchPane )
  1104.                             DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP);
  1105. #else
  1106.                         DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP);
  1107. #endif
  1108.                     }
  1109.                     SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1110.                 }
  1111.                 
  1112.                 return 1;
  1113.             }
  1114.             case WM_NOTIFY:
  1115.                 return pQueryFrame->OnNotify((int)wParam, (LPNMHDR)lParam);
  1116.             case WM_SIZE:
  1117.                 pQueryFrame->OnSize(LOWORD(lParam), HIWORD(lParam));
  1118.                 return(1);
  1119.             case WM_GETMINMAXINFO:
  1120.                 pQueryFrame->OnGetMinMaxInfo((LPMINMAXINFO)lParam);
  1121.                 return(1);
  1122.             case WM_COMMAND:
  1123.                 pQueryFrame->OnCommand(wParam, lParam);
  1124.                 return(1);
  1125.             case WM_ACTIVATE:
  1126.                 pQueryFrame->_pQueryHandler->ActivateView(wParam ? CQRVA_ACTIVATE : CQRVA_DEACTIVATE, 0, 0);
  1127.                 return(1);
  1128.             
  1129.             case WM_INITMENU:
  1130.                 pQueryFrame->OnInitMenu((HMENU)wParam);
  1131.                 return(1);
  1132.             case WM_SETCURSOR:
  1133.             {
  1134.                 // do we have any scopes? if not then let us display the wait
  1135.                 // cursor for the user.  if we have a query running then lets
  1136.                 // display the app start cursor.
  1137.                 if ( !pQueryFrame->_fAddScopesNYI &&
  1138.                             !ComboBox_GetCount(pQueryFrame->_hwndLookIn) )
  1139.                 {
  1140.                     if ( LOWORD(lParam) == HTCLIENT )
  1141.                     {
  1142.                         SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));
  1143.                         SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1144.                         return 1;
  1145.                     }
  1146.                 }
  1147.                 break;
  1148.             }
  1149.             case WM_INITMENUPOPUP:
  1150.             {
  1151.                 // only send sub-menu activates if the menu bar is being tracked, this is
  1152.                 // handled within OnInitMenu, if we are not tracking the menu then we
  1153.                 // assume that the client has already primed the menu and that they are
  1154.                 // using some kind of popup menu.
  1155.                 if ( pQueryFrame->_fTrackingMenuBar )
  1156.                     pQueryFrame->_pQueryHandler->ActivateView(CQRVA_INITMENUBARPOPUP, wParam, lParam);
  1157.                 return(1);
  1158.             }
  1159.             
  1160.             case WM_ENTERMENULOOP:
  1161.                 pQueryFrame->OnEnterMenuLoop(TRUE);
  1162.                 return(1);
  1163.             case WM_EXITMENULOOP:
  1164.                 pQueryFrame->OnEnterMenuLoop(FALSE);
  1165.                 return(1);
  1166.             case WM_MENUSELECT:
  1167.             {
  1168.                 UINT uID = LOWORD(wParam);
  1169.                 UINT uFlags = HIWORD(wParam);
  1170.                 HMENU hMenu = (HMENU)lParam;
  1171.                 
  1172.                 // the command opens a popup menu the the uID is actually
  1173.                 // the index into the menu, so lets ensure that we pick
  1174.                 // up the correct ID by calling GetMenuItemInfo, note that
  1175.                 // GetMenuItemID returns -1 in this case which is totally
  1176.                 // useless.
  1177.                 if ( uFlags & MF_POPUP )    
  1178.                 {
  1179.                     MENUITEMINFO mii;
  1180.                     ZeroMemory(&mii, SIZEOF(mii));
  1181.                     mii.cbSize = SIZEOF(mii);
  1182.                     mii.fMask = MIIM_ID;
  1183.                     if ( GetMenuItemInfo(hMenu, uID, TRUE, &mii) )
  1184.                         uID = mii.wID;
  1185.                 }
  1186.                 pQueryFrame->OnMenuSelect(hMenu, uID);
  1187.                 return(1);
  1188.             }
  1189.             case WM_SYSCOMMAND:
  1190.                 if ( wParam == SC_CLOSE )
  1191.                 {
  1192.                     pQueryFrame->CloseQueryFrame(S_FALSE);
  1193.                     return(1);
  1194.                 }
  1195.                 break;
  1196.             case WM_CONTEXTMENU:
  1197.             {
  1198.                 // there are a couple of controls we don't care about for the
  1199.                 // frame, so lets ignore those when passing the CQRVA_CONTEXTMENU
  1200.                 // through to the handler.
  1201.                 POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  1202.                 ScreenToClient((HWND)wParam, &pt);
  1203.                 
  1204.                 switch ( GetDlgCtrlID(ChildWindowFromPoint((HWND)wParam, pt)) )
  1205.                 {
  1206.                     case IDC_FORMAREA:
  1207.                     case IDC_FINDANIMATION:
  1208.                     case IDC_STATUS:
  1209.                         return TRUE;                // handled
  1210.                     default:
  1211.                         pQueryFrame->_pQueryHandler->ActivateView(CQRVA_CONTEXTMENU, wParam, lParam);
  1212.                         return TRUE;
  1213.                 }
  1214.                 return FALSE;
  1215.             }
  1216.             
  1217.             case WM_HELP:
  1218.             {
  1219.                 LPHELPINFO phi = (LPHELPINFO)lParam;
  1220.                 // filter out those controls we are not interested in (they make no sense)
  1221.                 // to bother the user with
  1222.                 switch ( GetDlgCtrlID((HWND)phi->hItemHandle) )
  1223.                 {
  1224.                     case IDC_FORMAREA:
  1225.                     case IDC_FINDANIMATION:
  1226.                     case IDC_STATUS:
  1227.                         return TRUE;
  1228.                     default:
  1229.                         pQueryFrame->OnHelp(phi);
  1230.                         return TRUE;
  1231.                 }
  1232.                 return FALSE;                   
  1233.             }
  1234.             case CQFWM_ADDSCOPE:
  1235.             {
  1236.                 LPCQSCOPE pScope = (LPCQSCOPE)wParam;
  1237.                 BOOL fSelect = LOWORD(lParam);
  1238.                 INT iIndex = HIWORD(lParam);
  1239.                 if ( SUCCEEDED(pQueryFrame->AddScope(pScope, iIndex, fSelect)) )
  1240.                     SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1241.                 return 1;
  1242.             }
  1243.             case CQFWM_GETFRAME:
  1244.             {
  1245.                 IQueryFrame** ppQueryFrame = (IQueryFrame**)lParam;
  1246.                 if ( ppQueryFrame )
  1247.                 {
  1248.                     pQueryFrame->AddRef();
  1249.                     *ppQueryFrame = pQueryFrame;
  1250.                     SetWindowLongPtr(hwnd, DWLP_MSGRESULT, 1L);
  1251.                 }
  1252.                 return 1;
  1253.             }
  1254.             case CQFWM_ALLSCOPESADDED:
  1255.             {
  1256.                 // there is an async scope collector, it has added all the scopes
  1257.                 // so we must now attempt to issue the query if the we are in the
  1258.                 // holding pattern waiting for the scopes to be collected.
  1259.                 pQueryFrame->_fScopesAddedAsync = FALSE;            // all scopes have been added
  1260.                 if ( pQueryFrame->_pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN )
  1261.                     PostMessage(pQueryFrame->_hwnd, CQFWM_STARTQUERY, 0, 0);
  1262.                 return 1;
  1263.             }
  1264.             case CQFWM_STARTQUERY:
  1265.                 pQueryFrame->OnFindNow();
  1266.                 return 1;
  1267.             default:
  1268.                 break;
  1269.         }
  1270.     }
  1271. exit_gracefully:
  1272.     return(0);
  1273. }
  1274. /*-----------------------------------------------------------------------------
  1275. / CQueryFrame::CloseQueryFrame
  1276. / ----------------------------
  1277. /   Close the query window passing back the data object if required, and ensuring
  1278. /   that our result code indicates what is going on.
  1279. /
  1280. / In:
  1281. /   hResult = result code to pass to the caller
  1282. /
  1283. / Out:
  1284. /   -
  1285. /----------------------------------------------------------------------------*/
  1286. VOID CQueryFrame::CloseQueryFrame(HRESULT hres)
  1287. {
  1288.     TraceEnter(TRACE_FRAME, "CQueryFrame::CloseQueryFrame");
  1289.     Trace(TEXT("hResult %08x"), hres);
  1290.     // If we succeeded then attempt to collect the IDataObject and pass it
  1291.     // back to the caller.
  1292.     if ( hres == S_OK )
  1293.     {
  1294.         if ( _ppDataObject )
  1295.         {
  1296.             hres = _pQueryHandler->GetViewObject(CQRVS_SELECTION, IID_IDataObject, (LPVOID*)_ppDataObject);
  1297.             FailGracefully(hres, "Failed when collecting the data object");
  1298.         }
  1299.         if ( (_pOpenQueryWnd->dwFlags & OQWF_SAVEQUERYONOK) && _pOpenQueryWnd->pPersistQuery )
  1300.         {
  1301.             hres = SaveQuery(_pOpenQueryWnd->pPersistQuery);
  1302.             FailGracefully(hres, "Failed when persisting query to IPersistQuery blob");
  1303.         }
  1304.         hres = S_OK;           // success
  1305.     }
  1306. exit_gracefully:
  1307.     _hResult = hres;
  1308.     _fExitModalLoop = TRUE;                // bomb out of the modal loop
  1309.     TraceLeave();
  1310. }
  1311. /*-----------------------------------------------------------------------------
  1312. / CQueryFrame::HideSearchPane
  1313. / -------------------------
  1314. /   Hide the form area of the query window.  This involves hiding the controls
  1315. /   present and moving the contents of the windo to reflect the change we
  1316. /   are making.
  1317. /
  1318. / In:
  1319. /   fHide = show/hide flag
  1320. /
  1321. / Out:
  1322. /   -
  1323. /----------------------------------------------------------------------------*/
  1324. #if HIDE_SEARCH_PANE
  1325. const UINT g_idControls[] =
  1326. {   
  1327.     CQID_BROWSE,
  1328.     CQID_FINDNOW,
  1329.     CQID_STOP,
  1330.     CQID_CLEARALL,
  1331.     IDC_FORMAREA,
  1332.     IDC_FINDANIMATION,
  1333. };
  1334. VOID CQueryFrame::HideSearchPane(BOOL fHide)
  1335. {
  1336.     RECT rect, rcClient;
  1337.     MINMAXINFO mmi;
  1338.     INT i, cx, cy, cxClient, cyClient;
  1339.     INT nCmdShow = fHide ? SW_HIDE:SW_SHOW;
  1340.     TraceEnter(TRACE_FRAME, "CQueryFrame::HideSearchPane");
  1341.     if ( _fHideSearchPane != fHide )
  1342.     {   
  1343.         _fHideSearchPane = fHide;
  1344.         LockWindowUpdate(_hwnd);
  1345.         // hide the window controls that we are not interested in,
  1346.         // taking special care for the optional controls on the window
  1347.         for ( i = 0 ; i < ARRAYSIZE(g_idControls); i++ )
  1348.             ShowWindow(GetDlgItem(_hwnd, g_idControls[i]), nCmdShow);
  1349.            
  1350.         if ( _pCurrentFormPage && _pCurrentFormPage->hwndPage )
  1351.             ShowWindow(_pCurrentFormPage->hwndPage, nCmdShow);
  1352.         if ( !(_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS) )
  1353.         {
  1354.             ShowWindow(_hwndLookForLabel, nCmdShow);
  1355.             ShowWindow(_hwndLookFor, nCmdShow);
  1356.         }
  1357.         if ( !(_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES) )
  1358.         {
  1359.             ShowWindow(_hwndLookInLabel, nCmdShow);
  1360.             ShowWindow(_hwndLookIn, nCmdShow);
  1361.         }
  1362.         if ( _pOpenQueryWnd->dwFlags & OQWF_OKCANCEL )
  1363.         {
  1364.             ShowWindow(_hwndOK, nCmdShow);
  1365.             if ( _hwndCancel )
  1366.                 ShowWindow(_hwndCancel, nCmdShow);
  1367.         }
  1368.         // now adjust the main window area to cope with the
  1369.         // form being hidden or shown.
  1370.         GetClientRect(_hwnd, &rcClient);
  1371.         GetWindowRect(_hwnd, &rect);
  1372.         cxClient = rcClient.right - rcClient.left;
  1373.         cyClient = rcClient.bottom - rcClient.top;
  1374.         if ( _fHideSearchPane )
  1375.         {
  1376.             OnSize(cxClient, cyClient);
  1377.         }
  1378.         else
  1379.         {
  1380.             // when enabling the form area we must ensure that the window is
  1381.             // at least big enough to show it, therefore we need to get the
  1382.             // min track size, and apply that the current size.  If there is
  1383.             // no change then we don't bother calling SetWindowPos, we just
  1384.             // call OnSize and let that take care of verything.
  1385.             OnGetMinMaxInfo(&mmi);    
  1386.             cx = max(rect.right-rect.left, mmi.ptMinTrackSize.x);   // width
  1387.             cy = max(rect.bottom-rect.top, mmi.ptMinTrackSize.y);   // height
  1388.             if ( (cx == (rect.right - rect.left)) && (cy == (rect.bottom - rect.top)) )
  1389.             {
  1390.                 TraceMsg("Calling OnSize, no physical size change to window");
  1391.                 OnSize(cxClient, cyClient);
  1392.             }
  1393.             else
  1394.             {
  1395.                 TraceMsg("Sizing window to make form visible");
  1396.                 SetWindowPos(_hwnd, NULL, 0, 0, cx, cy, SWP_NOZORDER|SWP_NOMOVE);
  1397.             }
  1398.         }
  1399.         LockWindowUpdate(NULL);
  1400.         RedrawWindow(_hwnd, NULL, NULL, RDW_ERASE|RDW_FRAME|RDW_UPDATENOW|RDW_ALLCHILDREN);
  1401.     }
  1402.     DoEnableControls();             // ensure we fix the grey state of the controls
  1403.     TraceLeave();
  1404. }
  1405. #endif
  1406. /*-----------------------------------------------------------------------------
  1407. / CQueryFrame::FrameMessageBox
  1408. / ----------------------------
  1409. /   Our message box for putting up prompts that relate to the current
  1410. /   query.  We handle getting the view information and displaying
  1411. /   the prompt, returning the result from MessageBox.
  1412. /
  1413. / In:
  1414. /   pPrompt = text displayed as a prompt
  1415. /   uType = message box type
  1416. /
  1417. / Out:
  1418. /   INT
  1419. /----------------------------------------------------------------------------*/
  1420. INT CQueryFrame::FrameMessageBox(LPCTSTR pPrompt, UINT uType)
  1421. {
  1422.     TCHAR szTitle[MAX_PATH];        
  1423.     CQVIEWINFO vi;
  1424.     TraceEnter(TRACE_FRAME, "CQueryFrame::FrameMessageBox");
  1425.     ZeroMemory(&vi, SIZEOF(vi));
  1426.     //vi. dwFlags = 0;                // display attributes
  1427.     if ( SUCCEEDED(_pQueryHandler->GetViewInfo(&vi)) && vi.hInstance && vi.idTitle )
  1428.         LoadString(vi.hInstance, vi.idTitle, szTitle, ARRAYSIZE(szTitle));
  1429.     else
  1430.         GetWindowText(_hwnd, szTitle, ARRAYSIZE(szTitle));
  1431.     TraceLeaveValue(MessageBox(_hwnd, pPrompt, szTitle, uType));    
  1432. }
  1433. /*-----------------------------------------------------------------------------
  1434. / CQueryFrame::OnInitDlg
  1435. / ----------------------
  1436. /   Handle a WM_INITDAILOG message, this is sent as the first thing the
  1437. /   dialog receives, therefore we must handle our initialization that
  1438. /   was not handled in the constructor.
  1439. /
  1440. / In:
  1441. /   hwnd = handle of dialog we are initializing
  1442. /
  1443. / Out:
  1444. /   HRESULT
  1445. /----------------------------------------------------------------------------*/
  1446. HRESULT CQueryFrame::OnInitDialog(HWND hwnd)
  1447. {
  1448.     HRESULT hres;
  1449.     HICON hIcon = NULL;
  1450.     TCHAR szGUID[GUIDSTR_MAX+1];
  1451.     TCHAR szBuffer[MAX_PATH];
  1452.     CQVIEWINFO vi;
  1453.     INT dyControls = 0;
  1454.     RECT rect, rect2;
  1455.     SIZE size;
  1456.     
  1457.     TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnInitDialog");
  1458.     // get the HKEY for the handler we are using
  1459.     hres = GetKeyForCLSID(_pOpenQueryWnd->clsidHandler, NULL, &_hkHandler);
  1460.     FailGracefully(hres, "Failed to open handlers HKEY");
  1461.     // pick up the control handles and store them, saves picking them up later
  1462.     _hwnd              = hwnd;
  1463.     _hwndFrame         = GetDlgItem(hwnd, IDC_FORMAREA);
  1464.     _hwndLookForLabel  = GetDlgItem(hwnd, CQID_LOOKFORLABEL);
  1465.     _hwndLookFor       = GetDlgItem(hwnd, CQID_LOOKFOR); 
  1466.     _hwndLookInLabel   = GetDlgItem(hwnd, CQID_LOOKINLABEL);
  1467.     _hwndLookIn        = GetDlgItem(hwnd, CQID_LOOKIN);    
  1468.     _hwndBrowse        = GetDlgItem(hwnd, CQID_BROWSE);
  1469.     _hwndFindNow       = GetDlgItem(hwnd, CQID_FINDNOW);
  1470.     _hwndStop          = GetDlgItem(hwnd, CQID_STOP);
  1471.     _hwndNewQuery      = GetDlgItem(hwnd, CQID_CLEARALL);
  1472.     _hwndFindAnimation = GetDlgItem(hwnd, IDC_FINDANIMATION);
  1473.     _hwndOK            = GetDlgItem(hwnd, IDOK);
  1474.     _hwndCancel        = GetDlgItem(hwnd, IDCANCEL);
  1475.     // call the IQueryHandler interface and get its display attributes,
  1476.     // then reflect these into the dialog we are about to display to the
  1477.     // outside world.
  1478.     vi.dwFlags = 0;
  1479.     vi.hInstance = NULL;
  1480.     vi.idLargeIcon = 0;
  1481.     vi.idSmallIcon = 0;
  1482.     vi.idTitle = 0;
  1483.     vi.idAnimation = 0;
  1484.     hres = _pQueryHandler->GetViewInfo(&vi);
  1485.     FailGracefully(hres, "Failed when getting the view info from the handler");
  1486.     _dwHandlerViewFlags = vi.dwFlags;
  1487.     if ( vi.hInstance )
  1488.     {
  1489.         HICON hiTemp = NULL;
  1490.         if ( vi.idLargeIcon )
  1491.         {
  1492.             _hiconLarge = (HICON)LoadImage(vi.hInstance, 
  1493.                                            MAKEINTRESOURCE(vi.idLargeIcon), 
  1494.                                            IMAGE_ICON,
  1495.                                            0, 0, 
  1496.                                            LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
  1497.             if ( _hiconLarge )
  1498.                 SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)_hiconLarge);
  1499.         }
  1500.         if ( vi.idSmallIcon )
  1501.         {
  1502.             _hiconSmall = (HICON)LoadImage(vi.hInstance, 
  1503.                                            MAKEINTRESOURCE(vi.idLargeIcon), 
  1504.                                            IMAGE_ICON,
  1505.                                            GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 
  1506.                                            LR_DEFAULTCOLOR);
  1507.             if ( _hiconSmall )
  1508.                 SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)_hiconSmall);
  1509.         }
  1510.         if ( vi.idTitle )
  1511.         {
  1512.             LoadString(vi.hInstance, vi.idTitle, szBuffer, ARRAYSIZE(szBuffer));
  1513.             SetWindowText(hwnd, szBuffer);
  1514.         }
  1515.     }
  1516.     if ( vi.hInstance && vi.idAnimation )
  1517.     {
  1518.         SetWindowLongPtr(_hwndFindAnimation, GWLP_HINSTANCE, (LRESULT)vi.hInstance);
  1519.         Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(vi.idAnimation));
  1520.     }
  1521.     else
  1522.     {
  1523.         Animate_Open(_hwndFindAnimation, MAKEINTRESOURCE(AVI_FIND));
  1524.     }
  1525.     // now adjust the positions and hide the controls we are not interested in
  1526.     if ( _pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS )
  1527.     {
  1528.         ShowWindow(_hwndLookForLabel, SW_HIDE);
  1529.         ShowWindow(_hwndLookFor, SW_HIDE);
  1530.     }
  1531.     if ( _pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES )
  1532.     {
  1533.         ShowWindow(_hwndLookInLabel, SW_HIDE);
  1534.         ShowWindow(_hwndLookIn, SW_HIDE);
  1535.         ShowWindow(_hwndBrowse, SW_HIDE);
  1536.     }
  1537.     // hiding both the scopes and the forms control causes us to
  1538.     // move all the controls up by so many units.  
  1539.     if ( (_pOpenQueryWnd->dwFlags & (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES)) 
  1540.                                         == (OQWF_REMOVEFORMS|OQWF_REMOVESCOPES) )
  1541.     {
  1542.         GetRealWindowInfo(_hwndLookForLabel, &rect, NULL);
  1543.         GetRealWindowInfo(_hwndFrame, &rect2, NULL);
  1544.         dyControls += rect2.top - rect.top;         
  1545.         Trace(TEXT("Moving all controls up by %d units"), dyControls);
  1546.         OffsetWindow(_hwndFrame, 0, -dyControls);
  1547.         OffsetWindow(_hwndFindNow, 0, -dyControls);
  1548.         OffsetWindow(_hwndStop, 0, -dyControls);
  1549.         OffsetWindow(_hwndNewQuery, 0, -dyControls);
  1550.         OffsetWindow(_hwndFindAnimation, 0, -dyControls);
  1551.         OffsetWindow(_hwndOK, 0, -dyControls);
  1552.         if ( _hwndCancel )
  1553.             OffsetWindow(_hwndCancel, 0, -dyControls);
  1554.     }
  1555.     // hiding OK/Cancel so lets adjust the size here to include the
  1556.     // OK/Cancel buttons disappearing, note that we update dyControls
  1557.     // to include this delta
  1558.     if ( !(_pOpenQueryWnd->dwFlags & OQWF_OKCANCEL) )
  1559.     {
  1560.         ShowWindow(_hwndOK, SW_HIDE);        
  1561.         if ( _hwndCancel )
  1562.             ShowWindow(_hwndCancel, SW_HIDE);
  1563.         // if this is the filter dialog then lets ensure that 
  1564.         // we trim the OK/Cancel buttons from the size by adjusting the 
  1565.         // dyControls further.
  1566.         GetRealWindowInfo(_hwndOK, &rect, NULL);
  1567.         GetRealWindowInfo(_hwndFrame, &rect2, NULL);
  1568.         dyControls += rect.bottom - rect2.bottom;
  1569.     }
  1570.     // having performed that extra bit of initialization lets cache the
  1571.     // positions of the various controls, to make sizing more fun...
  1572.     GetClientRect(hwnd, &rect2);
  1573.     rect2.bottom -= dyControls;
  1574.     _dyResultsTop = rect2.bottom;    
  1575.     GetRealWindowInfo(hwnd, NULL, &size);
  1576.     GetRealWindowInfo(_hwndFrame, &rect, &_szForm);
  1577.     Trace(TEXT("dyControls %d"), dyControls);
  1578.     size.cy -= dyControls;
  1579.     _dxFormAreaLeft = rect.left;
  1580.     _dxFormAreaRight = rect2.right - rect.right;
  1581.     
  1582.     _szMinTrack.cx = size.cx - _szForm.cx;
  1583.     _szMinTrack.cy = size.cy - _szForm.cy;
  1584.     if ( !(_pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS) )
  1585.     {
  1586.         TraceMsg("Adjusting _szMinTrack.cy to account for menu bar");
  1587.         _szMinTrack.cy += GetSystemMetrics(SM_CYMENU);
  1588.     }
  1589.     
  1590.     GetRealWindowInfo(_hwndBrowse, &rect, NULL);
  1591.     _dxButtonsLeft = rect2.right - rect.left;
  1592.     GetRealWindowInfo(_hwndLookIn, &rect, NULL);
  1593.     _dxGap = (rect2.right - rect.right) - _dxButtonsLeft;
  1594.     GetRealWindowInfo(_hwndFindAnimation, &rect, NULL);
  1595.     _dxAnimationLeft = rect2.right - rect.left;
  1596.     GetRealWindowInfo(_hwndOK, &rect, NULL);
  1597.     _dyOKTop = rect2.bottom - rect.top;
  1598.     _dyGap = size.cy - rect.bottom;
  1599.     // Now collect the forms and pages, then walk them building the size
  1600.     // information that we need.
  1601.     hres = GatherForms();
  1602.     FailGracefully(hres, "Failed to init form list");
  1603.     _szMinTrack.cx += _szForm.cx;
  1604.     _szMinTrack.cy += _szForm.cy;
  1605.     // Populate the scope control by querying the handler for them,
  1606.     // if there are none then we display a suitable message box and
  1607.     // let the user know that something went wrong.
  1608.     hres = PopulateScopeControl();
  1609.     FailGracefully(hres, "Failed to init scope list");
  1610.     _fScopesPopulated = TRUE;                              // scope control now populated
  1611.     // perform final fix up of the window, ensure that we size it so that
  1612.     // the entire form and buttons are visible.  Then set ourselves into the
  1613.     // no query state and reset the animation.
  1614.     SetWindowPos(hwnd, 
  1615.                  NULL,
  1616.                  0, 0,
  1617.                  _szMinTrack.cx, _szMinTrack.cy,
  1618.                  SWP_NOMOVE|SWP_NOZORDER);
  1619.     if ( _pOpenQueryWnd->dwFlags & OQWF_HIDEMENUS )
  1620.         ::SetMenu(hwnd, NULL);
  1621.     hres = PopulateFormControl(_pOpenQueryWnd->dwFlags & OQWF_SHOWOPTIONAL);
  1622.     FailGracefully(hres, "Failed to populate form control");
  1623.     // Now load the query which inturn selects the form that we should be using,
  1624.     // if there is no query to load then either use the default form or
  1625.     // the first in the list.
  1626.     if ( (_pOpenQueryWnd->dwFlags & OQWF_LOADQUERY) && _pOpenQueryWnd->pPersistQuery ) 
  1627.     {
  1628.         hres = LoadQuery(_pOpenQueryWnd->pPersistQuery);
  1629.         FailGracefully(hres, "Failed when to load query from supplied IPersistQuery");
  1630.     }
  1631.     else
  1632.     {
  1633.         if ( _pOpenQueryWnd->dwFlags & OQWF_DEFAULTFORM )
  1634.         {
  1635.             SelectForm(_pOpenQueryWnd->clsidDefaultForm);
  1636.             if ( !_pCurrentForm )
  1637.                 ExitGracefully(hres, E_FAIL, "Failed to select the query form");                
  1638.         }
  1639.         else
  1640.         {
  1641.             INT iForm = (int)ComboBox_GetItemData(_hwndLookFor, 0);
  1642.             LPQUERYFORM pQueryForm = (LPQUERYFORM)DSA_GetItemPtr(_hdsaForms, iForm);
  1643.             TraceAssert(pQueryForm);
  1644.             SelectForm(pQueryForm->clsidForm);
  1645.         }
  1646.     }
  1647.     StartQuery(FALSE);
  1648.     
  1649.     if ( _pCurrentFormPage )
  1650.     {
  1651.         Trace(TEXT("Setting focus to the form page (%08x)"), _pCurrentFormPage->hwndPage);
  1652.         SetFocus(_pCurrentFormPage->hwndPage);
  1653.     }
  1654. #if HIDE_SEARCH_PANE
  1655.     // If we need to be issuing the query on open then lets ensure that
  1656.     // we have some scopes, if we do then we can just post ourselves a
  1657.     // WM_COMMAND with the relevant ID (IDC_FINDNOW).
  1658.     if ( _pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN ) 
  1659.     {
  1660.         if ( _pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHPANE )
  1661.             HideSearchPane(TRUE);
  1662.         PostMessage(_hwnd, CQFWM_STARTQUERY, 0, 0);
  1663.     }
  1664. #else
  1665.     // issue on open, therefore lets get the query going, if there is async
  1666.     // scope collection then the query will be issued by the bg thread.
  1667.     if ( _pOpenQueryWnd->dwFlags & OQWF_ISSUEONOPEN )
  1668.         PostMessage(_hwnd, CQFWM_STARTQUERY, 0, 0);
  1669. #endif
  1670.     SetForegroundWindow(hwnd);
  1671.     hres = S_OK;                          // success
  1672. exit_gracefully:
  1673.     TraceLeaveResult(hres);
  1674. }
  1675. /*-----------------------------------------------------------------------------
  1676. / CQueryFrame::EnableControls
  1677. / ---------------------------
  1678. /   Set the controls into their enabled/disabled state based on the
  1679. /   state of the dialog.
  1680. /
  1681. / In:
  1682. /   -
  1683. /
  1684. / Out:
  1685. /   HRESULT
  1686. /----------------------------------------------------------------------------*/
  1687. VOID CQueryFrame::DoEnableControls(VOID)
  1688. {   
  1689.     BOOL fScopes = (_fAddScopesNYI || ComboBox_GetCount(_hwndLookIn));
  1690. #if HIDE_SEARCH_PANE
  1691.     BOOL fEnable = fScopes && !_fHideSearchPane;
  1692. #else
  1693.     BOOL fEnable = fScopes;
  1694. #endif
  1695.     UINT uEnable = fScopes ? MF_ENABLED:MF_GRAYED;
  1696.     HMENU hMenu = GetMenu(_hwnd);
  1697.     INT i;
  1698.     TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::DoEnableControls");
  1699.     EnableWindow(_hwndFindNow, !_fQueryRunning && fEnable);
  1700.     EnableWindow(_hwndStop, _fQueryRunning && fEnable);
  1701.     EnableWindow(_hwndNewQuery, fEnable);
  1702.     EnableWindow(_hwndLookFor, !_fQueryRunning && fEnable);
  1703.     EnableWindow(_hwndLookIn, !_fQueryRunning && fEnable);
  1704.     EnableWindow(_hwndBrowse, !_fQueryRunning && fEnable);
  1705.     if ( _pCurrentForm )
  1706.         CallFormPages(_pCurrentForm, CALLFORMPAGES_ALL, CQPM_ENABLE, (BOOL)(!_fQueryRunning && fEnable), 0);
  1707.     if ( _hwndOK )
  1708.         EnableWindow(_hwndOK, !_fQueryRunning && fEnable);
  1709.     if ( _hwndCancel )
  1710.         EnableWindow(_hwndCancel, !_fQueryRunning && fEnable);
  1711.     for ( i = 0 ; i < GetMenuItemCount(hMenu) ; i++ )
  1712.         EnableMenuItem(hMenu, i, MF_BYPOSITION|uEnable);
  1713.     DrawMenuBar(_hwnd);
  1714.     TraceLeave();
  1715. }
  1716. /*-----------------------------------------------------------------------------
  1717. / CQueryFrame::OnNotify
  1718. / ---------------------
  1719. /   Notify event received, decode it and handle accordingly
  1720. /
  1721. / In:
  1722. /   idCtrl = ID of control issuing notify
  1723. /   pNotify -> LPNMHDR structure
  1724. /
  1725. / Out:
  1726. /   LRESULT
  1727. /----------------------------------------------------------------------------*/
  1728. LRESULT CQueryFrame::OnNotify(INT idCtrl, LPNMHDR pNotify)
  1729. {
  1730.     LRESULT lr = 0;
  1731.     TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnNotify");
  1732.     // TCN_SELCHANGE used to indicate that the currently active
  1733.     // tab has been changed
  1734.     if ( pNotify->code == TCN_SELCHANGE )
  1735.     {
  1736.         INT iPage = TabCtrl_GetCurSel(_hwndFrame);
  1737.         TraceAssert(iPage >= 0);
  1738.         if ( iPage >= 0 )
  1739.         {
  1740.             SelectFormPage(_pCurrentForm, iPage);
  1741.             lr = 0;
  1742.         }
  1743.     }
  1744.     TraceLeaveResult((HRESULT)lr);
  1745. }
  1746. /*-----------------------------------------------------------------------------
  1747. / CQueryFrame::OnSize
  1748. / -------------------
  1749. /   The window is being sized and we received a WM_SIZE, therefore move 
  1750. /   the content of the window about.
  1751. /
  1752. / In:
  1753. /   cx = new width
  1754. /   cy = new height
  1755. /
  1756. / Out:
  1757. /   -
  1758. /----------------------------------------------------------------------------*/
  1759. VOID CQueryFrame::OnSize(INT cx, INT cy)
  1760. {
  1761.     HDWP hdwp;
  1762.     RECT rect, rect2;
  1763.     SIZE sz, sz2;
  1764.     INT x, cxForm, cyForm;
  1765.     INT dyResultsTop = 0;
  1766.     TraceEnter(TRACE_FRAMEDLG, "CQueryFrame::OnSize");
  1767.     // do as much as we can within a DefWindowPos to aVOID too
  1768.     // much flicker.
  1769.     hdwp = BeginDeferWindowPos(16);
  1770.     if ( hdwp )
  1771.     {
  1772.         {
  1773.             // adjust the look for controls, if there is no scope then 
  1774.             // stretch the look for control over the entire client area
  1775.             // of the window.
  1776.             if ( !(_pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS) )
  1777.             {
  1778.                 if ( _pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES )
  1779.                 {
  1780.                     GetRealWindowInfo(_hwndLookFor, &rect, &sz);
  1781.                     hdwp = DeferWindowPos(hdwp, _hwndLookFor, NULL,
  1782.                                        0, 0, 
  1783.                                        (cx - _dxFormAreaRight) - rect.left, sz.cy,
  1784.                                        SWP_NOZORDER|SWP_NOMOVE);
  1785.                 }
  1786.             }
  1787.             // adjust the "look in" controls, if there is a form control
  1788.             // then stretch across the remaining space, otherwise move the
  1789.             // label and stretch the scope over the remaining space.
  1790.         
  1791.             if ( !(_pOpenQueryWnd->dwFlags & OQWF_REMOVESCOPES) )
  1792.             {
  1793.                 INT xScopeRight;
  1794.                 GetRealWindowInfo(_hwndLookIn, &rect, &sz);
  1795.                 xScopeRight = cx - _dxFormAreaRight - _dxGap;
  1796.                              
  1797.                 if ( _pOpenQueryWnd->dwFlags & OQWF_HIDESEARCHUI )
  1798.                 {
  1799.                     // 
  1800.                     // when hiding the search UI, then adjust the button position to account for the
  1801.                     // right edge of the dialog not having buttons.
  1802.                     //
  1803.                     xScopeRight -= (_dxButtonsLeft - _dxFormAreaRight) + _dxGap;
  1804.                 }
  1805.                 
  1806.                 if ( _pOpenQueryWnd->dwFlags & OQWF_REMOVEFORMS )
  1807.                 {
  1808.                     GetRealWindowInfo(_hwndLookInLabel, &rect2, &sz2);
  1809.                     hdwp = DeferWindowPos(hdwp, _hwndLookInLabel, NULL,
  1810.                                           _dxFormAreaLeft, rect2.top, 
  1811.                                           0, 0,
  1812.                                           SWP_NOSIZE|SWP_NOZORDER);
  1813.                     hdwp = DeferWindowPos(hdwp, _hwndLookIn, NULL,