|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
QFixApp.cpp
Abstract:
Contains the application entry point, user interface code, and some supporting functions.
Notes:
ANSI & Unicode via TCHAR - runs on NT/2K/XP etc.
History:
02/16/00 clupu Created 11/10/00 rparsons Minor common dialog change 11/23/00 rparsons Added save XML file capability 11/25/00 rparsons Matching file on a different drive can be selected 05/19/01 rparsons Added context menu for file tree. Added URL for WU package/helpcenter. Added Remove Matching File button. Converted shim list to list view. 07/06/01 rparsons Static tab control -> child dialogs 09/24/01 rparsons Spawn a separate VDM when running apps 10/09/01 rparsons Flags have a command-line 10/26/01 rparsons No change - 476903. 01/26/02 rparsons Fix bug # 491301 02/20/02 rparsons Implemented strsafe functions 03/22/02 rparsons Fix bug # 583475
--*/ #include "afxwin.h"
#include "commctrl.h"
#include "commdlg.h"
#include "shlwapi.h"
#include "shellapi.h"
#include "shlobj.h"
#include "shlobjp.h" // needed for Link Window support
#include "uxtheme.h" // needed for tab control theme support
#include "resource.h"
#include <tchar.h>
#include <aclapi.h>
#include <strsafe.h>
#include "QFixApp.h"
#include "dbSupport.h"
extern "C" { #include "shimdb.h"
}
CWinApp theApp;
/*
* Global Variables */
HINSTANCE g_hInstance; HWND g_hDlg; HWND g_hLayersDlg; HWND g_hFixesDlg;
HWND g_hwndTab; HWND g_hwndListLayers;
TCHAR g_szAppTitle[64];
TCHAR g_szWinDir[MAX_PATH]; // %windir%
TCHAR g_szSysDir[MAX_PATH]; // %windir%\System32
TCHAR g_szBinary[MAX_PATH]; // the full path of the main binary being shimmed
TCHAR g_szShortName[128]; // the short name of the main EXE
TCHAR g_szParentExeName[MAX_PATH]; // the short name of the parent EXE
TCHAR g_szParentExeFullPath[MAX_PATH]; // the full path of the parent EXE
TCHAR g_szSDBToDelete[MAX_PATH]; // the SDB file to delete from a previous 'Run'
int g_nCrtTab;
HWND g_hwndShimList; // the handle to the list view control
// containing all the shims available
HWND g_hwndFilesTree; // the handle to the tree view control
// containing the matching files selected
HWND g_hwndModuleList; // the handle to the list view control
// containing module information
BOOL g_bSimpleEdition; // simple or dev edition
BOOL g_fW2K; // Win2K or XP
BOOL g_fNETServer; // indicates if we're running on .NET Server
RECT g_rcDlgBig, g_rcDlgSmall; // rectangle of the simple and the dev edition
// of the dialog
BOOL g_bAllShims; // indicates if all shims should be displayed
BOOL g_bShowXML; // indicates if we should hide the 'Show XML' button
BOOL g_bSelectedParentExe; // flag to indicate if a parent EXE has been
// selected
BOOL g_bSDBInstalled; // flag to indicate if the user installed the SDB
// associated with the current EXE
PFIX g_pFixHead;
TCHAR g_szXPUrl[] = _T("hcp://services/subsite?node=TopLevelBucket_4/") _T("Fixing_a_problem&topic=MS-ITS%3A%25HELP_LOCATION") _T("%25%5Cmisc.chm%3A%3A/compatibility_tab_and_wizard.htm") _T("&select=TopLevelBucket_4/Fixing_a_problem/") _T("Application_and_software_problems");
TCHAR g_szNETUrl[] = _T("hcp://services/subsite?node=Troubleshooting_Strategies&") _T("topic=MS-ITS%3A%25HELP_LOCATION%25%5Cmisc.chm%3A%3A/") _T("compatibility_tab_and_wizard.htm");
TCHAR g_szW2KUrl[] = _T("http://www.microsoft.com/windows2000/") _T("downloads/tools/appcompat/");
#define ID_COUNT_SHIMS 1234
typedef HRESULT (*PFNEnableThemeDialogTexture)(HWND hwnd, DWORD dwFlags);
/*++
Routine Description:
Prints a formatted string to the debugger.
Arguments:
dwDetail - Specifies the level of the information provided. pszFmt - The string to be displayed. ... - A va_list of insertion strings.
Return Value:
None.
--*/ void __cdecl DebugPrintfEx( IN LPSTR pszFmt, ... ) { char szT[1024]; va_list arglist; int len;
va_start(arglist, pszFmt);
//
// Reserve one character for the potential '\n' that we may be adding.
//
StringCchVPrintfA(szT, sizeof(szT) - 1, pszFmt, arglist);
va_end(arglist);
//
// Make sure we have a '\n' at the end of the string
//
len = strlen(szT);
if (len > 0 && szT[len - 1] != '\n') { szT[len] = '\n'; szT[len + 1] = 0; }
OutputDebugStringA(szT); }
BOOL SearchGroupForSID( IN DWORD dwGroup, OUT BOOL* pfIsMember ) { PSID pSID; SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; BOOL fRes = TRUE;
if (!AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, dwGroup, 0, 0, 0, 0, 0, 0, &pSID)) { fRes = FALSE; }
if (!CheckTokenMembership(NULL, pSID, pfIsMember)) { fRes = FALSE; }
FreeSid(pSID);
return fRes; }
BOOL IsUserAnAdministrator( void ) /*++
IsUserAnAdministrator
Description: Determine if the currently logged on user is an admin.
--*/ { BOOL fIsAdmin;
if (!SearchGroupForSID(DOMAIN_ALIAS_RID_ADMINS, &fIsAdmin)) { return FALSE; }
return fIsAdmin; }
BOOL CheckForSDB( void ) /*++
CheckForSDB
Description: Attempts to locate sysmain.sdb in the apppatch directory.
--*/ { TCHAR szSDBPath[MAX_PATH]; BOOL fResult = FALSE; HRESULT hr;
hr = StringCchPrintf(szSDBPath, ARRAYSIZE(szSDBPath), _T("%s\\AppPatch\\sysmain.sdb"), g_szWinDir);
if (FAILED(hr)) { DPF("[CheckForSDB] 0x%08X Buffer too small", HRESULT_CODE(hr)); return FALSE; }
if (GetFileAttributes(szSDBPath) != -1) { fResult = TRUE; }
return fResult; }
void AddModuleToListView( TCHAR* pModuleName, UINT uOption ) /*++
AddModuleToListView
Description: Adds the specified module to the list view.
--*/ { LVITEM lvi; int nIndex; TCHAR szInclude[MAX_PATH]; TCHAR szExclude[MAX_PATH];
LoadString(g_hInstance, IDS_INCLUDE_HDR, szInclude, ARRAYSIZE(szInclude)); LoadString(g_hInstance, IDS_EXCLUDE_HDR, szExclude, ARRAYSIZE(szExclude));
lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.lParam = uOption == BST_CHECKED ? 1 : 0; lvi.pszText = uOption == BST_CHECKED ? szInclude : szExclude; lvi.iItem = ListView_GetItemCount(g_hwndModuleList); lvi.iSubItem = 0;
nIndex = ListView_InsertItem(g_hwndModuleList, &lvi);
ListView_SetItemText(g_hwndModuleList, nIndex, 1, pModuleName); }
void BuildModuleListForShim( PFIX pFix, DWORD dwFlags ) /*++
BuildModuleListForShim
Description: Based on the flag, adds modules to the list view for the specified shim or retrieves them and adds them to the linked list.
--*/ { PMODULE pModule, pModuleTmp, pModuleNew; int cItems, nIndex, nLen; LVITEM lvi; TCHAR szBuffer[MAX_PATH];
if (dwFlags & BML_ADDTOLISTVIEW) {
//
// Walk the linked list and add the modules to the list view.
//
pModule = pFix->pModule;
while (pModule) {
AddModuleToListView(pModule->pszName, pModule->fInclude ? BST_CHECKED : 0);
pModule = pModule->pNext; }
}
if (dwFlags & BML_DELFRLISTVIEW) {
pModule = pFix->pModule;
while (NULL != pModule) {
pModuleTmp = pModule->pNext;
HeapFree(GetProcessHeap(), 0, pModule->pszName); HeapFree(GetProcessHeap(), 0, pModule);
pModule = pModuleTmp; }
pFix->pModule = NULL;
}
if (dwFlags & BML_GETFRLISTVIEW) {
pModule = pFix->pModule;
while (NULL != pModule) {
pModuleTmp = pModule->pNext;
HeapFree(GetProcessHeap(), 0, pModule->pszName); HeapFree(GetProcessHeap(), 0, pModule);
pModule = pModuleTmp; }
pFix->pModule = NULL;
//
// Get each module from the list view and add it to the linked list.
//
cItems = ListView_GetItemCount(g_hwndModuleList);
if (cItems == 0) { return; }
for (nIndex = cItems - 1; nIndex >= 0; nIndex--) {
lvi.mask = LVIF_PARAM; lvi.iItem = nIndex; lvi.iSubItem = 0;
ListView_GetItem(g_hwndModuleList, &lvi);
ListView_GetItemText(g_hwndModuleList, nIndex, 1, szBuffer, ARRAYSIZE(szBuffer));
pModuleNew = (PMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MODULE));
if (!pModuleNew) { DPF("[BuildModuleListForShim] Couldn't allocate memory for node"); return; }
nLen = _tcslen(szBuffer) + 1;
pModuleNew->pszName = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLen * sizeof(TCHAR));
if (!pModuleNew->pszName) { DPF("[BuildModuleListForShim] Couldn't allocate memory to store module info"); HeapFree(GetProcessHeap(), 0, pModuleNew); return; }
StringCchCopy(pModuleNew->pszName, nLen, szBuffer); pModuleNew->fInclude = (BOOL)lvi.lParam;
pModuleNew->pNext = pFix->pModule; pFix->pModule = pModuleNew; } } }
int CountShims( BOOL fCountSelected ) /*++
CountShims
Description: Counts the number of selected shims in the list and updates the text on the dialog. --*/ { int cShims = 0, nTotalShims, nShims = 0; BOOL fReturn; TCHAR szShims[MAX_PATH]; TCHAR szTemp[MAX_PATH]; HRESULT hr;
cShims = ListView_GetItemCount(g_hwndShimList);
if (fCountSelected) {
for (nTotalShims = 0; nTotalShims < cShims; nTotalShims++) {
fReturn = ListView_GetCheckState(g_hwndShimList, nTotalShims);
if (fReturn) { nShims++; } } }
LoadString(g_hInstance, IDS_SEL_CAPTION, szTemp, ARRAYSIZE(szTemp));
hr = StringCchPrintf(szShims, ARRAYSIZE(szShims), szTemp, nShims, cShims);
if (FAILED(hr)) { DPF("[CountShims] 0x%08X Buffer too small", HRESULT_CODE(hr)); return 0; }
SetDlgItemText(g_hFixesDlg, IDC_SELECTED_SHIMS, szShims);
return cShims; }
void DisplayAttrContextMenu( POINT* pt ) /*++
DisplayAttrContextMenu
Description: Displays a popup menu for the attributes tree.
--*/
{ HMENU hPopupMenu, hTrackPopup;
//
// Load the popup menu and display it.
//
hPopupMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDM_ATTR_POPUP));
if (hPopupMenu == NULL) { return; }
hTrackPopup = GetSubMenu(hPopupMenu, 0);
TrackPopupMenu(hTrackPopup, TPM_LEFTBUTTON | TPM_NOANIMATION | TPM_LEFTALIGN, pt->x, pt->y, 0, g_hDlg, NULL);
DestroyMenu(hPopupMenu); }
void InsertListViewColumn( HWND hWndListView, LPTSTR lpColumnName, BOOL fCenter, int nColumnID, int nSize ) /*++
InsertListViewColumn
Description: Wrapper for ListView_InsertColumn.
--*/ { LV_COLUMN lvColumn;
if (fCenter) { lvColumn.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT; } else { lvColumn.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; }
//
// Fill in the structure and add the column.
//
lvColumn.fmt = LVCFMT_CENTER; lvColumn.cx = nSize; lvColumn.iSubItem = 0; lvColumn.pszText = lpColumnName; ListView_InsertColumn(hWndListView, nColumnID, &lvColumn); }
void EnableTabBackground( HWND hDlg ) { PFNEnableThemeDialogTexture pFnEnableThemeDialogTexture; HMODULE hUxTheme;
hUxTheme = (HMODULE)LoadLibrary(_T("uxtheme.dll")); if (hUxTheme) { pFnEnableThemeDialogTexture = (PFNEnableThemeDialogTexture) GetProcAddress(hUxTheme, "EnableThemeDialogTexture"); if (pFnEnableThemeDialogTexture) { pFnEnableThemeDialogTexture(hDlg, ETDT_USETABTEXTURE); }
FreeLibrary(hUxTheme); } }
void HandleLayersDialogInit( HWND hDlg ) { HWND hParent; DLGHDR* pHdr;
g_hLayersDlg = hDlg;
hParent = GetParent(hDlg);
pHdr = (DLGHDR*)GetWindowLongPtr(hParent, DWLP_USER);
//
// Position the dialog within the tab.
//
SetWindowPos(hDlg, HWND_TOP, pHdr->rcDisplay.left, pHdr->rcDisplay.top, pHdr->rcDisplay.right - pHdr->rcDisplay.left, pHdr->rcDisplay.bottom - pHdr->rcDisplay.top, 0);
g_hwndListLayers = GetDlgItem(hDlg, IDC_LAYERS);
EnableTabBackground(hDlg); }
BOOL HandleFixesDialogInit( HWND hDlg ) { HWND hParent; DLGHDR* pHdr; int nCount = 0; TCHAR szColumn[MAX_PATH];
g_hFixesDlg = hDlg;
hParent = GetParent(hDlg);
pHdr = (DLGHDR*)GetWindowLongPtr(hParent, DWLP_USER);
//
// Position the dialog within the tab.
//
SetWindowPos(hDlg, HWND_TOP, pHdr->rcDisplay.left, pHdr->rcDisplay.top, pHdr->rcDisplay.right - pHdr->rcDisplay.left, pHdr->rcDisplay.bottom - pHdr->rcDisplay.top, 0);
g_hwndShimList = GetDlgItem(hDlg, IDC_SHIMS);
//
// Set up the shim list.
//
LoadString(g_hInstance, IDS_FIXNAME_COLUMN, szColumn, ARRAYSIZE(szColumn)); InsertListViewColumn(g_hwndShimList, szColumn, FALSE, 0, 200); LoadString(g_hInstance, IDS_CMDLINE_COLUMN, szColumn, ARRAYSIZE(szColumn)); InsertListViewColumn(g_hwndShimList, szColumn, TRUE, 1, 59); LoadString(g_hInstance, IDS_MODULE_COLUMN, szColumn, ARRAYSIZE(szColumn)); InsertListViewColumn(g_hwndShimList, szColumn, TRUE, 2, 52);
ListView_SetExtendedListViewStyle(g_hwndShimList, LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
//
// Query the database and show the available general purpose fixes.
//
ShowAvailableFixes(g_hwndShimList);
nCount = CountShims(FALSE);
if (!nCount) { return FALSE; }
ListView_SetItemCount(g_hwndShimList, nCount);
EnableTabBackground(hDlg);
return TRUE; }
DLGTEMPLATE* LockDlgRes( LPCTSTR lpResName ) { HRSRC hrsrc = FindResource(NULL, lpResName, RT_DIALOG);
if (NULL == hrsrc) { return NULL; }
HGLOBAL hglb = LoadResource(g_hInstance, hrsrc);
if (NULL == hglb) { return NULL; }
return (DLGTEMPLATE*)LockResource(hglb); }
void InitTabs( HWND hMainDlg, HWND hTab ) { DLGHDR* pHdr; TCITEM tcitem; RECT rcTab; int nCount; TCHAR szTabText[MAX_PATH]; TCHAR szError[MAX_PATH];
pHdr = (DLGHDR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DLGHDR));
if (NULL == pHdr) { LoadString(g_hInstance, IDS_TAB_SETUP_FAIL, szError, ARRAYSIZE(szError)); MessageBox(hMainDlg, szError, g_szAppTitle, MB_ICONERROR); return; }
//
// Save away a pointer to the structure.
//
SetWindowLongPtr(hMainDlg, DWLP_USER, (LONG_PTR)pHdr);
//
// Save away the handle to the tab control.
//
pHdr->hTab = hTab;
//
// Add the tabs.
//
LoadString(g_hInstance, IDS_TAB_FIRST_TEXT, szTabText, ARRAYSIZE(szTabText)); tcitem.mask = TCIF_TEXT | TCIF_PARAM; tcitem.pszText = szTabText; tcitem.lParam = 0; TabCtrl_InsertItem(pHdr->hTab, 0, &tcitem);
LoadString(g_hInstance, IDS_TAB_SECOND_TEXT, szTabText, ARRAYSIZE(szTabText)); tcitem.pszText = szTabText; tcitem.lParam = 1; TabCtrl_InsertItem(pHdr->hTab, 1, &tcitem);
//
// Lock the resources for two child dialog boxes.
//
pHdr->pRes[0] = LockDlgRes(MAKEINTRESOURCE(IDD_LAYERS_TAB)); pHdr->pDlgProc[0] = LayersTabDlgProc; pHdr->pRes[1] = LockDlgRes(MAKEINTRESOURCE(IDD_FIXES_TAB)); pHdr->pDlgProc[1] = FixesTabDlgProc;
//
// Determine the bounding rectangle for all child dialog boxes.
//
GetWindowRect(pHdr->hTab, &rcTab); TabCtrl_AdjustRect(pHdr->hTab, FALSE, &rcTab); InflateRect(&rcTab, 1, 1); rcTab.left -= 2;
MapWindowPoints(NULL, hMainDlg, (LPPOINT)&rcTab, 2);
pHdr->rcDisplay = rcTab;
//
// Create both dialog boxes.
//
for (nCount = 0; nCount < NUM_TABS; nCount++) { pHdr->hDisplay[nCount] = CreateDialogIndirect(g_hInstance, pHdr->pRes[nCount], hMainDlg, pHdr->pDlgProc[nCount]); } }
TCHAR* GetRelativePath( TCHAR* pExeFile, TCHAR* pMatchFile ) /*++
GetRelativePath
Description: Returns a relative path based on an EXE and a matching file. The caller must free the memory using HeapFree.
--*/ { int nLenExe = 0; int nLenMatch = 0; TCHAR* pExe = NULL; TCHAR* pMatch = NULL; TCHAR* pReturn = NULL; TCHAR result[MAX_PATH] = { _T('\0') }; TCHAR* resultIdx = result; BOOL bCommonBegin = FALSE; // Indicates if the paths have a common beginning
pExe = _tcschr(pExeFile, _T('\\')); pMatch = _tcschr(pMatchFile, _T('\\'));
while (pExe && pMatch) {
nLenExe = (int)(pExe - pExeFile); nLenMatch = (int)(pMatch - pMatchFile);
if (nLenExe != nLenMatch) { break; }
if (!(_tcsnicmp(pExeFile, pMatchFile, nLenExe) == 0)) { break; }
bCommonBegin = TRUE; pExeFile = pExe + 1; pMatchFile = pMatch + 1;
pExe = _tcschr(pExeFile, _T('\\')); pMatch = _tcschr(pMatchFile, _T('\\')); }
//
// Walk the path and put '..\' where necessary
//
if (bCommonBegin) {
while (pExe) {
StringCchCopy(resultIdx, ARRAYSIZE(result), _T("..\\")); resultIdx = resultIdx + 3; pExeFile = pExe + 1; pExe = _tcschr(pExeFile, _T('\\')); }
StringCchCopy(resultIdx, ARRAYSIZE(result), pMatchFile);
nLenExe = _tcslen(result) + 1;
pReturn = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLenExe * sizeof(TCHAR));
if (!pReturn) { return NULL; }
StringCchCopy(pReturn, nLenExe, result);
return pReturn; }
return NULL; }
void SaveEntryToFile( HWND hDlg, HWND hEdit, LPCTSTR lpFileName ) /*++
SaveEntryToFile
Description: Writes the XML out to a file.
--*/ { int cchSize = 0; DWORD cbBytesWritten; HANDLE hFile = NULL; LPTSTR lpData = NULL; TCHAR szError[MAX_PATH];
//
// Determine how much space we need for the buffer, then allocate it.
//
cchSize = GetWindowTextLength(hEdit);
if (cchSize) { //
// Account for the additional byte & the NULL that we're storing
// in the file.
//
cchSize += 2; lpData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cchSize * sizeof(TCHAR));
if (!lpData) { LoadString(g_hInstance, IDS_BUFFER_ALLOC_FAIL, szError, ARRAYSIZE(szError)); MessageBox(hDlg, szError, g_szAppTitle, MB_ICONERROR); return; }
//
// Ensure that the file is saved as Unicode.
//
lpData[0] = 0xFEFF;
//
// Get the text out of the text box and write it out to our file.
//
if (!GetWindowText(hEdit, lpData + 1, cchSize - 1)) { goto Cleanup; }
hFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { LoadString(g_hInstance, IDS_FILE_CREATE_FAIL, szError, ARRAYSIZE(szError)); MessageBox(hDlg, szError, g_szAppTitle, MB_ICONERROR); goto Cleanup; }
WriteFile(hFile, lpData, cchSize * sizeof(TCHAR), &cbBytesWritten, NULL);
CloseHandle(hFile);
}
Cleanup:
HeapFree(GetProcessHeap(), 0, lpData);
}
void DoFileSave( HWND hDlg ) /*++
DoFileSave
Description: Displays the common dialog allowing for file save.
--*/ { TCHAR szFilter[MAX_PATH] = _T(""); TCHAR szTemp[MAX_PATH] = _T(""); OPENFILENAME ofn = {0};
*szTemp = 0;
LoadString(g_hInstance, IDS_SAVE_FILTER, szFilter, ARRAYSIZE(szFilter));
ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = (LPTSTR)NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 1; ofn.lpstrFile = szTemp; ofn.nMaxFile = sizeof(szTemp); ofn.lpstrTitle = NULL; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = _T("xml"); ofn.lCustData = 0; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
if (GetSaveFileName(&ofn)) { SaveEntryToFile(hDlg, GetDlgItem(hDlg, IDC_XML), szTemp); } }
void GetTopLevelWindowIntoView( HWND hwnd ) { RECT rectWindow, rectScreen; int nCx, nCy, nCxScreen, nCyScreen; int dx = 0, dy = 0; HWND hwndDesktop;
if (GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD) { return; }
hwndDesktop = GetDesktopWindow();
GetWindowRect(hwnd, &rectWindow); GetWindowRect(hwndDesktop, &rectScreen);
nCx = rectWindow.right - rectWindow.left; nCy = rectWindow.bottom - rectWindow.top;
nCxScreen = rectScreen.right - rectScreen.left; nCyScreen = rectScreen.bottom - rectScreen.top;
//
// Make it fix on the x coord.
//
if (rectWindow.left < rectScreen.left) { dx = rectScreen.left - rectWindow.left;
rectWindow.left += dx; rectWindow.right += dx; }
if (rectWindow.right > rectScreen.right) { if (nCx < nCxScreen) { dx = rectScreen.right - rectWindow.right;
rectWindow.left += dx; rectWindow.right += dx; } }
//
// Make it fix on the y coord.
//
if (rectWindow.top < rectScreen.top) { dy = rectScreen.top - rectWindow.top;
rectWindow.top += dy; rectWindow.bottom += dy; }
if (rectWindow.bottom > rectScreen.bottom) { if (nCy < nCyScreen) { dy = rectScreen.bottom - rectWindow.bottom;
rectWindow.top += dy; rectWindow.bottom += dy; } }
if (dx != 0 || dy != 0) { MoveWindow(hwnd, rectWindow.left, rectWindow.top, nCx, nCy, TRUE); } }
void ReplaceCmdLine( PFIX pFix, TCHAR* pszNewCmdLine ) /*++
ReplaceCmdLine
Description: Replaces the command line for a shim DLL.
--*/ { TCHAR szError[MAX_PATH]; int nLen;
if (pFix->pszCmdLine != NULL) { HeapFree(GetProcessHeap(), 0, pFix->pszCmdLine); pFix->pszCmdLine = NULL; }
if (pszNewCmdLine == NULL) { return;
} else if ((*pszNewCmdLine == '"') && (_tcslen(pszNewCmdLine) == 1)) { LoadString(g_hInstance, IDS_INVALID_CMD_LINE, szError, ARRAYSIZE(szError)); MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONEXCLAMATION); return; }
nLen = _tcslen(pszNewCmdLine) + 1;
pFix->pszCmdLine = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLen * sizeof(TCHAR));
if (pFix->pszCmdLine != NULL) { StringCchCopy(pFix->pszCmdLine, nLen, pszNewCmdLine); } else { DPF("[ReplaceCmdLine] Failed to replace the cmd line for '%S'", pFix->pszName); } }
void DeselectAllShims( HWND hdlg ) /*++
DeselectAllShims
Description: Removes selections for all shims listed.
--*/ { int cShims, nIndex; LVITEM lvi;
//
// Walk all the shims in the list view and deselect them.
//
ZeroMemory(&lvi, sizeof(lvi));
cShims = ListView_GetItemCount(g_hwndShimList);
for (nIndex = 0; nIndex < cShims; nIndex++) {
PFIX pFix;
lvi.iItem = nIndex; lvi.mask = LVIF_STATE | LVIF_PARAM; lvi.stateMask = LVIS_STATEIMAGEMASK;
ListView_GetItem(g_hwndShimList, &lvi);
pFix = (PFIX)lvi.lParam;
//
// Clear the check box, removes the 'X', clear the command line,
// and clear the modules.
//
ListView_SetItemText(g_hwndShimList, nIndex, 1, _T("")); ListView_SetItemText(g_hwndShimList, nIndex, 2, _T("")); ListView_SetCheckState(g_hwndShimList, nIndex, FALSE); ReplaceCmdLine(pFix, NULL); BuildModuleListForShim(pFix, BML_DELFRLISTVIEW); }
//
// Update the count of selected shims.
//
SetTimer(hdlg, ID_COUNT_SHIMS, 100, NULL); }
void AddMatchingFile( HWND hdlg, LPCTSTR pszFullPath, LPCTSTR pszRelativePath, BOOL bMainEXE ) /*++
AddMatchingFile
Description: Adds a matching file and it's attributes to the tree.
--*/ { TVINSERTSTRUCT is; HTREEITEM hParent; DWORD dwCount; DWORD dwAttrCount; TCHAR szItem[MAX_PATH]; PATTRINFO pAttrInfo = NULL;
//
// Call the attribute manager to get all the attributes for this file.
//
if (!SdbGetFileAttributes(pszFullPath, &pAttrInfo, &dwAttrCount)) { DPF("[AddMatchingFile] Failed to get attributes for %S", pszFullPath); return; }
is.hParent = TVI_ROOT; is.hInsertAfter = TVI_LAST; is.item.lParam = (LPARAM)pAttrInfo; is.item.mask = TVIF_TEXT | TVIF_PARAM; is.item.pszText = (LPTSTR)pszRelativePath;
hParent = TreeView_InsertItem(g_hwndFilesTree, &is);
is.hParent = hParent;
is.item.mask = TVIF_TEXT | TVIF_STATE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; is.item.pszText = szItem;
is.item.iImage = 0; is.item.iSelectedImage = 1;
//
// By default the attributes are not selected. To have them selected
// by default you need to replace the following 1 with 2.
//
is.item.state = INDEXTOSTATEIMAGEMASK(1); is.item.stateMask = TVIS_STATEIMAGEMASK;
//
// Loop through all the attributes and show the ones that are available.
//
for (dwCount = 0; dwCount < dwAttrCount; dwCount++) {
if (!SdbFormatAttribute(&pAttrInfo[dwCount], szItem, ARRAYSIZE(szItem))) { continue; }
//
// EXETYPE is a bogus attribute. Don't show it!
//
is.item.lParam = dwCount; TreeView_InsertItem(g_hwndFilesTree, &is); }
TreeView_Expand(g_hwndFilesTree, hParent, TVE_EXPAND); }
void BrowseForApp( HWND hdlg ) /*++
BrowseForApp
Description: Browse for the main executable for which a shim will be applied. --*/ { TCHAR szFilter[MAX_PATH] = _T(""); TCHAR szTitle[MAX_PATH] = _T(""); TCHAR szExe[MAX_PATH] = _T(""); TCHAR szShortName[MAX_PATH] = _T(""); OPENFILENAME ofn = {0}; HRESULT hr;
LoadString(g_hInstance, IDS_BROWSE_FILTER, szFilter, ARRAYSIZE(szFilter)); LoadString(g_hInstance, IDS_BROWSE_TITLE, szTitle, ARRAYSIZE(szTitle));
//
// Use locals instead of globals because if the user cancels
// the dialog without selecting, we'll ruin whatever app is
// already selected.
// rparsons - 14 Jan 02
//
ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hdlg; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szExe; ofn.nMaxFile = ARRAYSIZE(szExe); ofn.lpstrFileTitle = szShortName; ofn.nMaxFileTitle = ARRAYSIZE(szShortName); ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = szTitle; ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = _T("exe");
if (GetOpenFileName(&ofn)) {
TCHAR szMainEXE[128];
g_bSDBInstalled = FALSE;
StringCchCopy(g_szBinary, ARRAYSIZE(g_szBinary), szExe); StringCchCopy(g_szShortName, ARRAYSIZE(g_szShortName), szShortName);
//
// The parent exe defaults to the same as the EXE.
//
StringCchCopy(g_szParentExeName, ARRAYSIZE(g_szParentExeName), g_szShortName);
StringCchCopy(g_szParentExeFullPath, ARRAYSIZE(g_szParentExeFullPath), g_szBinary);
g_bSelectedParentExe = FALSE;
SetDlgItemText(hdlg, IDC_BINARY, g_szBinary);
EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_RUN), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_CREATEFILE), TRUE); EnableWindow(GetDlgItem(hdlg, IDC_SHOWXML), TRUE);
TreeView_DeleteAllItems(g_hwndFilesTree);
hr = StringCchPrintf(szMainEXE, ARRAYSIZE(szMainEXE), _T("Main executable (%s)"), g_szShortName);
if (FAILED(hr)) { DPF("[BrowseForApp] 0x%08X Buffer too small", HRESULT_CODE(hr)); return; }
AddMatchingFile(hdlg, g_szBinary, szMainEXE, TRUE); } }
void PromptAddMatchingFile( HWND hdlg ) /*++
PromptAddMatchingFile
Description: Show the open file dialog to allow the user to add a matching file. --*/ { TCHAR szFullPath[MAX_PATH] = _T(""); TCHAR szShortName[MAX_PATH] = _T(""); TCHAR szFilter[MAX_PATH] = _T(""); TCHAR szTitle[MAX_PATH] = _T(""); TCHAR szParentTitle[MAX_PATH] = _T(""); TCHAR szInitialPath[MAX_PATH] = _T(""); TCHAR szDrive[_MAX_DRIVE] = _T(""); TCHAR szDir[_MAX_DIR] = _T(""); TCHAR* pMatch = NULL; TCHAR szError[MAX_PATH]; OPENFILENAME ofn = {0};
*szInitialPath = 0;
LoadString(g_hInstance, IDS_MATCH_FILTER, szFilter, ARRAYSIZE(szFilter)); LoadString(g_hInstance, IDS_MATCH_TITLE, szTitle, ARRAYSIZE(szTitle));
if (*g_szParentExeFullPath) { _tsplitpath(g_szParentExeFullPath, szDrive, szDir, NULL, NULL);
StringCchCopy(szInitialPath, ARRAYSIZE(szInitialPath), szDrive); StringCchCat(szInitialPath, ARRAYSIZE(szInitialPath), szDir); }
ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hdlg; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = szFullPath; ofn.nMaxFile = ARRAYSIZE(szFullPath); ofn.lpstrFileTitle = szShortName; ofn.nMaxFileTitle = ARRAYSIZE(szShortName); ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = szTitle; ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = _T("exe");
if (GetOpenFileName(&ofn)) { //
// Determine if the matching file is on the same drive
// as the EXE that was selected.
//
if (!PathIsSameRoot(szFullPath, g_szParentExeFullPath) && !g_bSelectedParentExe) {
TCHAR szParentFile[MAX_PATH];
//
// Prompt the user for the parent EXE.
//
*szParentFile = 0; *szInitialPath = 0;
if (*szFullPath) { _tsplitpath(szFullPath, szDrive, szDir, NULL, NULL); StringCchCopy(szInitialPath, ARRAYSIZE(szInitialPath), szDrive); StringCchCat(szInitialPath, ARRAYSIZE(szInitialPath), szDir); }
LoadString(g_hInstance, IDS_PARENT_TITLE, szParentTitle, ARRAYSIZE(szParentTitle));
ofn.lpstrTitle = szParentTitle; ofn.lpstrFile = szParentFile; ofn.nMaxFile = sizeof(szParentFile);
if (GetOpenFileName(&ofn) == TRUE) { StringCchCopy(g_szParentExeName, ARRAYSIZE(g_szParentExeName), szShortName);
StringCchCopy(g_szParentExeFullPath, ARRAYSIZE(g_szParentExeFullPath), szParentFile);
g_bSelectedParentExe = TRUE; } }
//
// Check the drive letters to see which drive the match file is on
// then calculate a relative path to the matching file.
//
if (PathIsSameRoot(szFullPath, g_szParentExeFullPath)) {
pMatch = GetRelativePath(g_szParentExeFullPath, szFullPath);
} else if (PathIsSameRoot(szFullPath, g_szBinary)) {
pMatch = GetRelativePath(g_szBinary, szFullPath);
} else { LoadString(g_hInstance, IDS_MATCH_PATH_NOT_RELATIVE, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION); return; }
if (pMatch) { //
// Finally add the maching file and free the memory
//
AddMatchingFile(hdlg, szFullPath, pMatch, FALSE);
HeapFree(GetProcessHeap(), 0, pMatch); } } }
void ShowAvailableFixes( HWND hList ) /*++
ShowAvailableFixes
Description: Query the shim database and populate the shim list with all the available shims. --*/ { LVITEM lvitem; PFIX pFix; TCHAR szError[MAX_PATH]; UINT uCount = 0;
g_pFixHead = ReadFixesFromSdb(_T("sysmain.sdb"), g_bAllShims);
if (g_pFixHead == NULL) { LoadString(g_hInstance, IDS_SDB_READ_FAIL, szError, ARRAYSIZE(szError)); MessageBox(NULL, szError, g_szAppTitle, MB_ICONERROR); return; }
//
// Walk the list and add all the fixes to the list view.
//
pFix = g_pFixHead;
while (pFix != NULL) {
if (pFix->dwFlags & FIX_TYPE_LAYER) { LPARAM lInd;
lInd = SendMessage(g_hwndListLayers, LB_ADDSTRING, 0, (LPARAM)pFix->pszName); SendMessage(g_hwndListLayers, LB_SETITEMDATA, lInd, (LPARAM)pFix); } else { lvitem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; lvitem.lParam = (LPARAM)pFix; lvitem.pszText = pFix->pszName; lvitem.iItem = ListView_GetItemCount(g_hwndShimList); lvitem.iSubItem = 0; lvitem.state = INDEXTOSTATEIMAGEMASK(1); lvitem.stateMask = LVIS_STATEIMAGEMASK;
ListView_InsertItem(hList, &lvitem); }
pFix = pFix->pNext; } }
BOOL InstallSDB( TCHAR* pszFileName, BOOL fInstall ) /*++
InstallSDB
Description: Launch sdbinst.exe to install or uninstall the specified SDB.
--*/ { HRESULT hr; TCHAR szAppName[MAX_PATH]; TCHAR szCmdLine[MAX_PATH]; STARTUPINFO si; PROCESS_INFORMATION pi;
//
// Build a path to our application name and command-line.
//
hr = StringCchPrintf(szAppName, ARRAYSIZE(szAppName), _T("%s\\sdbinst.exe"), g_szSysDir);
if (FAILED(hr)) { DPF("[InstallSDB] 0x%08X Buffer too small (1)", HRESULT_CODE(hr)); return FALSE; }
hr = StringCchPrintf(szCmdLine, ARRAYSIZE(szCmdLine), fInstall ? _T("\"%s\" -q \"%s\"") : _T("\"%s\" -q -u \"%s\""), szAppName, pszFileName);
if (FAILED(hr)) { DPF("[InstallSDB] 0x%08X Buffer too small (2)", HRESULT_CODE(hr)); return FALSE; }
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(si);
DPF("[InstallSDB] AppName: %S CmdLine: %S\n", szAppName, szCmdLine);
if (!CreateProcess(szAppName, szCmdLine, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
DPF("[InstallSDB] 0x%08X CreateProcess '%S %S' failed", szAppName, szCmdLine, GetLastError()); return FALSE; }
//
// Wait for SDBInst to complete it's work.
//
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
return TRUE; }
void CreateSupportForApp( HWND hdlg ) /*++
CreateSupportForApp
Description: Build an SDB for the application and offer the user the chance to install it. --*/ { BOOL bok; TCHAR szFileCreated[MAX_PATH]; TCHAR szError[MAX_PATH]; TCHAR szTemp[MAX_PATH]; HRESULT hr; int nAnswer;
CleanupSupportForApp(g_szShortName);
bok = CollectFix(g_hwndListLayers, g_hwndShimList, g_hwndFilesTree, g_szShortName, g_szBinary, (g_nCrtTab == 0 ? CFF_USELAYERTAB : 0) | (g_fW2K ? CFF_ADDW2KSUPPORT : 0), szFileCreated);
if (!bok) { LoadString(g_hInstance, IDS_FIX_CREATE_FAIL, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONERROR); } else { LoadString(g_hInstance, IDS_CREATE_FIX, szTemp, ARRAYSIZE(szTemp));
hr = StringCchPrintf(szError, ARRAYSIZE(szError), szTemp, szFileCreated);
if (FAILED(hr)) { DPF("[CreateSupportForApp] 0x%08X Buffer too small", HRESULT_CODE(hr)); return; }
nAnswer = MessageBox(hdlg, szError, g_szAppTitle, MB_YESNO | MB_ICONQUESTION);
if (IDYES == nAnswer) { bok = InstallSDB(szFileCreated, TRUE);
if (!bok) { LoadString(g_hInstance, IDS_INSTALL_FIX_FAIL, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONERROR); } else { LoadString(g_hInstance, IDS_INSTALL_FIX_OK, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONINFORMATION); g_bSDBInstalled = TRUE; } } else { //
// NTRAID#583475-rparsons The user decided not to install the database.
// Ensure that we do not remove the file that we created upon exit.
//
*g_szSDBToDelete = 0; } } }
BOOL ShowXML( HWND hdlg ) /*++
ShowXML
Description: Show the XML for the current selections.
--*/ { BOOL bok; TCHAR szError[MAX_PATH];
bok = CollectFix(g_hwndListLayers, g_hwndShimList, g_hwndFilesTree, g_szShortName, g_szBinary, CFF_SHOWXML | (g_nCrtTab == 0 ? CFF_USELAYERTAB : 0) | (g_fW2K ? CFF_ADDW2KSUPPORT : 0), NULL);
if (!bok) { LoadString(g_hInstance, IDS_TOO_MANY_FILES, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION); }
return bok; }
void RunTheApp( HWND hdlg ) /*++
RunTheApp
Description: Run the selected app.
--*/ { STARTUPINFO si; PROCESS_INFORMATION pi; TCHAR szFileCreated[MAX_PATH]; TCHAR szCmdLine[MAX_PATH]; TCHAR szFullCmdLine[MAX_PATH]; TCHAR szError[MAX_PATH]; TCHAR szRun[MAX_PATH]; TCHAR* pszCmd; TCHAR* pszDir; TCHAR* psz; BOOL bok; HRESULT hr;
//
// Cleanup for the previous app.
//
CleanupSupportForApp(g_szShortName);
bok = CollectFix(g_hwndListLayers, g_hwndShimList, g_hwndFilesTree, g_szShortName, g_szBinary, CFF_SHIMLOG | CFF_APPENDLAYER | (g_nCrtTab == 0 ? CFF_USELAYERTAB : 0) | (g_fW2K ? CFF_ADDW2KSUPPORT : 0), szFileCreated);
if (!bok) { LoadString(g_hInstance, IDS_ADD_SUPPORT_FAIL, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONERROR); return; }
//
// We need to install the fix for them.
//
if (!(InstallSDB(szFileCreated, TRUE))) { LoadString(g_hInstance, IDS_INSTALL_FIX_FAIL, szError, ARRAYSIZE(szError)); MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONERROR); return; }
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
//
// Get the command line, if there is one.
//
*szCmdLine = 0; *szFullCmdLine = 0; GetDlgItemText(hdlg, IDC_CMD_LINE, szCmdLine, ARRAYSIZE(szCmdLine));
//
// To have a proper command-line, we need to the module name.
//
if (*szCmdLine) { hr = StringCchPrintf(szFullCmdLine, ARRAYSIZE(szFullCmdLine), _T("%s %s"), g_szBinary, szCmdLine);
if (FAILED(hr)) { DPF("[RunTheApp] 0x%08X Buffer too small", HRESULT_CODE(hr)); LoadString(g_hInstance, IDS_RUNAPP_FAILED, szError, ARRAYSIZE(szError)); MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONERROR); return; } }
StringCchCopy(szRun, ARRAYSIZE(szRun), g_szBinary);
pszCmd = szRun; pszDir = g_szBinary;
//
// We need to change the current directory or some apps won't run.
//
psz = pszDir + _tcslen(pszDir) - 1;
while (psz > pszDir && *psz != _T('\\')) { psz--; }
if (psz > pszDir) { *psz = 0; SetCurrentDirectory(pszDir); *psz = _T('\\'); }
DPF("[RunTheApp] AppName: %S CmdLine: %S", szRun, szCmdLine);
if (!CreateProcess(szRun, *szFullCmdLine ? szFullCmdLine : NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_SEPARATE_WOW_VDM, NULL, NULL, &si, &pi)) {
LoadString(g_hInstance, IDS_RUNAPP_FAILED, szError, ARRAYSIZE(szError)); MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONERROR); DPF("[RunTheApp] CreateProcess failed 0x%08X", GetLastError()); } else { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); }
//
// Save this SDB for later so we can remove it.
//
StringCchCopy(g_szSDBToDelete, ARRAYSIZE(g_szSDBToDelete), szFileCreated); }
void ExpandCollapseDialog( HWND hdlg, BOOL bHide ) /*++
ExpandCollapseDialog
Description: Change the current view of the dialog.
--*/ { TCHAR szSimple[64]; TCHAR szAdvanced[64]; int i, nShow; DWORD arrId[] = {IDC_ADD_MATCHING, IDC_FILE_ATTRIBUTES_STATIC, IDC_ATTRIBUTES, IDC_CREATEFILE, 0};
if (!bHide) { SetWindowPos(hdlg, NULL, 0, 0, g_rcDlgBig.right - g_rcDlgBig.left, g_rcDlgBig.bottom - g_rcDlgBig.top, SWP_NOMOVE | SWP_NOZORDER); nShow = SW_SHOW; g_bSimpleEdition = FALSE; LoadString(g_hInstance, IDS_SIMPLE_TEXT, szSimple, ARRAYSIZE(szSimple)); SetDlgItemText(hdlg, IDC_DETAILS, szSimple); SendDlgItemMessage(hdlg, IDC_CREATEFILE, BM_SETCHECK, BST_CHECKED, 0);
//
// Make sure the dialog is in view.
//
GetTopLevelWindowIntoView(hdlg); } else { nShow = SW_HIDE; g_bSimpleEdition = TRUE; LoadString(g_hInstance, IDS_ADVANCED_TEXT, szAdvanced, ARRAYSIZE(szAdvanced)); SetDlgItemText(hdlg, IDC_DETAILS, szAdvanced); SendDlgItemMessage(hdlg, IDC_CREATEFILE, BM_SETCHECK, BST_UNCHECKED, 0); }
for (i = 0; arrId[i] != 0; i++) { ShowWindow(GetDlgItem(hdlg, arrId[i]), nShow); }
if (bHide) { SetWindowPos(hdlg, NULL, 0, 0, g_rcDlgSmall.right - g_rcDlgSmall.left, g_rcDlgSmall.bottom - g_rcDlgSmall.top, SWP_NOMOVE | SWP_NOZORDER); } }
void LayerChanged( HWND hdlg ) /*++
LayerChanged
Description: Changing the layer has the effect of selecting the shims that the layer consists of. --*/ { LRESULT lSel; PFIX pFix; LVITEM lvi; int nIndex, cShims = 0;
lSel = SendMessage(g_hwndListLayers, LB_GETCURSEL, 0, 0);
if (lSel == LB_ERR) { DPF("[LayerChanged] No layer selected"); return; }
pFix = (PFIX)SendMessage(g_hwndListLayers, LB_GETITEMDATA, lSel, 0);
if (pFix->parrShim == NULL) { DPF("[LayerChanged] No array of DLLs"); return; }
// Remove any prior selections.
DeselectAllShims(g_hFixesDlg);
//
// Loop through all the items in the shim list and make the
// appropriate selections.
//
cShims = ListView_GetItemCount(g_hwndShimList);
for (nIndex = 0; nIndex < cShims; nIndex++) {
PFIX pFixItem; int nInd = 0;
lvi.mask = LVIF_PARAM; lvi.iItem = nIndex; lvi.iSubItem = 0;
ListView_GetItem(g_hwndShimList, &lvi);
pFixItem = (PFIX)lvi.lParam;
//
// See if this shim DLL is in the array for the selected layer.
//
while (pFix->parrShim[nInd] != NULL) {
if (pFix->parrShim[nInd] == pFixItem) { break; }
nInd++; }
//
// Put a check next to this shim DLL. If he has a command line,
// put an 'X' in the CmdLine subitem.
//
if (pFix->parrShim[nInd] != NULL) { ListView_SetCheckState(g_hwndShimList, nIndex, TRUE); } else { ListView_SetCheckState(g_hwndShimList, nIndex, FALSE); }
if (pFix->parrCmdLine[nInd] != NULL) { ReplaceCmdLine(pFixItem, pFix->parrCmdLine[nInd]); ListView_SetItemText(g_hwndShimList, nIndex, 1, _T("X")); }
ListView_SetItem(g_hwndShimList, &lvi); }
//
// Update the count of selected shims.
//
SetTimer(g_hFixesDlg, ID_COUNT_SHIMS, 100, NULL); }
BOOL InitMainDialog( HWND hdlg ) /*++
InitMainDialog
Description: Init routine called during WM_INITDIALOG for the main dialog of QFixApp. --*/ { HICON hIcon; RECT rcList, rcTree; HIMAGELIST hImage; TCHAR szText[MAX_PATH];
//
// Initialize globals.
//
g_bSDBInstalled = FALSE; g_szParentExeFullPath[0] = 0; g_szBinary[0] = 0; g_hDlg = hdlg;
//
// If we didn't get the proper command-line, disable the 'Show XML'
// button.
//
if (!g_bShowXML) { ShowWindow(GetDlgItem(hdlg, IDC_SHOWXML), SW_HIDE); }
//
// The dialog has two views. Calculate the size of the smaller
// view and show the simpler view by default.
//
GetWindowRect(hdlg, &g_rcDlgBig);
GetWindowRect(GetDlgItem(hdlg, IDC_ATTRIBUTES), &rcList); GetWindowRect(GetDlgItem(hdlg, IDC_TAB_FIXES), &rcTree);
g_rcDlgSmall.left = g_rcDlgBig.left; g_rcDlgSmall.top = g_rcDlgBig.top; g_rcDlgSmall.bottom = g_rcDlgBig.bottom; g_rcDlgSmall.right = g_rcDlgBig.right - (rcList.right - rcList.left) - (rcList.left - rcTree.right);
ExpandCollapseDialog(hdlg, TRUE);
//
// Disable a bunch of controls.
//
EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_REMOVE_MATCHING), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_RUN), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_CREATEFILE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_SHOWXML), FALSE);
//
// Show the app icon.
//
hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
SetClassLongPtr(hdlg, GCLP_HICON, (LONG_PTR)hIcon);
g_hwndTab = GetDlgItem(hdlg, IDC_TAB_FIXES); g_hwndFilesTree = GetDlgItem(hdlg, IDC_ATTRIBUTES);
//
// Set up the tab control.
//
InitTabs(hdlg, g_hwndTab);
hImage = ImageList_LoadImage(g_hInstance, MAKEINTRESOURCE(IDB_BMP_CHECK), 16, 0, CLR_DEFAULT, IMAGE_BITMAP, LR_LOADTRANSPARENT);
if (hImage != NULL) { TreeView_SetImageList(g_hwndFilesTree, hImage, TVSIL_STATE); } else { DPF("[InitMainDialog] Failed to load imagelist"); }
//
// Set the text for the link window.
//
LoadString(g_hInstance, g_fW2K ? IDS_W2K_LINK : IDS_XP_LINK, szText, ARRAYSIZE(szText)); SetDlgItemText(g_hDlg, IDC_DOWNLOAD_WU, szText);
//
// Limit the amount of text that can be typed into the command-line
// edit box for safety.
//
SendDlgItemMessage(hdlg, IDC_CMD_LINE, EM_LIMITTEXT, (WPARAM)MAX_COMMAND_LINE, 0);
//
// Try selecting the Win95 layer.
//
SendMessage(g_hwndListLayers, LB_SELECTSTRING, (WPARAM)(-1), (LPARAM)_T("Win95"));
LayerChanged(hdlg);
TabCtrl_SetCurFocus(g_hwndTab, 0); ShowWindow(g_hLayersDlg, SW_SHOWNORMAL);
return TRUE; }
void FileTreeToggleSelection( HTREEITEM hItem, int uMode ) /*++
FileTreeToggleSelection
Description: Changes the selection on the attributes tree.
--*/ { UINT State; TVITEM item;
switch (uMode) { case uSelect: State = INDEXTOSTATEIMAGEMASK(2); break;
case uDeselect: State = INDEXTOSTATEIMAGEMASK(1); break;
case uReverse: { item.mask = TVIF_HANDLE | TVIF_STATE; item.hItem = hItem; item.stateMask = TVIS_STATEIMAGEMASK;
TreeView_GetItem(g_hwndFilesTree, &item);
State = item.state & TVIS_STATEIMAGEMASK;
if (State) { if (((State >> 12) & 0x03) == 2) { State = INDEXTOSTATEIMAGEMASK(1); } else { State = INDEXTOSTATEIMAGEMASK(2); } } break; }
default: DPF("[FileTreeToggleSelection] Invalid mode %u", uMode); return; }
item.mask = TVIF_HANDLE | TVIF_STATE; item.hItem = hItem; item.state = State; item.stateMask = TVIS_STATEIMAGEMASK;
TreeView_SetItem(g_hwndFilesTree, &item); }
void SelectAttrsInTree( BOOL fSelect ) /*++
SelectAttrsInTree
Description: Walks each attribute in tree and reverses it's selection.
--*/ { HTREEITEM hItem, hChildItem;
hItem = TreeView_GetSelection(g_hwndFilesTree);
hChildItem = TreeView_GetChild(g_hwndFilesTree, hItem);
FileTreeToggleSelection(hChildItem, fSelect ? uSelect : uDeselect);
while (hChildItem) { hChildItem = TreeView_GetNextSibling(g_hwndFilesTree, hChildItem); FileTreeToggleSelection(hChildItem, fSelect ? uSelect : uDeselect); } }
void ShimListToggleSelection( int nItem, int uMode ) /*++
ShimListToggleSelection
Description: Changes the selection on the shim list.
--*/ { UINT uState;
switch (uMode) { case uSelect: ListView_SetCheckState(g_hwndShimList, nItem, TRUE); break;
case uDeselect: ListView_SetCheckState(g_hwndShimList, nItem, FALSE); break;
case uReverse:
uState = ListView_GetItemState(g_hwndShimList, nItem, LVIS_STATEIMAGEMASK);
if (uState) { if (((uState >> 12) & 0x03) == 2) { uState = INDEXTOSTATEIMAGEMASK(2); } else { uState = INDEXTOSTATEIMAGEMASK(1); } }
ListView_SetItemState(g_hwndShimList, nItem, uState, LVIS_STATEIMAGEMASK);
break; } }
void HandleTabNotification( HWND hdlg, LPARAM lParam ) /*++
HandleTabNotification
Description: Handle all the notifications we care about for the tab.
--*/ { LPNMHDR pnm = (LPNMHDR)lParam; int ind = 0;
switch (pnm->code) {
case TCN_SELCHANGE: { int nSel;
DLGHDR *pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, DWLP_USER);
nSel = TabCtrl_GetCurSel(pHdr->hTab);
if (-1 == nSel) { break; }
g_nCrtTab = nSel;
if (nSel == 0) { ShowWindow(pHdr->hDisplay[1], SW_HIDE); ShowWindow(pHdr->hDisplay[0], SW_SHOW); } else { ShowWindow(pHdr->hDisplay[0], SW_HIDE); ShowWindow(pHdr->hDisplay[1], SW_SHOW); }
break; }
default: break; } }
INT_PTR CALLBACK OptionsDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
OptionsDlgProc
Description: Handles messages for the options dialog.
--*/ { int wCode = LOWORD(wParam); int wNotifyCode = HIWORD(wParam);
switch (uMsg) { case WM_INITDIALOG: { PFIX pFix; TCHAR szTitle[MAX_PATH]; TCHAR szTemp[MAX_PATH]; TCHAR szType[64]; TCHAR szModuleName[128]; HRESULT hr;
pFix = (PFIX)lParam;
//
// Limit the amount of text that can be typed into the command-line
// and module name edit boxes for safety.
//
SendDlgItemMessage(hdlg, IDC_SHIM_CMD_LINE, EM_LIMITTEXT, (WPARAM)SHIM_COMMAND_LINE_MAX_BUFFER, 0);
SendDlgItemMessage(hdlg, IDC_MOD_NAME, EM_LIMITTEXT, (WPARAM)MAX_PATH, 0);
LoadString(g_hInstance, IDS_MOD_TYPE, szType, ARRAYSIZE(szType)); LoadString(g_hInstance, IDS_MOD_NAME, szModuleName, ARRAYSIZE(szModuleName)); LoadString(g_hInstance, IDS_OPTIONS_TITLE, szTemp, ARRAYSIZE(szTemp));
SetWindowLongPtr(hdlg, DWLP_USER, lParam);
EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), FALSE);
g_hwndModuleList = GetDlgItem(hdlg, IDC_MOD_LIST);
InsertListViewColumn(g_hwndModuleList, szType, FALSE, 0, 75); InsertListViewColumn(g_hwndModuleList, szModuleName, FALSE, 1, 115);
ListView_SetExtendedListViewStyle(g_hwndModuleList, LVS_EX_FULLROWSELECT);
hr = StringCchPrintf(szTitle, ARRAYSIZE(szTitle), szTemp, pFix->pszName);
if (FAILED(hr)) { DPF("[OptionsDlgProc] 0x%08X Buffer too small", HRESULT_CODE(hr)); return 0; }
SetWindowText(hdlg, szTitle);
if (NULL != pFix->pszCmdLine) { SetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, pFix->pszCmdLine); }
//
// If this is a flag, disable the module include/exclude controls.
//
if (pFix->dwFlags & FIX_TYPE_FLAGVDM) { EnableWindow(g_hwndModuleList, FALSE); EnableWindow(GetDlgItem(hdlg, IDC_ADD), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_INCLUDE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_EXCLUDE), FALSE); EnableWindow(GetDlgItem(hdlg, IDC_MOD_NAME), FALSE); } else { CheckDlgButton(hdlg, IDC_INCLUDE, BST_CHECKED);
// Add any modules to the list view.
BuildModuleListForShim(pFix, BML_ADDTOLISTVIEW); }
break; }
case WM_NOTIFY: HandleModuleListNotification(hdlg, lParam); break;
case WM_COMMAND: switch (wCode) {
case IDC_ADD: { TCHAR szModName[MAX_PATH]; TCHAR szError[MAX_PATH]; UINT uInclude, uExclude;
GetDlgItemText(hdlg, IDC_MOD_NAME, szModName, ARRAYSIZE(szModName));
if (*szModName == 0) { LoadString(g_hInstance, IDS_NO_MOD, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION); SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME)); break; }
uInclude = IsDlgButtonChecked(hdlg, IDC_INCLUDE); uExclude = IsDlgButtonChecked(hdlg, IDC_EXCLUDE);
if ((BST_CHECKED == uInclude) || (BST_CHECKED == uExclude)) { AddModuleToListView(szModName, uInclude); SetDlgItemText(hdlg, IDC_MOD_NAME, _T("")); SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME)); } else { LoadString(g_hInstance, IDS_NO_INCEXC, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION); SetFocus(GetDlgItem(hdlg, IDC_INCLUDE)); break; } break;
} case IDC_REMOVE: { int nIndex;
nIndex = ListView_GetSelectionMark(g_hwndModuleList);
ListView_DeleteItem(g_hwndModuleList, nIndex);
EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), FALSE);
SetFocus(GetDlgItem(hdlg, IDC_MOD_NAME));
break; } case IDOK: { PFIX pFix; TCHAR szCmdLine[1024] = _T("");
pFix = (PFIX)GetWindowLongPtr(hdlg, DWLP_USER);
GetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, szCmdLine, 1023);
if (*szCmdLine != 0) { ReplaceCmdLine(pFix, szCmdLine); } else { ReplaceCmdLine(pFix, NULL); }
// Retrieve any modules from the list view.
BuildModuleListForShim(pFix, BML_GETFRLISTVIEW);
EndDialog(hdlg, TRUE); break; } case IDCANCEL: EndDialog(hdlg, FALSE); break;
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
INT_PTR CALLBACK MsgBoxDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
MsgBoxDlgProc
Description: Displays a message box dialog so we can use the hyperlink.
--*/ { int wCode = LOWORD(wParam); int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG: { TCHAR szLink[MAX_PATH]; UINT uNoSDB;
uNoSDB = (UINT)lParam;
//
// Use the parameter to determine what text to display.
//
if (uNoSDB) { LoadString(g_hInstance, IDS_W2K_NO_SDB, szLink, ARRAYSIZE(szLink)); SetDlgItemText(hdlg, IDC_MESSAGE, szLink); } else { LoadString(g_hInstance, IDS_SP2_SDB, szLink, ARRAYSIZE(szLink)); SetDlgItemText(hdlg, IDC_MESSAGE, szLink); }
LoadString(g_hInstance, IDS_MSG_LINK, szLink, ARRAYSIZE(szLink)); SetDlgItemText(hdlg, IDC_MSG_LINK, szLink);
break; }
case WM_NOTIFY: if (wParam == IDC_MSG_LINK) {
NMHDR* pHdr = (NMHDR*)lParam;
if (pHdr->code == NM_CLICK || pHdr->code == NM_RETURN) {
SHELLEXECUTEINFO sei = { 0 };
sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.fMask = SEE_MASK_DOENVSUBST; sei.hwnd = hdlg; sei.nShow = SW_SHOWNORMAL; sei.lpFile = g_szW2KUrl;
ShellExecuteEx(&sei); break; } } break;
case WM_COMMAND: switch (wCode) {
case IDCANCEL: EndDialog(hdlg, TRUE); break;
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
INT_PTR CALLBACK LayersTabDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
LayersTabDlgProc
Description: Handle messages for the layers tab.
--*/ { int wCode = LOWORD(wParam); int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG: HandleLayersDialogInit(hdlg); break;
case WM_COMMAND:
if (wNotifyCode == LBN_SELCHANGE && wCode == IDC_LAYERS) { LayerChanged(hdlg); break; }
switch (wCode) {
case IDCANCEL: EndDialog(hdlg, TRUE); break;
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
INT_PTR CALLBACK FixesTabDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
LayersDlgProc
Description: Handle messages for the fixes tab.
--*/ { int wCode = LOWORD(wParam); int wNotifyCode = HIWORD(wParam);
switch (uMsg) {
case WM_INITDIALOG: if (!HandleFixesDialogInit(hdlg)) { EndDialog(g_hDlg, 0); } break;
case WM_NOTIFY: if (wParam == IDC_SHIMS) { HandleShimListNotification(hdlg, lParam); } break;
case WM_TIMER: if (wParam == ID_COUNT_SHIMS) { KillTimer(hdlg, ID_COUNT_SHIMS); CountShims(TRUE); } break;
case WM_COMMAND: switch (wCode) {
case IDCANCEL: EndDialog(hdlg, TRUE); break;
case IDC_CLEAR_SHIMS: DeselectAllShims(hdlg); break;
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
void HandleModuleListNotification( HWND hdlg, LPARAM lParam ) /*++
HandleModuleListNotification
Description: Handle all the notifications we care about for the shim list. --*/ { LPNMHDR pnm = (LPNMHDR)lParam;
switch (pnm->code) {
case NM_CLICK: { LVHITTESTINFO lvhti;
GetCursorPos(&lvhti.pt); ScreenToClient(g_hwndShimList, &lvhti.pt);
ListView_HitTest(g_hwndShimList, &lvhti);
//
// If the user clicked on a list view item,
// enable the Remove button.
//
if (lvhti.flags & LVHT_ONITEMLABEL) { EnableWindow(GetDlgItem(hdlg, IDC_REMOVE), TRUE); }
break; } default: break; } }
void HandleShimListNotification( HWND hdlg, LPARAM lParam ) /*++
HandleShimListNotification
Description: Handle all the notifications we care about for the shim list. --*/ { LPNMHDR pnm = (LPNMHDR)lParam;
switch (pnm->code) {
case NM_CLICK: { LVHITTESTINFO lvhti;
GetCursorPos(&lvhti.pt); ScreenToClient(g_hwndShimList, &lvhti.pt);
ListView_HitTest(g_hwndShimList, &lvhti);
//
// If the check box state has changed,
// toggle the selection. Either way,
// maintain selection as we go.
//
if (lvhti.flags & LVHT_ONITEMSTATEICON) { ShimListToggleSelection(lvhti.iItem, uReverse); }
ListView_SetItemState(g_hwndShimList, lvhti.iItem, LVIS_FOCUSED | LVIS_SELECTED, 0x000F);
SetTimer(hdlg, ID_COUNT_SHIMS, 100, NULL); break; }
case NM_DBLCLK: { LVITEM lvi; int nItem; PFIX pFix;
nItem = ListView_GetSelectionMark(g_hwndShimList);
if (-1 == nItem) { break; }
lvi.mask = LVIF_PARAM; lvi.iItem = nItem;
ListView_GetItem(g_hwndShimList, &lvi);
pFix = (PFIX)lvi.lParam;
if ((pFix->dwFlags & FIX_TYPE_SHIM) || (pFix->dwFlags & FIX_TYPE_FLAGVDM)) { if (DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_OPTIONS), hdlg, OptionsDlgProc, (LPARAM)pFix)) {
if (NULL != pFix->pszCmdLine) { ListView_SetItemText(g_hwndShimList, nItem, 1, _T("X")); } else { ListView_SetItemText(g_hwndShimList, nItem, 1, _T("")); }
if (NULL != pFix->pModule) { ListView_SetItemText(g_hwndShimList, nItem, 2, _T("X")); } else { ListView_SetItemText(g_hwndShimList, nItem, 2, _T("")); } } } break; }
case LVN_ITEMCHANGED: { LPNMLISTVIEW lpnmlv; PFIX pFix;
lpnmlv = (LPNMLISTVIEW)lParam; pFix = (PFIX)lpnmlv->lParam;
//
// Only change the text if our selection has changed.
// If we don't do this, the text goes bye-bye when
// the user clicks the Clear button.
//
if ((lpnmlv->uChanged & LVIF_STATE) && (lpnmlv->uNewState & LVIS_SELECTED)) { SetDlgItemText(hdlg, IDC_SHIM_DESCRIPTION, pFix->pszDesc); ListView_SetSelectionMark(g_hwndShimList, lpnmlv->iItem); } break; } default: break; } }
void HandleAttributeTreeNotification( HWND hdlg, LPARAM lParam ) /*++
HandleAttributeTreeNotification
Description: Handle all the notifications we care about for the file attributes tree. --*/ { LPNMHDR pnm = (LPNMHDR)lParam;
switch (pnm->code) {
case NM_CLICK: { TVHITTESTINFO HitTest;
GetCursorPos(&HitTest.pt); ScreenToClient(g_hwndFilesTree, &HitTest.pt);
TreeView_HitTest(g_hwndFilesTree, &HitTest);
if (HitTest.flags & TVHT_ONITEMSTATEICON) { FileTreeToggleSelection(HitTest.hItem, uReverse);
} else if (HitTest.flags & TVHT_ONITEMLABEL) {
HWND hwndButton; HTREEITEM hItem, hRoot;
hwndButton = GetDlgItem(hdlg, IDC_REMOVE_MATCHING);
hItem = TreeView_GetParent(g_hwndFilesTree, HitTest.hItem);
hRoot = TreeView_GetRoot(g_hwndFilesTree);
//
// If the selected item has no parent and it's not
// the root, enable the remove matching button.
//
if ((NULL == hItem) && (hRoot != HitTest.hItem)) { EnableWindow(hwndButton, TRUE); } else { EnableWindow(hwndButton, FALSE); } } break; }
case NM_RCLICK: { TVHITTESTINFO HitTest; POINT pt;
GetCursorPos(&HitTest.pt);
pt.x = HitTest.pt.x; pt.y = HitTest.pt.y;
ScreenToClient(g_hwndFilesTree, &HitTest.pt);
TreeView_HitTest(g_hwndFilesTree, &HitTest);
if (HitTest.flags & TVHT_ONITEMLABEL) { HTREEITEM hParentItem;
TreeView_SelectItem(g_hwndFilesTree, HitTest.hItem);
//
// If the selected item has no parent, we assume that a
// matching file was right-clicked.
//
hParentItem = TreeView_GetParent(g_hwndFilesTree, HitTest.hItem);
if (NULL == hParentItem) { DisplayAttrContextMenu(&pt); } } break; } case TVN_KEYDOWN: { LPNMTVKEYDOWN lpKeyDown = (LPNMTVKEYDOWN)lParam; HTREEITEM hItem;
if (lpKeyDown->wVKey == VK_SPACE) {
hItem = TreeView_GetSelection(g_hwndFilesTree);
if (hItem != NULL) { FileTreeToggleSelection(hItem, uReverse); } } else if (lpKeyDown->wVKey == VK_DELETE) {
HTREEITEM hParentItem;
hItem = TreeView_GetSelection(g_hwndFilesTree);
hParentItem = TreeView_GetParent(g_hwndFilesTree, hItem);
if (hParentItem == NULL) { if (TreeView_GetPrevSibling(g_hwndFilesTree, hItem) != NULL) { TreeView_DeleteItem(g_hwndFilesTree, hItem); } } } break; } default: break; } }
INT_PTR CALLBACK QFixAppDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) /*++
QFixAppDlgProc
Description: The dialog proc of QFixApp.
--*/ { int wCode = LOWORD(wParam); int wNotifyCode = HIWORD(wParam);
switch (uMsg) { case WM_INITDIALOG: if (!InitMainDialog(hdlg)) { EndDialog(hdlg, TRUE); } break;
case WM_NOTIFY: if (wParam == IDC_SHIMS) { HandleShimListNotification(hdlg, lParam); } else if (wParam == IDC_ATTRIBUTES) { HandleAttributeTreeNotification(hdlg, lParam); } else if (wParam == IDC_TAB_FIXES) { HandleTabNotification(hdlg, lParam); } else if (wParam == IDC_DOWNLOAD_WU) {
NMHDR* pHdr = (NMHDR*)lParam;
if (pHdr->code == NM_CLICK || pHdr->code == NM_RETURN) {
SHELLEXECUTEINFO sei = { 0 };
sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.fMask = SEE_MASK_DOENVSUBST; sei.hwnd = hdlg; sei.nShow = SW_SHOWNORMAL;
if (g_fW2K) { sei.lpFile = g_szW2KUrl; } else if (g_fNETServer) { sei.lpFile = g_szNETUrl; } else { sei.lpFile = g_szXPUrl; }
ShellExecuteEx(&sei); break; } } break;
case WM_DESTROY: { DLGHDR* pHdr;
//
// Destory the dialogs and remove any misc files.
//
pHdr = (DLGHDR*)GetWindowLongPtr(hdlg, DWLP_USER);
DestroyWindow(pHdr->hDisplay[0]); DestroyWindow(pHdr->hDisplay[1]);
CleanupSupportForApp(g_szShortName);
break; }
case WM_COMMAND:
if (wNotifyCode == LBN_SELCHANGE && wCode == IDC_LAYERS) { LayerChanged(hdlg); break; }
switch (wCode) {
case IDC_RUN: RunTheApp(hdlg); break;
case IDC_BROWSE: BrowseForApp(hdlg); break;
case IDC_DETAILS: ExpandCollapseDialog(hdlg, !g_bSimpleEdition); break;
case IDC_CREATEFILE: CreateSupportForApp(hdlg); break;
case IDC_SHOWXML: ShowXML(hdlg); break;
case IDC_ADD_MATCHING: PromptAddMatchingFile(hdlg); break;
case IDC_VIEW_LOG: ShowShimLog(); break;
case IDCANCEL: EndDialog(hdlg, TRUE); break;
case IDM_SELECT_ALL: SelectAttrsInTree(TRUE); break;
case IDM_CLEAR_ALL: SelectAttrsInTree(FALSE); break;
case IDC_REMOVE_MATCHING: { HTREEITEM hParentItem, hItem; TCHAR szError[MAX_PATH];
hItem = TreeView_GetSelection(g_hwndFilesTree);
if (NULL == hItem) { LoadString(g_hInstance, IDS_NO_SELECTION, szError, ARRAYSIZE(szError)); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION); return TRUE; }
hParentItem = TreeView_GetParent(g_hwndFilesTree, hItem);
if (hParentItem == NULL) { if (TreeView_GetPrevSibling(g_hwndFilesTree, hItem) != NULL) { TreeView_DeleteItem(g_hwndFilesTree, hItem); EnableWindow(GetDlgItem(hdlg, IDC_REMOVE_MATCHING), FALSE); } } break; }
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
BOOL QFixAppInitialize( void ) /*++
QFixAppInitialize
Description: Initializes common paths, etc.
--*/ { UINT cchSize; INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_TAB_CLASSES;
//
// Initialize the common controls.
//
if (!InitCommonControlsEx(&icex)) { InitCommonControls(); }
//
// Set up our hyperlink control.
//
LinkWindow_RegisterClass();
//
// Save away common paths for later use.
//
cchSize = GetSystemDirectory(g_szSysDir, ARRAYSIZE(g_szSysDir));
if (cchSize > ARRAYSIZE(g_szSysDir) || cchSize == 0) { DPF("[QFixAppInitialize] 0x%08X Failed to get system directory", GetLastError()); return FALSE; }
cchSize = GetSystemWindowsDirectory(g_szWinDir, ARRAYSIZE(g_szWinDir));
if (cchSize > ARRAYSIZE(g_szWinDir) || cchSize == 0) { DPF("[QFixAppInitialize] 0x%08X Failed to get windows directory", GetLastError()); return FALSE; }
return TRUE; }
int WINAPI wWinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPTSTR lpszCmd, int swShow ) /*++
WinMain
Description: Application entry point.
--*/ { BOOL fSP2 = FALSE; TCHAR szError[MAX_PATH]; OSVERSIONINFOEX osviex;
LoadString(g_hInstance, IDS_APP_TITLE, g_szAppTitle, ARRAYSIZE(g_szAppTitle));
g_hInstance = hInst;
osviex.dwOSVersionInfoSize = sizeof(osviex);
GetVersionEx((OSVERSIONINFO*)&osviex);
//
// See if they're an administrator - bail if not.
//
if (!(IsUserAnAdministrator())) { LoadString(g_hInstance, IDS_NOT_ADMIN, szError, ARRAYSIZE(szError)); MessageBox(NULL, szError, g_szAppTitle, MB_ICONERROR); return 0; }
//
// See if we're running on Windows 2000, then check for SP2, then
// check for .NET Server.
//
if ((osviex.dwMajorVersion == 5 && osviex.dwMinorVersion == 0)) { g_fW2K = TRUE; }
if (g_fW2K && (!_tcscmp(osviex.szCSDVersion, _T("Service Pack 2")))) { fSP2 = TRUE; }
if (!(osviex.wProductType == VER_NT_WORKSTATION)) { g_fNETServer = TRUE; }
//
// Perform some necessary initialization.
//
if (!QFixAppInitialize()) { LoadString(g_hInstance, IDS_INIT_FAILED, szError, ARRAYSIZE(szError)); MessageBox(GetDesktopWindow(), szError, g_szAppTitle, MB_ICONERROR); return 0; }
//
// Attempt to locate the SDB in the AppPatch directory.
//
if (!CheckForSDB()) { if (g_fW2K) { DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_MSGBOX_SDB), GetDesktopWindow(), MsgBoxDlgProc, (LPARAM)1); return 0; } else { LoadString(g_hInstance, IDS_XP_NO_SDB, szError, ARRAYSIZE(szError)); MessageBox(GetDesktopWindow(), szError, g_szAppTitle, MB_ICONEXCLAMATION); return 0; } }
//
// If this is SP2, and the SDB is older, bail out.
//
if (fSP2) { if (IsSDBFromSP2()) { DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_MSGBOX_SP2), GetDesktopWindow(), MsgBoxDlgProc, (LPARAM)0); return 0; } }
//
// Check for command line options.
//
if (lpszCmd) { DPF("[WinMain] Command line '%S'", lpszCmd);
while (*lpszCmd) { if (*lpszCmd == _T('a') || *lpszCmd == _T('A')) { g_bAllShims = TRUE; } else if (*lpszCmd == _T('x') || *lpszCmd == _T('X')) { g_bShowXML = TRUE; }
lpszCmd++; } }
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG), GetDesktopWindow(), QFixAppDlgProc);
return 1; }
|