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.
1680 lines
44 KiB
1680 lines
44 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
dbSupport.cpp
|
|
|
|
Abstract:
|
|
|
|
Contains code that allows us to read/create SDBs.
|
|
|
|
Notes:
|
|
|
|
ANSI & Unicode via TCHAR - runs on NT/2K/XP etc.
|
|
|
|
History:
|
|
|
|
02/16/00 clupu Created
|
|
02/20/02 rparsons Implemented strsafe functions
|
|
|
|
--*/
|
|
#include "windows.h"
|
|
#include "commctrl.h"
|
|
#include "shlwapi.h"
|
|
#include <tchar.h>
|
|
|
|
#include "qfixapp.h"
|
|
#include "dbSupport.h"
|
|
#include "resource.h"
|
|
#include <strsafe.h>
|
|
|
|
#define _WANT_TAG_INFO
|
|
|
|
extern "C" {
|
|
#include "shimdb.h"
|
|
|
|
BOOL
|
|
ShimdbcExecute(
|
|
LPCWSTR lpszCmdLine
|
|
);
|
|
}
|
|
|
|
extern HINSTANCE g_hInstance;
|
|
extern HWND g_hDlg;
|
|
extern TCHAR g_szSDBToDelete[MAX_PATH];
|
|
extern BOOL g_bSDBInstalled;
|
|
extern TCHAR g_szAppTitle[64];
|
|
extern TCHAR g_szWinDir[MAX_PATH];
|
|
extern TCHAR g_szSysDir[MAX_PATH];
|
|
|
|
#define MAX_CMD_LINE 1024
|
|
#define MAX_SHIM_DESCRIPTION 1024
|
|
#define MAX_SHIM_NAME 128
|
|
|
|
#define MAX_BUFFER_SIZE 1024
|
|
|
|
#define SHIM_FILE_LOG_NAME _T("QFixApp.log")
|
|
|
|
// Temp buffer to read UNICODE strings from the database.
|
|
TCHAR g_szData[MAX_BUFFER_SIZE];
|
|
|
|
#define MAX_XML_SIZE 1024 * 16
|
|
|
|
//
|
|
// Buffers for display XML and SDB XML.
|
|
//
|
|
TCHAR g_szDisplayXML[MAX_XML_SIZE];
|
|
TCHAR g_szSDBXML[MAX_XML_SIZE];
|
|
|
|
TCHAR g_szLayerName[] = _T("!#RunLayer");
|
|
|
|
INT_PTR
|
|
CALLBACK
|
|
ShowXMLDlgProc(
|
|
HWND hdlg,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
/*++
|
|
ShowXMLDlgProc
|
|
|
|
Description: Show the dialog with the XML for the current selections.
|
|
|
|
--*/
|
|
{
|
|
int wCode = LOWORD(wParam);
|
|
int wNotifyCode = HIWORD(wParam);
|
|
|
|
switch (uMsg) {
|
|
case WM_INITDIALOG:
|
|
//
|
|
// By default we'll show the 'display XML'.
|
|
//
|
|
CheckDlgButton(hdlg, IDC_DISPLAY_XML, BST_CHECKED);
|
|
SetDlgItemText(hdlg, IDC_XML, (LPTSTR)lParam);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (wCode) {
|
|
case IDC_DISPLAY_XML:
|
|
case IDC_SDB_XML:
|
|
if (BN_CLICKED == wNotifyCode) {
|
|
if (IsDlgButtonChecked(hdlg, IDC_DISPLAY_XML)) {
|
|
SetDlgItemText(hdlg, IDC_XML, g_szDisplayXML);
|
|
}
|
|
else if (IsDlgButtonChecked(hdlg, IDC_SDB_XML)) {
|
|
SetDlgItemText(hdlg, IDC_XML, g_szSDBXML + 1);
|
|
}
|
|
SendDlgItemMessage(hdlg, IDC_XML, EM_SETSEL, 0, -1);
|
|
SetFocus(GetDlgItem(hdlg, IDC_XML));
|
|
}
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hdlg, TRUE);
|
|
break;
|
|
|
|
case IDC_SAVE_XML:
|
|
DoFileSave(hdlg);
|
|
EndDialog(hdlg, TRUE);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LPTSTR
|
|
ReadAndAllocateString(
|
|
PDB pdb,
|
|
TAGID tiString
|
|
)
|
|
{
|
|
TCHAR* psz = NULL;
|
|
int nLen;
|
|
|
|
*g_szData = 0;
|
|
|
|
SdbReadStringTag(pdb, tiString, g_szData, MAX_BUFFER_SIZE);
|
|
|
|
if (!*g_szData) {
|
|
DPF("[ReadAndAllocateString] Couldn't read the string");
|
|
return NULL;
|
|
}
|
|
|
|
nLen = _tcslen(g_szData) + 1;
|
|
|
|
psz = (LPTSTR)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
nLen * sizeof(TCHAR));
|
|
|
|
if (!psz) {
|
|
return NULL;
|
|
} else {
|
|
StringCchCopy(psz, nLen, g_szData);
|
|
}
|
|
|
|
return psz;
|
|
}
|
|
|
|
BOOL
|
|
GetShimsFlagsForLayer(
|
|
PDB pdb,
|
|
PFIX pFixHead,
|
|
PFIX* parrShim,
|
|
TCHAR** parrCmdLine,
|
|
TAGID tiLayer,
|
|
BOOL fGetShims
|
|
)
|
|
/*++
|
|
GetShimsFlagsForLayer
|
|
|
|
Description: Based on the flag, get the shims or flags for the given
|
|
layer and put them in the array.
|
|
|
|
--*/
|
|
{
|
|
TAGID tiTmp, tiName;
|
|
int nInd = 0;
|
|
TCHAR szName[MAX_SHIM_NAME] = _T("");
|
|
|
|
//
|
|
// If we're going to get flags, find the next available element
|
|
// in the array so we can perform an insertion.
|
|
//
|
|
if (!fGetShims) {
|
|
while (parrShim[nInd]) {
|
|
nInd++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Based on the flag, find the first tag ID in the layer.
|
|
//
|
|
tiTmp = SdbFindFirstTag(pdb, tiLayer, fGetShims ? TAG_SHIM_REF : TAG_FLAG_REF);
|
|
|
|
while (tiTmp != TAGID_NULL) {
|
|
*szName = 0;
|
|
PFIX pFixWalk = NULL;
|
|
|
|
tiName = SdbFindFirstTag(pdb, tiTmp, TAG_NAME);
|
|
|
|
if (tiName == TAGID_NULL) {
|
|
DPF("[GetShimsFlagForLayer] Failed to get the name of shim/flag");
|
|
return FALSE;
|
|
}
|
|
|
|
SdbReadStringTag(pdb, tiName, szName, MAX_SHIM_NAME);
|
|
|
|
if (!*szName) {
|
|
DPF("[GetShimsFlagForLayer] Couldn't read the name of shim/flag");
|
|
return FALSE;
|
|
}
|
|
|
|
pFixWalk = pFixHead;
|
|
|
|
while (pFixWalk != NULL) {
|
|
if (!(pFixWalk->dwFlags & FIX_TYPE_LAYER)) {
|
|
if (_tcsicmp(pFixWalk->pszName, szName) == 0) {
|
|
parrShim[nInd] = pFixWalk;
|
|
|
|
if (fGetShims) {
|
|
//
|
|
// Now get the command line for this shim in the layer.
|
|
//
|
|
tiName = SdbFindFirstTag(pdb, tiTmp, TAG_COMMAND_LINE);
|
|
|
|
if (tiName != TAGID_NULL) {
|
|
parrCmdLine[nInd] = ReadAndAllocateString(pdb, tiName);
|
|
}
|
|
}
|
|
|
|
nInd++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pFixWalk = pFixWalk->pNext;
|
|
}
|
|
|
|
tiTmp = SdbFindNextTag(pdb, tiLayer, tiTmp);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PFIX
|
|
ParseTagFlag(
|
|
PDB pdb,
|
|
TAGID tiFlag,
|
|
BOOL bAllFlags
|
|
)
|
|
/*++
|
|
ParseTagFlag
|
|
|
|
Description: Parse a Flag tag for the NAME, DESCRIPTION and MASK
|
|
|
|
--*/
|
|
{
|
|
TAGID tiFlagInfo;
|
|
TAG tWhichInfo;
|
|
PFIX pFix = NULL;
|
|
TCHAR* pszName = NULL;
|
|
TCHAR* pszDesc = NULL;
|
|
DWORD dwFlags = 0;
|
|
BOOL bGeneral = (bAllFlags ? TRUE : FALSE);
|
|
|
|
tiFlagInfo = SdbGetFirstChild(pdb, tiFlag);
|
|
|
|
while (tiFlagInfo != 0) {
|
|
tWhichInfo = SdbGetTagFromTagID(pdb, tiFlagInfo);
|
|
|
|
switch (tWhichInfo) {
|
|
case TAG_GENERAL:
|
|
bGeneral = TRUE;
|
|
break;
|
|
|
|
case TAG_NAME:
|
|
pszName = ReadAndAllocateString(pdb, tiFlagInfo);
|
|
break;
|
|
|
|
case TAG_DESCRIPTION:
|
|
pszDesc = ReadAndAllocateString(pdb, tiFlagInfo);
|
|
break;
|
|
|
|
case TAG_FLAGS_NTVDM1:
|
|
case TAG_FLAGS_NTVDM2:
|
|
case TAG_FLAGS_NTVDM3:
|
|
dwFlags = FIX_TYPE_FLAGVDM;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
tiFlagInfo = SdbGetNextChild(pdb, tiFlag, tiFlagInfo);
|
|
}
|
|
|
|
if (!bGeneral) {
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Done. Add the fix to the list.
|
|
//
|
|
pFix = (PFIX)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FIX));
|
|
|
|
if (pFix == NULL || pszName == NULL) {
|
|
|
|
cleanup:
|
|
if (pFix != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pFix);
|
|
}
|
|
|
|
if (pszName != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pszName);
|
|
}
|
|
|
|
if (pszDesc != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pszDesc);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
pFix->pszName = pszName;
|
|
pFix->dwFlags |= dwFlags | FIX_TYPE_FLAG;
|
|
|
|
if (pszDesc) {
|
|
pFix->pszDesc = pszDesc;
|
|
} else {
|
|
TCHAR* pszNone = NULL;
|
|
|
|
pszNone = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
|
|
if (!pszNone) {
|
|
return NULL;
|
|
}
|
|
|
|
*pszNone = 0;
|
|
|
|
LoadString(g_hInstance, IDS_NO_DESCR_AVAIL, pszNone, MAX_PATH);
|
|
pFix->pszDesc = pszNone;
|
|
}
|
|
|
|
return pFix;
|
|
}
|
|
|
|
PFIX
|
|
ParseTagShim(
|
|
PDB pdb,
|
|
TAGID tiShim,
|
|
BOOL bAllShims
|
|
)
|
|
/*++
|
|
ParseTagShim
|
|
|
|
Description: Parse a Shim tag for the NAME, SHORTNAME, DESCRIPTION ...
|
|
|
|
--*/
|
|
{
|
|
TAGID tiShimInfo;
|
|
TAG tWhichInfo;
|
|
PFIX pFix = NULL;
|
|
TCHAR* pszName = NULL;
|
|
TCHAR* pszDesc = NULL;
|
|
BOOL bGeneral = (bAllShims ? TRUE : FALSE);
|
|
|
|
tiShimInfo = SdbGetFirstChild(pdb, tiShim);
|
|
|
|
while (tiShimInfo != 0) {
|
|
tWhichInfo = SdbGetTagFromTagID(pdb, tiShimInfo);
|
|
|
|
switch (tWhichInfo) {
|
|
case TAG_GENERAL:
|
|
bGeneral = TRUE;
|
|
break;
|
|
|
|
case TAG_NAME:
|
|
pszName = ReadAndAllocateString(pdb, tiShimInfo);
|
|
break;
|
|
|
|
case TAG_DESCRIPTION:
|
|
pszDesc = ReadAndAllocateString(pdb, tiShimInfo);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
tiShimInfo = SdbGetNextChild(pdb, tiShim, tiShimInfo);
|
|
}
|
|
|
|
if (!bGeneral) {
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Done. Add the fix to the list.
|
|
//
|
|
pFix = (PFIX)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FIX));
|
|
|
|
if (pFix == NULL || pszName == NULL) {
|
|
|
|
cleanup:
|
|
if (pFix != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pFix);
|
|
}
|
|
|
|
if (pszName != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pszName);
|
|
}
|
|
|
|
if (pszDesc != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pszDesc);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
pFix->pszName = pszName;
|
|
pFix->dwFlags = FIX_TYPE_SHIM;
|
|
|
|
//
|
|
// If we didn't find a description, load it from the resource table.
|
|
//
|
|
if (pszDesc) {
|
|
pFix->pszDesc = pszDesc;
|
|
} else {
|
|
TCHAR* pszNone;
|
|
|
|
pszNone = (TCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
|
|
if (!pszNone) {
|
|
return NULL;
|
|
}
|
|
|
|
*pszNone = 0;
|
|
|
|
LoadString(g_hInstance, IDS_NO_DESCR_AVAIL, pszNone, MAX_PATH);
|
|
pFix->pszDesc = pszNone;
|
|
}
|
|
|
|
return pFix;
|
|
}
|
|
|
|
PFIX
|
|
ParseTagLayer(
|
|
PDB pdb,
|
|
TAGID tiLayer,
|
|
PFIX pFixHead
|
|
)
|
|
/*++
|
|
ParseTagLayer
|
|
|
|
Description: Parse a LAYER tag for the NAME and the SHIMs that it contains.
|
|
|
|
--*/
|
|
{
|
|
PFIX pFix = NULL;
|
|
TAGID tiFlag, tiShim, tiName;
|
|
int nShimCount;
|
|
TCHAR* pszName = NULL;
|
|
PFIX* parrShim = NULL;
|
|
TCHAR** parrCmdLine = NULL;
|
|
|
|
tiName = SdbFindFirstTag(pdb, tiLayer, TAG_NAME);
|
|
|
|
if (tiName == TAGID_NULL) {
|
|
DPF("[ParseTagLayer] Failed to get the name of the layer");
|
|
return NULL;
|
|
}
|
|
|
|
pszName = ReadAndAllocateString(pdb, tiName);
|
|
|
|
//
|
|
// Now loop through all the SHIMs that this LAYER consists of and
|
|
// allocate an array to keep all the pointers to the SHIMs' pFix
|
|
// structures. We do this in 2 passes. First we calculate how many
|
|
// SHIMs are in the layer, then we lookup their appropriate pFix-es.
|
|
//
|
|
tiShim = SdbFindFirstTag(pdb, tiLayer, TAG_SHIM_REF);
|
|
|
|
nShimCount = 0;
|
|
|
|
while (tiShim != TAGID_NULL) {
|
|
nShimCount++;
|
|
tiShim = SdbFindNextTag(pdb, tiLayer, tiShim);
|
|
}
|
|
|
|
//
|
|
// We have a count of the shims in the layer. Now we need to
|
|
// add the flags that are included in this layer to the count.
|
|
//
|
|
tiFlag = SdbFindFirstTag(pdb, tiLayer, TAG_FLAG_REF);
|
|
|
|
while (tiFlag != TAGID_NULL) {
|
|
nShimCount++;
|
|
tiFlag = SdbFindNextTag(pdb, tiLayer, tiFlag);
|
|
}
|
|
|
|
parrShim = (PFIX*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PFIX) * (nShimCount + 1));
|
|
parrCmdLine = (TCHAR**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TCHAR*) * (nShimCount + 1));
|
|
|
|
//
|
|
// Done. Add the fix to the list.
|
|
//
|
|
pFix = (PFIX)HeapAlloc(GetProcessHeap(), 0, sizeof(FIX));
|
|
|
|
if (pFix == NULL || parrCmdLine == NULL || pszName == NULL || parrShim == NULL) {
|
|
|
|
cleanup:
|
|
if (pFix != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pFix);
|
|
}
|
|
|
|
if (parrCmdLine != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, parrCmdLine);
|
|
}
|
|
|
|
if (parrShim != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, parrShim);
|
|
}
|
|
|
|
if (pszName != NULL) {
|
|
HeapFree(GetProcessHeap(), 0, pszName);
|
|
}
|
|
|
|
DPF("[ParseTagLayer] Memory allocation error");
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Call the function that will fill in the array of PFIX
|
|
// pointers and their corresponding command lines.
|
|
// We do this for shims first.
|
|
//
|
|
if (!GetShimsFlagsForLayer(pdb,
|
|
pFixHead,
|
|
parrShim,
|
|
parrCmdLine,
|
|
tiLayer,
|
|
TRUE)) {
|
|
|
|
DPF("[ParseTagLayer] Failed to get shims for layer");
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Now do the same thing for flags.
|
|
//
|
|
if (!GetShimsFlagsForLayer(pdb,
|
|
pFixHead,
|
|
parrShim,
|
|
NULL,
|
|
tiLayer,
|
|
FALSE)) {
|
|
|
|
DPF("[ParseTagLayer] Failed to get flags for layer");
|
|
goto cleanup;
|
|
}
|
|
|
|
pFix->pszName = pszName;
|
|
pFix->dwFlags = FIX_TYPE_LAYER;
|
|
pFix->parrShim = parrShim;
|
|
pFix->parrCmdLine = parrCmdLine;
|
|
|
|
return pFix;
|
|
}
|
|
|
|
BOOL
|
|
IsSDBFromSP2(
|
|
void
|
|
)
|
|
/*++
|
|
IsSDBFromSP2
|
|
|
|
Description: Determine if the SDB is from Service Pack 2.
|
|
|
|
--*/
|
|
{
|
|
BOOL fResult = FALSE;
|
|
PDB pdb;
|
|
TAGID tiDatabase;
|
|
TAGID tiLibrary;
|
|
TAGID tiChild;
|
|
PFIX pFix = NULL;;
|
|
TCHAR szSDBPath[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
hr = StringCchPrintf(szSDBPath,
|
|
ARRAYSIZE(szSDBPath) - 1,
|
|
_T("%s\\AppPatch\\sysmain.sdb"),
|
|
g_szWinDir);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[IsSDBFromSP2] 0x%08X Buffer too small", HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Open the shim database.
|
|
//
|
|
pdb = SdbOpenDatabase(szSDBPath, DOS_PATH);
|
|
|
|
if (!pdb) {
|
|
DPF("[IsSDBFromSP2] Cannot open shim DB '%S'", szSDBPath);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Now browse the shim DB and look only for tags Shim within
|
|
// the LIBRARY list tag.
|
|
//
|
|
tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
|
|
|
|
if (tiDatabase == TAGID_NULL) {
|
|
DPF("[IsSDBFromSP2] Cannot find TAG_DATABASE under the root tag");
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get TAG_LIBRARY.
|
|
//
|
|
tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
|
|
|
|
if (tiLibrary == TAGID_NULL) {
|
|
DPF("[IsSDBFromSP2] Cannot find TAG_LIBRARY under the TAG_DATABASE tag");
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Loop get the first shim in the library.
|
|
//
|
|
tiChild = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
|
|
|
|
if (tiChild == NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// Get information about the first shim listed.
|
|
//
|
|
pFix = ParseTagShim(pdb, tiChild, TRUE);
|
|
|
|
if (!pFix) {
|
|
goto cleanup;
|
|
}
|
|
|
|
//
|
|
// If the first shim listed is 2GbGetDiskFreeSpace, this is SP2.
|
|
//
|
|
if (!(_tcsicmp(pFix->pszName, _T("2GbGetDiskFreeSpace.dll")))) {
|
|
fResult = TRUE;
|
|
}
|
|
|
|
cleanup:
|
|
SdbCloseDatabase(pdb);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
PFIX
|
|
ReadFixesFromSdb(
|
|
LPTSTR pszSdb,
|
|
BOOL bAllFixes
|
|
)
|
|
/*++
|
|
ReadFixesFromSdb
|
|
|
|
Description: Query the database and enumerate all available shims fixes.
|
|
|
|
--*/
|
|
{
|
|
PDB pdb;
|
|
TAGID tiDatabase;
|
|
TAGID tiLibrary;
|
|
TAGID tiChild;
|
|
PFIX pFixHead = NULL;
|
|
PFIX pFix = NULL;
|
|
TCHAR szSDBPath[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
hr = StringCchPrintf(szSDBPath,
|
|
ARRAYSIZE(szSDBPath),
|
|
_T("%s\\AppPatch\\%s"),
|
|
g_szWinDir,
|
|
pszSdb);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[ReadFixesFromSdb] 0x%08X Buffer too small", HRESULT_CODE(hr));
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Open the shim database.
|
|
//
|
|
pdb = SdbOpenDatabase(szSDBPath, DOS_PATH);
|
|
|
|
if (!pdb) {
|
|
DPF("[ReadFixesFromSdb] Cannot open shim DB '%S'", szSDBPath);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Now browse the shim DB and look only for tags Shim within
|
|
// the LIBRARY list tag.
|
|
//
|
|
tiDatabase = SdbFindFirstTag(pdb, TAGID_ROOT, TAG_DATABASE);
|
|
|
|
if (tiDatabase == TAGID_NULL) {
|
|
DPF("[ReadFixesFromSdb] Cannot find TAG_DATABASE under the root tag");
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get TAG_LIBRARY.
|
|
//
|
|
tiLibrary = SdbFindFirstTag(pdb, tiDatabase, TAG_LIBRARY);
|
|
|
|
if (tiLibrary == TAGID_NULL) {
|
|
DPF("[ReadFixesFromSdb] Cannot find TAG_LIBRARY under the TAG_DATABASE tag");
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Loop through all TAG_SHIM tags within TAG_LIBRARY.
|
|
//
|
|
tiChild = SdbFindFirstTag(pdb, tiLibrary, TAG_SHIM);
|
|
|
|
while (tiChild != TAGID_NULL) {
|
|
pFix = ParseTagShim(pdb, tiChild, bAllFixes);
|
|
|
|
if (pFix != NULL) {
|
|
pFix->pNext = pFixHead;
|
|
pFixHead = pFix;
|
|
}
|
|
|
|
tiChild = SdbFindNextTag(pdb, tiLibrary, tiChild);
|
|
}
|
|
|
|
//
|
|
// Loop through all TAG_FLAG tags within TAG_LIBRARY.
|
|
//
|
|
tiChild = SdbFindFirstTag(pdb, tiLibrary, TAG_FLAG);
|
|
|
|
while (tiChild != TAGID_NULL) {
|
|
pFix = ParseTagFlag(pdb, tiChild, bAllFixes);
|
|
|
|
if (pFix != NULL) {
|
|
pFix->pNext = pFixHead;
|
|
pFixHead = pFix;
|
|
}
|
|
|
|
tiChild = SdbFindNextTag(pdb, tiLibrary, tiChild);
|
|
}
|
|
|
|
//
|
|
// Loop through all TAG_LAYER tags within TAG_DATABASE.
|
|
//
|
|
tiChild = SdbFindFirstTag(pdb, tiDatabase, TAG_LAYER);
|
|
|
|
while (tiChild != TAGID_NULL) {
|
|
|
|
pFix = ParseTagLayer(pdb, tiChild, pFixHead);
|
|
|
|
if (pFix != NULL) {
|
|
pFix->pNext = pFixHead;
|
|
pFixHead = pFix;
|
|
}
|
|
|
|
tiChild = SdbFindNextTag(pdb, tiDatabase, tiChild);
|
|
}
|
|
|
|
Cleanup:
|
|
SdbCloseDatabase(pdb);
|
|
|
|
return pFixHead;
|
|
}
|
|
|
|
#define ADD_AND_CHECK(cbSizeX, cbCrtSizeX, pszDst) \
|
|
{ \
|
|
TCHAR* pszSrc = szBuffer; \
|
|
\
|
|
while (*pszSrc != 0) { \
|
|
\
|
|
if (cbSizeX - cbCrtSizeX <= 5) { \
|
|
DPF("[ADD_AND_CHECK] Out of space"); \
|
|
return FALSE; \
|
|
} \
|
|
\
|
|
if (*pszSrc == _T('&') && *(pszSrc + 1) != _T('q')) { \
|
|
StringCbCopy(pszDst, cbSizeX, _T("&")); \
|
|
pszDst += 5; \
|
|
cbCrtSizeX += 5; \
|
|
} else { \
|
|
*pszDst++ = *pszSrc; \
|
|
cbCrtSizeX++; \
|
|
} \
|
|
pszSrc++; \
|
|
} \
|
|
*pszDst = 0; \
|
|
cbCrtSizeX++; \
|
|
}
|
|
|
|
BOOL
|
|
CollectShims(
|
|
HWND hListShims,
|
|
LPTSTR pszXML,
|
|
int cbSize
|
|
)
|
|
/*++
|
|
CollectShims
|
|
|
|
Description: Collects all the shims from the list view
|
|
and generates the XML in pszXML
|
|
|
|
--*/
|
|
{
|
|
int cShims = 0, nShimsApplied = 0, nIndex;
|
|
int cbCrtSize = 0;
|
|
BOOL fSelected = FALSE;
|
|
LVITEM lvi;
|
|
TCHAR szBuffer[1024];
|
|
|
|
cShims = ListView_GetItemCount(hListShims);
|
|
|
|
for (nIndex = 0; nIndex < cShims; nIndex++) {
|
|
|
|
fSelected = ListView_GetCheckState(hListShims, nIndex);
|
|
|
|
if (fSelected) {
|
|
//
|
|
// This shim is selected - add it to the XML.
|
|
//
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = nIndex;
|
|
lvi.iSubItem = 0;
|
|
|
|
ListView_GetItem(hListShims, &lvi);
|
|
|
|
PFIX pFix = (PFIX)lvi.lParam;
|
|
PMODULE pModule = pFix->pModule;
|
|
|
|
if (pFix->dwFlags & FIX_TYPE_FLAG) {
|
|
if (NULL != pFix->pszCmdLine) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <FLAG NAME=\"%s\" COMMAND_LINE=\"%s\"/>\r\n"),
|
|
pFix->pszName,
|
|
pFix->pszCmdLine);
|
|
} else {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <FLAG NAME=\"%s\"/>\r\n"),
|
|
pFix->pszName);
|
|
}
|
|
} else {
|
|
//
|
|
// Check for module include/exclude so we know how to open/close the XML.
|
|
//
|
|
if (NULL != pModule) {
|
|
if (NULL != pFix->pszCmdLine) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <SHIM NAME=\"%s\" COMMAND_LINE=\"%s\">\r\n"),
|
|
pFix->pszName,
|
|
pFix->pszCmdLine);
|
|
|
|
} else {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <SHIM NAME=\"%s\">\r\n"),
|
|
pFix->pszName);
|
|
|
|
}
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
|
|
//
|
|
// Add the modules to the XML.
|
|
//
|
|
while (NULL != pModule) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <%s MODULE=\"%s\"/>\r\n"),
|
|
pModule->fInclude ? _T("INCLUDE") : _T("EXCLUDE"),
|
|
pModule->pszName);
|
|
|
|
pModule = pModule->pNext;
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
}
|
|
|
|
//
|
|
// Close the SHIM tag.
|
|
//
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" </SHIM>\r\n"));
|
|
} else {
|
|
//
|
|
// No include/exclude was provided - just build the shim tag normally.
|
|
//
|
|
if (NULL != pFix->pszCmdLine) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <SHIM NAME=\"%s\" COMMAND_LINE=\"%s\"/>\r\n"),
|
|
pFix->pszName,
|
|
pFix->pszCmdLine);
|
|
|
|
} else {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <SHIM NAME=\"%s\"/>\r\n"),
|
|
pFix->pszName);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
|
|
nShimsApplied++;
|
|
}
|
|
}
|
|
|
|
DPF("[CollectShims] %d shim(s) selected", nShimsApplied);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CollectFileAttributes(
|
|
HWND hTreeFiles,
|
|
LPTSTR pszXML,
|
|
int cbSize
|
|
)
|
|
/*++
|
|
CollectFileAttributes
|
|
|
|
Description: Collects the attributes of all the files in the tree
|
|
and generates the XML in pszXML.
|
|
|
|
--*/
|
|
{
|
|
HTREEITEM hBinItem;
|
|
HTREEITEM hItem;
|
|
PATTRINFO pAttrInfo;
|
|
UINT State;
|
|
TVITEM item;
|
|
int cbCrtSize = 0;
|
|
TCHAR szItem[MAX_PATH];
|
|
TCHAR szBuffer[1024];
|
|
|
|
//
|
|
// First get the main EXE.
|
|
//
|
|
hBinItem = TreeView_GetChild(hTreeFiles, TVI_ROOT);
|
|
|
|
item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_TEXT;
|
|
item.hItem = hBinItem;
|
|
item.pszText = szItem;
|
|
item.cchTextMax = MAX_PATH;
|
|
|
|
TreeView_GetItem(hTreeFiles, &item);
|
|
|
|
pAttrInfo = (PATTRINFO)(item.lParam);
|
|
|
|
hItem = TreeView_GetChild(hTreeFiles, hBinItem);
|
|
|
|
while (hItem != NULL) {
|
|
item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
|
|
item.hItem = hItem;
|
|
|
|
TreeView_GetItem(hTreeFiles, &item);
|
|
|
|
State = item.state & TVIS_STATEIMAGEMASK;
|
|
|
|
if (State) {
|
|
if (((State >> 12) & 0x03) == 2) {
|
|
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" %s"),
|
|
(LPTSTR)item.pszText);
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
}
|
|
}
|
|
|
|
hItem = TreeView_GetNextSibling(hTreeFiles, hItem);
|
|
}
|
|
|
|
StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), _T(">\r\n"));
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
|
|
//
|
|
// Done with the main binary. Now enumerate the matching files.
|
|
//
|
|
hBinItem = TreeView_GetNextSibling(hTreeFiles, hBinItem);
|
|
|
|
while (hBinItem != NULL) {
|
|
|
|
item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
|
|
item.hItem = hBinItem;
|
|
item.pszText = szItem;
|
|
item.cchTextMax = MAX_PATH;
|
|
|
|
TreeView_GetItem(hTreeFiles, &item);
|
|
|
|
pAttrInfo = (PATTRINFO)(item.lParam);
|
|
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <MATCHING_FILE NAME=\"%s\""),
|
|
szItem);
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
|
|
hItem = TreeView_GetChild(hTreeFiles, hBinItem);
|
|
|
|
while (hItem != NULL) {
|
|
item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_STATE | TVIF_TEXT;
|
|
item.hItem = hItem;
|
|
|
|
TreeView_GetItem(hTreeFiles, &item);
|
|
|
|
State = item.state & TVIS_STATEIMAGEMASK;
|
|
|
|
if (State) {
|
|
if (((State >> 12) & 0x03) == 2) {
|
|
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" %s"),
|
|
(LPTSTR)item.pszText);
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
}
|
|
}
|
|
|
|
hItem = TreeView_GetNextSibling(hTreeFiles, hItem);
|
|
}
|
|
|
|
StringCchCopy(szBuffer, ARRAYSIZE(szBuffer), _T("/>\r\n"));
|
|
|
|
ADD_AND_CHECK(cbSize, cbCrtSize, pszXML);
|
|
|
|
hBinItem = TreeView_GetNextSibling(hTreeFiles, hBinItem);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CreateSDBFile(
|
|
LPCTSTR pszShortName,
|
|
LPTSTR pszSDBName
|
|
)
|
|
/*++
|
|
CreateSDBFile
|
|
|
|
Description: Creates the XML file on the user's hard drive and
|
|
generates the SDB using shimdbc.
|
|
--*/
|
|
{
|
|
TCHAR* psz = NULL;
|
|
TCHAR szShortName[MAX_PATH];
|
|
TCHAR szAppPatchDir[MAX_PATH];
|
|
TCHAR szSDBFile[MAX_PATH];
|
|
TCHAR szXMLFile[MAX_PATH];
|
|
TCHAR szCompiler[MAX_PATH];
|
|
HANDLE hFile;
|
|
DWORD cbBytesWritten;
|
|
HRESULT hr;
|
|
|
|
hr = StringCchPrintf(szAppPatchDir,
|
|
ARRAYSIZE(szAppPatchDir),
|
|
_T("%s\\AppPatch"),
|
|
g_szWinDir);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[CreateSDBFile] 0x%08X Buffer too small (1)", HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
SetCurrentDirectory(szAppPatchDir);
|
|
|
|
hr = StringCchCopy(szShortName, ARRAYSIZE(szShortName), pszShortName);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[CreateSDBFile] 0x%08X Buffer too small (2)", HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
psz = PathFindExtension(szShortName);
|
|
|
|
if (!psz) {
|
|
return FALSE;
|
|
} else {
|
|
*psz = '\0';
|
|
}
|
|
|
|
hr = StringCchPrintf(szXMLFile,
|
|
ARRAYSIZE(szXMLFile),
|
|
_T("%s\\%s.xml"),
|
|
szAppPatchDir,
|
|
szShortName);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[CreateSDBFile] 0x%08X Buffer too small (3)", HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
hr = StringCchPrintf(szSDBFile,
|
|
ARRAYSIZE(szSDBFile),
|
|
_T("%s\\%s.sdb"),
|
|
szAppPatchDir,
|
|
szShortName);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[CreateSDBFile] 0x%08X Buffer too small (4)", HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
hFile = CreateFile(szXMLFile,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
DPF("[CreateSDBFile] 0x%08X CreateFile '%S' failed",
|
|
szXMLFile,
|
|
GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(WriteFile(hFile,
|
|
g_szSDBXML,
|
|
_tcslen(g_szSDBXML) * sizeof(TCHAR),
|
|
&cbBytesWritten,
|
|
NULL))) {
|
|
DPF("[CreateSDBFile] 0x%08X WriteFile '%S' failed",
|
|
szXMLFile,
|
|
GetLastError());
|
|
CloseHandle(hFile);
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
|
|
hr = StringCchPrintf(szCompiler,
|
|
ARRAYSIZE(szCompiler),
|
|
_T("shimdbc.exe fix -q \"%s\" \"%s\""),
|
|
szXMLFile,
|
|
szSDBFile);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[CreateSDBFile] 0x%08X Buffer too small (5)", HRESULT_CODE(hr));
|
|
return FALSE;
|
|
}
|
|
|
|
if (!ShimdbcExecute(szCompiler)) {
|
|
DPF("[CreateSDBFile] 0x%08X CreateProcess '%S' failed",
|
|
szCompiler,
|
|
GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Give the SDB name back to the caller if they want it.
|
|
//
|
|
if (pszSDBName) {
|
|
StringCchCopy(pszSDBName, MAX_PATH, szSDBFile);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
BuildDisplayXML(
|
|
HWND hTreeFiles,
|
|
HWND hListShims,
|
|
LPCTSTR pszLayerName,
|
|
LPCTSTR pszShortName,
|
|
DWORD dwBinaryType,
|
|
BOOL fAddW2K
|
|
)
|
|
/*++
|
|
BuildDisplayXML
|
|
|
|
Description: Builds the XML that will be inserted into DBU.XML.
|
|
|
|
--*/
|
|
{
|
|
TCHAR szBuffer[1024];
|
|
TCHAR* pszXML = NULL;
|
|
int cbCrtXmlSize = 0, cbLength;
|
|
int cbXmlSize = MAX_XML_SIZE;
|
|
|
|
//
|
|
// Initialize our global and point to it.
|
|
//
|
|
*g_szDisplayXML = 0;
|
|
pszXML = g_szDisplayXML;
|
|
|
|
//
|
|
// Build the header for the XML.
|
|
//
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n")
|
|
_T("<DATABASE NAME=\"%s custom database\">\r\n"),
|
|
pszShortName);
|
|
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
//
|
|
// Add the APP and EXE elements to the XML.
|
|
//
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <APP NAME=\"%s\" VENDOR=\"Unknown\">\r\n")
|
|
_T(" <%s NAME=\"%s\""),
|
|
pszShortName,
|
|
(dwBinaryType == SCS_32BIT_BINARY ? _T("EXE") : _T("EXE - ERROR: 16-BIT BINARY")),
|
|
pszShortName);
|
|
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
//
|
|
// Add the matching files and their attributes to the XML.
|
|
//
|
|
if (!CollectFileAttributes(hTreeFiles,
|
|
pszXML,
|
|
cbXmlSize - cbCrtXmlSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
cbLength = _tcslen(pszXML);
|
|
pszXML += cbLength;
|
|
cbCrtXmlSize += cbLength + 1;
|
|
|
|
//
|
|
// If a layer was provided, use it. Otherwise, build the list
|
|
// of shims and add it to the XML.
|
|
//
|
|
if (pszLayerName) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <LAYER NAME=\"%s\"/>\r\n"),
|
|
pszLayerName);
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
} else {
|
|
if (!CollectShims(hListShims, pszXML, cbXmlSize - cbCrtXmlSize)) {
|
|
return FALSE;
|
|
}
|
|
cbLength = _tcslen(pszXML);
|
|
pszXML += cbLength;
|
|
cbCrtXmlSize += cbLength + 1;
|
|
}
|
|
|
|
//
|
|
// If this is Windows 2000, add Win2kPropagateLayer.
|
|
//
|
|
if (fAddW2K) {
|
|
StringCchCopy(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <SHIM NAME=\"Win2kPropagateLayer\"/>\r\n"));
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
}
|
|
|
|
//
|
|
// Finally, close the open tags.
|
|
//
|
|
StringCchCopy(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" </EXE>\r\n </APP>\r\n</DATABASE>"));
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
DPF("[BuildDisplayXML] XML:\n %S", g_szDisplayXML);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
BuildSDBXML(
|
|
HWND hTreeFiles,
|
|
HWND hListShims,
|
|
LPCTSTR pszLayerName,
|
|
LPCTSTR pszShortName,
|
|
DWORD dwBinaryType,
|
|
BOOL fAddW2K
|
|
)
|
|
/*++
|
|
BuildSDBXML
|
|
|
|
Description: Builds the XML that will be used for SDB generation.
|
|
|
|
--*/
|
|
{
|
|
TCHAR szBuffer[1024];
|
|
TCHAR* pszXML = NULL;
|
|
WCHAR wszUnicodeHdr = 0xFEFF;
|
|
int cbCrtXmlSize = 0, cbLength;
|
|
int cbXmlSize = MAX_XML_SIZE;
|
|
|
|
//
|
|
// Initialize our global and point to it.
|
|
//
|
|
g_szSDBXML[0] = 0;
|
|
pszXML = g_szSDBXML;
|
|
|
|
//
|
|
// Build the header for the XML.
|
|
//
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T("%lc<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n")
|
|
_T("<DATABASE NAME=\"%s custom database\">\r\n"),
|
|
wszUnicodeHdr,
|
|
pszShortName);
|
|
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
//
|
|
// If no layer was provided, this indicates that the user has
|
|
// selected individual shims and we need to build our own layer.
|
|
//
|
|
if (!pszLayerName) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <LIBRARY>\r\n <LAYER NAME=\"%s\">\r\n"),
|
|
g_szLayerName + 2);
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
if (!CollectShims(hListShims,
|
|
pszXML,
|
|
cbXmlSize - cbCrtXmlSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
cbLength = _tcslen(pszXML);
|
|
pszXML += cbLength;
|
|
cbCrtXmlSize += cbLength + 1;
|
|
|
|
//
|
|
// If this is Windows 2000, add Win2kPropagateLayer.
|
|
//
|
|
if (fAddW2K) {
|
|
StringCchCopy(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <SHIM NAME=\"Win2kPropagateLayer\"/>\r\n"));
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
}
|
|
|
|
//
|
|
// Close the open tags.
|
|
//
|
|
StringCchCopy(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" </LAYER>\r\n </LIBRARY>\r\n"));
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
}
|
|
|
|
//
|
|
// Add the APP and EXE elements to the XML.
|
|
//
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <APP NAME=\"%s\" VENDOR=\"Unknown\">\r\n")
|
|
_T(" <EXE NAME=\"%s\""),
|
|
pszShortName,
|
|
pszShortName);
|
|
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
//
|
|
// Add the matching files and their attributes to the XML.
|
|
//
|
|
if (!CollectFileAttributes(hTreeFiles,
|
|
pszXML,
|
|
cbXmlSize - cbCrtXmlSize)) {
|
|
return FALSE;
|
|
}
|
|
|
|
cbLength = _tcslen(pszXML);
|
|
pszXML += cbLength;
|
|
cbCrtXmlSize += cbLength + 1;
|
|
|
|
//
|
|
// Add the LAYER element to the XML. This will either be a predefined
|
|
// layer name or the special 'RunLayer' indicating we built our own.
|
|
//
|
|
if (!pszLayerName) {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <LAYER NAME=\"%s\"/>\r\n"),
|
|
g_szLayerName + 2);
|
|
} else {
|
|
StringCchPrintf(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" <LAYER NAME=\"%s\"/>\r\n"),
|
|
pszLayerName);
|
|
}
|
|
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
//
|
|
// Finally, close the open tags.
|
|
//
|
|
StringCchCopy(szBuffer,
|
|
ARRAYSIZE(szBuffer),
|
|
_T(" </EXE>\r\n </APP>\r\n</DATABASE>"));
|
|
|
|
ADD_AND_CHECK(cbXmlSize, cbCrtXmlSize, pszXML);
|
|
|
|
DPF("[BuildSDBXML] XML:\n %S", g_szSDBXML);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CollectFix(
|
|
HWND hListLayers,
|
|
HWND hListShims,
|
|
HWND hTreeFiles,
|
|
LPCTSTR pszShortName,
|
|
LPCTSTR pszFullPath,
|
|
DWORD dwFlags,
|
|
LPTSTR pszFileCreated
|
|
)
|
|
/*++
|
|
CollectFix
|
|
|
|
Description: Adds the necessary support to apply shim(s) for
|
|
the specified app.
|
|
--*/
|
|
{
|
|
BOOL fAddW2K = FALSE;
|
|
TCHAR szError[MAX_PATH];
|
|
TCHAR szXmlFile[MAX_PATH];
|
|
TCHAR* pszLayerName = NULL;
|
|
TCHAR szLayer[128];
|
|
DWORD dwBinaryType = SCS_32BIT_BINARY;
|
|
|
|
//
|
|
// If the user has selected a predefined layer, we'll use that.
|
|
// Otherwise, assign the 'RunLayer' name which has a special
|
|
// meaning.
|
|
//
|
|
if (dwFlags & CFF_USELAYERTAB) {
|
|
|
|
LRESULT lSel;
|
|
|
|
lSel = SendMessage(hListLayers, LB_GETCURSEL, 0, 0);
|
|
|
|
if (lSel == LB_ERR) {
|
|
LoadString(g_hInstance, IDS_LAYER_SELECT, szError, ARRAYSIZE(szError));
|
|
MessageBox(g_hDlg, szError, g_szAppTitle, MB_ICONEXCLAMATION);
|
|
return TRUE;
|
|
}
|
|
|
|
SendMessage(hListLayers, LB_GETTEXT, lSel, (LPARAM)szLayer);
|
|
|
|
pszLayerName = szLayer;
|
|
}
|
|
|
|
//
|
|
// Determine the binary type.
|
|
//
|
|
GetBinaryType(pszFullPath, &dwBinaryType);
|
|
|
|
//
|
|
// If this is Windows 2000 and they're not using
|
|
// a predefined layer, add Win2kPropagateLayer.
|
|
//
|
|
if ((dwFlags & CFF_ADDW2KSUPPORT) && !(dwFlags & CFF_USELAYERTAB)) {
|
|
fAddW2K = TRUE;
|
|
}
|
|
|
|
//
|
|
// Build the display version of the XML.
|
|
//
|
|
if (!BuildDisplayXML(hTreeFiles,
|
|
hListShims,
|
|
pszLayerName,
|
|
pszShortName,
|
|
dwBinaryType,
|
|
fAddW2K)) {
|
|
DPF("Failed to build display XML");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Build the version of the XML that we'll use to generate the SDB.
|
|
//
|
|
if (!BuildSDBXML(hTreeFiles,
|
|
hListShims,
|
|
pszLayerName,
|
|
pszShortName,
|
|
dwBinaryType,
|
|
fAddW2K)) {
|
|
DPF("Failed to build SDB XML");
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Display the XML if the user wants to see it.
|
|
//
|
|
if (dwFlags & CFF_SHOWXML) {
|
|
DialogBoxParam(g_hInstance,
|
|
MAKEINTRESOURCE(IDD_XML),
|
|
g_hDlg,
|
|
ShowXMLDlgProc,
|
|
(LPARAM)(g_szDisplayXML));
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Create the SDB file for the user.
|
|
//
|
|
if (!(CreateSDBFile(pszShortName, pszFileCreated))) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Delete the XML file that we created.
|
|
//
|
|
StringCchCopy(szXmlFile, ARRAYSIZE(szXmlFile), pszFileCreated);
|
|
PathRenameExtension(szXmlFile, _T(".xml"));
|
|
DeleteFile(szXmlFile);
|
|
|
|
//
|
|
// Set the SHIM_FILE_LOG env var.
|
|
//
|
|
if (dwFlags & CFF_SHIMLOG) {
|
|
DeleteFile(SHIM_FILE_LOG_NAME);
|
|
SetEnvironmentVariable(_T("SHIM_FILE_LOG"), SHIM_FILE_LOG_NAME);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
CleanupSupportForApp(
|
|
TCHAR* pszShortName
|
|
)
|
|
/*++
|
|
CleanupSupportForApp
|
|
|
|
Description: Cleanup the mess after we're done with the specified app.
|
|
|
|
--*/
|
|
{
|
|
TCHAR szSDBPath[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
hr = StringCchPrintf(szSDBPath,
|
|
ARRAYSIZE(szSDBPath),
|
|
_T("%s\\AppPatch\\%s"),
|
|
g_szWinDir,
|
|
pszShortName);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[CleanupSupportForApp] 0x%08X Buffer too small", HRESULT_CODE(hr));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Attempt to delete the XML file.
|
|
//
|
|
PathRenameExtension(szSDBPath, _T(".xml"));
|
|
DeleteFile(szSDBPath);
|
|
|
|
//
|
|
// Remove the previous SDB file, if one exists.
|
|
//
|
|
// NTRAID#583475-rparsons Don't remove the SDB if the user
|
|
// installed it.
|
|
//
|
|
//
|
|
if (*g_szSDBToDelete && !g_bSDBInstalled) {
|
|
InstallSDB(g_szSDBToDelete, FALSE);
|
|
DeleteFile(g_szSDBToDelete);
|
|
}
|
|
}
|
|
|
|
void
|
|
ShowShimLog(
|
|
void
|
|
)
|
|
/*++
|
|
ShowShimLog
|
|
|
|
Description: Show the shim log file in notepad.
|
|
|
|
--*/
|
|
{
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
TCHAR szAppName[MAX_PATH];
|
|
TCHAR szCmdLine[MAX_PATH];
|
|
TCHAR szError[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
hr = StringCchPrintf(szAppName,
|
|
ARRAYSIZE(szAppName),
|
|
_T("%s\\notepad.exe"),
|
|
g_szSysDir);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[ShowShimLog] 0x%08X Buffer too small (1)", HRESULT_CODE(hr));
|
|
return;
|
|
}
|
|
|
|
hr = StringCchPrintf(szCmdLine,
|
|
ARRAYSIZE(szCmdLine),
|
|
_T("%s\\AppPatch\\")SHIM_FILE_LOG_NAME,
|
|
g_szWinDir);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[ShowShimLog] 0x%08X Buffer too small (2)", HRESULT_CODE(hr));
|
|
return;
|
|
}
|
|
|
|
if (GetFileAttributes(szCmdLine) == -1) {
|
|
LoadString(g_hInstance, IDS_NO_LOGFILE, szError, ARRAYSIZE(szError));
|
|
MessageBox(NULL, szError, g_szAppTitle, MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
hr = StringCchPrintf(szCmdLine,
|
|
ARRAYSIZE(szCmdLine),
|
|
_T("%s %s\\AppPatch\\")SHIM_FILE_LOG_NAME,
|
|
szAppName,
|
|
g_szWinDir);
|
|
|
|
if (FAILED(hr)) {
|
|
DPF("[ShowShimLog] 0x%08X Buffer too small (3)", HRESULT_CODE(hr));
|
|
return;
|
|
}
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
|
|
if (!CreateProcess(szAppName,
|
|
szCmdLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&pi)) {
|
|
|
|
DPF("[ShowShimLog] 0x%08X CreateProcess '%S %S' failed",
|
|
szAppName,
|
|
szCmdLine,
|
|
GetLastError());
|
|
return;
|
|
}
|
|
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(pi.hProcess);
|
|
}
|