|
|
/***************************************************************************
* Quick shim application tools * * Author: clupu (Feb 16, 2000) * \**************************************************************************/
#include "windows.h"
#include "commctrl.h"
#include "commdlg.h"
#include "resource.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "shimWin2000.h"
#include "shimWhistler.h"
#include "..\acFileAttr\acFileAttr.h"
/*
* Global Variables */
HINSTANCE g_hInstance; HWND g_hDlg;
char g_szBinary[MAX_PATH]; // the full path of the main binary being shimmed
char g_szShortName[128]; // the short name of the main EXE
char* g_pszShimDLL;
char g_szBinaryOther[MAX_PATH]; // the full path of the optional EXE that will
// be launched instead (setup case)
HWND g_hwndShimTree; // the handle to the tree view control
// containing all the shims available
HWND g_hwndFilesTree; // the handle to the tree view control
// containing the matching files selected
BOOL g_bWin2k; // are we running on Win2k or Whistler
BOOL g_bRunOther; // TRUE - run g_szBinaryOther instead
BOOL g_bSimpleEdition; // simple or dev edition
RECT g_rcDlgBig, g_rcDlgSmall; // rectangle of the simple and the dev edition
// of the dialog
#if DBG
/*********************************************************************
* LogMsgDbg * *********************************************************************/ void LogMsgDbg( LPSTR pszFmt, ... ) { CHAR gszT[1024]; va_list arglist;
va_start(arglist, pszFmt); _vsnprintf(gszT, 1023, pszFmt, arglist); gszT[1023] = 0; va_end(arglist); OutputDebugString(gszT); }
#endif // DBG
/*******************************************************************************
* CenterWindow * * This function must be called at the WM_INIDIALOG in order to * move the dialog window centered in the client area of the * parent or owner window. *******************************************************************************/ BOOL CenterWindow( HWND hWnd) { RECT rectWindow, rectParent, rectScreen; int nCX, nCY; HWND hParent; POINT ptPoint;
hParent = GetParent(hWnd); if (hParent == NULL) hParent = GetDesktopWindow();
GetWindowRect(hParent, (LPRECT)&rectParent); GetWindowRect(hWnd, (LPRECT)&rectWindow); GetWindowRect(GetDesktopWindow(), (LPRECT)&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; }
/*********************************************************************
* AddMatchingFile * * Adds a matching file and it's attributes to the tree * *********************************************************************/ VOID AddMatchingFile( HWND hdlg, char* pszFullPath, char* pszRelativePath, BOOL bMainEXE) { HANDLE hMgr; TVINSERTSTRUCT is; HTREEITEM hParent; int i; int nAttrCount; char szItem[256]; hMgr = ReadFileAttributes(pszFullPath, &nAttrCount);
is.hParent = TVI_ROOT; is.hInsertAfter = TVI_LAST; is.item.lParam = (LONG)hMgr; is.item.mask = TVIF_TEXT | TVIF_PARAM; is.item.pszText = pszRelativePath;
hParent = TreeView_InsertItem(g_hwndFilesTree, &is);
is.hParent = hParent; is.item.mask = TVIF_TEXT; is.item.pszText = szItem;
is.item.mask |= TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; is.item.iImage = 0; is.item.iSelectedImage = 1; is.item.state = INDEXTOSTATEIMAGEMASK(1); is.item.stateMask = TVIS_STATEIMAGEMASK;
for (i = 0; i < nAttrCount; i++) { PSTR pszValue; DWORD id; HTREEITEM hItem;
if (!IsAttrAvailable(hMgr, i)) continue; // filter the attributes for Whistler (temporary)
if (!g_bWin2k) { id = GetAttrId(i); if (id != VTID_FILESIZE && id != VTID_CHECKSUM) continue; }
pszValue = GetAttrValue(hMgr, i); if (pszValue == NULL) continue; wsprintf(szItem, "%s: %s", GetAttrName(i), pszValue); is.item.lParam = i; hItem = TreeView_InsertItem(g_hwndFilesTree, &is); }
TreeView_Expand(g_hwndFilesTree, hParent, TVE_EXPAND); }
/*********************************************************************
* AddNewMainBinary * * Start with a new main executable * *********************************************************************/ VOID AddNewMainBinary( HWND hdlg) { char szMainEXE[128];
TreeView_DeleteAllItems(g_hwndFilesTree);
wsprintf(szMainEXE, "Main executable (%s)", g_szShortName);
AddMatchingFile(hdlg, g_szBinary, szMainEXE, TRUE); }
/*********************************************************************
* DoBrowseForApp * * Browse for the main executable for which a shim will be applied * *********************************************************************/ VOID DoBrowseForApp( HWND hdlg) { OPENFILENAME ofn; g_szBinary[0] = 0; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hdlg; ofn.hInstance = 0; ofn.lpstrFilter = NULL; 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 = "Choose an executable binary to shim"; ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST; ofn.lpstrDefExt = "EXE"; if (GetOpenFileName(&ofn)) { SetDlgItemText(hdlg, IDC_BINARY, g_szBinary);
EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), TRUE); AddNewMainBinary(hdlg); } }
/*********************************************************************
* DoBrowseOther * * Browse for a different EXE that will be launched instead of the * main EXE selected. This is for the setup case where setup.exe * launches another process _INS0432._MP for example. * *********************************************************************/ VOID DoBrowseOther( HWND hdlg) { OPENFILENAME ofn; g_szBinaryOther[0] = 0; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hdlg; ofn.hInstance = 0; ofn.lpstrFilter = NULL; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; ofn.lpstrFile = g_szBinaryOther; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = "Choose the application to run"; ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST; ofn.lpstrDefExt = "EXE"; if (GetOpenFileName(&ofn)) { SetDlgItemText(hdlg, IDC_RUN_OTHER, g_szBinaryOther); } }
/*********************************************************************
* DoAddMatchingFile * *********************************************************************/ VOID DoAddMatchingFile( HWND hdlg) { char szFullPath[MAX_PATH]; char szShortName[128]; char szRelativePath[MAX_PATH]; OPENFILENAME ofn; szFullPath[0] = 0; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hdlg; ofn.hInstance = 0; ofn.lpstrFilter = NULL; 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 = "Choose the application to run"; ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOTESTFILECREATE | OFN_PATHMUSTEXIST; ofn.lpstrDefExt = "EXE"; if (GetOpenFileName(&ofn)) { char* pszBin; char* pszNew;
// need to modify the path to be a relative path to g_szBinary
if (g_szBinary[0] != szFullPath[0]) { MessageBox(hdlg, "A matching file must be located on the same drive", "Warning", MB_ICONEXCLAMATION | MB_OK); return; }
// walk both strings untill they differ
pszBin = g_szBinary; pszNew = szFullPath;
szRelativePath[0] = 0;
while (*pszBin == *pszNew) { pszBin++; pszNew++; }
// go back to the last \ while (*(pszBin - 1) != '\\') { pszBin--; pszNew--; }
while (lstrcmp(pszBin, g_szShortName) != 0) { // add ..\ each time a subdir is identified (not the short name)
lstrcat(szRelativePath, "..\\");
while (*pszBin != '\\') pszBin++; pszBin++; } lstrcat(szRelativePath, pszNew); // finally add the maching file
AddMatchingFile(hdlg, szFullPath, szRelativePath, FALSE); } }
/*********************************************************************
* PopulateTree * *********************************************************************/ VOID PopulateTree( HWND hTree) { TVINSERTSTRUCT is; PFIX pFix;
TreeView_DeleteAllItems(hTree);
if (g_bWin2k) { pFix = ReadFixes_Win2000(); if (pFix == NULL) { MessageBox(NULL, "You need to have a copy of the file Shim2000.txt" " in the directory where you started QShimApp.exe", "Error", MB_ICONEXCLAMATION | MB_OK); return; } } else { pFix = ReadFixes_Whistler(); if (pFix == NULL) { MessageBox(NULL, "The shim database doesn't exist or it is corrupted", "Error", MB_ICONEXCLAMATION | MB_OK); return; } }
is.hParent = TVI_ROOT; is.hInsertAfter = TVI_SORT; is.item.mask = TVIF_TEXT | TVIF_PARAM; // walk the list and add all the fixes to the tree view
while (pFix != NULL) { is.item.lParam = (LPARAM)pFix; is.item.pszText = pFix->pszName; TreeView_InsertItem(hTree, &is);
pFix = pFix->pNext; } }
/*********************************************************************
* RunShimmedApp * *********************************************************************/ DWORD WINAPI RunShimmedApp( LPVOID lParam) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si);
// Try to run the app
if (!CreateProcess(NULL, (g_bRunOther ? g_szBinaryOther : g_szBinary), NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi)) { LogMsg("CreateProcess failed with status: 0x%X\n", GetLastError()); return 0; } CloseHandle(pi.hThread); WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess); if (g_bWin2k) { CleanupShimForApp_Win2000(); } else { CleanupShimForApp_Whistler(); }
return 1; }
/*********************************************************************
* DoRunApp * *********************************************************************/ VOID DoRunApp( HWND hdlg) { HANDLE hThread; DWORD dwThreadId; BOOL bCreateFile; // Make sure an app was selected first
if (g_szBinary[0] == 0) { MessageBox(hdlg, "You need to select the application first", "Error", MB_ICONEXCLAMATION | MB_OK); return; } // check to see if another app was selected to run
if (SendDlgItemMessage(hdlg, IDC_RUN_OTHER_CHECK, BM_GETCHECK, 0, 0) == BST_CHECKED) { g_bRunOther = TRUE; // Make sure the other app is selected
if (g_szBinaryOther[0] == 0) { GetDlgItemText(hdlg, IDC_RUN_OTHER, g_szBinaryOther, MAX_PATH);
if (g_szBinaryOther[0] == 0) { MessageBox(hdlg, "You need to select the other application first", "Error", MB_ICONEXCLAMATION | MB_OK); return; } } } else { g_bRunOther = FALSE; } bCreateFile = (SendDlgItemMessage(hdlg, IDC_CREATEFILE, BM_GETCHECK, 0, 0) == BST_CHECKED); if (g_bWin2k) { if (!AddShimForApp_Win2000(g_hwndShimTree, g_hwndFilesTree, g_szShortName, bCreateFile)) { LogMsg("AddShimForApp_Win2000 failed...\n"); return; } } else { if (!AddShimForApp_Whistler(g_hwndShimTree, g_hwndFilesTree, g_szShortName, bCreateFile)) { LogMsg("AddShimForApp_Whistler failed...\n"); return; } } // Create a thread that will run the app and wait on it to end.
// This will allow the app to still process messages and thus it
// will not block apps that broadcast messages blocking
// themselves.
hThread = CreateThread( NULL, 0, RunShimmedApp, NULL, 0, &dwThreadId); if (hThread != NULL) { CloseHandle(hThread); } }
/*********************************************************************
* HideStrictGroup * *********************************************************************/ VOID HideStrictGroup( HWND hdlg, BOOL bHide) { static BOOL sbFirstTime = TRUE;
int i, nShow; DWORD arrId[] = {IDC_STRICT_GROUP, IDC_COMMENT, IDC_ADD_MATCHING, IDC_FILE_ATTRIBUTES_STATIC, IDC_ATTRIBUTES, IDC_CREATEFILE, IDC_CREATEFILE_STATIC, 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; SetDlgItemText(hdlg, IDC_DETAILS, "<< Simple"); // The first time the user goes to the dev edition center
// the big dialog on the screen
if (sbFirstTime) { sbFirstTime = FALSE; CenterWindow(hdlg); } } else { nShow = SW_HIDE; g_bSimpleEdition = TRUE; SetDlgItemText(hdlg, IDC_DETAILS, "Advanced >>"); } 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); }
}
/*********************************************************************
* DoDetails * *********************************************************************/ VOID DoDetails( HWND hdlg) { HideStrictGroup(hdlg, !g_bSimpleEdition); }
/*********************************************************************
* Restart * *********************************************************************/ VOID Restart( HWND hdlg) { PopulateTree(g_hwndShimTree); }
/*********************************************************************
* DoInitDialog * *********************************************************************/ VOID DoInitDialog( HWND hdlg) { HICON hIcon; RECT rcGroup, rcList;
g_hDlg = hdlg;
GetWindowRect(hdlg, &g_rcDlgBig);
GetWindowRect(GetDlgItem(hdlg, IDC_STRICT_GROUP), &rcGroup); GetWindowRect(GetDlgItem(hdlg, IDC_ATTRIBUTES), &rcList);
g_rcDlgSmall.left = g_rcDlgBig.left; g_rcDlgSmall.top = g_rcDlgBig.top; g_rcDlgSmall.bottom = g_rcDlgBig.bottom; g_rcDlgSmall.right = g_rcDlgBig.right - (rcGroup.right - rcGroup.left) - (rcList.left - rcGroup.left);
HideStrictGroup(hdlg, TRUE);
CenterWindow(hdlg);
EnableWindow(GetDlgItem(hdlg, IDC_ADD_MATCHING), FALSE);
if (g_bWin2k) { SendDlgItemMessage(hdlg, IDC_WIN2K, BM_SETCHECK, BST_CHECKED, 0); } else { SendDlgItemMessage(hdlg, IDC_WHISTLER, BM_SETCHECK, BST_CHECKED, 0); }
hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
SetClassLongPtr(hdlg, GCLP_HICON, (LONG_PTR)hIcon);
g_hwndShimTree = GetDlgItem(hdlg, IDC_TREE); g_hwndFilesTree = GetDlgItem(hdlg, IDC_ATTRIBUTES);
HIMAGELIST hImage = ImageList_Create( int cx, int cy, UINT flags, int cInitial, int cGrow );
g_szBinary[0] = 0;
PopulateTree(g_hwndShimTree); }
/*********************************************************************
* QShimAppDlgProc * *********************************************************************/ INT_PTR CALLBACK QShimAppDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { int wCode = LOWORD(wParam); int wNotifyCode = HIWORD(wParam);
switch (uMsg) { case WM_INITDIALOG: DoInitDialog(hdlg); break;
case WM_NOTIFY: if (wParam == IDC_TREE) { LPNMHDR pnm = (LPNMHDR)lParam;
switch (pnm->code) { case TVN_SELCHANGED: { LPNMTREEVIEW lpnmtv; PFIX pFix;
lpnmtv = (LPNMTREEVIEW)lParam; pFix = (PFIX)lpnmtv->itemNew.lParam; SetDlgItemText(hdlg, IDC_SHIM_DESCRIPTION, pFix->pszDesc); break; } default: break; } } break;
case WM_DESTROY: if (g_bWin2k) { CleanupShimForApp_Win2000(); } else { CleanupShimForApp_Whistler(); } break;
case WM_COMMAND: switch (wCode) { case IDC_RUN: DoRunApp(hdlg); break; case IDC_WIN2K: g_bWin2k = TRUE; Restart(hdlg); break; case IDC_WHISTLER: g_bWin2k = FALSE; Restart(hdlg); break; case IDC_BROWSE: DoBrowseForApp(hdlg); break; case IDC_BROWSE_OTHER: DoBrowseOther(hdlg); break; case IDC_DETAILS: DoDetails(hdlg); break;
case IDC_ADD_MATCHING: DoAddMatchingFile(hdlg); break;
case IDCANCEL: EndDialog(hdlg, TRUE); break;
default: return FALSE; } break;
default: return FALSE; }
return TRUE; }
/*********************************************************************
* WinMain * *********************************************************************/ int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hInstPrev, LPSTR lpszCmd, int swShow) { char szShimDB[MAX_PATH]; HANDLE hFile;
InitCommonControls();
g_hInstance = hInst;
// find out if we're on Whistler or not
GetSystemWindowsDirectory(szShimDB, MAX_PATH); lstrcat(szShimDB, "\\AppPatch\\sysmain.sdb"); hFile = CreateFile( szShimDB, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { LogMsg("Running on Win2k\n"); g_bWin2k = TRUE; } else { CloseHandle(hFile); LogMsg("Running on Whistler\n"); g_bWin2k = FALSE; }
DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG), GetDesktopWindow(), QShimAppDlgProc);
return 1; }
|