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

/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
QueryDB_UI.cpp
Abstract:
GUI for the Query Databases option
Author:
kinshu created October 12, 2001
Notes:
The query dialog box performs two types of searches. One is when it actually makes a SQL
query and passes it to the SQL driver and shows the results in the result list view.
The lParam of the list view then are pointers to RESULT_ITEM objects. (1,2,4) tab pages
Second is the case when we are doing a query for some shims, like show all the shims that have 'x'
in their desc. text. (3rd tab page). In this case the query is not passed to the sql driver
and we do the query on our own. The SQL driver can execute queries where the result is some
fixed program entry (and the database that it lives in, please see RESULT_ITEM).
In this case the lparam of the list view is pointers to the individual shims in the system database
We do not free anything from the lParam of the list view. In the case when the query is of type
1 as mentioned above, the RESULT_ITEM are freed when we close the Statement.
In case of queries of type 2, the shims themseleves should not be freed, they belong to the database
they live in (The system database).
--*/
#include "precomp.h"
//////////////////////// Defines ///////////////////////////////////////////////
// Number of pages in the tab
#define PAGE_COUNT 4
// ID for the first tab page
#define QDB_PAGE1 0
// ID for the second tab page
#define QDB_PAGE2 1
// ID for the third tab page
#define QDB_PAGE3 2
// ID for the fourth tab page
#define QDB_PAGE4 3
// We want to search all the databases
#define DATABASE_ALL 0
// Indexes into DatabasesMapping
#define IND_SYSTDB 0
#define IND_INSTDB 1
#define IND_CUSTDB 2
// Maximum for the progress bar
#define MAX_PROGRESS 2000
//
// Maximum buffer size to be allocated for the string that will store
// search string in the third wizard page, where the user tries to search for
// fixes that have specific words in their description text
#define MAX_FIXDESC_SEARCH 1024
// Maximum number fof tchars that can come in the SELECT clause.
#define MAX_SELECT 512
// Maximum number fof tchars that can come in the WHERE clause.
#define MAX_WHERE 1022
// Width of a column in the result list view when searching for entries
#define COLUMN_WIDTH 20
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Externs //////////////////////////////////////////////
extern HWND g_hwndEntryTree;
extern HINSTANCE g_hInstance;
extern BOOL g_bSomeWizardActive;
extern struct _tagAttributeShowMapping AttributeShowMapping[];
extern struct _tagAttributeMatchMapping AttributeMatchMapping[];
extern struct _tagDatabasesMapping DatabasesMapping[3];
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Global Variables /////////////////////////////////////
// The statement
Statement stmt;
// The width of the query db Dialog
int g_cWidthQuery = 0;
// The height of the query db Dialog
int g_cHeightQuery = 0;
// The handle to the main dialog
HWND g_hdlgQueryDB;
// The type of search we did last time
INT g_iLastSearchType;
// The bit array that describes what columns are sorted in what manner
static LONG s_lColumnSort;
// Do we have a empty column header that we have to remove
static BOOL s_bEmptyHeader = TRUE;
// The thread that performs the query
static HANDLE s_hThread;
// The handle to the wait window. This window will pop up if we are trying to close the
// qdb window when the thread is busy.
static HWND s_hWaitDialog;
// Code for any error that occur while collecting info from the GUI.
// If this is non-zero then we display some error and SQL query is not executed
static INT s_iErrorCode;
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Typedefs/Enums ///////////////////////////////////////
typedef enum {
QDB_SEARCH_ANYWORD = 0,
QDB_SEARCH_ALLWORDS = 1
} QDB_SEARCH_TYPE;
typedef struct _tagDialogData
{
HANDLE hMainThread;
HWND hdlg;
}DIALOG_DATA;
typedef struct tag_dlghdr {
HWND hwndTab; // tab control
HWND hwndPages[PAGE_COUNT];
INT iPresentTabIndex;
RECT rcDisplay;
tag_dlghdr()
{
ZeroMemory(hwndPages, sizeof(hwndPages));
iPresentTabIndex = -1;
}
} DLGHDR;
///////////////////////////////////////////////////////////////////////////////
//////////////////////// Function Declarations ////////////////////////////////
INT_PTR CALLBACK
QdbWaitDlg(
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
void
GotoQdbEntry(
HWND hdlg,
LPARAM lParam
);
void
SaveResultsQdb(
HWND hdlg
);
void
DoNewQdb(
HWND hdlg
);
void
OnSearch(
HWND hdlg
);
void
HandleQueryDBSizing(
HWND hDlg
);
void
Start(
HWND hdlg
);
void
HandleListNotification(
HWND hdlg,
LPARAM lParam
);
DWORD WINAPI
QueryDBThread(
LPVOID pVoid
);
VOID
WINAPI
OnChildDialogInit(
HWND hwndDlg
);
VOID
WINAPI
OnChildDialogInit(
HWND hwndDlg
);
VOID
WINAPI
OnSelChanged(
HWND hwndDlg
);
INT_PTR
CALLBACK
SearchOnAppDlgProc(
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
INT_PTR CALLBACK
SearchOnFixDlgProc(
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam);
INT_PTR
CALLBACK
AdvancedSearchDlgProc(
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
INT_PTR
CALLBACK
SearchFixDescDlgProc(
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
void
HandleTabNotification(
HWND hdlg,
LPARAM lParam
);
void
HandleAdvancedListNotification(
HWND hdlg,
LPARAM lParam
);
void
DeleteAll(
HWND hdlg
);
///////////////////////////////////////////////////////////////////////////////
void
LoadDatabaseTypes(
IN HWND hdlg
)
/*++
LoadDatabaseTypes
Desc: Loads the database types in the combo box
Params:
IN HWND hdlg: The query dialog box
Return:
void
--*/
{
HWND hwndCombo = GetDlgItem(hdlg, IDC_COMBO);
//
// All databases
//
INT iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_ALLDATABASES));
SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_ALL);
//
// System database
//
iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_SYSDB));
SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_TYPE_GLOBAL);
//
// Installed databases
//
iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_INSTALLEDDB));
SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_TYPE_INSTALLED);
//
// Custom databases
//
iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_WORKDB));
SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)DATABASE_TYPE_WORKING);
//
// Select the first string
//
SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
}
INT_PTR CALLBACK
QueryDBDlg(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
QueryDBDlg
Desc: Dialog Proc for the main Query database dialog.
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG:
{
DLGHDR* pHdr = NULL;
TCITEM tie;
RECT r;
//
// Limit the text field for the hidden text box. Please note that
// we will concatenate the results of the select and the where text fields
// and put the actual SQL in the form of 'SELECT .. FROM .. [WHERE ..]' in this
// text field
//
SendMessage(GetDlgItem(hdlg, IDC_SQL),
EM_LIMITTEXT,
(WPARAM)MAX_SQL_LENGTH - 1,
(LPARAM)0);
g_hdlgQueryDB = hdlg;
s_lColumnSort = 0;
ListView_SetExtendedListViewStyleEx(GetDlgItem(hdlg, IDC_LIST),
0,
LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), TEXT(""));
LoadDatabaseTypes(hdlg);
Animate_OpenEx(GetDlgItem(hdlg, IDC_ANIMATE),
g_hInstance,
MAKEINTRESOURCE(IDA_SEARCH));
//
// Set up the tab control
//
pHdr = new DLGHDR;
if (pHdr == NULL) {
MEM_ERR;
break;
}
pHdr->hwndTab = GetDlgItem(hdlg, IDC_TAB);
GetWindowRect(pHdr->hwndTab, &pHdr->rcDisplay);
SendMessage(pHdr->hwndTab, WM_SETREDRAW, TRUE, 0);
SetWindowLongPtr(hdlg, GWLP_USERDATA, (LONG_PTR)pHdr);
ZeroMemory(&tie, sizeof(tie));
tie.mask = TCIF_TEXT;
tie.pszText = GetString(IDS_APP_PROPERTIES);
TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE1, &tie);
tie.pszText = GetString(IDS_FIX_PROPERTIES);
TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE2, &tie);
tie.pszText = GetString(IDS_ADVANCED);
TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE4, &tie);
tie.pszText = GetString(IDS_FIX_DESCRIPTION);
TabCtrl_InsertItem(pHdr->hwndTab, QDB_PAGE3, &tie);
//
// The page where we select apps by name
//
pHdr->hwndPages[QDB_PAGE1] = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_QDB_PAGE1),
hdlg,
SearchOnAppDlgProc);
//
// The page where we select apps by the fixes applied
//
pHdr->hwndPages[QDB_PAGE2] = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_QDB_PAGE2),
hdlg,
SearchOnFixDlgProc);
//
// The page where we search by the words in the descriptipon of the fix or in the name
//
pHdr->hwndPages[QDB_PAGE3] = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_QDB_PAGE3),
hdlg,
SearchFixDescDlgProc);
//
// The advanced page
//
pHdr->hwndPages[QDB_PAGE4] = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_QDB_PAGE4),
hdlg,
AdvancedSearchDlgProc);
//
// Set the background properly and position the pages in the tab control
//
OnChildDialogInit(pHdr->hwndPages[QDB_PAGE1]);
OnChildDialogInit(pHdr->hwndPages[QDB_PAGE2]);
OnChildDialogInit(pHdr->hwndPages[QDB_PAGE3]);
OnChildDialogInit(pHdr->hwndPages[QDB_PAGE4]);
//
// Select the first page
//
OnSelChanged(hdlg);
//
// Get the height and width so that we can properly resize the dialog box
//
GetWindowRect(hdlg, &r);
g_cWidthQuery = r.right - r.left;
g_cHeightQuery = r.bottom - r.top;
InsertColumnIntoListView(GetDlgItem(hdlg, IDC_LIST), TEXT(""), 0, 100);
s_bEmptyHeader = TRUE;
break;
}
case WM_GETMINMAXINFO:
{
//
// Limit the min width and height of the dialog box
//
MINMAXINFO* pmmi = (MINMAXINFO*)lParam;
pmmi->ptMinTrackSize.x = 550;
pmmi->ptMinTrackSize.y = 365;
return 0;
break;
}
case WM_SIZE:
if (wParam != SIZE_MINIMIZED) {
HandleQueryDBSizing(hdlg);
}
break;
case WM_COMMAND:
{
switch (wCode) {
case ID_SEARCH:
{
DLGHDR* pHdr = (DLGHDR*)GetWindowLongPtr(g_hdlgQueryDB, GWLP_USERDATA);
HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
if (pHdr == NULL) {
assert(FALSE);
break;
}
g_iLastSearchType = pHdr->iPresentTabIndex;
//
// When the user will click on some column for the first time, we will now
// sort that in ascending order
//
s_lColumnSort = -1;
if (GetFocus() == hwndList
&& ListView_GetNextItem(hwndList, -1, LVNI_SELECTED) != -1) {
//
// We will get this message when we press enter in the list box,
// as ID_SEARCH is the default button.
// So in this case we have to pretend as the user double clicked in the list
// view
//
SendNotifyMessage(hdlg, WM_COMMAND, (WPARAM)ID_VIEWCONTENTS, 0);
} else if (pHdr->iPresentTabIndex == QDB_PAGE3) {
//
// We are trying to do a search on fix description
//
SendMessage(pHdr->hwndPages[QDB_PAGE3], WM_USER_DOTHESEARCH, 0, 0);
} else {
//
// Normal SQL query
//
OnSearch(hdlg);
}
}
break;
case ID_VIEWCONTENTS:
{
//
// The user wishes to see the contents. We must now find and select
// the correct entry in the db tree and the entry tree
//
HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
INT iSelection = ListView_GetSelectionMark(hwndList);
if (iSelection == -1) {
break;
}
LVITEM lvi;
PMATCHEDENTRY pmMatched;
ZeroMemory(&lvi, sizeof(lvi));
lvi.iItem = iSelection;
lvi.iSubItem = 0;
lvi.mask = LVIF_PARAM;
if (ListView_GetItem(hwndList, &lvi)) {
GotoQdbEntry(hdlg, lvi.lParam);
}
break;
}
case IDCANCEL:
if (s_hThread) {
//
// Need to wait for thread to terminate if it is running
//
if (!s_hWaitDialog) {
s_hWaitDialog = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_QDBWAIT),
g_hdlgQueryDB,
QdbWaitDlg);
ShowWindow(s_hWaitDialog, SW_NORMAL);
}
break;
}
Animate_Close(GetDlgItem(hdlg, IDC_ANIMATE));
stmt.Close();
DestroyWindow(hdlg);
break;
case IDC_NEWSEARCH:
DoNewQdb(hdlg);
break;
case IDC_SAVE:
SaveResultsQdb(hdlg);
break;
case ID_QDB_HELP:
ShowInlineHelp(TEXT("using_the_query_tool.htm"));
break;
default:
return FALSE;
}
}
break;
case WM_DESTROY:
{
DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
//
// Destroy the individual modeless dialog boxes
//
DestroyWindow(pHdr->hwndPages[QDB_PAGE1]);
DestroyWindow(pHdr->hwndPages[QDB_PAGE2]);
DestroyWindow(pHdr->hwndPages[QDB_PAGE3]);
DestroyWindow(pHdr->hwndPages[QDB_PAGE4]);
if (pHdr) {
delete pHdr;
pHdr = NULL;
}
stmt.Close();
g_hdlgQueryDB = NULL;
PostMessage(g_hDlg, WM_USER_ACTIVATE, 0, 0);
break;
}
case WM_NOTIFY:
{
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
if (lpnmhdr && lpnmhdr->idFrom == IDC_LIST) {
HandleListNotification(hdlg, lParam);
} else if (lpnmhdr && lpnmhdr->idFrom == IDC_TAB) {
HandleTabNotification(hdlg, lParam);
}
break;
}
default: return FALSE;
}
return TRUE;
}
void
Start(
IN HWND hdlg
)
/*++
Start
Desc: Creates the thread that will do the actual search.
Params:
IN HWND hdlg: Handle to the query dialog box.
Return:
void
--*/
{
DWORD dwID; // Will contain the thread id.
ENABLEWINDOW(GetDlgItem(hdlg, ID_SEARCH), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_NEWSEARCH), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_SAVE), FALSE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_STATIC_CAPTION), FALSE);
SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), TEXT(""));
s_hThread = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START)QueryDBThread, (PVOID)hdlg, 0, (unsigned int*)&dwID);
}
DWORD WINAPI
QueryDBThread(
IN LPVOID pVoid
)
/*++
QueryDBThread
Desc: The thread routine that does the actual search
Params:
IN LPVOID pVoid: The handle to the query dialog
Return:
0
--*/
{
HWND hdlg = (HWND)pVoid;
CSTRING strStatus;
TCHAR szBuffer[32];
INT iTotalResults;
ResultSet* prs = NULL;
static TCHAR s_szSQL[MAX_SQL_LENGTH] = TEXT("");
GetWindowText(GetDlgItem(hdlg, IDC_SQL), s_szSQL, ARRAYSIZE(s_szSQL) - 1);
s_szSQL[ARRAYSIZE(s_szSQL) - 1] = 0;
if (CSTRING::Trim(s_szSQL) == 0) {
MessageBox(hdlg,
GetString(IDS_ERROR_SELECT_NOTFOUND),
g_szAppName,
MB_ICONERROR);
goto End;
}
Animate_Play(GetDlgItem(hdlg, IDC_ANIMATE), 0, -1, -1);
//
// We do not want the user to make changes in the databases, when we are running the
// query.
//
ENABLEWINDOW(g_hDlg, FALSE);
prs = stmt.ExecuteSQL(hdlg, s_szSQL);
//
// Do not forget to enable the main window again
//
ENABLEWINDOW(g_hDlg, TRUE);
//
// Now first of all add the columns to the listview
//
PNODELIST pShowList = stmt.GetShowList();
if (pShowList == NULL) {
goto End;
}
UINT uCols = pShowList->m_uCount;
HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
TCHAR szColumnName[64];
PNODE pNodeShow = pShowList->m_pHead;
if (pNodeShow) {
//
// If the empty header is still there, must get rid of it.
//
if (s_bEmptyHeader) {
ListView_DeleteColumn(hwndList, 0);
s_bEmptyHeader = FALSE;
}
}
INT iIndex = 0;
//
// Add all the columns for the clauses in SELECT in the list view
//
while (pNodeShow) {
*szColumnName = 0;
InsertColumnIntoListView(hwndList,
pNodeShow->ToString(szColumnName, ARRAYSIZE(szColumnName)),
iIndex, COLUMN_WIDTH);
pNodeShow = pNodeShow->pNext;
++iIndex;
}
LVITEM lvi;
TCHAR szString[MAX_PATH];
int iIndexDesired = 0;
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_TEXT | LVIF_PARAM;
if (uCols > 0) {
while (prs && prs->GetNext()) {
PNODE pNodeRow = new NODE[uCols];
if (pNodeRow == NULL) {
MEM_ERR;
goto End;
}
//
// Create the new list view item for this row of results
//
prs->GetCurrentRow(pNodeRow);
*szString = 0;
lvi.pszText = pNodeRow[0].ToString(szString, ARRAYSIZE(szString));
lvi.iSubItem = 0;
lvi.lParam = (LPARAM)prs->GetCursor();
lvi.iItem = iIndexDesired;
INT iRowIndex = ListView_InsertItem(hwndList, &lvi);
//
// Put values for all other sub-columns
//
for (UINT iColIndex = 1; iColIndex < uCols; ++iColIndex) {
*szString = 0;
pNodeRow[iColIndex].ToString(szString, ARRAYSIZE(szString));
ListView_SetItemText(hwndList, iRowIndex, iColIndex, szString);
}
iIndexDesired++;
if (pNodeRow) {
delete[] pNodeRow;
pNodeRow = NULL;
}
}
}
End:
ENABLEWINDOW(GetDlgItem(hdlg, ID_SEARCH), TRUE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_NEWSEARCH), TRUE);
ENABLEWINDOW(GetDlgItem(hdlg, IDC_SAVE), TRUE);
iTotalResults = (prs) ? prs->GetCount() : 0;
*szBuffer = 0;
strStatus.Sprintf(GetString(IDS_QDB_COUNT),
_itot(iTotalResults,
szBuffer,
10));
SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), strStatus);
//
// Stop the animation.
//
Animate_Stop(GetDlgItem(hdlg, IDC_ANIMATE));
CloseHandle(s_hThread);
s_hThread = NULL;
ENABLEWINDOW(GetDlgItem(hdlg, IDC_STATIC_CAPTION), iTotalResults > 0);
SetActiveWindow(g_hdlgQueryDB);
SetFocus(g_hdlgQueryDB);
return 0;
}
void
ProcessItemChanged(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
ProcessItemChange
Desc: Processes the LVN_ITEMCHANGED message for the search list
Please note that we process this message only when we did a shim search
Params:
IN HWND hdlg: The query dialog box
IN LPARAM lParam: The lParam that comes with WM_NOTIFY
--*/
{
LVITEM lvItem;
TYPE type;
LPNMLISTVIEW pnmlv;
CSTRING strDescription;
HWND hwndList;
HWND hwndFixDesc;
DLGHDR* pHdr = NULL;
//
// If we have searched for shims last time then we must set the description text for the
// shim in the description window of the shim search page
//
if (g_iLastSearchType != QDB_PAGE3) {
goto End;
}
pHdr = (DLGHDR*)GetWindowLongPtr(g_hdlgQueryDB, GWLP_USERDATA);
if (pHdr == NULL) {
assert(FALSE);
goto End;
}
hwndList = GetDlgItem(hdlg, IDC_LIST);
hwndFixDesc = GetDlgItem(pHdr->hwndPages[QDB_PAGE3], IDC_DESC);
pnmlv = (LPNMLISTVIEW)lParam;
if (pnmlv && (pnmlv->uChanged & LVIF_STATE)) {
//
// State changed
//
if (pnmlv->uNewState & LVIS_SELECTED) {
//
// New item is selected
//
lvItem.mask = TVIF_PARAM;
lvItem.iItem = pnmlv->iItem;
lvItem.iSubItem = 0;
if (!ListView_GetItem(hwndList, &lvItem)) {
goto End;
}
type = ConvertLparam2Type(lvItem.lParam);
if (type == FIX_FLAG || type == FIX_SHIM) {
//
// We only process this message when the item in the list view is shim or a flag
//
GetDescriptionString(lvItem.lParam,
strDescription,
NULL,
NULL,
NULL,
hwndList,
pnmlv->iItem);
if (strDescription.Length() > 0) {
//
// For some fixes, we do not have a desc. but we did find one for the
// presently selected fix
//
SetWindowText(hwndFixDesc, (LPCTSTR)strDescription);
} else {
//
// No description is available for this fix
//
SetWindowText(hwndFixDesc, GetString(IDS_NO_DESC_AVAILABLE));
}
} else {
assert(FALSE);
}
}
}
End: ;
}
void
HandleListNotification(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
HandleListNotification
Desc: Handles the notification messages for the search results list view
Params:
IN HWND hdlg: The query dialog box
IN LPARAM lParam: The LPARAM of WM_NOTIFY
Return:
void
--*/
{
HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
if (lpnmhdr == NULL) {
return;
}
switch (lpnmhdr->code) {
case LVN_COLUMNCLICK:
{
LPNMLISTVIEW pnmlv = (LPNMLISTVIEW)lParam;
COLSORT colSort;
colSort.hwndList = hwndList;
colSort.iCol = pnmlv->iSubItem;
colSort.lSortColMask = s_lColumnSort;
ListView_SortItemsEx(hwndList, CompareItemsEx, &colSort);
if ((s_lColumnSort & 1L << colSort.iCol) == 0) {
//
// Was in ascending order
//
s_lColumnSort |= (1L << colSort.iCol);
} else {
s_lColumnSort &= (~(1L << colSort.iCol));
}
break;
}
case NM_DBLCLK:
{
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
LVITEM lvItem = {0};
if (lpnmitem == NULL) {
break;
}
lvItem.mask = TVIF_PARAM;
lvItem.iItem = lpnmitem->iItem;
lvItem.iSubItem = 0;
if (!ListView_GetItem(hwndList, &lvItem)) {
break;
}
GotoQdbEntry(hdlg, lvItem.lParam);
break;
}
case LVN_ITEMCHANGED:
ProcessItemChanged(hdlg, lParam);
break;
}
}
VOID WINAPI
OnSelChanged(
IN HWND hwndDlg
)
/*++
OnSelChanged
Desc: Handles the change of the tab. Hides the present tab and shows the
next tab.
Params:
IN HWND hwndDlg: The query dialog box
Return:
void
--*/
{
DLGHDR* pHdr = (DLGHDR*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
if (pHdr == NULL || hwndDlg == NULL) {
assert(FALSE);
return;
}
int iSel = TabCtrl_GetCurSel(pHdr->hwndTab);
HWND hwndCombo;
hwndCombo = GetDlgItem(hwndDlg, IDC_COMBO);
if (iSel != -1 && pHdr->iPresentTabIndex != -1) {
ShowWindow(pHdr->hwndPages[pHdr->iPresentTabIndex], SW_HIDE);
}
pHdr->iPresentTabIndex = iSel;
ShowWindow(pHdr->hwndPages[iSel], SW_SHOWNORMAL);
//
// Set the focus to the first child that has tab set
//
switch (iSel) {
case QDB_PAGE1:
ENABLEWINDOW(hwndCombo, TRUE);
SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_APPNAME));
break;
case QDB_PAGE2:
ENABLEWINDOW(hwndCombo, TRUE);
SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_NAME));
break;
case QDB_PAGE3:
ENABLEWINDOW(hwndCombo, FALSE);
SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_TEXT));
break;
case QDB_PAGE4:
ENABLEWINDOW(hwndCombo, TRUE);
SetFocus(GetDlgItem(pHdr->hwndPages[iSel], IDC_SELECT));
break;
}
}
VOID
WINAPI
OnChildDialogInit(
IN HWND hwndDlg
)
/*++
OnChildDialogInit
Desc: This routine is called when a page of the tab is first loaded.
This routine sets the background properly for the tab
and positions the page
Params:
IN HWND hwndDlg: The query dialog box
Return:
void
--*/
{
HWND hwndParent = GetParent(hwndDlg);
DLGHDR* pHdr = (DLGHDR*)GetWindowLongPtr(hwndParent, GWLP_USERDATA);
HWND hwndTab = pHdr->hwndTab;
RECT rcTab;
EnableTabBackground(hwndDlg);
GetWindowRect(hwndTab, &rcTab);
TabCtrl_AdjustRect(hwndTab, FALSE, &rcTab);
MapWindowPoints(NULL, GetParent(hwndTab), (LPPOINT)&rcTab, 2);
SetWindowPos(hwndDlg,
HWND_TOP,
rcTab.left,
rcTab.top,
rcTab.right - rcTab.left,
rcTab.bottom - rcTab.top,
SWP_HIDEWINDOW);
return;
}
void
SearchOnAppOnGetSql(
IN HWND hdlg,
IN WPARAM wParam,
IN OUT LPARAM lParam
)
/*++
SearchOnAppOnGetUserSql
Desc: Processes the WM_USER_GETSQL for the first tab page
Params:
IN HWND hdlg: The handle to the First page of the tab
IN WPARAM wParam: The length of the string buffer that is in lParam. The length is in
TCHARs
IN OUT LPARAM lParam: The pointer to the string. This will contain the "FROM" clause.
The completed SQL will be returned in this.
Return:
void
--*/
{
TCHAR szFrom[260];
TCHAR szAppName[260];
TCHAR szEntryName[MAX_PATH];
CSTRING strSelectClauses;
CSTRING strWhereClauses;
TCHAR* pszSQL = (TCHAR*)lParam;
BOOL bPreFixAdded = FALSE; // Whether we have added the 'AND (' prefix for this part of the SQL
if (pszSQL == NULL) {
assert(FALSE);
return;
}
//
// Set the attributes that we are always going to show
//
strSelectClauses = TEXT("APP_NAME, PROGRAM_NAME");
*szFrom = 0;
SafeCpyN(szFrom, pszSQL, ARRAYSIZE(szFrom));
//
// We will now create the sql.
//
*szEntryName = *szAppName = 0;
GetDlgItemText(hdlg, IDC_APPNAME, szAppName, ARRAYSIZE(szAppName));
//
// Get rid of quotes if the user puts them
//
ReplaceChar(szAppName, TEXT('\"'), TEXT(' '));
if (CSTRING::Trim(szAppName) == 0) {
//
// Field was empty, replace with wild-card
//
SetDlgItemText(hdlg, IDC_APPNAME, TEXT("%"));
szAppName[0] = TEXT('%');
szAppName[1] = TEXT('\0');
}
GetDlgItemText(hdlg, IDC_ENTRYNAME, szEntryName, ARRAYSIZE(szEntryName));
ReplaceChar(szEntryName, TEXT('\"'), TEXT(' '));
if (CSTRING::Trim(szEntryName) == 0) {
//
// Field was empty, replace with wild-card
//
SetDlgItemText(hdlg, IDC_ENTRYNAME, TEXT("%"));
szEntryName[0] = TEXT('%');
szEntryName[1] = TEXT('\0');
}
//
// Set the default where clause for this page
//
strWhereClauses.Sprintf(TEXT("APP_NAME = \"%s\" AND PROGRAM_NAME = \"%s\" "),
szAppName,
szEntryName);
//
// Check if the layer check box is selected
//
if (SendMessage(GetDlgItem(hdlg, IDC_LAYERS), BM_GETCHECK, 0, 0) == BST_CHECKED) {
//
// We now need to show the count and the names of the layers
//
strSelectClauses.Strcat(TEXT(", MODE_COUNT, MODE_NAME "));
//
// Add the where clauses for the layers
//
bPreFixAdded = TRUE;
strWhereClauses.Strcat(TEXT(" AND ( MODE_COUNT > 0 "));
}
//
// check if the shim check box is selected
//
if (SendMessage(GetDlgItem(hdlg, IDC_SHIMS), BM_GETCHECK, 0, 0) == BST_CHECKED) {
//
// We now need to show the count and the names of the shims
//
strSelectClauses.Strcat(TEXT(", FIX_COUNT, FIX_NAME"));
//
// Add the where clauses for the shims
//
if (bPreFixAdded == FALSE) {
strWhereClauses.Strcat(TEXT(" AND ( "));
bPreFixAdded = TRUE;
} else {
strWhereClauses.Strcat(TEXT(" AND "));
}
strWhereClauses.Strcat(TEXT(" FIX_COUNT > 0 "));
}
//
// check if the apphelp check box is selected
//
if (SendMessage(GetDlgItem(hdlg, IDC_APPHELP), BM_GETCHECK, 0, 0) == BST_CHECKED) {
if (bPreFixAdded == FALSE) {
strWhereClauses.Strcat(TEXT(" AND ( "));
bPreFixAdded = TRUE;
} else {
strWhereClauses.Strcat(TEXT(" AND "));
}
strWhereClauses.Strcat(TEXT(" PROGRAM_APPHELPUSED = TRUE "));
}
if (bPreFixAdded) {
//
// Must close the parenthesis
//
strWhereClauses.Strcat(TEXT(")"));
}
if (StringCchPrintf(pszSQL,
wParam,
TEXT("SELECT %s FROM %s WHERE %s"),
(LPCTSTR)strSelectClauses,
szFrom,
(LPCTSTR)strWhereClauses) != S_OK) {
assert(FALSE);
Dbg(dlError, "SearchOnAppOnGetSql", "Inadequate buffer size");
}
}
void
SearchOnFixOnGetSql(
IN HWND hdlg,
IN WPARAM wParam,
IN OUT LPARAM lParam
)
/*++
SearchOnAppOnGetUserSql
Desc: Processes the WM_USER_GETSQL for the first tab page
Params:
IN HWND hdlg: The handle to the First page of the tab
IN WPARAM wParam: The length of the string buffer that is in lParam. The length is in
TCHARs
IN OUT LPARAM lParam: The pointer to the string. This will contain the "FROM" clause.
The completed SQL will be returned in this.
Return:
void
--*/
{
TCHAR* pszSQL = (TCHAR*)lParam;
TCHAR szFrom[MAX_PATH];
TCHAR szName[MAX_PATH]; // The string that will take in the contents of the text field
CSTRING strSelectClauses;
CSTRING strWhereClauses;
BOOL bPreFixAdded = FALSE; // Whether we have added the 'AND ' prefix for this part of the SQL
BOOL bValid = FALSE; // Did the user select some check box
if (pszSQL == NULL) {
assert(FALSE);
return;
}
//
// Set the attributes that we are always going to show
//
strSelectClauses = TEXT("APP_NAME, PROGRAM_NAME");
*szFrom = 0;
SafeCpyN(szFrom, pszSQL, ARRAYSIZE(szFrom));
GetDlgItemText(hdlg, IDC_NAME, szName, ARRAYSIZE(szName));
//
// Get rid of quotes if the user puts them
//
ReplaceChar(szName, TEXT('\"'), TEXT(' '));
if (CSTRING::Trim(szName) == 0) {
//
// Field was empty, replace with wild-card
//
SetDlgItemText(hdlg, IDC_NAME, TEXT("%"));
szName[0] = TEXT('%');
szName[1] = TEXT('\0');
}
//
// check if the shim check box is selected
//
if (SendMessage(GetDlgItem(hdlg, IDC_SHIM), BM_GETCHECK, 0, 0) == BST_CHECKED) {
bPreFixAdded = TRUE;
//
// We now need to show the names of the fixes
//
strSelectClauses.Strcat(TEXT(", FIX_NAME "));
//
// Add the where clauses for the fixes
//
strWhereClauses.Strcat(TEXT(" FIX_NAME HAS \""));
strWhereClauses.Strcat(szName);
strWhereClauses.Strcat(TEXT("\""));
bValid = TRUE;
}
//
// check if the layer check box is selected
//
if (SendMessage(GetDlgItem(hdlg, IDC_MODE), BM_GETCHECK, 0, 0) == BST_CHECKED) {
//
// We now need to show the names of the fixes
//
strSelectClauses.Strcat(TEXT(", MODE_NAME "));
if (bPreFixAdded) {
strWhereClauses.Strcat(TEXT(" AND "));
}
//
// Add the where clauses for the layers
//
strWhereClauses.Strcat(TEXT(" MODE_NAME HAS \""));
strWhereClauses.Strcat(szName);
strWhereClauses.Strcat(TEXT("\""));
bValid = TRUE;
}
if (bValid == FALSE) {
s_iErrorCode = ERROR_GUI_NOCHECKBOXSELECTED;
}
if (StringCchPrintf(pszSQL,
wParam,
TEXT("SELECT %s FROM %s WHERE %s"),
(LPCTSTR)strSelectClauses,
szFrom,
(LPCTSTR)strWhereClauses) != S_OK) {
assert(FALSE);
Dbg(dlError, "SearchOnFixOnGetSql", "Inadequate buffer space");
}
}
void
HandleTabNotification(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
HandleTabNotification
Desc: Handles the notification messages for the tab control in the query dialog
Params:
IN HWND hdlg: The query dialog box
IN LPARAM lParam: The LPARAM of WM_NOTIFY
Return:
void
--*/
{
LPNMHDR pnm = (LPNMHDR)lParam;
int ind = 0;
switch (pnm->code) {
// Handle mouse clicks and keyboard events
case TCN_SELCHANGE:
OnSelChanged(hdlg);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
//
// Dialog Procs for the pages of the Tab
//
//
INT_PTR CALLBACK
SearchOnAppDlgProc(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
SearchOnAppDlgProc
Desc: Dialog proc for the first tab page. This page handles searches
based on the application information.
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG:
{
//
// Restrict the length of the text fields
//
SendMessage(GetDlgItem(hdlg, IDC_APPNAME),
EM_LIMITTEXT,
(WPARAM)LIMIT_APP_NAME,
(LPARAM)0);
SendMessage(GetDlgItem(hdlg, IDC_ENTRYNAME),
EM_LIMITTEXT,
(WPARAM)MAX_PATH - 1,
(LPARAM)0);
break;
}
case WM_USER_NEWQDB:
SetDlgItemText(hdlg, IDC_APPNAME, TEXT(""));
SetDlgItemText(hdlg, IDC_ENTRYNAME, TEXT(""));
SendMessage(GetDlgItem(hdlg, IDC_LAYERS), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hdlg, IDC_SHIMS), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hdlg, IDC_APPHELP), BM_SETCHECK, BST_UNCHECKED, 0);
DeleteAll(GetParent(hdlg));
break;
case WM_USER_GETSQL:
SearchOnAppOnGetSql(hdlg, wParam, lParam);
break;
default: return FALSE;
}
return TRUE;
}
INT_PTR CALLBACK
SearchOnFixDlgProc(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
SearchOnFixDlgProc
Desc: Dialog proc for the second tab page. This page handles searches
based on the layer/shim name contained in the entries
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG:
{
SendMessage(GetDlgItem(hdlg, IDC_NAME),
EM_LIMITTEXT,
(WPARAM)LIMIT_APP_NAME,
(LPARAM)0);
break;
}
case WM_USER_NEWQDB:
SetDlgItemText(hdlg, IDC_NAME, TEXT(""));
SendMessage(GetDlgItem(hdlg, IDC_SHIM), BM_SETCHECK, BST_UNCHECKED, 0);
SendMessage(GetDlgItem(hdlg, IDC_MODE), BM_SETCHECK, BST_UNCHECKED, 0);
DeleteAll(GetParent(hdlg));
break;
case WM_USER_GETSQL:
{
SearchOnFixOnGetSql(hdlg, wParam, lParam);
break;
}
default: return FALSE;
}
return TRUE;
}
void
LoadSelectList(
IN HWND hdlg
)
/*++
LoadSelectList
Desc: Loads the list of attributes in the SELECT clause list view. This is used in
the advanced tab page
Params:
IN HWND hdlg: The query dialog box
Return:
void
--*/
{
HWND hwndList = GetDlgItem(hdlg, IDC_SELECT_LIST);
LVITEM lvi;
INT iIndex = 0;
ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT);
InsertColumnIntoListView(hwndList, 0, 0, 97);
lvi.mask = LVIF_TEXT | LVIF_PARAM;
for (iIndex = 0; iIndex < GetSelectAttrCount() ; ++iIndex) {
lvi.pszText = AttributeShowMapping[iIndex].szAttribute;
lvi.iSubItem = 0;
lvi.lParam = iIndex;
lvi.iItem = iIndex;
ListView_InsertItem(hwndList, &lvi);
}
//
// We have to add the "*" separately. Do NOT have this in the AttributeMatchMapping
//
lvi.lParam = iIndex;
lvi.iItem = iIndex;
lvi.pszText = TEXT("*");
ListView_InsertItem(hwndList, &lvi);
InvalidateRect(hwndList, NULL, TRUE);
UpdateWindow(hwndList);
}
void
LoadWhereList(
HWND hdlg
)
{
/*++
LoadWhereList
Desc: Loads the list of "where" attributes. This is used in
the advanced tab page
Params:
IN HWND hdlg: The query dialog box
Return:
void
--*/
HWND hwndList = GetDlgItem(hdlg, IDC_WHERE_LIST);
LVITEM lvi = {0};
INT iIndex = 0;
ListView_SetExtendedListViewStyle(hwndList, LVS_EX_FULLROWSELECT);
InsertColumnIntoListView(hwndList, 0, 0, 97);
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.iSubItem = 0;
for (iIndex = 0; iIndex < GetMatchAttrCount(); ++iIndex) {
lvi.pszText = AttributeMatchMapping[iIndex].szAttribute;
lvi.lParam = iIndex;
lvi.iItem = iIndex;
ListView_InsertItem(hwndList, &lvi);
}
InvalidateRect(hwndList, NULL, TRUE);
UpdateWindow(hwndList);
}
INT_PTR CALLBACK
AdvancedSearchDlgProc(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
AdvancedSearchDlgProc
Desc: Dialog proc for the fourth tab page. This page handles the advanced
search option.
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG:
{
SendMessage(GetDlgItem(hdlg, IDC_SELECT), EM_LIMITTEXT,(WPARAM)MAX_SELECT, (LPARAM)0);
SendMessage(GetDlgItem(hdlg, IDC_WHERE), EM_LIMITTEXT,(WPARAM)MAX_WHERE, (LPARAM)0);
//
// Populate the list views with the search and the where attributes
//
LoadSelectList(hdlg);
LoadWhereList(hdlg);
break;
}
case WM_NOTIFY:
{
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
if (lpnmhdr && (lpnmhdr->idFrom == IDC_SELECT_LIST
|| lpnmhdr->idFrom == IDC_WHERE_LIST)) {
HandleAdvancedListNotification(hdlg, lParam);
}
break;
}
case WM_USER_NEWQDB:
SetDlgItemText(hdlg, IDC_SELECT, TEXT(""));
SetDlgItemText(hdlg, IDC_WHERE, TEXT(""));
DeleteAll(GetParent(hdlg));
break;
case WM_USER_GETSQL:
{
//
// lParam: the pointer to the string.
// This will contain the "FROM" clause.
// The completed SQL will be retuned in this.
// wParam: the length of the string
TCHAR* pszSQL = (TCHAR*) lParam;
TCHAR szFrom[MAX_PATH];
TCHAR szSelect[1024], szWhere[1024];
*szSelect = *szWhere = 0;
if (pszSQL == NULL) {
assert(FALSE);
break;
}
*szFrom = 0;
SafeCpyN(szFrom, pszSQL, ARRAYSIZE(szFrom));
GetDlgItemText(hdlg, IDC_SELECT, szSelect, ARRAYSIZE(szSelect));
GetDlgItemText(hdlg, IDC_WHERE, szWhere, ARRAYSIZE(szWhere));
if (CSTRING::Trim(szWhere) != 0) {
StringCchPrintf(pszSQL,
wParam,
TEXT("SELECT %s FROM %s WHERE %s "),
szSelect,
szFrom,
szWhere);
} else {
StringCchPrintf(pszSQL,
wParam,
TEXT("SELECT %s FROM %s "),
szSelect,
szFrom);
}
break;
}
default: return FALSE;
}
return TRUE;
}
void
HandleAdvancedListNotification(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
HandleAdvancedListNotification
Desc: Handles the list notifications for the advanced page of the tab. i.e.
the SELECT list view and the WHERE list view
This will add the SELECT parameters to the SELECT text box
if we double click on the "SELECT" list box.
If we double click on the "Where" list box, this routine will
add the selected param to the WHERE text box
Params:
IN HWND hdlg: The query dialog box
IN LPARAM lParam: The LPARAM for WM_NOTIFY.
Return:
void
--*/
{
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
if (lpnmhdr == NULL) {
return;
}
switch (lpnmhdr->code) {
case NM_DBLCLK:
{
HWND hwndList; // Handle to either the IDC_SELECT_LIST or the IDC_WHERE_LIST
BOOL bEmpty = FALSE; // Whether the text box was empty. This is needed to determine if we should add a leading ','
HWND hwndText;
LVITEM lvItem;
TCHAR szBuffer[MAX_PATH];
TCHAR szTextBoxContents[2096];
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE) lParam;
INT iLength = 0;
if (lpnmitem == NULL) {
break;
}
*szBuffer = *szTextBoxContents = 0;
if (lpnmhdr->idFrom == IDC_SELECT_LIST) {
hwndList = GetDlgItem(hdlg, IDC_SELECT_LIST);
hwndText = GetDlgItem(hdlg, IDC_SELECT);
iLength = MAX_SELECT;
} else {
hwndList = GetDlgItem(hdlg, IDC_WHERE_LIST);
hwndText = GetDlgItem(hdlg, IDC_WHERE);
iLength = MAX_WHERE;
}
lvItem.mask = LVIF_TEXT;
lvItem.iItem = lpnmitem->iItem;
lvItem.iSubItem = 0;
lvItem.pszText = szBuffer;
lvItem.cchTextMax = ARRAYSIZE(szBuffer);
if (!ListView_GetItem(hwndList, &lvItem)) {
break;
}
GetWindowText(hwndText, szTextBoxContents, iLength);
if ((lstrlen(szTextBoxContents) + lstrlen(szBuffer) + 3) >= iLength) { // 3 because we might append a " = "
//
// We might exceed the limitation that we set using WM_LIMITTEXT, do not allow that.
//
MessageBeep(MB_ICONASTERISK);
break;
}
if (CSTRING::Trim(szTextBoxContents) == 0) {
bEmpty = TRUE;
}
if (bEmpty == FALSE) {
if (lpnmhdr->idFrom == IDC_SELECT_LIST) {
StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), TEXT(", "));
} else {
StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), TEXT(" "));
}
}
StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), szBuffer);
if (lpnmhdr->idFrom == IDC_WHERE_LIST) {
StringCchCat(szTextBoxContents, ARRAYSIZE(szTextBoxContents), TEXT(" = "));
}
SetWindowText(hwndText, szTextBoxContents);
//
// Let us now position the caret at the end of the text box
// We send the text box a VK_END key down message
//
SendMessage(hwndText, WM_KEYDOWN, (WPARAM)(INT)VK_END, (LPARAM)0);
break;
}
}
}
void
HandleQueryDBSizing(
IN HWND hDlg
)
/*++
HandleQueryDBSizing
Desc: Handles the sizing of the Query db dialog
Params:
IN HWND hDlg: The query dialog box
Return:
void
--*/
{
int nWidth;
int nHeight;
int nStatusbarTop;
RECT rDlg;
HWND hwnd;
RECT r;
if (g_cWidthQuery == 0 || g_cWidthQuery == 0) {
return;
}
GetWindowRect(hDlg, &rDlg);
nWidth = rDlg.right - rDlg.left;
nHeight = rDlg.bottom - rDlg.top;
int deltaW = nWidth - g_cWidthQuery;
int deltaH = nHeight - g_cHeightQuery;
//
// The status bar
//
hwnd = GetDlgItem(hDlg, IDC_STATUSBAR);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left,
nStatusbarTop = r.top + deltaH,
r.right - r.left + deltaW,
r.bottom - r.top,
TRUE);
//
// The List
//
hwnd = GetDlgItem(hDlg, IDC_LIST);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left,
r.top,
r.right - r.left + deltaW,
nStatusbarTop - r.top,
TRUE);
//
// The search button
//
hwnd = GetDlgItem(hDlg, ID_SEARCH);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left + deltaW,
r.top,
r.right - r.left,
r.bottom - r.top,
TRUE);
//
// The save button
//
hwnd = GetDlgItem(hDlg, IDC_SAVE);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left + deltaW,
r.top,
r.right - r.left,
r.bottom - r.top,
TRUE);
//
// The animate control
//
hwnd = GetDlgItem(hDlg, IDC_ANIMATE);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left + deltaW,
r.top,
r.right - r.left,
r.bottom - r.top,
TRUE);
//
// The cancel button
//
hwnd = GetDlgItem(hDlg, IDC_STOP);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left + deltaW,
r.top,
r.right - r.left,
r.bottom - r.top,
TRUE);
//
// The new search button
//
hwnd = GetDlgItem(hDlg, IDC_NEWSEARCH);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left + deltaW,
r.top,
r.right - r.left,
r.bottom - r.top,
TRUE);
//
// The help button
//
hwnd = GetDlgItem(hDlg, ID_QDB_HELP);
GetWindowRect(hwnd, &r);
MapWindowPoints(NULL, hDlg, (LPPOINT)&r, 2);
MoveWindow(hwnd,
r.left + deltaW,
r.top,
r.right - r.left,
r.bottom - r.top,
TRUE);
g_cWidthQuery = nWidth;
g_cHeightQuery = nHeight;
}
void
OnSearch(
IN HWND hdlg
)
/*++
OnSearch
Desc: Handles the pressing of the Find Now button
Params:
IN HWND hdlg: The query dialog box
Return:
void
Notes: We will obtain the query string from the active tab page and
then set the text of IDC_SQL (this is an invisible control) to the SQL
The query processing routines i.e the SQLDriver will read the string
from IDC_SQL. This approach is needed to avoid global variables
--*/
{
TCHAR szSQL[2096];
//
// Remove any existing results...
//
DeleteAll(hdlg);
stmt.Close();
stmt.Init();
stmt.SetWindow(hdlg);
//
// Prepare the FROM string
//
*szSQL = 0;
INT iIndex = SendMessage(GetDlgItem(hdlg, IDC_COMBO), CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR) {
return;
}
LPARAM lParam = SendMessage(GetDlgItem(hdlg, IDC_COMBO), CB_GETITEMDATA, iIndex, 0);
if (lParam == CB_ERR) {
return;
}
switch (lParam) {
case DATABASE_ALL:
StringCchPrintf(szSQL,
ARRAYSIZE(szSQL),
TEXT("%s, %s ,%s"),
DatabasesMapping[IND_SYSTDB].szDatabaseType,
DatabasesMapping[IND_INSTDB].szDatabaseType,
DatabasesMapping[IND_CUSTDB].szDatabaseType);
break;
case DATABASE_TYPE_GLOBAL:
SafeCpyN(szSQL, DatabasesMapping[IND_SYSTDB].szDatabaseType, ARRAYSIZE(szSQL));
break;
case DATABASE_TYPE_INSTALLED:
SafeCpyN(szSQL, DatabasesMapping[IND_INSTDB].szDatabaseType, ARRAYSIZE(szSQL));
break;
case DATABASE_TYPE_WORKING:
SafeCpyN(szSQL, DatabasesMapping[IND_CUSTDB].szDatabaseType, ARRAYSIZE(szSQL));
break;
}
DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
if (pHdr == NULL) {
assert(FALSE);
return;
}
s_iErrorCode = 0;
SendMessage(pHdr->hwndPages[pHdr->iPresentTabIndex],
WM_USER_GETSQL,
(WPARAM)ARRAYSIZE(szSQL),
(LPARAM)szSQL);
if (!s_iErrorCode) {
SetDlgItemText(hdlg, IDC_SQL, szSQL);
Start(hdlg);
} else {
//
// Display the proper error
//
TCHAR szErrormsg[512];
*szErrormsg = 0;
switch (s_iErrorCode) {
case ERROR_GUI_NOCHECKBOXSELECTED:
SafeCpyN(szErrormsg,
GetString(IDS_ERROR_GUI_NOCHECKBOXSELECTED),
ARRAYSIZE(szErrormsg));
break;
}
MessageBox(hdlg, szErrormsg, g_szAppName, MB_ICONINFORMATION);
}
}
void
DoNewQdb(
IN HWND hdlg
)
/*++
DoNewQdb
Desc: Handles the pressing of the New Search button
Params:
IN HWND hdlg: The query dialog box
Return:
void
--*/
{
DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, GWLP_USERDATA);
if (pHdr == NULL) {
assert(FALSE);
return;
}
//
// Request the active tab page to clear its contents
//
SendMessage(pHdr->hwndPages[pHdr->iPresentTabIndex], WM_USER_NEWQDB, 0, 0);
}
void
DeleteAll(
IN HWND hdlg
)
/*++
DeleteAll
Desc: Deletes all the results items from the query dialog's search result
list view
Params:
IN HWND hdlg: The query dialog box
Return:
void
Notes: We do not try to free the pointers in the lParam of the list view items.
If we have done a SQL query:
The lParam of the list view will be pointers to items of type PRESULT_ITEM
which are freed when we close the statement. (Closing the statement closes
the ResultSet of the statement)
If we have done a special database query like searching for fixes that
have some words in their description then the lParam will point to the
FIX_SHIM in the database and we do not want to free that
--*/
{
HWND hwndList = GetDlgItem(hdlg, IDC_LIST);
UINT uColCount = stmt.GetShowList()->m_uCount;
INT iIndex = 0;
SendMessage(hwndList, WM_SETREDRAW, FALSE, 0);
if (s_bEmptyHeader == FALSE) {
for (iIndex = uColCount; iIndex >= 0; --iIndex) {
ListView_DeleteColumn(hwndList, iIndex);
}
InsertColumnIntoListView(hwndList, TEXT(""), 0, 100);
s_bEmptyHeader = TRUE;
}
ListView_DeleteAllItems(hwndList);
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0);
SetStatus(GetDlgItem(hdlg, IDC_STATUSBAR), TEXT(""));
UpdateWindow(hwndList);
}
void
SaveResultsQdb(
IN HWND hdlg
)
/*++
SaveResultsQdb
Desc: Saves all the results items from the query dialog's search result
list view in a tab separated text file
Params:
IN HWND hdlg: The query dialog box
Return:
void
--*/
{
CSTRING strFileName;
TCHAR szTitle[256], szFilter[128], szExt[8];
*szTitle = *szFilter = *szExt = 0;
BOOL bResult = GetFileName(hdlg,
GetString(IDS_SAVE_RESULTS_TITLE, szTitle, ARRAYSIZE(szTitle)),
GetString(IDS_SAVE_RESULTS_FILTER, szFilter, ARRAYSIZE(szFilter)),
TEXT(""),
GetString(IDS_SAVE_RESULTS_EXT, szExt, ARRAYSIZE(szExt)),
OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT,
FALSE,
strFileName,
TRUE);
if (bResult) {
SetCursor(LoadCursor(NULL, IDC_WAIT));
SaveListViewToFile(GetDlgItem(hdlg, IDC_LIST),
stmt.GetShowList()->m_uCount,
strFileName.pszString,
NULL);
SetCursor(LoadCursor(NULL, IDC_ARROW));
}
}
void
GotoQdbEntry(
IN HWND hdlg,
IN LPARAM lParam
)
/*++
GotoQdbEntry
Desc: Selects the entry in the entry tree.
The lParam is the lParam of the list view row that specifies that entry.
Params:
IN HWND hdlg: The query db dialog box
IN LPARAM lParam: The list view item whose 'details' we want to see
--*/
{
PRESULT_ITEM pResult;
PDBENTRY pApp;
if (g_iLastSearchType == QDB_PAGE3) {
//
// We had performed a search for shims last time, so we do not have PRESULT_ITEM
// items in the list view
//
goto End;
}
if (g_bSomeWizardActive) {
//
// We do not want that the focus should go to some other database, because
// some wizard is active, which believes that he is modal.
//
MessageBox(g_hdlgQueryDB,
GetString(IDS_SOMEWIZARDACTIVE),
g_szAppName,
MB_ICONINFORMATION);
goto End;
}
pResult = (PRESULT_ITEM)lParam;
pApp = NULL;
if (pResult == NULL) {
assert(FALSE);
goto End;
}
pApp = GetAppForEntry(pResult->pDatabase, pResult->pEntry);
//
// First select the app from in the db tree.
//
HTREEITEM hItemApp = DBTree.FindChild(pResult->pDatabase->hItemAllApps, (LPARAM)pApp);
if (hItemApp == NULL) {
MessageBox(hdlg, GetString(IDS_NOLONGEREXISTS), g_szAppName, MB_ICONWARNING);
goto End;
}
TreeView_SelectItem(DBTree.m_hLibraryTree , hItemApp);
//
// Now from the entry tree select the particular entry
//
HTREEITEM hItemEntry = CTree::FindChild(g_hwndEntryTree, TVI_ROOT, (LPARAM)pResult->pEntry);
if (hItemEntry == NULL) {
MessageBox(hdlg, GetString(IDS_NOLONGEREXISTS), g_szAppName, MB_ICONWARNING);
goto End;
}
TreeView_SelectItem(g_hwndEntryTree, hItemEntry);
SetFocus(g_hwndEntryTree);
End: ;
}
INT_PTR CALLBACK
QdbWaitDlg(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
QdbWaitDlg
Desc: Dialog Proc for the wait window which will pop up,
if we are trying to close the query window,
when it the thread is still doing some useful work.
This will be essentially true when we are trying to load the system
database or we are trying to populate the list view
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
static HWND s_hwndPB;
switch (uMsg) {
case WM_INITDIALOG:
s_hwndPB = GetDlgItem(hdlg, IDC_PROGRESS);
SendMessage(s_hwndPB, PBM_SETRANGE, 0, MAKELPARAM(0, 2000));
SendMessage(s_hwndPB, PBM_SETSTEP, (WPARAM) 1, 0);
SetTimer(hdlg, 0, 100, NULL);
break;
case WM_TIMER:
if (s_hThread) {
if (WAIT_OBJECT_0 == WaitForSingleObject(s_hThread, 0)) {
//
// The handle to the thread is closed and nulled when it is
// about to terminate
//
KillTimer(hdlg, 0);
s_hThread = NULL;
s_hWaitDialog = NULL;
SendMessage(s_hwndPB, PBM_SETPOS, MAX_PROGRESS, 0);
SendMessage(g_hdlgQueryDB, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 0);
DestroyWindow(hdlg);
} else {
SendMessage(s_hwndPB, PBM_STEPIT, 0, 0);
}
} else {
KillTimer(hdlg, 0);
s_hWaitDialog = NULL;
SendMessage(s_hwndPB, PBM_SETPOS, MAX_PROGRESS, 0);
//
// Let the user see that it is completed
//
Sleep(1000);
SendMessage(g_hdlgQueryDB, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), 0);
DestroyWindow(hdlg);
}
break;
case WM_COMMAND:
switch (wCode) {
case IDCANCEL:
KillTimer(hdlg, 0);
DestroyWindow(hdlg);
break;
default: return FALSE;
}
break;
case WM_DESTROY:
s_hWaitDialog = NULL;
break;
default: return FALSE;
}
return TRUE;
}
void
SearchAndAddToUIFixes(
IN CSTRINGLIST& strlTokens,
IN QDB_SEARCH_TYPE searchtype,
IN PVOID pShimOrFix,
IN TYPE type
)
/*++
SearchAndAddToUIFixes
Desc: Typecasts pShimOrFix to either a shim or a flag pointer as per type and
then checks if it contains matches the tokens
Params:
IN CSTRINGLIST& strlTokens: The list of tokens
IN QDB_SEARCH_TYPE searchtype: The type of search to perform
IN PVOID pShimOrFix: Pointer to a shim or a fix
IN TYPE type: Whether this is a shim or a fix
Return:
void
--*/
{
PSTRLIST pslListOfTokensLoop = strlTokens.m_pHead;
BOOL bFound = FALSE;
LVITEM lvi;
HWND hwndSearchList = NULL;
PCTSTR pszName = NULL;
PCTSTR pszDescription = NULL;
if (pShimOrFix == NULL) {
assert(FALSE);
return;
}
pShimOrFix = (PSHIM_FIX)pShimOrFix;
if (type == FIX_SHIM) {
pszName = (LPCTSTR)((PSHIM_FIX)pShimOrFix)->strName;
pszDescription = (LPCTSTR)((PSHIM_FIX)pShimOrFix)->strDescription;
} else if (type == FIX_FLAG) {
pszName = (LPCTSTR)((PFLAG_FIX)pShimOrFix)->strName;
pszDescription = (LPCTSTR)((PFLAG_FIX)pShimOrFix)->strDescription;
} else {
assert(FALSE);
return;
}
hwndSearchList = GetDlgItem(g_hdlgQueryDB, IDC_LIST);
//
// Check if the present fix has the desired tokens. If we search type specifies
// all tokens then we have to look for all tokens otherwise we can break
// when we find the first token that is present in the name of desc. of the shim
//
while (pslListOfTokensLoop) {
//
// Does the name of the fix has this token?
//
bFound = (StrStrI(pszName,
(LPCTSTR)pslListOfTokensLoop->szStr) == NULL) ? FALSE : TRUE ;
if (!bFound) {
//
// Name does not contain this token, so we must look in the description text
//
bFound = (StrStrI(pszDescription,
(LPCTSTR)pslListOfTokensLoop->szStr) == NULL) ? FALSE : TRUE;
}
if (searchtype == QDB_SEARCH_ALLWORDS && !bFound) {
//
// We wanted that all words should be found and we did not find this particular
// word, search failed
//
break;
}
if (searchtype == QDB_SEARCH_ANYWORD && bFound) {
//
// We wanted that any word should match and this word was found, so
// search was successfull
//
break;
}
//
// Search if the next token matches
//
pslListOfTokensLoop = pslListOfTokensLoop->pNext;
}
if (bFound) {
//
// This fix matched our criteria, so add this to the list view
//
lvi.mask = LVIF_TEXT | LVIF_PARAM;
lvi.lParam = (LPARAM)pShimOrFix;
lvi.pszText = (LPTSTR)pszName;
lvi.iSubItem = 0;
ListView_InsertItem(hwndSearchList, &lvi);
}
}
void
DoTheFixesSearch(
IN HWND hdlg
)
/*++
DoTheFixesSearch
Desc: Searches for fixes in the system database that have the words that the user
wants to look for
Params:
IN HWND hdlg: The fix search page in the query db tab. This is the fourth page of the
tab
Return:
void
--*/
{
LPARAM lParam;
INT iIndex;
QDB_SEARCH_TYPE searchtype;
TCHAR szSearch[MAX_FIXDESC_SEARCH];
HWND hwndSearch = GetDlgItem(hdlg, IDC_TEXT);
HWND hwndCombo = GetDlgItem(hdlg, IDC_COMBO);
HWND hwndList = GetDlgItem(g_hdlgQueryDB, IDC_LIST);
PSHIM_FIX psfLoop = GlobalDataBase.pShimFixes;
PFLAG_FIX pffLoop = GlobalDataBase.pFlagFixes;
BOOL bFound = FALSE;
CSTRINGLIST strlTokens;
CSTRING strStatus;
TCHAR szBuffer[32];
INT iTotalResults;
//
// Clear any existing results
//
DeleteAll(GetParent(hdlg));
SetDlgItemText(hdlg, IDC_DESC, TEXT(""));
//
// Users cannot double click on the search list if we are showing shims, so
// we disable the text that says they can.
//
ENABLEWINDOW(GetDlgItem(GetParent(hdlg), IDC_STATIC_CAPTION), FALSE);
if (s_bEmptyHeader) {
//
// If the empty column is still there, must get rid of it
//
ListView_DeleteColumn(hwndList, 0);
s_bEmptyHeader = FALSE;
}
//
// Insert the new column
//
InsertColumnIntoListView(hwndList,
GetString(IDS_COMPATFIXES),
0,
100);
GetWindowText(hwndSearch, szSearch, ARRAYSIZE(szSearch));
if (CSTRING::Trim(szSearch) == 0) {
//
// No text was typed in for search
//
MessageBox(hdlg,
GetString(IDS_QDB_NO_TEXTTO_SEARCH),
g_szAppName,
MB_ICONWARNING);
goto End;
}
//
// Get the search type
//
iIndex = SendMessage(GetDlgItem(hdlg, IDC_COMBO), CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR) {
assert(FALSE);
goto End;
}
lParam = SendMessage(hwndCombo, CB_GETITEMDATA, iIndex, 0);
if (lParam == CB_ERR) {
assert(FALSE);
goto End;
}
searchtype = (QDB_SEARCH_TYPE)lParam;
//
// The search string is comma separated, get the individual tokens and search for that token
// first in the name of the fix and then in the description. As for now we do not do any
// rating on the search. We show results as they come
//
//
// Fist get the tokens
//
if (Tokenize(szSearch, lstrlen(szSearch), TEXT(","), strlTokens)) {
//
// We found some tokens, now for each token let us see if it is in the fix name
// or the fix description
//
//
// Search in the shims and add to the list view
//
while (psfLoop) {
if (psfLoop->bGeneral || g_bExpert) {
//
// In non-expert mode we should only show the general shims
//
SearchAndAddToUIFixes(strlTokens, searchtype, psfLoop, FIX_SHIM);
}
psfLoop = psfLoop->pNext;
}
//
// Search in the flags and add it to the list view
//
while (pffLoop) {
if (pffLoop->bGeneral || g_bExpert) {
//
// In non-expert mode we should only show the general flags
//
SearchAndAddToUIFixes(strlTokens, searchtype, pffLoop, FIX_FLAG);
}
pffLoop = pffLoop->pNext;
}
}
End:
//
// Set the status bar text to how many results we have found
//
*szBuffer = 0;
iTotalResults = ListView_GetItemCount(hwndList);
strStatus.Sprintf(GetString(IDS_QDB_COUNT),
_itot(iTotalResults, szBuffer, 10));
SetStatus(GetDlgItem(GetParent(hdlg), IDC_STATUSBAR), strStatus);
}
INT_PTR
SearchFixDescDlgProcOnInitDialog(
IN HWND hdlg
)
/*++
SearchFixDescDlgProcOnInitDialog
Desc: The handler of WM_INITDIALOG for the third qdb tab page. This page
searches for fixes based on key words that are searached in the description
text of the fix
Params:
IN HWND hDlg: The third wizard page
Return:
TRUE
--*/
{
INT iIndex = 0;
HWND hwndSearch = GetDlgItem(hdlg, IDC_TEXT);
HWND hwndCombo = GetDlgItem(hdlg, IDC_COMBO);
//
// Restrict the length of the text
//
SendMessage(hwndSearch, EM_LIMITTEXT, (WPARAM)MAX_FIXDESC_SEARCH - 1, (LPARAM)0);
//
// Add the search type strings
//
iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_QDB_ANYWORD));
SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)QDB_SEARCH_ANYWORD);
iIndex = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM)GetString(IDS_QDB_ALLWORDS));
SendMessage(hwndCombo, CB_SETITEMDATA, iIndex, (LPARAM)QDB_SEARCH_ALLWORDS);
//
// Select the first string
//
SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
return TRUE;
}
INT_PTR CALLBACK
SearchFixDescDlgProc(
IN HWND hdlg,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
SearchFixDescDlgProc
Desc: Dialog proc for the third tab page. This page finds fixes that have specific
words in their description text or in their names
Params: Standard dialog handler parameters
IN HWND hDlg
IN UINT uMsg
IN WPARAM wParam
IN LPARAM lParam
Return: Standard dialog handler return
--*/
{
int wCode = LOWORD(wParam);
int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG:
SearchFixDescDlgProcOnInitDialog(hdlg);
break;
case WM_USER_NEWQDB:
SetDlgItemText(hdlg, IDC_TEXT, TEXT(""));
SetDlgItemText(hdlg, IDC_DESC, TEXT(""));
DeleteAll(GetParent(hdlg));
break;
case WM_USER_DOTHESEARCH:
SetCursor(LoadCursor(NULL, IDC_WAIT));
DoTheFixesSearch(hdlg);
SetCursor(LoadCursor(NULL, IDC_ARROW));
break;
default: return FALSE;
}
return TRUE;
}