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.

2937 lines
76 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. QueryDB_UI.cpp
  5. Abstract:
  6. GUI for the Query Databases option
  7. Author:
  8. kinshu created October 12, 2001
  9. Notes:
  10. The query dialog box performs two types of searches. One is when it actually makes a SQL
  11. query and passes it to the SQL driver and shows the results in the result list view.
  12. The lParam of the list view then are pointers to RESULT_ITEM objects. (1,2,4) tab pages
  13. Second is the case when we are doing a query for some shims, like show all the shims that have 'x'
  14. in their desc. text. (3rd tab page). In this case the query is not passed to the sql driver
  15. and we do the query on our own. The SQL driver can execute queries where the result is some
  16. fixed program entry (and the database that it lives in, please see RESULT_ITEM).
  17. In this case the lparam of the list view is pointers to the individual shims in the system database
  18. We do not free anything from the lParam of the list view. In the case when the query is of type
  19. 1 as mentioned above, the RESULT_ITEM are freed when we close the Statement.
  20. In case of queries of type 2, the shims themseleves should not be freed, they belong to the database
  21. they live in (The system database).
  22. --*/
  23. #include "precomp.h"
  24. //////////////////////// Defines ///////////////////////////////////////////////
  25. // Number of pages in the tab
  26. #define PAGE_COUNT 4
  27. // ID for the first tab page
  28. #define QDB_PAGE1 0
  29. // ID for the second tab page
  30. #define QDB_PAGE2 1
  31. // ID for the third tab page
  32. #define QDB_PAGE3 2
  33. // ID for the fourth tab page
  34. #define QDB_PAGE4 3
  35. // We want to search all the databases
  36. #define DATABASE_ALL 0
  37. // Indexes into DatabasesMapping
  38. #define IND_SYSTDB 0
  39. #define IND_INSTDB 1
  40. #define IND_CUSTDB 2
  41. // Maximum for the progress bar
  42. #define MAX_PROGRESS 2000
  43. //
  44. // Maximum buffer size to be allocated for the string that will store
  45. // search string in the third wizard page, where the user tries to search for
  46. // fixes that have specific words in their description text
  47. #define MAX_FIXDESC_SEARCH 1024
  48. // Maximum number fof tchars that can come in the SELECT clause.
  49. #define MAX_SELECT 512
  50. // Maximum number fof tchars that can come in the WHERE clause.
  51. #define MAX_WHERE 1022
  52. // Width of a column in the result list view when searching for entries
  53. #define COLUMN_WIDTH 20
  54. ///////////////////////////////////////////////////////////////////////////////
  55. //////////////////////// Externs //////////////////////////////////////////////
  56. extern HWND g_hwndEntryTree;
  57. extern HINSTANCE g_hInstance;
  58. extern BOOL g_bSomeWizardActive;
  59. extern struct _tagAttributeShowMapping AttributeShowMapping[];
  60. extern struct _tagAttributeMatchMapping AttributeMatchMapping[];
  61. extern struct _tagDatabasesMapping DatabasesMapping[3];
  62. ///////////////////////////////////////////////////////////////////////////////
  63. //////////////////////// Global Variables /////////////////////////////////////
  64. // The statement
  65. Statement stmt;
  66. // The width of the query db Dialog
  67. int g_cWidthQuery = 0;
  68. // The height of the query db Dialog
  69. int g_cHeightQuery = 0;
  70. // The handle to the main dialog
  71. HWND g_hdlgQueryDB;
  72. // The type of search we did last time
  73. INT g_iLastSearchType;
  74. // The bit array that describes what columns are sorted in what manner
  75. static LONG s_lColumnSort;
  76. // Do we have a empty column header that we have to remove
  77. static BOOL s_bEmptyHeader = TRUE;
  78. // The thread that performs the query
  79. static HANDLE s_hThread;
  80. // The handle to the wait window. This window will pop up if we are trying to close the
  81. // qdb window when the thread is busy.
  82. static HWND s_hWaitDialog;
  83. // Code for any error that occur while collecting info from the GUI.
  84. // If this is non-zero then we display some error and SQL query is not executed
  85. static INT s_iErrorCode;
  86. ///////////////////////////////////////////////////////////////////////////////
  87. //////////////////////// Typedefs/Enums ///////////////////////////////////////
  88. typedef enum {
  89. QDB_SEARCH_ANYWORD = 0,
  90. QDB_SEARCH_ALLWORDS = 1
  91. } QDB_SEARCH_TYPE;
  92. typedef struct _tagDialogData
  93. {
  94. HANDLE hMainThread;
  95. HWND hdlg;
  96. }DIALOG_DATA;
  97. typedef struct tag_dlghdr {
  98. HWND hwndTab; // tab control
  99. HWND hwndPages[PAGE_COUNT];
  100. INT iPresentTabIndex;
  101. RECT rcDisplay;
  102. tag_dlghdr()
  103. {
  104. ZeroMemory(hwndPages, sizeof(hwndPages));
  105. iPresentTabIndex = -1;
  106. }
  107. } DLGHDR;
  108. ///////////////////////////////////////////////////////////////////////////////
  109. //////////////////////// Function Declarations ////////////////////////////////
  110. INT_PTR CALLBACK
  111. QdbWaitDlg(
  112. HWND hdlg,
  113. UINT uMsg,
  114. WPARAM wParam,
  115. LPARAM lParam
  116. );
  117. void
  118. GotoQdbEntry(
  119. HWND hdlg,
  120. LPARAM lParam
  121. );
  122. void
  123. SaveResultsQdb(
  124. HWND hdlg
  125. );
  126. void
  127. DoNewQdb(
  128. HWND hdlg
  129. );
  130. void
  131. OnSearch(
  132. HWND hdlg
  133. );
  134. void
  135. HandleQueryDBSizing(
  136. HWND hDlg
  137. );
  138. void
  139. Start(
  140. HWND hdlg
  141. );
  142. void
  143. HandleListNotification(
  144. HWND hdlg,
  145. LPARAM lParam
  146. );
  147. DWORD WINAPI
  148. QueryDBThread(
  149. LPVOID pVoid
  150. );
  151. VOID
  152. WINAPI
  153. OnChildDialogInit(
  154. HWND hwndDlg
  155. );
  156. VOID
  157. WINAPI
  158. OnChildDialogInit(
  159. HWND hwndDlg
  160. );
  161. VOID
  162. WINAPI
  163. OnSelChanged(
  164. HWND hwndDlg
  165. );
  166. INT_PTR
  167. CALLBACK
  168. SearchOnAppDlgProc(
  169. HWND hdlg,
  170. UINT uMsg,
  171. WPARAM wParam,
  172. LPARAM lParam
  173. );
  174. INT_PTR CALLBACK
  175. SearchOnFixDlgProc(
  176. HWND hdlg,
  177. UINT uMsg,
  178. WPARAM wParam,
  179. LPARAM lParam);
  180. INT_PTR
  181. CALLBACK
  182. AdvancedSearchDlgProc(
  183. HWND hdlg,
  184. UINT uMsg,
  185. WPARAM wParam,
  186. LPARAM lParam
  187. );
  188. INT_PTR
  189. CALLBACK
  190. SearchFixDescDlgProc(
  191. HWND hdlg,
  192. UINT uMsg,
  193. WPARAM wParam,
  194. LPARAM lParam
  195. );
  196. void
  197. HandleTabNotification(
  198. HWND hdlg,
  199. LPARAM lParam
  200. );
  201. void
  202. HandleAdvancedListNotification(
  203. HWND hdlg,
  204. LPARAM lParam
  205. );
  206. void
  207. DeleteAll(
  208. HWND hdlg
  209. );
  210. ///////////////////////////////////////////////////////////////////////////////
  211. void
  212. LoadDatabaseTypes(
  213. IN HWND hdlg
  214. )
  215. /*++
  216. LoadDatabaseTypes
  217. Desc: Loads the database types in the combo box
  218. Params:
  219. IN HWND hdlg: The query dialog box
  220. Return:
  221. void
  222. --*/
  223. {
  224. HWND hwndCombo = GetDlgItem(hdlg, IDC_COMBO);
  225. //
  226. // All databases
  227. //
  228. INT iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_ALLDATABASES));
  229. SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_ALL);
  230. //
  231. // System database
  232. //
  233. iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_SYSDB));
  234. SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_TYPE_GLOBAL);
  235. //
  236. // Installed databases
  237. //
  238. iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_INSTALLEDDB));
  239. SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_TYPE_INSTALLED);
  240. //
  241. // Custom databases
  242. //
  243. iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_WORKDB));
  244. SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_TYPE_WORKING);
  245. //
  246. // Select the first string
  247. //
  248. SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
  249. }
  250. INT_PTR CALLBACK
  251. QueryDBDlg(
  252. IN HWND hdlg,
  253. IN UINT uMsg,
  254. IN WPARAM wParam,
  255. IN LPARAM lParam
  256. )
  257. /*++
  258. QueryDBDlg
  259. Desc: Dialog Proc for the main Query database dialog.
  260. Params: Standard dialog handler parameters
  261. IN HWND hDlg
  262. IN UINT uMsg
  263. IN WPARAM wParam
  264. IN LPARAM lParam
  265. Return: Standard dialog handler return
  266. --*/
  267. {
  268. int wCode = LOWORD(wParam);
  269. int wNotifyCode = HIWORD(wParam);
  270. switch (uMsg) {
  271. case WM_INITDIALOG:
  272. {
  273. DLGHDR* pHdr = NULL;
  274. TCITEM tie;
  275. RECT r;
  276. //
  277. // Limit the text field for the hidden text box. Please note that
  278. // we will concatenate the results of the select and the where text fields
  279. // and put the actual SQL in the form of 'SELECT .. FROM .. [WHERE ..]' in this
  280. // text field
  281. //
  282. SendMessage(GetDlgItem(hdlg, IDC_SQL),
  283. EM_LIMITTEXT,
  284. (WPARAM)MAX_SQL_LENGTH - 1,
  285. (LPARAM)0);
  286. g_hdlgQueryDB = hdlg;
  287. s_lColumnSort = 0;
  288. ListView_SetExtendedListViewStyleEx(GetDlgItem(hdlg, IDC_LIST),
  289. 0,
  290. LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
  291. SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), TEXT(""));
  292. LoadDatabaseTypes(hdlg);
  293. Animate_OpenEx(GetDlgItem(hdlg, IDC_ANIMATE),
  294. g_hInstance,
  295. MAKEINTRESOURCE(IDA_SEARCH));
  296. //
  297. // Set up the tab control
  298. //
  299. pHdr = new DLGHDR;
  300. if (pHdr == NULL) {
  301. MEM_ERR;
  302. break;
  303. }
  304. pHdr->hwndTab = GetDlgItem(hdlg, IDC_TAB);
  305. GetWindowRect(pHdr->hwndTab, &pHdr->rcDisplay);
  306. SendMessage(pHdr->hwndTab, WM_SETREDRAW, TRUE, 0);
  307. SetWindowLongPtr(hdlg, GWLP_USERDATA, (LONG_PTR)pHdr);
  308. ZeroMemory(&tie, sizeof(tie));
  309. tie.mask = TCIF_TEXT;
  310. tie.pszText = GetString(IDS_APP_PROPERTIES);
  311. TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE1, &tie);
  312. tie.pszText = GetString(IDS_FIX_PROPERTIES);
  313. TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE2, &tie);
  314. tie.pszText = GetString(IDS_ADVANCED);
  315. TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE4, &tie);
  316. tie.pszText = GetString(IDS_FIX_DESCRIPTION);
  317. TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE3, &tie);
  318. //
  319. // The page where we select apps by name
  320. //
  321. pHdr->hwndPages[QDB_PAGE1] = CreateDialog(g_hInstance,
  322. MAKEINTRESOURCE(IDD_QDB_PAGE1),
  323. hdlg,
  324. SearchOnAppDlgProc);
  325. //
  326. // The page where we select apps by the fixes applied
  327. //
  328. pHdr->hwndPages[QDB_PAGE2] = CreateDialog(g_hInstance,
  329. MAKEINTRESOURCE(IDD_QDB_PAGE2),
  330. hdlg,
  331. SearchOnFixDlgProc);
  332. //
  333. // The page where we search by the words in the descriptipon of the fix or in the name
  334. //
  335. pHdr->hwndPages[QDB_PAGE3] = CreateDialog(g_hInstance,
  336. MAKEINTRESOURCE(IDD_QDB_PAGE3),
  337. hdlg,
  338. SearchFixDescDlgProc);
  339. //
  340. // The advanced page
  341. //
  342. pHdr->hwndPages[QDB_PAGE4] = CreateDialog(g_hInstance,
  343. MAKEINTRESOURCE(IDD_QDB_PAGE4),
  344. hdlg,
  345. AdvancedSearchDlgProc);
  346. //
  347. // Set the background properly and position the pages in the tab control
  348. //
  349. OnChildDialogInit(pHdr->hwndPages[QDB_PAGE1]);
  350. OnChildDialogInit(pHdr->hwndPages[QDB_PAGE2]);
  351. OnChildDialogInit(pHdr->hwndPages[QDB_PAGE3]);
  352. OnChildDialogInit(pHdr->hwndPages[QDB_PAGE4]);
  353. //
  354. // Select the first page
  355. //
  356. OnSelChanged(hdlg);
  357. //
  358. // Get the height and width so that we can properly resize the dialog box
  359. //
  360. GetWindowRect(hdlg, &r);
  361. g_cWidthQuery = r.right - r.left;
  362. g_cHeightQuery = r.bottom - r.top;
  363. InsertColumnIntoListView(GetDlgItem(hdlg, IDC_LIST), TEXT(""), 0, 100);
  364. s_bEmptyHeader = TRUE;
  365. break;
  366. }
  367. case WM_GETMINMAXINFO:
  368. {
  369. //
  370. // Limit the min width and height of the dialog box
  371. //
  372. MINMAXINFO* pmmi = (MINMAXINFO*)lParam;
  373. pmmi->ptMinTrackSize.x = 550;
  374. pmmi->ptMinTrackSize.y = 365;
  375. return 0;
  376. break;
  377. }
  378. case WM_SIZE:
  379. if (wParam != SIZE_MINIMIZED) {
  380. HandleQueryDBSizing(hdlg);
  381. }
  382. break;
  383. case WM_COMMAND:
  384. {
  385. switch (wCode) {
  386. case ID_SEARCH:
  387. {
  388. DLGHDR* pHdr = (DLGHDR*)GetWindowLongPtr(g_hdlgQueryDB, GWLP_USERDATA);
  389. HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
  390. if (pHdr == NULL) {
  391. assert(FALSE);
  392. break;
  393. }
  394. g_iLastSearchType = pHdr->iPresentTabIndex;
  395. //
  396. // When the user will click on some column for the first time, we will now
  397. // sort that in ascending order
  398. //
  399. s_lColumnSort = -1;
  400. if (GetFocus() == hwndList
  401. && ListView_GetNextItem(hwndList, -1, LVNI_SELECTED) != -1) {
  402. //
  403. // We will get this message when we press enter in the list box,
  404. // as ID_SEARCH is the default button.
  405. // So in this case we have to pretend as the user double clicked in the list
  406. // view
  407. //
  408. SendNotifyMessage(hdlg, WM_COMMAND, (WPARAM)ID_VIEWCONTENTS, 0);
  409. } else if (pHdr->iPresentTabIndex == QDB_PAGE3) {
  410. //
  411. // We are trying to do a search on fix description
  412. //
  413. SendMessage(pHdr->hwndPages[QDB_PAGE3], WM_USER_DOTHESEARCH, 0, 0);
  414. } else {
  415. //
  416. // Normal SQL query
  417. //
  418. OnSearch(hdlg);
  419. }
  420. }
  421. break;
  422. case ID_VIEWCONTENTS:
  423. {
  424. //
  425. // The user wishes to see the contents. We must now find and select
  426. // the correct entry in the db tree and the entry tree
  427. //
  428. HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
  429. INT iSelection = ListView_GetSelectionMark(hwndList);
  430. if (iSelection == -1) {
  431. break;
  432. }
  433. LVITEM lvi;
  434. PMATCHEDENTRY pmMatched;
  435. ZeroMemory(&lvi, sizeof(lvi));
  436. lvi.iItem = iSelection;
  437. lvi.iSubItem = 0;
  438. lvi.mask = LVIF_PARAM;
  439. if (ListView_GetItem(hwndList, &lvi)) {
  440. GotoQdbEntry(hdlg, lvi.lParam);
  441. }
  442. break;
  443. }
  444. case IDCANCEL:
  445. if (s_hThread) {
  446. //
  447. // Need to wait for thread to terminate if it is running
  448. //
  449. if (!s_hWaitDialog) {
  450. s_hWaitDialog = CreateDialog(g_hInstance,
  451. MAKEINTRESOURCE(IDD_QDBWAIT),
  452. g_hdlgQueryDB,
  453. QdbWaitDlg);
  454. ShowWindow(s_hWaitDialog, SW_NORMAL);
  455. }
  456. break;
  457. }
  458. Animate_Close(GetDlgItem(hdlg, IDC_ANIMATE));
  459. stmt.Close();
  460. DestroyWindow(hdlg);
  461. break;
  462. case IDC_NEWSEARCH:
  463. DoNewQdb(hdlg);
  464. break;
  465. case IDC_SAVE:
  466. SaveResultsQdb(hdlg);
  467. break;
  468. case ID_QDB_HELP:
  469. ShowInlineHelp(TEXT("using_the_query_tool.htm"));
  470. break;
  471. default:
  472. return FALSE;
  473. }
  474. }
  475. break;
  476. case WM_DESTROY:
  477. {
  478. DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
  479. //
  480. // Destroy the individual modeless dialog boxes
  481. //
  482. DestroyWindow(pHdr->hwndPages[QDB_PAGE1]);
  483. DestroyWindow(pHdr->hwndPages[QDB_PAGE2]);
  484. DestroyWindow(pHdr->hwndPages[QDB_PAGE3]);
  485. DestroyWindow(pHdr->hwndPages[QDB_PAGE4]);
  486. if (pHdr) {
  487. delete pHdr;
  488. pHdr = NULL;
  489. }
  490. stmt.Close();
  491. g_hdlgQueryDB = NULL;
  492. PostMessage(g_hDlg, WM_USER_ACTIVATE, 0, 0);
  493. break;
  494. }
  495. case WM_NOTIFY:
  496. {
  497. LPNMHDR lpnmhdr = (LPNMHDR)lParam;
  498. if (lpnmhdr && lpnmhdr->idFrom == IDC_LIST) {
  499. HandleListNotification(hdlg, lParam);
  500. } else if (lpnmhdr && lpnmhdr->idFrom == IDC_TAB) {
  501. HandleTabNotification(hdlg, lParam);
  502. }
  503. break;
  504. }
  505. default: return FALSE;
  506. }
  507. return TRUE;
  508. }
  509. void
  510. Start(
  511. IN HWND hdlg
  512. )
  513. /*++
  514. Start
  515. Desc: Creates the thread that will do the actual search.
  516. Params:
  517. IN HWND hdlg: Handle to the query dialog box.
  518. Return:
  519. void
  520. --*/
  521. {
  522. DWORD dwID; // Will contain the thread id.
  523. ENABLEWINDOW(GetDlgItem(hdlg, ID_SEARCH), FALSE);
  524. ENABLEWINDOW(GetDlgItem(hdlg, IDC_NEWSEARCH), FALSE);
  525. ENABLEWINDOW(GetDlgItem(hdlg, IDC_SAVE), FALSE);
  526. ENABLEWINDOW(GetDlgItem(hdlg, IDC_STATIC_CAPTION), FALSE);
  527. SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), TEXT(""));
  528. s_hThread = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START)QueryDBThread, (PVOID)hdlg, 0, (unsigned int*)&dwID);
  529. }
  530. DWORD WINAPI
  531. QueryDBThread(
  532. IN LPVOID pVoid
  533. )
  534. /*++
  535. QueryDBThread
  536. Desc: The thread routine that does the actual search
  537. Params:
  538. IN LPVOID pVoid: The handle to the query dialog
  539. Return:
  540. 0
  541. --*/
  542. {
  543. HWND hdlg = (HWND)pVoid;
  544. CSTRING strStatus;
  545. TCHAR szBuffer[32];
  546. INT iTotalResults;
  547. ResultSet* prs = NULL;
  548. static TCHAR s_szSQL[MAX_SQL_LENGTH] = TEXT("");
  549. GetWindowText(GetDlgItem(hdlg, IDC_SQL), s_szSQL, ARRAYSIZE(s_szSQL) - 1);
  550. s_szSQL[ARRAYSIZE(s_szSQL) - 1] = 0;
  551. if (CSTRING::Trim(s_szSQL) == 0) {
  552. MessageBox(hdlg,
  553. GetString(IDS_ERROR_SELECT_NOTFOUND),
  554. g_szAppName,
  555. MB_ICONERROR);
  556. goto End;
  557. }
  558. Animate_Play(GetDlgItem(hdlg, IDC_ANIMATE), 0, -1, -1);
  559. //
  560. // We do not want the user to make changes in the databases, when we are running the
  561. // query.
  562. //
  563. ENABLEWINDOW(g_hDlg, FALSE);
  564. prs = stmt.ExecuteSQL(hdlg, s_szSQL);
  565. //
  566. // Do not forget to enable the main window again
  567. //
  568. ENABLEWINDOW(g_hDlg, TRUE);
  569. //
  570. // Now first of all add the columns to the listview
  571. //
  572. PNODELIST pShowList = stmt.GetShowList();
  573. if (pShowList == NULL) {
  574. goto End;
  575. }
  576. UINT uCols = pShowList->m_uCount;
  577. HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
  578. TCHAR szColumnName[64];
  579. PNODE pNodeShow = pShowList->m_pHead;
  580. if (pNodeShow) {
  581. //
  582. // If the empty header is still there, must get rid of it.
  583. //
  584. if (s_bEmptyHeader) {
  585. ListView_DeleteColumn(hwndList, 0);
  586. s_bEmptyHeader = FALSE;
  587. }
  588. }
  589. INT iIndex = 0;
  590. //
  591. // Add all the columns for the clauses in SELECT in the list view
  592. //
  593. while (pNodeShow) {
  594. *szColumnName = 0;
  595. InsertColumnIntoListView(hwndList,
  596. pNodeShow->ToString(szColumnName, ARRAYSIZE(szColumnName)),
  597. iIndex, COLUMN_WIDTH);
  598. pNodeShow = pNodeShow->pNext;
  599. ++iIndex;
  600. }
  601. LVITEM lvi;
  602. TCHAR szString[MAX_PATH];
  603. int iIndexDesired = 0;
  604. ZeroMemory(&lvi, sizeof(lvi));
  605. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  606. if (uCols > 0) {
  607. while (prs && prs->GetNext()) {
  608. PNODE pNodeRow = new NODE[uCols];
  609. if (pNodeRow == NULL) {
  610. MEM_ERR;
  611. goto End;
  612. }
  613. //
  614. // Create the new list view item for this row of results
  615. //
  616. prs->GetCurrentRow(pNodeRow);
  617. *szString = 0;
  618. lvi.pszText = pNodeRow[0].ToString(szString, ARRAYSIZE(szString));
  619. lvi.iSubItem = 0;
  620. lvi.lParam = (LPARAM)prs->GetCursor();
  621. lvi.iItem = iIndexDesired;
  622. INT iRowIndex = ListView_InsertItem(hwndList, &lvi);
  623. //
  624. // Put values for all other sub-columns
  625. //
  626. for (UINT iColIndex = 1; iColIndex < uCols; ++iColIndex) {
  627. *szString = 0;
  628. pNodeRow[iColIndex].ToString(szString, ARRAYSIZE(szString));
  629. ListView_SetItemText(hwndList, iRowIndex, iColIndex, szString);
  630. }
  631. iIndexDesired++;
  632. if (pNodeRow) {
  633. delete[] pNodeRow;
  634. pNodeRow = NULL;
  635. }
  636. }
  637. }
  638. End:
  639. ENABLEWINDOW(GetDlgItem(hdlg, ID_SEARCH), TRUE);
  640. ENABLEWINDOW(GetDlgItem(hdlg, IDC_NEWSEARCH), TRUE);
  641. ENABLEWINDOW(GetDlgItem(hdlg, IDC_SAVE), TRUE);
  642. iTotalResults = (prs) ? prs->GetCount() : 0;
  643. *szBuffer = 0;
  644. strStatus.Sprintf(GetString(IDS_QDB_COUNT),
  645. _itot(iTotalResults,
  646. szBuffer,
  647. 10));
  648. SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), strStatus);
  649. //
  650. // Stop the animation.
  651. //
  652. Animate_Stop(GetDlgItem(hdlg, IDC_ANIMATE));
  653. CloseHandle(s_hThread);
  654. s_hThread = NULL;
  655. ENABLEWINDOW(GetDlgItem(hdlg, IDC_STATIC_CAPTION), iTotalResults > 0);
  656. SetActiveWindow(g_hdlgQueryDB);
  657. SetFocus(g_hdlgQueryDB);
  658. return 0;
  659. }
  660. void
  661. ProcessItemChanged(
  662. IN HWND hdlg,
  663. IN LPARAM lParam
  664. )
  665. /*++
  666. ProcessItemChange
  667. Desc: Processes the LVN_ITEMCHANGED message for the search list
  668. Please note that we process this message only when we did a shim search
  669. Params:
  670. IN HWND hdlg: The query dialog box
  671. IN LPARAM lParam: The lParam that comes with WM_NOTIFY
  672. --*/
  673. {
  674. LVITEM lvItem;
  675. TYPE type;
  676. LPNMLISTVIEW pnmlv;
  677. CSTRING strDescription;
  678. HWND hwndList;
  679. HWND hwndFixDesc;
  680. DLGHDR* pHdr = NULL;
  681. //
  682. // If we have searched for shims last time then we must set the description text for the
  683. // shim in the description window of the shim search page
  684. //
  685. if (g_iLastSearchType != QDB_PAGE3) {
  686. goto End;
  687. }
  688. pHdr = (DLGHDR*)GetWindowLongPtr(g_hdlgQueryDB, GWLP_USERDATA);
  689. if (pHdr == NULL) {
  690. assert(FALSE);
  691. goto End;
  692. }
  693. hwndList = GetDlgItem(hdlg, IDC_LIST);
  694. hwndFixDesc = GetDlgItem(pHdr->hwndPages[QDB_PAGE3], IDC_DESC);
  695. pnmlv = (LPNMLISTVIEW)lParam;
  696. if (pnmlv && (pnmlv->uChanged & LVIF_STATE)) {
  697. //
  698. // State changed
  699. //
  700. if (pnmlv->uNewState & LVIS_SELECTED) {
  701. //
  702. // New item is selected
  703. //
  704. lvItem.mask = TVIF_PARAM;
  705. lvItem.iItem = pnmlv->iItem;
  706. lvItem.iSubItem = 0;
  707. if (!ListView_GetItem(hwndList, &lvItem)) {
  708. goto End;
  709. }
  710. type = ConvertLparam2Type(lvItem.lParam);
  711. if (type == FIX_FLAG || type == FIX_SHIM) {
  712. //
  713. // We only process this message when the item in the list view is shim or a flag
  714. //
  715. GetDescriptionString(lvItem.lParam,
  716. strDescription,
  717. NULL,
  718. NULL,
  719. NULL,
  720. hwndList,
  721. pnmlv->iItem);
  722. if (strDescription.Length() > 0) {
  723. //
  724. // For some fixes, we do not have a desc. but we did find one for the
  725. // presently selected fix
  726. //
  727. SetWindowText(hwndFixDesc, (LPCTSTR)strDescription);
  728. } else {
  729. //
  730. // No description is available for this fix
  731. //
  732. SetWindowText(hwndFixDesc, GetString(IDS_NO_DESC_AVAILABLE));
  733. }
  734. } else {
  735. assert(FALSE);
  736. }
  737. }
  738. }
  739. End: ;
  740. }
  741. void
  742. HandleListNotification(
  743. IN HWND hdlg,
  744. IN LPARAM lParam
  745. )
  746. /*++
  747. HandleListNotification
  748. Desc: Handles the notification messages for the search results list view
  749. Params:
  750. IN HWND hdlg: The query dialog box
  751. IN LPARAM lParam: The LPARAM of WM_NOTIFY
  752. Return:
  753. void
  754. --*/
  755. {
  756. HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
  757. LPNMHDR lpnmhdr = (LPNMHDR)lParam;
  758. if (lpnmhdr == NULL) {
  759. return;
  760. }
  761. switch (lpnmhdr->code) {
  762. case LVN_COLUMNCLICK:
  763. {
  764. LPNMLISTVIEW pnmlv = (LPNMLISTVIEW)lParam;
  765. COLSORT colSort;
  766. colSort.hwndList = hwndList;
  767. colSort.iCol = pnmlv->iSubItem;
  768. colSort.lSortColMask = s_lColumnSort;
  769. ListView_SortItemsEx(hwndList, CompareItemsEx, &colSort);
  770. if ((s_lColumnSort & 1L << colSort.iCol) == 0) {
  771. //
  772. // Was in ascending order
  773. //
  774. s_lColumnSort |= (1L << colSort.iCol);
  775. } else {
  776. s_lColumnSort &= (~(1L << colSort.iCol));
  777. }
  778. break;
  779. }
  780. case NM_DBLCLK:
  781. {
  782. LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
  783. LVITEM lvItem = {0};
  784. if (lpnmitem == NULL) {
  785. break;
  786. }
  787. lvItem.mask = TVIF_PARAM;
  788. lvItem.iItem = lpnmitem->iItem;
  789. lvItem.iSubItem = 0;
  790. if (!ListView_GetItem(hwndList, &lvItem)) {
  791. break;
  792. }
  793. GotoQdbEntry(hdlg, lvItem.lParam);
  794. break;
  795. }
  796. case LVN_ITEMCHANGED:
  797. ProcessItemChanged(hdlg, lParam);
  798. break;
  799. }
  800. }
  801. VOID WINAPI
  802. OnSelChanged(
  803. IN HWND hwndDlg
  804. )
  805. /*++
  806. OnSelChanged
  807. Desc: Handles the change of the tab. Hides the present tab and shows the
  808. next tab.
  809. Params:
  810. IN HWND hwndDlg: The query dialog box
  811. Return:
  812. void
  813. --*/
  814. {
  815. DLGHDR* pHdr = (DLGHDR*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
  816. if (pHdr == NULL || hwndDlg == NULL) {
  817. assert(FALSE);
  818. return;
  819. }
  820. int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
  821. HWND hwndCombo;
  822. hwndCombo = GetDlgItem(hwndDlg, IDC_COMBO);
  823. if (iSel != -1 && pHdr->iPresentTabIndex != -1) {
  824. ShowWindow(pHdr->hwndPages[pHdr->iPresentTabIndex], SW_HIDE);
  825. }
  826. pHdr->iPresentTabIndex = iSel;
  827. ShowWindow(pHdr->hwndPages[iSel], SW_SHOWNORMAL);
  828. //
  829. // Set the focus to the first child that has tab set
  830. //
  831. switch (iSel) {
  832. case QDB_PAGE1:
  833. ENABLEWINDOW(hwndCombo, TRUE);
  834. SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_APPNAME));
  835. break;
  836. case QDB_PAGE2:
  837. ENABLEWINDOW(hwndCombo, TRUE);
  838. SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_NAME));
  839. break;
  840. case QDB_PAGE3:
  841. ENABLEWINDOW(hwndCombo, FALSE);
  842. SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_TEXT));
  843. break;
  844. case QDB_PAGE4:
  845. ENABLEWINDOW(hwndCombo, TRUE);
  846. SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_SELECT));
  847. break;
  848. }
  849. }
  850. VOID
  851. WINAPI
  852. OnChildDialogInit(
  853. IN HWND hwndDlg
  854. )
  855. /*++
  856. OnChildDialogInit
  857. Desc: This routine is called when a page of the tab is first loaded.
  858. This routine sets the background properly for the tab
  859. and positions the page
  860. Params:
  861. IN HWND hwndDlg: The query dialog box
  862. Return:
  863. void
  864. --*/
  865. {
  866. HWND hwndParent = GetParent(hwndDlg);
  867. DLGHDR* pHdr = (DLGHDR*)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
  868. HWND hwndTab = pHdr->hwndTab;
  869. RECT rcTab;
  870. EnableTabBackground(hwndDlg);
  871. GetWindowRect(hwndTab, &rcTab);
  872. TabCtrl_AdjustRect(hwndTab, FALSE, &rcTab);
  873. MapWindowPoints(NULL, GetParent(hwndTab), (LPPOINT)&rcTab, 2);
  874. SetWindowPos(hwndDlg,
  875. HWND_TOP,
  876. rcTab.left,
  877. rcTab.top,
  878. rcTab.right - rcTab.left,
  879. rcTab.bottom - rcTab.top,
  880. SWP_HIDEWINDOW);
  881. return;
  882. }
  883. void
  884. SearchOnAppOnGetSql(
  885. IN HWND hdlg,
  886. IN WPARAM wParam,
  887. IN OUT LPARAM lParam
  888. )
  889. /*++
  890. SearchOnAppOnGetUserSql
  891. Desc: Processes the WM_USER_GETSQL for the first tab page
  892. Params:
  893. IN HWND hdlg: The handle to the First page of the tab
  894. IN WPARAM wParam: The length of the string buffer that is in lParam. The length is in
  895. TCHARs
  896. IN OUT LPARAM lParam: The pointer to the string. This will contain the "FROM" clause.
  897. The completed SQL will be returned in this.
  898. Return:
  899. void
  900. --*/
  901. {
  902. TCHAR szFrom[260];
  903. TCHAR szAppName[260];
  904. TCHAR szEntryName[MAX_PATH];
  905. CSTRING strSelectClauses;
  906. CSTRING strWhereClauses;
  907. TCHAR* pszSQL = (TCHAR*)lParam;
  908. BOOL bPreFixAdded = FALSE; // Whether we have added the 'AND (' prefix for this part of the SQL
  909. if (pszSQL == NULL) {
  910. assert(FALSE);
  911. return;
  912. }
  913. //
  914. // Set the attributes that we are always going to show
  915. //
  916. strSelectClauses = TEXT("APP_NAME, PROGRAM_NAME");
  917. *szFrom = 0;
  918. SafeCpyN(szFrom, pszSQL, ARRAYSIZE(szFrom));
  919. //
  920. // We will now create the sql.
  921. //
  922. *szEntryName = *szAppName = 0;
  923. GetDlgItemText(hdlg, IDC_APPNAME, szAppName, ARRAYSIZE(szAppName));
  924. //
  925. // Get rid of quotes if the user puts them
  926. //
  927. ReplaceChar(szAppName, TEXT('\"'), TEXT(' '));
  928. if (CSTRING::Trim(szAppName) == 0) {
  929. //
  930. // Field was empty, replace with wild-card
  931. //
  932. SetDlgItemText(hdlg, IDC_APPNAME, TEXT("%"));
  933. szAppName[0] = TEXT('%');
  934. szAppName[1] = TEXT('\0');
  935. }
  936. GetDlgItemText(hdlg, IDC_ENTRYNAME, szEntryName, ARRAYSIZE(szEntryName));
  937. ReplaceChar(szEntryName, TEXT('\"'), TEXT(' '));
  938. if (CSTRING::Trim(szEntryName) == 0) {
  939. //
  940. // Field was empty, replace with wild-card
  941. //
  942. SetDlgItemText(hdlg, IDC_ENTRYNAME, TEXT("%"));
  943. szEntryName[0] = TEXT('%');
  944. szEntryName[1] = TEXT('\0');
  945. }
  946. //
  947. // Set the default where clause for this page
  948. //
  949. strWhereClauses.Sprintf(TEXT("APP_NAME = \"%s\" AND PROGRAM_NAME = \"%s\" "),
  950. szAppName,
  951. szEntryName);
  952. //
  953. // Check if the layer check box is selected
  954. //
  955. if (SendMessage(GetDlgItem(hdlg, IDC_LAYERS), BM_GETCHECK, 0, 0) == BST_CHECKED) {
  956. //
  957. // We now need to show the count and the names of the layers
  958. //
  959. strSelectClauses.Strcat(TEXT(", MODE_COUNT, MODE_NAME "));
  960. //
  961. // Add the where clauses for the layers
  962. //
  963. bPreFixAdded = TRUE;
  964. strWhereClauses.Strcat(TEXT(" AND ( MODE_COUNT > 0 "));
  965. }
  966. //
  967. // check if the shim check box is selected
  968. //
  969. if (SendMessage(GetDlgItem(hdlg, IDC_SHIMS), BM_GETCHECK, 0, 0) == BST_CHECKED) {
  970. //
  971. // We now need to show the count and the names of the shims
  972. //
  973. strSelectClauses.Strcat(TEXT(", FIX_COUNT, FIX_NAME"));
  974. //
  975. // Add the where clauses for the shims
  976. //
  977. if (bPreFixAdded == FALSE) {
  978. strWhereClauses.Strcat(TEXT(" AND ( "));
  979. bPreFixAdded = TRUE;
  980. } else {
  981. strWhereClauses.Strcat(TEXT(" AND "));
  982. }
  983. strWhereClauses.Strcat(TEXT(" FIX_COUNT > 0 "));
  984. }
  985. //
  986. // check if the apphelp check box is selected
  987. //
  988. if (SendMessage(GetDlgItem(hdlg, IDC_APPHELP), BM_GETCHECK, 0, 0) == BST_CHECKED) {
  989. if (bPreFixAdded == FALSE) {
  990. strWhereClauses.Strcat(TEXT(" AND ( "));
  991. bPreFixAdded = TRUE;
  992. } else {
  993. strWhereClauses.Strcat(TEXT(" AND "));
  994. }
  995. strWhereClauses.Strcat(TEXT(" PROGRAM_APPHELPUSED = TRUE "));
  996. }
  997. if (bPreFixAdded) {
  998. //
  999. // Must close the parenthesis
  1000. //
  1001. strWhereClauses.Strcat(TEXT(")"));
  1002. }
  1003. if (StringCchPrintf(pszSQL,
  1004. wParam,
  1005. TEXT("SELECT %s FROM %s WHERE %s"),
  1006. (LPCTSTR)strSelectClauses,
  1007. szFrom,
  1008. (LPCTSTR)strWhereClauses) != S_OK) {
  1009. assert(FALSE);
  1010. Dbg(dlError, "SearchOnAppOnGetSql", "Inadequate buffer size");
  1011. }
  1012. }
  1013. void
  1014. SearchOnFixOnGetSql(
  1015. IN HWND hdlg,
  1016. IN WPARAM wParam,
  1017. IN OUT LPARAM lParam
  1018. )
  1019. /*++
  1020. SearchOnAppOnGetUserSql
  1021. Desc: Processes the WM_USER_GETSQL for the first tab page
  1022. Params:
  1023. IN HWND hdlg: The handle to the First page of the tab
  1024. IN WPARAM wParam: The length of the string buffer that is in lParam. The length is in
  1025. TCHARs
  1026. IN OUT LPARAM lParam: The pointer to the string. This will contain the "FROM" clause.
  1027. The completed SQL will be returned in this.
  1028. Return:
  1029. void
  1030. --*/
  1031. {
  1032. TCHAR* pszSQL = (TCHAR*)lParam;
  1033. TCHAR szFrom[MAX_PATH];
  1034. TCHAR szName[MAX_PATH]; // The string that will take in the contents of the text field
  1035. CSTRING strSelectClauses;
  1036. CSTRING strWhereClauses;
  1037. BOOL bPreFixAdded = FALSE; // Whether we have added the 'AND ' prefix for this part of the SQL
  1038. BOOL bValid = FALSE; // Did the user select some check box
  1039. if (pszSQL == NULL) {
  1040. assert(FALSE);
  1041. return;
  1042. }
  1043. //
  1044. // Set the attributes that we are always going to show
  1045. //
  1046. strSelectClauses = TEXT("APP_NAME, PROGRAM_NAME");
  1047. *szFrom = 0;
  1048. SafeCpyN(szFrom, pszSQL, ARRAYSIZE(szFrom));
  1049. GetDlgItemText(hdlg, IDC_NAME, szName, ARRAYSIZE(szName));
  1050. //
  1051. // Get rid of quotes if the user puts them
  1052. //
  1053. ReplaceChar(szName, TEXT('\"'), TEXT(' '));
  1054. if (CSTRING::Trim(szName) == 0) {
  1055. //
  1056. // Field was empty, replace with wild-card
  1057. //
  1058. SetDlgItemText(hdlg, IDC_NAME, TEXT("%"));
  1059. szName[0] = TEXT('%');
  1060. szName[1] = TEXT('\0');
  1061. }
  1062. //
  1063. // check if the shim check box is selected
  1064. //
  1065. if (SendMessage(GetDlgItem(hdlg, IDC_SHIM), BM_GETCHECK, 0, 0) == BST_CHECKED) {
  1066. bPreFixAdded = TRUE;
  1067. //
  1068. // We now need to show the names of the fixes
  1069. //
  1070. strSelectClauses.Strcat(TEXT(", FIX_NAME "));
  1071. //
  1072. // Add the where clauses for the fixes
  1073. //
  1074. strWhereClauses.Strcat(TEXT(" FIX_NAME HAS \""));
  1075. strWhereClauses.Strcat(szName);
  1076. strWhereClauses.Strcat(TEXT("\""));
  1077. bValid = TRUE;
  1078. }
  1079. //
  1080. // check if the layer check box is selected
  1081. //
  1082. if (SendMessage(GetDlgItem(hdlg, IDC_MODE), BM_GETCHECK, 0, 0) == BST_CHECKED) {
  1083. //
  1084. // We now need to show the names of the fixes
  1085. //
  1086. strSelectClauses.Strcat(TEXT(", MODE_NAME "));
  1087. if (bPreFixAdded) {
  1088. strWhereClauses.Strcat(TEXT(" AND "));
  1089. }
  1090. //
  1091. // Add the where clauses for the layers
  1092. //
  1093. strWhereClauses.Strcat(TEXT(" MODE_NAME HAS \""));
  1094. strWhereClauses.Strcat(szName);
  1095. strWhereClauses.Strcat(TEXT("\""));
  1096. bValid = TRUE;
  1097. }
  1098. if (bValid == FALSE) {
  1099. s_iErrorCode = ERROR_GUI_NOCHECKBOXSELECTED;
  1100. }
  1101. if (StringCchPrintf(pszSQL,
  1102. wParam,
  1103. TEXT("SELECT %s FROM %s WHERE %s"),
  1104. (LPCTSTR)strSelectClauses,
  1105. szFrom,
  1106. (LPCTSTR)strWhereClauses) != S_OK) {
  1107. assert(FALSE);
  1108. Dbg(dlError, "SearchOnFixOnGetSql", "Inadequate buffer space");
  1109. }
  1110. }
  1111. void
  1112. HandleTabNotification(
  1113. IN HWND hdlg,
  1114. IN LPARAM lParam
  1115. )
  1116. /*++
  1117. HandleTabNotification
  1118. Desc: Handles the notification messages for the tab control in the query dialog
  1119. Params:
  1120. IN HWND hdlg: The query dialog box
  1121. IN LPARAM lParam: The LPARAM of WM_NOTIFY
  1122. Return:
  1123. void
  1124. --*/
  1125. {
  1126. LPNMHDR pnm = (LPNMHDR)lParam;
  1127. int ind = 0;
  1128. switch (pnm->code) {
  1129. // Handle mouse clicks and keyboard events
  1130. case TCN_SELCHANGE:
  1131. OnSelChanged(hdlg);
  1132. break;
  1133. }
  1134. }
  1135. ///////////////////////////////////////////////////////////////////////////////
  1136. //
  1137. // Dialog Procs for the pages of the Tab
  1138. //
  1139. //
  1140. INT_PTR CALLBACK
  1141. SearchOnAppDlgProc(
  1142. IN HWND hdlg,
  1143. IN UINT uMsg,
  1144. IN WPARAM wParam,
  1145. IN LPARAM lParam
  1146. )
  1147. /*++
  1148. SearchOnAppDlgProc
  1149. Desc: Dialog proc for the first tab page. This page handles searches
  1150. based on the application information.
  1151. Params: Standard dialog handler parameters
  1152. IN HWND hDlg
  1153. IN UINT uMsg
  1154. IN WPARAM wParam
  1155. IN LPARAM lParam
  1156. Return: Standard dialog handler return
  1157. --*/
  1158. {
  1159. int wCode = LOWORD(wParam);
  1160. int wNotifyCode = HIWORD(wParam);
  1161. switch (uMsg) {
  1162. case WM_INITDIALOG:
  1163. {
  1164. //
  1165. // Restrict the length of the text fields
  1166. //
  1167. SendMessage(GetDlgItem(hdlg, IDC_APPNAME),
  1168. EM_LIMITTEXT,
  1169. (WPARAM)LIMIT_APP_NAME,
  1170. (LPARAM)0);
  1171. SendMessage(GetDlgItem(hdlg, IDC_ENTRYNAME),
  1172. EM_LIMITTEXT,
  1173. (WPARAM)MAX_PATH - 1,
  1174. (LPARAM)0);
  1175. break;
  1176. }
  1177. case WM_USER_NEWQDB:
  1178. SetDlgItemText(hdlg, IDC_APPNAME, TEXT(""));
  1179. SetDlgItemText(hdlg, IDC_ENTRYNAME, TEXT(""));
  1180. SendMessage(GetDlgItem(hdlg, IDC_LAYERS), BM_SETCHECK, BST_UNCHECKED, 0);
  1181. SendMessage(GetDlgItem(hdlg, IDC_SHIMS), BM_SETCHECK, BST_UNCHECKED, 0);
  1182. SendMessage(GetDlgItem(hdlg, IDC_APPHELP), BM_SETCHECK, BST_UNCHECKED, 0);
  1183. DeleteAll(GetParent(hdlg));
  1184. break;
  1185. case WM_USER_GETSQL:
  1186. SearchOnAppOnGetSql(hdlg, wParam, lParam);
  1187. break;
  1188. default: return FALSE;
  1189. }
  1190. return TRUE;
  1191. }
  1192. INT_PTR CALLBACK
  1193. SearchOnFixDlgProc(
  1194. IN HWND hdlg,
  1195. IN UINT uMsg,
  1196. IN WPARAM wParam,
  1197. IN LPARAM lParam
  1198. )
  1199. /*++
  1200. SearchOnFixDlgProc
  1201. Desc: Dialog proc for the second tab page. This page handles searches
  1202. based on the layer/shim name contained in the entries
  1203. Params: Standard dialog handler parameters
  1204. IN HWND hDlg
  1205. IN UINT uMsg
  1206. IN WPARAM wParam
  1207. IN LPARAM lParam
  1208. Return: Standard dialog handler return
  1209. --*/
  1210. {
  1211. int wCode = LOWORD(wParam);
  1212. int wNotifyCode = HIWORD(wParam);
  1213. switch (uMsg) {
  1214. case WM_INITDIALOG:
  1215. {
  1216. SendMessage(GetDlgItem(hdlg, IDC_NAME),
  1217. EM_LIMITTEXT,
  1218. (WPARAM)LIMIT_APP_NAME,
  1219. (LPARAM)0);
  1220. break;
  1221. }
  1222. case WM_USER_NEWQDB:
  1223. SetDlgItemText(hdlg, IDC_NAME, TEXT(""));
  1224. SendMessage(GetDlgItem(hdlg, IDC_SHIM), BM_SETCHECK, BST_UNCHECKED, 0);
  1225. SendMessage(GetDlgItem(hdlg, IDC_MODE), BM_SETCHECK, BST_UNCHECKED, 0);
  1226. DeleteAll(GetParent(hdlg));
  1227. break;
  1228. case WM_USER_GETSQL:
  1229. {
  1230. SearchOnFixOnGetSql(hdlg, wParam, lParam);
  1231. break;
  1232. }
  1233. default: return FALSE;
  1234. }
  1235. return TRUE;
  1236. }
  1237. void
  1238. LoadSelectList(
  1239. IN HWND hdlg
  1240. )
  1241. /*++
  1242. LoadSelectList
  1243. Desc: Loads the list of attributes in the SELECT clause list view. This is used in
  1244. the advanced tab page
  1245. Params:
  1246. IN HWND hdlg: The query dialog box
  1247. Return:
  1248. void
  1249. --*/
  1250. {
  1251. HWND hwndList = GetDlgItem(hdlg, IDC_SELECT_LIST);
  1252. LVITEM lvi;
  1253. INT iIndex = 0;
  1254. ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT);
  1255. InsertColumnIntoListView(hwndList, 0, 0, 97);
  1256. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  1257. for (iIndex = 0; iIndex < GetSelectAttrCount() ; ++iIndex) {
  1258. lvi.pszText = AttributeShowMapping[iIndex].szAttribute;
  1259. lvi.iSubItem = 0;
  1260. lvi.lParam = iIndex;
  1261. lvi.iItem = iIndex;
  1262. ListView_InsertItem(hwndList, &lvi);
  1263. }
  1264. //
  1265. // We have to add the "*" separately. Do NOT have this in the AttributeMatchMapping
  1266. //
  1267. lvi.lParam = iIndex;
  1268. lvi.iItem = iIndex;
  1269. lvi.pszText = TEXT("*");
  1270. ListView_InsertItem(hwndList, &lvi);
  1271. InvalidateRect(hwndList, NULL, TRUE);
  1272. UpdateWindow(hwndList);
  1273. }
  1274. void
  1275. LoadWhereList(
  1276. HWND hdlg
  1277. )
  1278. {
  1279. /*++
  1280. LoadWhereList
  1281. Desc: Loads the list of "where" attributes. This is used in
  1282. the advanced tab page
  1283. Params:
  1284. IN HWND hdlg: The query dialog box
  1285. Return:
  1286. void
  1287. --*/
  1288. HWND hwndList = GetDlgItem(hdlg, IDC_WHERE_LIST);
  1289. LVITEM lvi = {0};
  1290. INT iIndex = 0;
  1291. ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT);
  1292. InsertColumnIntoListView(hwndList, 0, 0, 97);
  1293. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  1294. lvi.iSubItem = 0;
  1295. for (iIndex = 0; iIndex < GetMatchAttrCount(); ++iIndex) {
  1296. lvi.pszText = AttributeMatchMapping[iIndex].szAttribute;
  1297. lvi.lParam = iIndex;
  1298. lvi.iItem = iIndex;
  1299. ListView_InsertItem(hwndList, &lvi);
  1300. }
  1301. InvalidateRect(hwndList, NULL, TRUE);
  1302. UpdateWindow(hwndList);
  1303. }
  1304. INT_PTR CALLBACK
  1305. AdvancedSearchDlgProc(
  1306. IN HWND hdlg,
  1307. IN UINT uMsg,
  1308. IN WPARAM wParam,
  1309. IN LPARAM lParam
  1310. )
  1311. /*++
  1312. AdvancedSearchDlgProc
  1313. Desc: Dialog proc for the fourth tab page. This page handles the advanced
  1314. search option.
  1315. Params: Standard dialog handler parameters
  1316. IN HWND hDlg
  1317. IN UINT uMsg
  1318. IN WPARAM wParam
  1319. IN LPARAM lParam
  1320. Return: Standard dialog handler return
  1321. --*/
  1322. {
  1323. int wCode = LOWORD(wParam);
  1324. int wNotifyCode = HIWORD(wParam);
  1325. switch (uMsg) {
  1326. case WM_INITDIALOG:
  1327. {
  1328. SendMessage(GetDlgItem(hdlg, IDC_SELECT), EM_LIMITTEXT,(WPARAM)MAX_SELECT, (LPARAM)0);
  1329. SendMessage(GetDlgItem(hdlg, IDC_WHERE), EM_LIMITTEXT,(WPARAM)MAX_WHERE, (LPARAM)0);
  1330. //
  1331. // Populate the list views with the search and the where attributes
  1332. //
  1333. LoadSelectList(hdlg);
  1334. LoadWhereList(hdlg);
  1335. break;
  1336. }
  1337. case WM_NOTIFY:
  1338. {
  1339. LPNMHDR lpnmhdr = (LPNMHDR)lParam;
  1340. if (lpnmhdr && (lpnmhdr->idFrom == IDC_SELECT_LIST
  1341. || lpnmhdr->idFrom == IDC_WHERE_LIST)) {
  1342. HandleAdvancedListNotification(hdlg, lParam);
  1343. }
  1344. break;
  1345. }
  1346. case WM_USER_NEWQDB:
  1347. SetDlgItemText(hdlg, IDC_SELECT, TEXT(""));
  1348. SetDlgItemText(hdlg, IDC_WHERE, TEXT(""));
  1349. DeleteAll(GetParent(hdlg));
  1350. break;
  1351. case WM_USER_GETSQL:
  1352. {
  1353. //
  1354. // lParam: the pointer to the string.
  1355. // This will contain the "FROM" clause.
  1356. // The completed SQL will be retuned in this.
  1357. // wParam: the length of the string
  1358. TCHAR* pszSQL = (TCHAR*) lParam;
  1359. TCHAR szFrom[MAX_PATH];
  1360. TCHAR szSelect[1024], szWhere[1024];
  1361. *szSelect = *szWhere = 0;
  1362. if (pszSQL == NULL) {
  1363. assert(FALSE);
  1364. break;
  1365. }
  1366. *szFrom = 0;
  1367. SafeCpyN(szFrom, pszSQL, ARRAYSIZE(szFrom));
  1368. GetDlgItemText(hdlg, IDC_SELECT, szSelect, ARRAYSIZE(szSelect));
  1369. GetDlgItemText(hdlg, IDC_WHERE, szWhere, ARRAYSIZE(szWhere));
  1370. if (CSTRING::Trim(szWhere) != 0) {
  1371. StringCchPrintf(pszSQL,
  1372. wParam,
  1373. TEXT("SELECT %s FROM %s WHERE %s "),
  1374. szSelect,
  1375. szFrom,
  1376. szWhere);
  1377. } else {
  1378. StringCchPrintf(pszSQL,
  1379. wParam,
  1380. TEXT("SELECT %s FROM %s "),
  1381. szSelect,
  1382. szFrom);
  1383. }
  1384. break;
  1385. }
  1386. default: return FALSE;
  1387. }
  1388. return TRUE;
  1389. }
  1390. void
  1391. HandleAdvancedListNotification(
  1392. IN HWND hdlg,
  1393. IN LPARAM lParam
  1394. )
  1395. /*++
  1396. HandleAdvancedListNotification
  1397. Desc: Handles the list notifications for the advanced page of the tab. i.e.
  1398. the SELECT list view and the WHERE list view
  1399. This will add the SELECT parameters to the SELECT text box
  1400. if we double click on the "SELECT" list box.
  1401. If we double click on the "Where" list box, this routine will
  1402. add the selected param to the WHERE text box
  1403. Params:
  1404. IN HWND hdlg: The query dialog box
  1405. IN LPARAM lParam: The LPARAM for WM_NOTIFY.
  1406. Return:
  1407. void
  1408. --*/
  1409. {
  1410. LPNMHDR lpnmhdr = (LPNMHDR)lParam;
  1411. if (lpnmhdr == NULL) {
  1412. return;
  1413. }
  1414. switch (lpnmhdr->code) {
  1415. case NM_DBLCLK:
  1416. {
  1417. HWND hwndList; // Handle to either the IDC_SELECT_LIST or the IDC_WHERE_LIST
  1418. BOOL bEmpty = FALSE; // Whether the text box was empty. This is needed to determine if we should add a leading ','
  1419. HWND hwndText;
  1420. LVITEM lvItem;
  1421. TCHAR szBuffer[MAX_PATH];
  1422. TCHAR szTextBoxContents[2096];
  1423. LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) lParam;
  1424. INT iLength = 0;
  1425. if (lpnmitem == NULL) {
  1426. break;
  1427. }
  1428. *szBuffer = *szTextBoxContents = 0;
  1429. if (lpnmhdr->idFrom == IDC_SELECT_LIST) {
  1430. hwndList = GetDlgItem(hdlg, IDC_SELECT_LIST);
  1431. hwndText = GetDlgItem(hdlg, IDC_SELECT);
  1432. iLength = MAX_SELECT;
  1433. } else {
  1434. hwndList = GetDlgItem(hdlg, IDC_WHERE_LIST);
  1435. hwndText = GetDlgItem(hdlg, IDC_WHERE);
  1436. iLength = MAX_WHERE;
  1437. }
  1438. lvItem.mask = LVIF_TEXT;
  1439. lvItem.iItem = lpnmitem->iItem;
  1440. lvItem.iSubItem = 0;
  1441. lvItem.pszText = szBuffer;
  1442. lvItem.cchTextMax = ARRAYSIZE(szBuffer);
  1443. if (!ListView_GetItem(hwndList, &lvItem)) {
  1444. break;
  1445. }
  1446. GetWindowText(hwndText, szTextBoxContents, iLength);
  1447. if ((lstrlen(szTextBoxContents) + lstrlen(szBuffer) + 3) >= iLength) { // 3 because we might append a " = "
  1448. //
  1449. // We might exceed the limitation that we set using WM_LIMITTEXT, do not allow that.
  1450. //
  1451. MessageBeep(MB_ICONASTERISK);
  1452. break;
  1453. }
  1454. if (CSTRING::Trim(szTextBoxContents) == 0) {
  1455. bEmpty = TRUE;
  1456. }
  1457. if (bEmpty == FALSE) {
  1458. if (lpnmhdr->idFrom == IDC_SELECT_LIST) {
  1459. StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), TEXT(", "));
  1460. } else {
  1461. StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), TEXT(" "));
  1462. }
  1463. }
  1464. StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), szBuffer);
  1465. if (lpnmhdr->idFrom == IDC_WHERE_LIST) {
  1466. StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), TEXT(" = "));
  1467. }
  1468. SetWindowText(hwndText, szTextBoxContents);
  1469. //
  1470. // Let us now position the caret at the end of the text box
  1471. // We send the text box a VK_END key down message
  1472. //
  1473. SendMessage(hwndText, WM_KEYDOWN, (WPARAM)(INT)VK_END, (LPARAM)0);
  1474. break;
  1475. }
  1476. }
  1477. }
  1478. void
  1479. HandleQueryDBSizing(
  1480. IN HWND hDlg
  1481. )
  1482. /*++
  1483. HandleQueryDBSizing
  1484. Desc: Handles the sizing of the Query db dialog
  1485. Params:
  1486. IN HWND hDlg: The query dialog box
  1487. Return:
  1488. void
  1489. --*/
  1490. {
  1491. int nWidth;
  1492. int nHeight;
  1493. int nStatusbarTop;
  1494. RECT rDlg;
  1495. HWND hwnd;
  1496. RECT r;
  1497. if (g_cWidthQuery == 0 || g_cWidthQuery == 0) {
  1498. return;
  1499. }
  1500. GetWindowRect(hDlg, &rDlg);
  1501. nWidth = rDlg.right - rDlg.left;
  1502. nHeight = rDlg.bottom - rDlg.top;
  1503. int deltaW = nWidth - g_cWidthQuery;
  1504. int deltaH = nHeight - g_cHeightQuery;
  1505. //
  1506. // The status bar
  1507. //
  1508. hwnd = GetDlgItem(hDlg, IDC_STATUSBAR);
  1509. GetWindowRect(hwnd, &r);
  1510. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1511. MoveWindow(hwnd,
  1512. r.left,
  1513. nStatusbarTop = r.top + deltaH,
  1514. r.right - r.left + deltaW,
  1515. r.bottom - r.top,
  1516. TRUE);
  1517. //
  1518. // The List
  1519. //
  1520. hwnd = GetDlgItem(hDlg, IDC_LIST);
  1521. GetWindowRect(hwnd, &r);
  1522. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1523. MoveWindow(hwnd,
  1524. r.left,
  1525. r.top,
  1526. r.right - r.left + deltaW,
  1527. nStatusbarTop - r.top,
  1528. TRUE);
  1529. //
  1530. // The search button
  1531. //
  1532. hwnd = GetDlgItem(hDlg, ID_SEARCH);
  1533. GetWindowRect(hwnd, &r);
  1534. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1535. MoveWindow(hwnd,
  1536. r.left + deltaW,
  1537. r.top,
  1538. r.right - r.left,
  1539. r.bottom - r.top,
  1540. TRUE);
  1541. //
  1542. // The save button
  1543. //
  1544. hwnd = GetDlgItem(hDlg, IDC_SAVE);
  1545. GetWindowRect(hwnd, &r);
  1546. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1547. MoveWindow(hwnd,
  1548. r.left + deltaW,
  1549. r.top,
  1550. r.right - r.left,
  1551. r.bottom - r.top,
  1552. TRUE);
  1553. //
  1554. // The animate control
  1555. //
  1556. hwnd = GetDlgItem(hDlg, IDC_ANIMATE);
  1557. GetWindowRect(hwnd, &r);
  1558. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1559. MoveWindow(hwnd,
  1560. r.left + deltaW,
  1561. r.top,
  1562. r.right - r.left,
  1563. r.bottom - r.top,
  1564. TRUE);
  1565. //
  1566. // The cancel button
  1567. //
  1568. hwnd = GetDlgItem(hDlg, IDC_STOP);
  1569. GetWindowRect(hwnd, &r);
  1570. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1571. MoveWindow(hwnd,
  1572. r.left + deltaW,
  1573. r.top,
  1574. r.right - r.left,
  1575. r.bottom - r.top,
  1576. TRUE);
  1577. //
  1578. // The new search button
  1579. //
  1580. hwnd = GetDlgItem(hDlg, IDC_NEWSEARCH);
  1581. GetWindowRect(hwnd, &r);
  1582. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1583. MoveWindow(hwnd,
  1584. r.left + deltaW,
  1585. r.top,
  1586. r.right - r.left,
  1587. r.bottom - r.top,
  1588. TRUE);
  1589. //
  1590. // The help button
  1591. //
  1592. hwnd = GetDlgItem(hDlg, ID_QDB_HELP);
  1593. GetWindowRect(hwnd, &r);
  1594. MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
  1595. MoveWindow(hwnd,
  1596. r.left + deltaW,
  1597. r.top,
  1598. r.right - r.left,
  1599. r.bottom - r.top,
  1600. TRUE);
  1601. g_cWidthQuery = nWidth;
  1602. g_cHeightQuery = nHeight;
  1603. }
  1604. void
  1605. OnSearch(
  1606. IN HWND hdlg
  1607. )
  1608. /*++
  1609. OnSearch
  1610. Desc: Handles the pressing of the Find Now button
  1611. Params:
  1612. IN HWND hdlg: The query dialog box
  1613. Return:
  1614. void
  1615. Notes: We will obtain the query string from the active tab page and
  1616. then set the text of IDC_SQL (this is an invisible control) to the SQL
  1617. The query processing routines i.e the SQLDriver will read the string
  1618. from IDC_SQL. This approach is needed to avoid global variables
  1619. --*/
  1620. {
  1621. TCHAR szSQL[2096];
  1622. //
  1623. // Remove any existing results...
  1624. //
  1625. DeleteAll(hdlg);
  1626. stmt.Close();
  1627. stmt.Init();
  1628. stmt.SetWindow(hdlg);
  1629. //
  1630. // Prepare the FROM string
  1631. //
  1632. *szSQL = 0;
  1633. INT iIndex = SendMessage(GetDlgItem(hdlg, IDC_COMBO), CB_GETCURSEL, 0, 0);
  1634. if (iIndex == CB_ERR) {
  1635. return;
  1636. }
  1637. LPARAM lParam = SendMessage(GetDlgItem(hdlg, IDC_COMBO), CB_GETITEMDATA, iIndex, 0);
  1638. if (lParam == CB_ERR) {
  1639. return;
  1640. }
  1641. switch (lParam) {
  1642. case DATABASE_ALL:
  1643. StringCchPrintf(szSQL,
  1644. ARRAYSIZE(szSQL),
  1645. TEXT("%s, %s ,%s"),
  1646. DatabasesMapping[IND_SYSTDB].szDatabaseType,
  1647. DatabasesMapping[IND_INSTDB].szDatabaseType,
  1648. DatabasesMapping[IND_CUSTDB].szDatabaseType);
  1649. break;
  1650. case DATABASE_TYPE_GLOBAL:
  1651. SafeCpyN(szSQL, DatabasesMapping[IND_SYSTDB].szDatabaseType, ARRAYSIZE(szSQL));
  1652. break;
  1653. case DATABASE_TYPE_INSTALLED:
  1654. SafeCpyN(szSQL, DatabasesMapping[IND_INSTDB].szDatabaseType, ARRAYSIZE(szSQL));
  1655. break;
  1656. case DATABASE_TYPE_WORKING:
  1657. SafeCpyN(szSQL, DatabasesMapping[IND_CUSTDB].szDatabaseType, ARRAYSIZE(szSQL));
  1658. break;
  1659. }
  1660. DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
  1661. if (pHdr == NULL) {
  1662. assert(FALSE);
  1663. return;
  1664. }
  1665. s_iErrorCode = 0;
  1666. SendMessage(pHdr->hwndPages[pHdr->iPresentTabIndex],
  1667. WM_USER_GETSQL,
  1668. (WPARAM)ARRAYSIZE(szSQL),
  1669. (LPARAM)szSQL);
  1670. if (!s_iErrorCode) {
  1671. SetDlgItemText(hdlg, IDC_SQL, szSQL);
  1672. Start(hdlg);
  1673. } else {
  1674. //
  1675. // Display the proper error
  1676. //
  1677. TCHAR szErrormsg[512];
  1678. *szErrormsg = 0;
  1679. switch (s_iErrorCode) {
  1680. case ERROR_GUI_NOCHECKBOXSELECTED:
  1681. SafeCpyN(szErrormsg,
  1682. GetString(IDS_ERROR_GUI_NOCHECKBOXSELECTED),
  1683. ARRAYSIZE(szErrormsg));
  1684. break;
  1685. }
  1686. MessageBox(hdlg, szErrormsg, g_szAppName, MB_ICONINFORMATION);
  1687. }
  1688. }
  1689. void
  1690. DoNewQdb(
  1691. IN HWND hdlg
  1692. )
  1693. /*++
  1694. DoNewQdb
  1695. Desc: Handles the pressing of the New Search button
  1696. Params:
  1697. IN HWND hdlg: The query dialog box
  1698. Return:
  1699. void
  1700. --*/
  1701. {
  1702. DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
  1703. if (pHdr == NULL) {
  1704. assert(FALSE);
  1705. return;
  1706. }
  1707. //
  1708. // Request the active tab page to clear its contents
  1709. //
  1710. SendMessage(pHdr->hwndPages[pHdr->iPresentTabIndex], WM_USER_NEWQDB, 0, 0);
  1711. }
  1712. void
  1713. DeleteAll(
  1714. IN HWND hdlg
  1715. )
  1716. /*++
  1717. DeleteAll
  1718. Desc: Deletes all the results items from the query dialog's search result
  1719. list view
  1720. Params:
  1721. IN HWND hdlg: The query dialog box
  1722. Return:
  1723. void
  1724. Notes: We do not try to free the pointers in the lParam of the list view items.
  1725. If we have done a SQL query:
  1726. The lParam of the list view will be pointers to items of type PRESULT_ITEM
  1727. which are freed when we close the statement. (Closing the statement closes
  1728. the ResultSet of the statement)
  1729. If we have done a special database query like searching for fixes that
  1730. have some words in their description then the lParam will point to the
  1731. FIX_SHIM in the database and we do not want to free that
  1732. --*/
  1733. {
  1734. HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
  1735. UINT uColCount = stmt.GetShowList()->m_uCount;
  1736. INT iIndex = 0;
  1737. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
  1738. if (s_bEmptyHeader == FALSE) {
  1739. for (iIndex = uColCount; iIndex >= 0; --iIndex) {
  1740. ListView_DeleteColumn(hwndList, iIndex);
  1741. }
  1742. InsertColumnIntoListView(hwndList, TEXT(""), 0, 100);
  1743. s_bEmptyHeader = TRUE;
  1744. }
  1745. ListView_DeleteAllItems(hwndList);
  1746. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
  1747. SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), TEXT(""));
  1748. UpdateWindow(hwndList);
  1749. }
  1750. void
  1751. SaveResultsQdb(
  1752. IN HWND hdlg
  1753. )
  1754. /*++
  1755. SaveResultsQdb
  1756. Desc: Saves all the results items from the query dialog's search result
  1757. list view in a tab separated text file
  1758. Params:
  1759. IN HWND hdlg: The query dialog box
  1760. Return:
  1761. void
  1762. --*/
  1763. {
  1764. CSTRING strFileName;
  1765. TCHAR szTitle[256], szFilter[128], szExt[8];
  1766. *szTitle = *szFilter = *szExt = 0;
  1767. BOOL bResult = GetFileName(hdlg,
  1768. GetString(IDS_SAVE_RESULTS_TITLE, szTitle, ARRAYSIZE(szTitle)),
  1769. GetString(IDS_SAVE_RESULTS_FILTER, szFilter, ARRAYSIZE(szFilter)),
  1770. TEXT(""),
  1771. GetString(IDS_SAVE_RESULTS_EXT, szExt, ARRAYSIZE(szExt)),
  1772. OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT,
  1773. FALSE,
  1774. strFileName,
  1775. TRUE);
  1776. if (bResult) {
  1777. SetCursor(LoadCursor(NULL, IDC_WAIT));
  1778. SaveListViewToFile(GetDlgItem(hdlg, IDC_LIST),
  1779. stmt.GetShowList()->m_uCount,
  1780. strFileName.pszString,
  1781. NULL);
  1782. SetCursor(LoadCursor(NULL, IDC_ARROW));
  1783. }
  1784. }
  1785. void
  1786. GotoQdbEntry(
  1787. IN HWND hdlg,
  1788. IN LPARAM lParam
  1789. )
  1790. /*++
  1791. GotoQdbEntry
  1792. Desc: Selects the entry in the entry tree.
  1793. The lParam is the lParam of the list view row that specifies that entry.
  1794. Params:
  1795. IN HWND hdlg: The query db dialog box
  1796. IN LPARAM lParam: The list view item whose 'details' we want to see
  1797. --*/
  1798. {
  1799. PRESULT_ITEM pResult;
  1800. PDBENTRY pApp;
  1801. if (g_iLastSearchType == QDB_PAGE3) {
  1802. //
  1803. // We had performed a search for shims last time, so we do not have PRESULT_ITEM
  1804. // items in the list view
  1805. //
  1806. goto End;
  1807. }
  1808. if (g_bSomeWizardActive) {
  1809. //
  1810. // We do not want that the focus should go to some other database, because
  1811. // some wizard is active, which believes that he is modal.
  1812. //
  1813. MessageBox(g_hdlgQueryDB,
  1814. GetString(IDS_SOMEWIZARDACTIVE),
  1815. g_szAppName,
  1816. MB_ICONINFORMATION);
  1817. goto End;
  1818. }
  1819. pResult = (PRESULT_ITEM)lParam;
  1820. pApp = NULL;
  1821. if (pResult == NULL) {
  1822. assert(FALSE);
  1823. goto End;
  1824. }
  1825. pApp = GetAppForEntry(pResult->pDatabase, pResult->pEntry);
  1826. //
  1827. // First select the app from in the db tree.
  1828. //
  1829. HTREEITEM hItemApp = DBTree.FindChild(pResult->pDatabase->hItemAllApps, (LPARAM)pApp);
  1830. if (hItemApp == NULL) {
  1831. MessageBox(hdlg, GetString(IDS_NOLONGEREXISTS), g_szAppName, MB_ICONWARNING);
  1832. goto End;
  1833. }
  1834. TreeView_SelectItem(DBTree.m_hLibraryTree , hItemApp);
  1835. //
  1836. // Now from the entry tree select the particular entry
  1837. //
  1838. HTREEITEM hItemEntry = CTree::FindChild(g_hwndEntryTree, TVI_ROOT, (LPARAM)pResult->pEntry);
  1839. if (hItemEntry == NULL) {
  1840. MessageBox(hdlg, GetString(IDS_NOLONGEREXISTS), g_szAppName, MB_ICONWARNING);
  1841. goto End;
  1842. }
  1843. TreeView_SelectItem(g_hwndEntryTree, hItemEntry);
  1844. SetFocus(g_hwndEntryTree);
  1845. End: ;
  1846. }
  1847. INT_PTR CALLBACK
  1848. QdbWaitDlg(
  1849. IN HWND hdlg,
  1850. IN UINT uMsg,
  1851. IN WPARAM wParam,
  1852. IN LPARAM lParam
  1853. )
  1854. /*++
  1855. QdbWaitDlg
  1856. Desc: Dialog Proc for the wait window which will pop up,
  1857. if we are trying to close the query window,
  1858. when it the thread is still doing some useful work.
  1859. This will be essentially true when we are trying to load the system
  1860. database or we are trying to populate the list view
  1861. Params: Standard dialog handler parameters
  1862. IN HWND hDlg
  1863. IN UINT uMsg
  1864. IN WPARAM wParam
  1865. IN LPARAM lParam
  1866. Return: Standard dialog handler return
  1867. --*/
  1868. {
  1869. int wCode = LOWORD(wParam);
  1870. int wNotifyCode = HIWORD(wParam);
  1871. static HWND s_hwndPB;
  1872. switch (uMsg) {
  1873. case WM_INITDIALOG:
  1874. s_hwndPB = GetDlgItem(hdlg, IDC_PROGRESS);
  1875. SendMessage(s_hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 2000));
  1876. SendMessage(s_hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);
  1877. SetTimer(hdlg, 0, 100, NULL);
  1878. break;
  1879. case WM_TIMER:
  1880. if (s_hThread) {
  1881. if (WAIT_OBJECT_0 == WaitForSingleObject(s_hThread, 0)) {
  1882. //
  1883. // The handle to the thread is closed and nulled when it is
  1884. // about to terminate
  1885. //
  1886. KillTimer(hdlg, 0);
  1887. s_hThread = NULL;
  1888. s_hWaitDialog = NULL;
  1889. SendMessage(s_hwndPB, PBM_SETPOS, MAX_PROGRESS, 0);
  1890. SendMessage(g_hdlgQueryDB, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 0);
  1891. DestroyWindow(hdlg);
  1892. } else {
  1893. SendMessage(s_hwndPB, PBM_STEPIT, 0, 0);
  1894. }
  1895. } else {
  1896. KillTimer(hdlg, 0);
  1897. s_hWaitDialog = NULL;
  1898. SendMessage(s_hwndPB, PBM_SETPOS, MAX_PROGRESS, 0);
  1899. //
  1900. // Let the user see that it is completed
  1901. //
  1902. Sleep(1000);
  1903. SendMessage(g_hdlgQueryDB, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 0);
  1904. DestroyWindow(hdlg);
  1905. }
  1906. break;
  1907. case WM_COMMAND:
  1908. switch (wCode) {
  1909. case IDCANCEL:
  1910. KillTimer(hdlg, 0);
  1911. DestroyWindow(hdlg);
  1912. break;
  1913. default: return FALSE;
  1914. }
  1915. break;
  1916. case WM_DESTROY:
  1917. s_hWaitDialog = NULL;
  1918. break;
  1919. default: return FALSE;
  1920. }
  1921. return TRUE;
  1922. }
  1923. void
  1924. SearchAndAddToUIFixes(
  1925. IN CSTRINGLIST& strlTokens,
  1926. IN QDB_SEARCH_TYPE searchtype,
  1927. IN PVOID pShimOrFix,
  1928. IN TYPE type
  1929. )
  1930. /*++
  1931. SearchAndAddToUIFixes
  1932. Desc: Typecasts pShimOrFix to either a shim or a flag pointer as per type and
  1933. then checks if it contains matches the tokens
  1934. Params:
  1935. IN CSTRINGLIST& strlTokens: The list of tokens
  1936. IN QDB_SEARCH_TYPE searchtype: The type of search to perform
  1937. IN PVOID pShimOrFix: Pointer to a shim or a fix
  1938. IN TYPE type: Whether this is a shim or a fix
  1939. Return:
  1940. void
  1941. --*/
  1942. {
  1943. PSTRLIST pslListOfTokensLoop = strlTokens.m_pHead;
  1944. BOOL bFound = FALSE;
  1945. LVITEM lvi;
  1946. HWND hwndSearchList = NULL;
  1947. PCTSTR pszName = NULL;
  1948. PCTSTR pszDescription = NULL;
  1949. if (pShimOrFix == NULL) {
  1950. assert(FALSE);
  1951. return;
  1952. }
  1953. pShimOrFix = (PSHIM_FIX)pShimOrFix;
  1954. if (type == FIX_SHIM) {
  1955. pszName = (LPCTSTR)((PSHIM_FIX)pShimOrFix)->strName;
  1956. pszDescription = (LPCTSTR)((PSHIM_FIX)pShimOrFix)->strDescription;
  1957. } else if (type == FIX_FLAG) {
  1958. pszName = (LPCTSTR)((PFLAG_FIX)pShimOrFix)->strName;
  1959. pszDescription = (LPCTSTR)((PFLAG_FIX)pShimOrFix)->strDescription;
  1960. } else {
  1961. assert(FALSE);
  1962. return;
  1963. }
  1964. hwndSearchList = GetDlgItem(g_hdlgQueryDB, IDC_LIST);
  1965. //
  1966. // Check if the present fix has the desired tokens. If we search type specifies
  1967. // all tokens then we have to look for all tokens otherwise we can break
  1968. // when we find the first token that is present in the name of desc. of the shim
  1969. //
  1970. while (pslListOfTokensLoop) {
  1971. //
  1972. // Does the name of the fix has this token?
  1973. //
  1974. bFound = (StrStrI(pszName,
  1975. (LPCTSTR)pslListOfTokensLoop->szStr) == NULL) ? FALSE : TRUE ;
  1976. if (!bFound) {
  1977. //
  1978. // Name does not contain this token, so we must look in the description text
  1979. //
  1980. bFound = (StrStrI(pszDescription,
  1981. (LPCTSTR)pslListOfTokensLoop->szStr) == NULL) ? FALSE : TRUE;
  1982. }
  1983. if (searchtype == QDB_SEARCH_ALLWORDS && !bFound) {
  1984. //
  1985. // We wanted that all words should be found and we did not find this particular
  1986. // word, search failed
  1987. //
  1988. break;
  1989. }
  1990. if (searchtype == QDB_SEARCH_ANYWORD && bFound) {
  1991. //
  1992. // We wanted that any word should match and this word was found, so
  1993. // search was successfull
  1994. //
  1995. break;
  1996. }
  1997. //
  1998. // Search if the next token matches
  1999. //
  2000. pslListOfTokensLoop = pslListOfTokensLoop->pNext;
  2001. }
  2002. if (bFound) {
  2003. //
  2004. // This fix matched our criteria, so add this to the list view
  2005. //
  2006. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  2007. lvi.lParam = (LPARAM)pShimOrFix;
  2008. lvi.pszText = (LPTSTR)pszName;
  2009. lvi.iSubItem = 0;
  2010. ListView_InsertItem(hwndSearchList, &lvi);
  2011. }
  2012. }
  2013. void
  2014. DoTheFixesSearch(
  2015. IN HWND hdlg
  2016. )
  2017. /*++
  2018. DoTheFixesSearch
  2019. Desc: Searches for fixes in the system database that have the words that the user
  2020. wants to look for
  2021. Params:
  2022. IN HWND hdlg: The fix search page in the query db tab. This is the fourth page of the
  2023. tab
  2024. Return:
  2025. void
  2026. --*/
  2027. {
  2028. LPARAM lParam;
  2029. INT iIndex;
  2030. QDB_SEARCH_TYPE searchtype;
  2031. TCHAR szSearch[MAX_FIXDESC_SEARCH];
  2032. HWND hwndSearch = GetDlgItem(hdlg, IDC_TEXT);
  2033. HWND hwndCombo = GetDlgItem(hdlg, IDC_COMBO);
  2034. HWND hwndList = GetDlgItem(g_hdlgQueryDB, IDC_LIST);
  2035. PSHIM_FIX psfLoop = GlobalDataBase.pShimFixes;
  2036. PFLAG_FIX pffLoop = GlobalDataBase.pFlagFixes;
  2037. BOOL bFound = FALSE;
  2038. CSTRINGLIST strlTokens;
  2039. CSTRING strStatus;
  2040. TCHAR szBuffer[32];
  2041. INT iTotalResults;
  2042. //
  2043. // Clear any existing results
  2044. //
  2045. DeleteAll(GetParent(hdlg));
  2046. SetDlgItemText(hdlg, IDC_DESC, TEXT(""));
  2047. //
  2048. // Users cannot double click on the search list if we are showing shims, so
  2049. // we disable the text that says they can.
  2050. //
  2051. ENABLEWINDOW(GetDlgItem(GetParent(hdlg), IDC_STATIC_CAPTION), FALSE);
  2052. if (s_bEmptyHeader) {
  2053. //
  2054. // If the empty column is still there, must get rid of it
  2055. //
  2056. ListView_DeleteColumn(hwndList, 0);
  2057. s_bEmptyHeader = FALSE;
  2058. }
  2059. //
  2060. // Insert the new column
  2061. //
  2062. InsertColumnIntoListView(hwndList,
  2063. GetString(IDS_COMPATFIXES),
  2064. 0,
  2065. 100);
  2066. GetWindowText(hwndSearch, szSearch, ARRAYSIZE(szSearch));
  2067. if (CSTRING::Trim(szSearch) == 0) {
  2068. //
  2069. // No text was typed in for search
  2070. //
  2071. MessageBox(hdlg,
  2072. GetString(IDS_QDB_NO_TEXTTO_SEARCH),
  2073. g_szAppName,
  2074. MB_ICONWARNING);
  2075. goto End;
  2076. }
  2077. //
  2078. // Get the search type
  2079. //
  2080. iIndex = SendMessage(GetDlgItem(hdlg, IDC_COMBO), CB_GETCURSEL, 0, 0);
  2081. if (iIndex == CB_ERR) {
  2082. assert(FALSE);
  2083. goto End;
  2084. }
  2085. lParam = SendMessage(hwndCombo, CB_GETITEMDATA, iIndex, 0);
  2086. if (lParam == CB_ERR) {
  2087. assert(FALSE);
  2088. goto End;
  2089. }
  2090. searchtype = (QDB_SEARCH_TYPE)lParam;
  2091. //
  2092. // The search string is comma separated, get the individual tokens and search for that token
  2093. // first in the name of the fix and then in the description. As for now we do not do any
  2094. // rating on the search. We show results as they come
  2095. //
  2096. //
  2097. // Fist get the tokens
  2098. //
  2099. if (Tokenize(szSearch, lstrlen(szSearch), TEXT(","), strlTokens)) {
  2100. //
  2101. // We found some tokens, now for each token let us see if it is in the fix name
  2102. // or the fix description
  2103. //
  2104. //
  2105. // Search in the shims and add to the list view
  2106. //
  2107. while (psfLoop) {
  2108. if (psfLoop->bGeneral || g_bExpert) {
  2109. //
  2110. // In non-expert mode we should only show the general shims
  2111. //
  2112. SearchAndAddToUIFixes(strlTokens, searchtype, psfLoop, FIX_SHIM);
  2113. }
  2114. psfLoop = psfLoop->pNext;
  2115. }
  2116. //
  2117. // Search in the flags and add it to the list view
  2118. //
  2119. while (pffLoop) {
  2120. if (pffLoop->bGeneral || g_bExpert) {
  2121. //
  2122. // In non-expert mode we should only show the general flags
  2123. //
  2124. SearchAndAddToUIFixes(strlTokens, searchtype, pffLoop, FIX_FLAG);
  2125. }
  2126. pffLoop = pffLoop->pNext;
  2127. }
  2128. }
  2129. End:
  2130. //
  2131. // Set the status bar text to how many results we have found
  2132. //
  2133. *szBuffer = 0;
  2134. iTotalResults = ListView_GetItemCount(hwndList);
  2135. strStatus.Sprintf(GetString(IDS_QDB_COUNT),
  2136. _itot(iTotalResults, szBuffer, 10));
  2137. SetStatus(GetDlgItem(GetParent(hdlg), IDC_STATUSBAR), strStatus);
  2138. }
  2139. INT_PTR
  2140. SearchFixDescDlgProcOnInitDialog(
  2141. IN HWND hdlg
  2142. )
  2143. /*++
  2144. SearchFixDescDlgProcOnInitDialog
  2145. Desc: The handler of WM_INITDIALOG for the third qdb tab page. This page
  2146. searches for fixes based on key words that are searached in the description
  2147. text of the fix
  2148. Params:
  2149. IN HWND hDlg: The third wizard page
  2150. Return:
  2151. TRUE
  2152. --*/
  2153. {
  2154. INT iIndex = 0;
  2155. HWND hwndSearch = GetDlgItem(hdlg, IDC_TEXT);
  2156. HWND hwndCombo = GetDlgItem(hdlg, IDC_COMBO);
  2157. //
  2158. // Restrict the length of the text
  2159. //
  2160. SendMessage(hwndSearch, EM_LIMITTEXT, (WPARAM)MAX_FIXDESC_SEARCH - 1, (LPARAM)0);
  2161. //
  2162. // Add the search type strings
  2163. //
  2164. iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_QDB_ANYWORD));
  2165. SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)QDB_SEARCH_ANYWORD);
  2166. iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_QDB_ALLWORDS));
  2167. SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)QDB_SEARCH_ALLWORDS);
  2168. //
  2169. // Select the first string
  2170. //
  2171. SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
  2172. return TRUE;
  2173. }
  2174. INT_PTR CALLBACK
  2175. SearchFixDescDlgProc(
  2176. IN HWND hdlg,
  2177. IN UINT uMsg,
  2178. IN WPARAM wParam,
  2179. IN LPARAM lParam
  2180. )
  2181. /*++
  2182. SearchFixDescDlgProc
  2183. Desc: Dialog proc for the third tab page. This page finds fixes that have specific
  2184. words in their description text or in their names
  2185. Params: Standard dialog handler parameters
  2186. IN HWND hDlg
  2187. IN UINT uMsg
  2188. IN WPARAM wParam
  2189. IN LPARAM lParam
  2190. Return: Standard dialog handler return
  2191. --*/
  2192. {
  2193. int wCode = LOWORD(wParam);
  2194. int wNotifyCode = HIWORD(wParam);
  2195. switch (uMsg) {
  2196. case WM_INITDIALOG:
  2197. SearchFixDescDlgProcOnInitDialog(hdlg);
  2198. break;
  2199. case WM_USER_NEWQDB:
  2200. SetDlgItemText(hdlg, IDC_TEXT, TEXT(""));
  2201. SetDlgItemText(hdlg, IDC_DESC, TEXT(""));
  2202. DeleteAll(GetParent(hdlg));
  2203. break;
  2204. case WM_USER_DOTHESEARCH:
  2205. SetCursor(LoadCursor(NULL, IDC_WAIT));
  2206. DoTheFixesSearch(hdlg);
  2207. SetCursor(LoadCursor(NULL, IDC_ARROW));
  2208. break;
  2209. default: return FALSE;
  2210. }
  2211. return TRUE;
  2212. }