|
|
/***************************************************************************
* Quick fix application tools * * Author: clupu (Feb 16, 2000) * * History: * * rparsons - 11/10/2000 - Modified titles on common dialogs * * rparsons - 11/23/2000 - Added ability to save XML to file * * rparsons - 11/25/2000 - Modified to allow matching file on a * different drive to be selected * * rparsons - 05/19/2001 - Added context menu on file tree. * Added URL for WU package. * Added Remove Matching button. * Converted shim list to list view. * * rparsons - 07/06/2001 - Converted static tab control to use * child dialogs. * \**************************************************************************/
#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 "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_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
RECT g_rcDlgBig, g_rcDlgSmall; // rectangle of the simple and the dev edition
// of the dialog
BOOL g_bAllShims;
BOOL g_bSelectedParentExe; // flag to indicate if a parent EXE has been
// selected
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_szW2KUrl[] = _T("http://www.microsoft.com/windows2000/") _T("downloads/tools/appcompat/");
#define ID_COUNT_SHIMS 1234
typedef HRESULT (*PFNEnableThemeDialogTexture)(HWND hwnd, DWORD dwFlags);
#if DBG
void LogMsgDbg( LPTSTR pszFmt, ... ) /*++
LogMsgDbg
Description: DbgPrint.
--*/ { TCHAR gszT[1024]; va_list arglist;
va_start(arglist, pszFmt); _vsntprintf(gszT, 1023, pszFmt, arglist); gszT[1023] = 0; va_end(arglist);
OutputDebugString(gszT); }
#endif // DBG
BOOL IsUserAnAdministrator( void ) /*++
IsUserAnAdministrator
Description: Determine if the currently logged on user is an admin.
--*/ { HANDLE hToken; DWORD dwStatus = 0, dwAccessMask = 0; DWORD dwAccessDesired = 0, dwACLSize = 0; DWORD dwStructureSize = sizeof(PRIVILEGE_SET); PACL pACL = NULL; PSID psidAdmin = NULL; BOOL fReturn = FALSE; PRIVILEGE_SET ps; GENERIC_MAPPING GenericMapping; PSECURITY_DESCRIPTOR psdAdmin = NULL; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
// AccessCheck() requires an impersonation token
if (!ImpersonateSelf(SecurityImpersonation)) { goto cleanup; }
// Attempt to access the token for the current thread
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) { if (GetLastError() != ERROR_NO_TOKEN) { goto cleanup; } // If the thread does not have an access token, we'll
// examine the access token associated with the process.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { goto cleanup; } }
// Build a SID for administrators group
if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin)) { goto cleanup; } // Allocate memory for the security descriptor
psdAdmin = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (psdAdmin == NULL) { goto cleanup; } // Initialize the new security descriptor
if (!InitializeSecurityDescriptor(psdAdmin, SECURITY_DESCRIPTOR_REVISION)) { goto cleanup; } // Compute size needed for the ACL
dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdmin) - sizeof(DWORD);
// Allocate memory for ACL
pACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwACLSize);
if (pACL == NULL) { goto cleanup; } // Initialize the new ACL
if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) { goto cleanup; } dwAccessMask = ACCESS_READ | ACCESS_WRITE;
// Add the access-allowed ACE to the DACL
if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask, psidAdmin)) { goto cleanup; } // Set our DACL to the security descriptor
if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE)) { goto cleanup; } // AccessCheck is sensitive about the format of the
// security descriptor; set the group & owner
SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE); SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
// Ensure that the SD is valid
if (!IsValidSecurityDescriptor(psdAdmin)) { goto cleanup; } dwAccessDesired = ACCESS_READ;
// Initialize GenericMapping structure even though we
// won't be using generic rights.
GenericMapping.GenericRead = ACCESS_READ; GenericMapping.GenericWrite = ACCESS_WRITE; GenericMapping.GenericExecute = 0; GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
// After all that work, it boils down to this call
if (!AccessCheck(psdAdmin, hToken, dwAccessDesired, &GenericMapping, &ps, &dwStructureSize, &dwStatus, &fReturn)) { goto cleanup; } RevertToSelf();
cleanup:
if (pACL) { HeapFree(GetProcessHeap(), 0, pACL); } if (psdAdmin){ HeapFree(GetProcessHeap(), 0, psdAdmin); } if (psidAdmin){ FreeSid(psidAdmin); } return (fReturn); }
BOOL CheckForSDB( void ) /*++
CheckForSDB
Description: Attempts to locate sysmain.sdb in the apppatch directory.
--*/ { HANDLE hFile; TCHAR szSDBPath[MAX_PATH]; BOOL fResult = FALSE;
if (!GetSystemWindowsDirectory(szSDBPath, MAX_PATH)) { return FALSE; }
_tcscat(szSDBPath, _T("\\apppatch\\sysmain.sdb"));
hFile = CreateFile(szSDBPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE != hFile) { CloseHandle(hFile); 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, MAX_PATH); LoadString(g_hInstance, IDS_EXCLUDE_HDR, szExclude, MAX_PATH);
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 nItemCount = 0, nIndex; 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 shim from the list view and add it to the list.
//
nItemCount = ListView_GetItemCount(g_hwndModuleList);
if (nItemCount == 0) { return; }
for (nIndex = nItemCount - 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, MAX_PATH); pModuleNew = (PMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MODULE)); pModuleNew->pszName = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR) * (lstrlen(szBuffer) + 1)); if (pModuleNew == NULL || pModuleNew->pszName == NULL) { LogMsg(_T("[BuildModuleListForShim] Couldn't allocate memory to store module info.")); return; } lstrcpy(pModuleNew->pszName, 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];
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, MAX_PATH); wsprintf(szShims, szTemp, nShims, cShims);
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, MAX_PATH); InsertListViewColumn(g_hwndShimList, szColumn, FALSE, 0, 200); LoadString(g_hInstance, IDS_CMDLINE_COLUMN, szColumn, MAX_PATH); InsertListViewColumn(g_hwndShimList, szColumn, TRUE, 1, 59); LoadString(g_hInstance, IDS_MODULE_COLUMN, szColumn, MAX_PATH); 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, MAX_PATH); MessageBox(hMainDlg, szError, g_szAppTitle, MB_OK | 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, MAX_PATH); 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, MAX_PATH); 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 free.
--*/ { 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
//
// Ensure that the beginning of the path matches between the two files
//
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) {
lstrcpy(resultIdx, _T("..\\")); resultIdx = resultIdx + 3; pExeFile = pExe + 1; pExe = _tcschr(pExeFile, _T('\\')); }
lstrcpy(resultIdx, pMatchFile); pReturn = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR) * (lstrlen(result) + 1)); if (NULL == pReturn) { return NULL; }
lstrcpy(pReturn, result);
return pReturn; }
// the two paths don't have a common beginning,
// and there is no relative path
return NULL; }
void SaveEntryToFile( HWND hDlg, HWND hEdit, LPCTSTR lpFileName ) /*++
SaveEntryToFile
Description: Writes the XML out to a file.
--*/ { int nLen = 0; DWORD dwBytesWritten = 0; HANDLE hFile = NULL; LPTSTR lpData = NULL; TCHAR szError[MAX_PATH];
//
// Determine how much space we need for the buffer, then allocate it.
//
nLen = GetWindowTextLength(hEdit);
if (nLen) {
lpData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nLen * 2 * sizeof(TCHAR));
if (lpData == NULL) { LoadString(g_hInstance, IDS_BUFFER_ALLOC_FAIL, szError, MAX_PATH); MessageBox(hDlg, szError, g_szAppTitle, MB_OK | MB_ICONERROR); return; }
//
// Get the text out of the text box and write it out to our file.
//
GetWindowText(hEdit, lpData, nLen * 2);
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, MAX_PATH); MessageBox(hDlg, szError, g_szAppTitle, MB_OK | MB_ICONERROR); goto Cleanup; }
WriteFile(hFile, lpData, nLen * 2, &dwBytesWritten, NULL);
CloseHandle(hFile); }
Cleanup:
HeapFree(GetProcessHeap(), 0, lpData); }
void DoFileSave( HWND hDlg ) /*++
DoFileSave
Description: Displays the common dialog allowing for file save.
--*/ { int nAnswer; TCHAR szError[MAX_PATH]; TCHAR szFilter[MAX_PATH] = _T(""); TCHAR szTemp[MAX_PATH+1] = _T(""); OPENFILENAME ofn = {0};
szTemp[0] = 0;
LoadString(g_hInstance, IDS_SAVE_FILTER, szFilter, MAX_PATH);
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); } }
BOOL CenterWindow( HWND hWnd ) /*++
CenterWindow
Description: Centers the window specified in hWnd.
--*/ { RECT rectWindow, rectParent, rectScreen; int nCX, nCY; HWND hParent; POINT ptPoint;
hParent = GetParent(hWnd); if (hParent == NULL) { hParent = GetDesktopWindow(); }
GetWindowRect(hParent, &rectParent); GetWindowRect(hWnd, &rectWindow); GetWindowRect(GetDesktopWindow(), &rectScreen);
nCX = rectWindow.right - rectWindow.left; nCY = rectWindow.bottom - rectWindow.top;
ptPoint.x = ((rectParent.right + rectParent.left) / 2) - (nCX / 2); ptPoint.y = ((rectParent.bottom + rectParent.top ) / 2) - (nCY / 2);
if (ptPoint.x < rectScreen.left) { ptPoint.x = rectScreen.left; } if (ptPoint.x > rectScreen.right - nCX) { ptPoint.x = rectScreen.right - nCX; } if (ptPoint.y < rectScreen.top) { ptPoint.y = rectScreen.top; } if (ptPoint.y > rectScreen.bottom - nCY) { ptPoint.y = rectScreen.bottom - nCY; }
if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) { ScreenToClient(hParent, (LPPOINT)&ptPoint); }
if (!MoveWindow(hWnd, ptPoint.x, ptPoint.y, nCX, nCY, TRUE)) { return FALSE; }
return TRUE; }
void ReplaceCmdLine( PFIX pFix, TCHAR* pszNewCmdLine ) /*++
ReplaceCmdLine
Description: Replaces the command line for a shim DLL.
--*/ { TCHAR szError[MAX_PATH];
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, MAX_PATH); MessageBox(g_hDlg, szError, g_szAppTitle, MB_OK | MB_ICONEXCLAMATION); return; } pFix->pszCmdLine = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR) * (lstrlen(pszNewCmdLine) + 1));
if (pFix->pszCmdLine != NULL) { lstrcpy(pFix->pszCmdLine, pszNewCmdLine); } else { LogMsg(_T("[ReplaceCmdLine] failed to replace the cmd line for \"%s\"\n"), pFix->pszName); } }
void DeselectAllShims( HWND hdlg ) /*++
DeselectAllShims
Description: Removes selections for all shims listed.
--*/ { int cShims, nIndex; LVITEM lvi; UINT uState;
//
// 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.
--*/ { PATTRINFO pAttrInfo; TVINSERTSTRUCT is; HTREEITEM hParent; DWORD i; DWORD dwAttrCount; TCHAR szItem[MAX_PATH];
//
// Call the attribute manager to get all the attributes for this file.
//
SdbGetFileAttributes(pszFullPath, &pAttrInfo, &dwAttrCount);
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 (i = 0; i < dwAttrCount; i++) {
if (!SdbFormatAttribute(&pAttrInfo[i], szItem, MAX_PATH)) { continue; } //
// EXETYPE is a bogus attribute. Don't show it!
//
is.item.lParam = i; 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(""); OPENFILENAME ofn = {0}; g_szBinary[0] = 0;
LoadString(g_hInstance, IDS_BROWSE_FILTER, szFilter, MAX_PATH); LoadString(g_hInstance, IDS_BROWSE_TITLE, szTitle, MAX_PATH);
ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hdlg; ofn.hInstance = NULL; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = g_szBinary; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = g_szShortName; ofn.nMaxFileTitle = 128; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = szTitle; ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; ofn.lpstrDefExt = _T("exe");
if (GetOpenFileName(&ofn)) {
TCHAR szMainEXE[128];
// the parent exe defaults to the same as the EXE
lstrcpy(g_szParentExeName, g_szShortName); lstrcpy(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);
wsprintf(szMainEXE, _T("Main executable (%s)"), g_szShortName);
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+1] = _T(""); TCHAR szShortName[128] = _T(""); TCHAR szRelativePath[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] = 0;
LoadString(g_hInstance, IDS_MATCH_FILTER, szFilter, MAX_PATH); LoadString(g_hInstance, IDS_MATCH_TITLE, szTitle, MAX_PATH);
if (g_szParentExeFullPath[0]) { _tsplitpath(g_szParentExeFullPath, szDrive, szDir, NULL, NULL); lstrcpy(szInitialPath, szDrive); lstrcat(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 = MAX_PATH; ofn.lpstrFileTitle = szShortName; ofn.nMaxFileTitle = 128; 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] = 0; szInitialPath[0] = 0; if (szFullPath[0]) { _tsplitpath(szFullPath, szDrive, szDir, NULL, NULL); lstrcpy(szInitialPath, szDrive); lstrcat(szInitialPath, szDir); }
LoadString(g_hInstance, IDS_PARENT_TITLE, szParentTitle, MAX_PATH);
ofn.lpstrTitle = szParentTitle; ofn.lpstrFile = szParentFile; ofn.nMaxFile = sizeof(szParentFile);
if (GetOpenFileName(&ofn) == TRUE) { lstrcpy(g_szParentExeName, szShortName); lstrcpy(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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_OK | 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, MAX_PATH); MessageBox(NULL, szError, g_szAppTitle, MB_OK | MB_ICONERROR); return; }
//
// Walk the list and add all the fixes to the list view.
//
pFix = g_pFixHead;
while (pFix != NULL) { if (pFix->bLayer) { 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 to install or uninstall the specified SDB.
--*/ { TCHAR szCmd[MAX_PATH]; TCHAR szExePath[MAX_PATH]; TCHAR* pExt = NULL; STARTUPINFO si; PROCESS_INFORMATION pi;
GetSystemDirectory(szExePath, MAX_PATH);
_tcscat(szExePath, _T("\\sdbinst.exe"));
if (GetFileAttributes(szExePath) == -1) { return FALSE; }
wsprintf(szCmd, fInstall ? _T("%s -q %s") : _T("%s -q -u %s"), szExePath, pszFileName);
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
if (!CreateProcess(NULL, szCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
LogMsg(_T("[InstallSDB] CreateProcess \"%s\" failed 0x%X\n"), szCmd, 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]; int nAnswer; 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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_OK | MB_ICONERROR); } else { LoadString(g_hInstance, IDS_CREATE_FIX, szTemp, MAX_PATH); wsprintf(szError, szTemp, szFileCreated); 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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_OK | MB_ICONERROR); } else { LoadString(g_hInstance, IDS_INSTALL_FIX_OK, szError, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_OK | MB_ICONINFORMATION); } } } }
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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_OK | 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 szError[MAX_PATH]; TCHAR szRun[MAX_PATH]; TCHAR* pszCmd; TCHAR* pszDir; TCHAR* psz; BOOL bok;
//
// 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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_OK | MB_ICONERROR); return; }
//
// We need to install the fix for them.
//
if (!(InstallSDB(szFileCreated, TRUE))) { LoadString(g_hInstance, IDS_INSTALL_FIX_FAIL, szError, MAX_PATH); MessageBox(g_hDlg, szError, g_szAppTitle, MB_OK | MB_ICONERROR); return; } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
//
// Try to run the app.
//
GetDlgItemText(hdlg, IDC_CMD_LINE, szCmdLine, MAX_PATH);
if (szCmdLine[0] == 0) { wsprintf(szRun, _T("\"%s\""), g_szBinary); } else { wsprintf(szRun, _T("\"%s\" %s"), g_szBinary, szCmdLine); }
pszCmd = szRun; pszDir = g_szBinary;
//
// We need to change the current directory or some
// apps won't run.
//
psz = pszDir + lstrlen(pszDir) - 1;
while (psz > pszDir && *psz != _T('\\')) { psz--; }
if (psz > pszDir) { *psz = 0; SetCurrentDirectory(pszDir); *psz = _T('\\'); }
LogMsg(_T("[RunTheApp] : %s\n"), pszCmd); if (!CreateProcess(NULL, pszCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) {
LogMsg(_T("[RunTheApp] CreateProcess failed 0x%X\n"), GetLastError()); return; }
CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
//
// Save this SDB for later so we can remove it.
//
lstrcpy(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, 64); 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, 64); 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) { LogMsg(_T("[LayerChanged] No layer selected.\n")); return; } pFix = (PFIX)SendMessage(g_hwndListLayers, LB_GETITEMDATA, lSel, 0);
if (pFix->parrShim == NULL) { LogMsg(_T("[LayerChanged] No array of DLLs.\n")); 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; TCHAR szText[1024]; 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_szParentExeFullPath[0] = 0; g_szBinary[0] = 0; g_hDlg = hdlg;
//
// 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);
CenterWindow(hdlg);
//
// 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 { LogMsg(_T("[InitMainDialog] Failed to load imagelist\n")); }
//
// Set the text for the link window.
//
LoadString(g_hInstance, g_fW2K ? IDS_W2K_LINK : IDS_XP_LINK, szText, MAX_PATH); SetDlgItemText(g_hDlg, IDC_DOWNLOAD_WU, szText);
//
// 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; } } 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];
pFix = (PFIX)lParam;
LoadString(g_hInstance, IDS_MOD_TYPE, szType, 64); LoadString(g_hInstance, IDS_MOD_NAME, szModuleName, 128); LoadString(g_hInstance, IDS_OPTIONS_TITLE, szTemp, MAX_PATH); CenterWindow(hdlg);
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);
wsprintf(szTitle, szTemp, pFix->pszName); SetWindowText(hdlg, szTitle); if (NULL != pFix->pszCmdLine) { SetDlgItemText(hdlg, IDC_SHIM_CMD_LINE, pFix->pszCmdLine); } 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]; LVITEM lvi; UINT uInclude, uExclude;
GetDlgItemText(hdlg, IDC_MOD_NAME, szModName, MAX_PATH);
if (*szModName == 0) { LoadString(g_hInstance, IDS_NO_MOD, szError, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION | MB_OK); 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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION | MB_OK); 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; CenterWindow(hdlg);
//
// Use the parameter to determine what text to display.
//
if (uNoSDB) { LoadString(g_hInstance, IDS_W2K_NO_SDB, szLink, MAX_PATH); SetDlgItemText(hdlg, IDC_MESSAGE, szLink); } else { LoadString(g_hInstance, IDS_SP2_SDB, szLink, MAX_PATH); SetDlgItemText(hdlg, IDC_MESSAGE, szLink); }
LoadString(g_hInstance, IDS_MSG_LINK, szLink, MAX_PATH); 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; LVITEM lvi; 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; LVITEM lvi; 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; TCHAR szShimName[MAX_PATH]; 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 this is a shim, display the options dialog.
if (!pFix->bFlag) {
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("")); } } } else { MessageBeep(MB_ICONEXCLAMATION); } 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; HTREEITEM hParentItem;
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 hItem, 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; sei.lpFile = g_fW2K ? g_szW2KUrl : 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, MAX_PATH); MessageBox(hdlg, szError, g_szAppTitle, MB_ICONEXCLAMATION | MB_OK); 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; }
int WINAPI wWinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPTSTR lpszCmd, int swShow ) /*++
WinMain
Description: Application entry point.
--*/ { BOOL fSP2 = FALSE; TCHAR szError[MAX_PATH]; OSVERSIONINFO osvi; INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_TAB_CLASSES;
if (!InitCommonControlsEx(&icex)) { InitCommonControls(); }
LoadString(g_hInstance, IDS_APP_TITLE, g_szAppTitle, 64);
LinkWindow_RegisterClass();
g_hInstance = hInst;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
//
// See if they're an administrator - bail if not.
//
if (!(IsUserAnAdministrator())) { LoadString(g_hInstance, IDS_NOT_ADMIN, szError, MAX_PATH); MessageBox(NULL, szError, g_szAppTitle, MB_ICONERROR | MB_OK); return 0; }
//
// See if we're running on Windows 2000.
//
if ((osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)) { g_fW2K = TRUE; }
// See if we're running on SP2
if (!(_tcscmp(osvi.szCSDVersion, _T("Service Pack 2")))) { fSP2 = TRUE; }
//
// 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, MAX_PATH); MessageBox(GetDesktopWindow(), szError, g_szAppTitle, MB_OK | 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; } }
LogMsg(_T("[WinMain] Command line \"%s\"\n"), lpszCmd);
//
// Check for command line options.
//
if (*lpszCmd == _T('a') || *lpszCmd == _T('A')) { g_bAllShims = TRUE; }
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG), GetDesktopWindow(), QFixAppDlgProc);
return 1; }
|