You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
826 lines
22 KiB
826 lines
22 KiB
/***************************************************************************
|
|
* 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;
|
|
}
|