windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/tools/migfiles/migfiles.c
2020-09-26 16:20:57 +08:00

1832 lines
55 KiB
C

#include "pch.h"
#include <advpub.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <tchar.h>
#include <locale.h>
#include <winnt32p.h>
#include <init9x.h>
#include <migdb.h>
#include <sysmig.h>
#include "..\..\w95upg\migapp\migdbp.h"
typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
INITROUTINE_PROTOTYPE MigUtil_Entry;
INITROUTINE_PROTOTYPE MemDb_Entry;
INITROUTINE_PROTOTYPE MigApp_Entry;
INITROUTINE_PROTOTYPE FileEnum_Entry;
HINSTANCE g_hInst;
HANDLE g_hHeap;
BOOL g_CancelFlag = FALSE;
#define ATTR_FILESIZE 0x1
#define ATTR_CHECKSUM 0x2
#define ATTR_COMPNAME 0x4
#define ATTR_FILEDESC 0x8
#define ATTR_FILEVER 0x10
#define ATTR_INTNAME 0x20
#define ATTR_LEGAL 0x40
#define ATTR_ORIGNAME 0x80
#define ATTR_PRODNAME 0x100
#define ATTR_PRODVER 0x200
#define ATTR_EXETYPE 0x400
#define ATTR_DESCR16 0x800
#ifdef DEBUG
extern BOOL g_DoLog;
#endif
extern POOLHANDLE g_MigDbPool;
extern PMIGDB_CONTEXT g_ContextList;
extern VOID *g_FileTable;
extern BOOL *g_CancelFlagPtr = &g_CancelFlag;
extern POOLHANDLE g_PathsPool;
extern PMIGDB_HOOK_PROTOTYPE g_MigDbHook;
typedef struct _PATTERN_FILE {
PCTSTR Pattern;
PMIGDB_ATTRIB PatternAttr;
struct _PATTERN_FILE *Next;
} PATTERN_FILE, *PPATTERN_FILE;
PPATTERN_FILE g_AttrPatterns = NULL;
BOOL
pScanForFile (
IN PINFCONTEXT Context,
IN DWORD FieldIndex
);
PMIGDB_ATTRIB
pLoadAttribData (
IN PCSTR MultiSzStr
);
BOOL
CallAttribute (
IN PMIGDB_ATTRIB MigDbAttrib,
IN PDBATTRIB_PARAMS AttribParams
);
BOOL
pWorkerFn (
VOID
);
BOOL
pLoadGoodFiles (
IN HINF ConfigHandle
);
BOOL
pLoadAttributes (
IN HINF ConfigHandle
);
BOOL
pLoadPatterns (
IN HINF ConfigHandle
);
BOOL
pHandleSection (
IN PCTSTR SectionName,
IN HINF ConfigHandle
);
BOOL
pWriteMemdbSection (
IN PCTSTR FileName,
IN PCTSTR MemDbCategory,
IN PCTSTR SectName,
IN BOOL WriteByValue
);
BOOL
pArrangeMigDbFile (
IN PCTSTR SrcFile,
IN PCTSTR DestFile
);
VOID
pUsage (
VOID
)
{
_tprintf (TEXT ("\nCommand line syntax:\n\n"
"migfiles [/B:BaseDir] [/T:TempDir] [/F[:SectionName]]\n\n"
"/B Specifies the base directory where all migdb files are\n"
" located. (migdb.inx, migdb.cfg)\n"
"/L Specifies full path to FILELIST.DAT\n"
"/T Specifies the temporary directory used for unpacking\n"
" cabinet files\n"
"/F Forces rescanning a particular section or all sections\n"));
}
PTSTR g_ConfigFile = NULL;
PTSTR g_TempDir = NULL;
PTSTR g_BaseDir = NULL;
PTSTR g_MessageFile= NULL;
PTSTR g_MigdbSrc = NULL;
PTSTR g_MigdbDest = NULL;
PTSTR g_MigdbDump = NULL;
PTSTR g_HistoryFile= NULL;
PTSTR g_RescanSect = NULL;
BOOL g_RescanFlag = FALSE;
extern HINF g_MigDbInf;
GROWBUFFER g_SectFiles = GROWBUF_INIT;
PTSTR g_FileListName = NULL;
#define MEMDB_CATEGORY_SECTFILES TEXT("SectFiles")
#define MEMDB_CATEGORY_GOODFILES TEXT("GoodFiles")
#define MEMDB_CATEGORY_WARNFILES TEXT("WarnFiles")
#define MEMDB_CATEGORY_DUPLFILES TEXT("DuplFiles")
#define MEMDB_CATEGORY_ACTION TEXT("Action")
#define MEMDB_CATEGORY_ATTRIBUTES TEXT("Attributes")
#define MEMDB_CATEGORY_RENAME_SRC TEXT("RenameSrc")
#define MEMDB_CATEGORY_RENAME_DEST TEXT("RenameDest")
#define MEMDB_CATEGORY_REQFILES TEXT("RequiredFiles")
void
__cdecl
main (
int argc,
CHAR *argv[]
)
{
INT argidx, index;
INT nextArg = 0;
LONG rc;
#ifdef DEBUG
g_DoLog = TRUE;
#endif
g_hInst = GetModuleHandle (NULL);
g_hHeap = GetProcessHeap();
if (!MigUtil_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
_tprintf (TEXT("MigUtil failed initializing\n"));
exit (1);
}
if (!MemDb_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
_tprintf (TEXT("MemDb failed initializing\n"));
exit(1);
}
if (!MigApp_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
_tprintf (TEXT("MigApp failed initializing\n"));
exit (1);
}
for (argidx = 1; argidx < argc; argidx++) {
if ((argv[argidx][0] != '-') &&
(argv[argidx][0] != '/')
) {
if (nextArg == 0) {
pUsage ();
exit (1);
}
switch (nextArg) {
case 1:
index = 0;
goto label1;
case 2:
index = 0;
goto label2;
case 3:
index = 0;
goto label3;
case 4:
index = 0;
goto label4;
}
}
switch (toupper(argv[argidx][1])) {
case 'B':
if (argv[argidx][2] == 0) {
nextArg = 1;
}
else {
if (argv[argidx][2] != ':') {
index = 2;
}
else {
index = 3;
}
label1:
nextArg = 0;
g_BaseDir = AllocPathString (MAX_TCHAR_PATH);
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_BaseDir, MAX_TCHAR_PATH);
#else
_tcsncpy (g_BaseDir, argv[argidx]+index, MAX_TCHAR_PATH);
#endif
}
break;
case 'T':
if (argv[argidx][2] == 0) {
nextArg = 2;
}
else {
if (argv[argidx][2] != ':') {
index = 2;
}
else {
index = 3;
}
label2:
nextArg = 0;
g_TempDir = AllocPathString (MAX_TCHAR_PATH);
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_TempDir, MAX_TCHAR_PATH);
#else
_tcsncpy (g_TempDir, argv[argidx]+index, MAX_TCHAR_PATH);
#endif
}
break;
case 'F':
g_RescanFlag = TRUE;
if (argv[argidx][2] == 0) {
nextArg = 3;
}
else {
if (argv[argidx][2] != ':') {
index = 2;
}
else {
index = 3;
}
label3:
nextArg = 0;
g_RescanSect = AllocPathString (MAX_TCHAR_PATH);
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_RescanSect, MAX_TCHAR_PATH);
#else
_tcsncpy (g_RescanSect, argv[argidx]+index, MAX_TCHAR_PATH);
#endif
}
break;
case 'L':
if (argv[argidx][2] == 0) {
nextArg = 4;
}
else {
if (argv[argidx][2] != ':') {
index = 2;
}
else {
index = 3;
}
label4:
nextArg = 0;
g_FileListName = AllocPathString (MAX_TCHAR_PATH);
#ifdef UNICODE
MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_FileListName, MAX_TCHAR_PATH);
#else
_tcsncpy (g_FileListName, argv[argidx]+index, MAX_TCHAR_PATH);
#endif
}
break;
default:
pUsage ();
exit (1);
}
}
if (g_BaseDir == NULL) {
g_BaseDir = AllocPathString (MAX_TCHAR_PATH);
_tcsncpy (g_BaseDir, TEXT(".\\"), MAX_TCHAR_PATH);
}
if (g_TempDir == NULL) {
g_TempDir = AllocPathString (MAX_TCHAR_PATH);
if (GetEnvironmentVariable (TEXT("TEMP"), g_TempDir, MAX_TCHAR_PATH) == 0) {
GetTempPath (MAX_TCHAR_PATH, g_TempDir);
}
}
g_ConfigFile = JoinPaths (g_BaseDir, TEXT("migdb.cfg"));
g_MessageFile = JoinPaths (g_BaseDir, TEXT("migdb.msg"));
g_HistoryFile = JoinPaths (g_BaseDir, TEXT("migdb.hst"));
g_MigdbSrc = JoinPaths (g_BaseDir, TEXT("migdb.inx"));
g_MigdbDest = JoinPaths (g_BaseDir, TEXT("migdb.tmp"));
g_MigdbDump = JoinPaths (g_BaseDir, TEXT("migdb.dmp"));
if (!DoesFileExist (g_FileListName)) {
_tprintf (TEXT("\nNT file list file not found. Exiting.\n"));
exit (1);
}
if (!DoesFileExist (g_MigdbSrc)) {
_tprintf (TEXT("\nSource file not found. Exiting.\n"));
exit (1);
}
if (!DoesFileExist (g_ConfigFile)) {
_tprintf (TEXT("\nConfiguration file not found. Exiting.\n"));
exit (1);
}
if (SearchPath (NULL, TEXT("extract.exe"), NULL, 0, NULL, NULL) == 0) {
_tprintf (TEXT("\nCannot find extract.exe. Exiting.\n"));
exit (1);
}
CopyFile (g_MigdbSrc, g_MigdbDest, FALSE);
DeleteFile (g_MessageFile);
DeleteFile (g_MigdbDump);
DISABLETRACKCOMMENT();
g_InAnyDir = TRUE;
_tprintf (TEXT("\nReading NT file list: %s"), g_FileListName);
if (!ReadNtFilesEx (g_FileListName, FALSE)) {
rc = GetLastError();
printf ("Could not read %s. Win32 Error Code: %x\n", g_FileListName, rc);
exit (1);
}
_tprintf (TEXT("\nReading configuration files..."));
if (!InitMigDbEx (g_MigdbSrc)) {
rc = GetLastError();
printf ("Could not read %s. Win32 Error Code: %x\n", g_MigdbSrc, rc);
exit (1);
}
DEBUGMSG ((DBG_ERROR , "TEST"));
DEBUGMSG ((DBG_WHOOPS, "TEST"));
pWorkerFn ();
if (g_MigDbInf != INVALID_HANDLE_VALUE) {
SetupCloseInfFile (g_MigDbInf);
}
pWriteMemdbSection (g_MessageFile, MEMDB_CATEGORY_GOODFILES, TEXT("KNOWN GOOD - FILES FOUND"), FALSE);
pWriteMemdbSection (g_MessageFile, MEMDB_CATEGORY_WARNFILES, TEXT("KNOWN GOOD - NAME COLLISIONS"), FALSE);
pWriteMemdbSection (g_MessageFile, MEMDB_CATEGORY_DUPLFILES, TEXT("DUPLICATE FILES"), FALSE);
// we need now to arrange a little bit the MIGDB.INX file
pArrangeMigDbFile (g_MigdbDest, g_MigdbSrc);
DeleteFile (g_MigdbDest);
if (g_FileTable != NULL) {
HtFree (g_FileTable);
}
if (g_MigDbPool != NULL) {
PoolMemDestroyPool (g_MigDbPool);
}
FreePathString (g_ConfigFile);
FreePathString (g_TempDir);
FreePathString (g_BaseDir);
FreePathString (g_MessageFile);
FreePathString (g_MigdbSrc);
FreePathString (g_MigdbDest);
FreePathString (g_MigdbDump);
FreePathString (g_HistoryFile);
g_InAnyDir = FALSE;
ENABLETRACKCOMMENT();
if (!MigApp_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
_tprintf (TEXT("MigApp failed initializing\n"));
exit(1);
}
if (!MemDb_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
_tprintf (TEXT("MemDb failed initializing\n"));
exit(1);
}
if (!MigUtil_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
_tprintf (TEXT("MigUtil failed initializing\n"));
exit (1);
}
}
UINT CALLBACK
pCabinetCallback (
IN PVOID Context, //context used by the callback routine
IN UINT Notification, //notification sent to callback routine
IN UINT Param1, //additional notification information
IN UINT Param2 //additional notification information );
)
{
PCTSTR tempDir = Context;
PCTSTR fileName = (PCTSTR)Param2 ;
PFILE_IN_CABINET_INFO fileInfo = (PFILE_IN_CABINET_INFO)Param1;
PCTSTR fromPtr, toPtr;
TCHAR tempStr [MEMDB_MAX];
if (Notification == SPFILENOTIFY_FILEINCABINET) {
if (toPtr = _tcschr (fileInfo->NameInCabinet, TEXT('\\'))) {
_tcscpy (fileInfo->FullTargetName, tempDir);
fromPtr = fileInfo->NameInCabinet;
while (toPtr) {
StringCopyAB (tempStr, fromPtr, toPtr);
_tcscat (fileInfo->FullTargetName, TEXT("\\"));
_tcscat (fileInfo->FullTargetName, tempStr);
CreateDirectory (fileInfo->FullTargetName, NULL);
toPtr = _tcsinc (toPtr);
fromPtr = toPtr;
toPtr = _tcschr (toPtr, TEXT('\\'));
}
}
_stprintf (fileInfo->FullTargetName, TEXT("%s\\%s"), tempDir, fileInfo->NameInCabinet);
return FILEOP_DOIT;
}
return NO_ERROR;
}
BOOL
pWorkerFn (
VOID
)
{
HINF configHandle = INVALID_HANDLE_VALUE;
INFCONTEXT context;
TCHAR fileName [MAX_TCHAR_PATH] = "";
TCHAR sectName [MAX_TCHAR_PATH];
PTSTR dontCare;
configHandle = SetupOpenInfFile (g_ConfigFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
if (configHandle == INVALID_HANDLE_VALUE) {
SearchPath (NULL, g_ConfigFile, NULL, MAX_TCHAR_PATH, fileName, &dontCare);
configHandle = SetupOpenInfFile (fileName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
if (configHandle == INVALID_HANDLE_VALUE) {
_tprintf (TEXT("\nCannot open configuration file %s. Exiting.\n"), g_ConfigFile);
return FALSE;
}
}
g_ContextList = (PMIGDB_CONTEXT) PoolMemGetMemory (g_MigDbPool, sizeof (MIGDB_CONTEXT));
if (g_ContextList == NULL) {
DEBUGMSG ((DBG_ERROR, "Unable to create empty context"));
return FALSE;
}
ZeroMemory (g_ContextList, sizeof (MIGDB_CONTEXT));
if (!pLoadGoodFiles (configHandle)) {
_tprintf (TEXT("\nUnable to load good files section. Exiting.\n"));
return FALSE;
}
if (!pLoadAttributes (configHandle)) {
_tprintf (TEXT("\nUnable to load attributes section.\n"));
}
if (!pLoadPatterns (configHandle)) {
_tprintf (TEXT("\nUnable to load patterns section.\n"));
}
else {
_tprintf (TEXT("done\n\n"));
}
if (SetupFindFirstLine (configHandle, TEXT("sections"), NULL, &context)) {
do {
if (!SetupGetStringField (&context, 1, sectName, MAX_TCHAR_PATH, NULL)) {
_tprintf (TEXT("\nBad section [SECTIONS] in %s. Exiting.\n"), g_ConfigFile);
return FALSE;
}
if (!pHandleSection (sectName, configHandle)) {
return FALSE;
}
}
while (SetupFindNextLine (&context, &context));
}
return TRUE;
}
BOOL
pLoadGoodFiles (
IN HINF ConfigHandle
)
{
INFCONTEXT context;
if (SetupFindFirstLine (ConfigHandle, TEXT("good files"), NULL, &context)) {
do {
if (!pScanForFile (&context, 1)) {
DEBUGMSG ((DBG_WARNING, "Scan for file failed:%d", GetLastError()));
return FALSE;
}
}
while (SetupFindNextLine (&context, &context));
}
return TRUE;
}
BOOL
pLoadAttributes (
IN HINF ConfigHandle
)
{
TCHAR fileName [MEMDB_MAX];
TCHAR attribStr [MEMDB_MAX];
PCTSTR currAttr;
DWORD attributes;
DWORD dontCare;
INFCONTEXT context;
if (SetupFindFirstLine (ConfigHandle, TEXT("Attributes"), NULL, &context)) {
do {
if (SetupGetStringField (&context, 1, fileName, MAX_TCHAR_PATH, NULL)) {
if (!SetupGetStringField (&context, 2, attribStr, MAX_TCHAR_PATH, NULL)) {
attribStr [0] = 0;
}
currAttr = attribStr;
attributes = 0;
while (*currAttr) {
switch (toupper(*currAttr)) {
case 'S':
attributes |= ATTR_FILESIZE;
break;
case 'C':
attributes |= ATTR_CHECKSUM;
break;
case 'N':
attributes |= ATTR_COMPNAME;
break;
case 'F':
attributes |= ATTR_FILEDESC;
break;
case 'V':
attributes |= ATTR_FILEVER;
break;
case 'I':
attributes |= ATTR_INTNAME;
break;
case 'L':
attributes |= ATTR_LEGAL;
break;
case 'O':
attributes |= ATTR_ORIGNAME;
break;
case 'P':
attributes |= ATTR_PRODNAME;
break;
case 'E':
attributes |= ATTR_PRODVER;
break;
case 'T':
attributes |= ATTR_EXETYPE;
break;
case 'D':
attributes |= ATTR_DESCR16;
break;
default:
_tprintf (TEXT("\nInvalid attributes:%s\n"), currAttr);
}
currAttr = _tcsinc (currAttr);
}
MemDbSetValueEx (
MEMDB_CATEGORY_ATTRIBUTES,
fileName,
NULL,
NULL,
attributes,
&dontCare
);
}
}
while (SetupFindNextLine (&context, &context));
}
return TRUE;
}
BOOL
pLoadPatterns (
IN HINF ConfigHandle
)
{
TCHAR patternFile [MEMDB_MAX];
TCHAR patternStr [MEMDB_MAX];
INFCONTEXT context;
PPATTERN_FILE fileStruct;
if (SetupFindFirstLine (ConfigHandle, TEXT("Patterns"), NULL, &context)) {
do {
if (SetupGetStringField (&context, 1, patternFile, MAX_TCHAR_PATH, NULL) &&
SetupGetMultiSzField (&context, 2, patternStr, MAX_TCHAR_PATH, NULL)
) {
fileStruct = (PPATTERN_FILE) PoolMemGetMemory (g_MigDbPool, sizeof (PATTERN_FILE));
fileStruct->Pattern = PoolMemDuplicateString (g_MigDbPool, patternFile);
fileStruct->PatternAttr = pLoadAttribData (patternStr);
fileStruct->Next = g_AttrPatterns;
g_AttrPatterns = fileStruct;
}
}
while (SetupFindNextLine (&context, &context));
}
return TRUE;
}
BOOL
pDeleteAllFiles (
IN PCTSTR DirPath
)
{
TREE_ENUM e;
BOOL dirsFirst = FALSE;
if (EnumFirstFileInTree (&e, DirPath, TEXT("*"), dirsFirst)) {
do {
if (e.Directory) {
pDeleteAllFiles (e.FullPath);
SetFileAttributes (e.FullPath, FILE_ATTRIBUTE_NORMAL);
RemoveDirectory (e.FullPath);
}
else {
SetFileAttributes (e.FullPath, FILE_ATTRIBUTE_NORMAL);
DeleteFile (e.FullPath);
}
} while (EnumNextFileInTree (&e));
}
return TRUE;
}
BOOL
pSelected (
IN PCTSTR FileName
)
{
MULTISZ_ENUM patternEnum;
if (EnumFirstMultiSz (&patternEnum, g_SectFiles.Buf)) {
do {
if (IsPatternMatch (patternEnum.CurrentString, FileName)) {
return TRUE;
}
}
while (EnumNextMultiSz (&patternEnum));
}
return FALSE;
}
BOOL
pSpecialSelected (
IN PCTSTR FileName,
OUT PTSTR NewName
)
{
MULTISZ_ENUM patternEnum;
PTSTR endPtr, endPtr1;
TCHAR savedVal;
if (EnumFirstMultiSz (&patternEnum, g_SectFiles.Buf)) {
do {
endPtr = _tcsdec (patternEnum.CurrentString, GetEndOfString (patternEnum.CurrentString));
savedVal = *endPtr;
*endPtr = TEXT('_');
if (IsPatternMatch (patternEnum.CurrentString, FileName)) {
StringCopy (NewName, FileName);
endPtr1 = _tcsdec (NewName, GetEndOfString (NewName));
*endPtr1 = savedVal;
*endPtr = savedVal;
return TRUE;
}
*endPtr = savedVal;
}
while (EnumNextMultiSz (&patternEnum));
}
StringCopy (NewName, FileName);
endPtr = _tcsdec (NewName, GetEndOfString (NewName));
*endPtr = TEXT('-');
return FALSE;
}
DWORD g_DirSequencer = 0;
DWORD g_FileSequencer = 0;
BOOL
pCabinetFile (
IN PCTSTR FileName
)
{
PCTSTR extPtr;
extPtr = GetFileExtensionFromPath (FileName);
if ((extPtr != NULL) &&
StringIMatch (extPtr, TEXT("CAB"))
) {
return TRUE;
}
return FALSE;
}
#define ATTR_FILESIZE 0x1
#define ATTR_CHECKSUM 0x2
#define ATTR_COMPNAME 0x4
#define ATTR_FILEDESC 0x8
#define ATTR_FILEVER 0x10
#define ATTR_INTNAME 0x20
#define ATTR_LEGAL 0x40
#define ATTR_ORIGNAME 0x80
#define ATTR_PRODNAME 0x100
#define ATTR_PRODVER 0x200
#define ATTR_EXETYPE 0x400
#define ATTR_DESCR16 0x800
typedef struct _VERSION_DATA {
PCSTR versionValue;
PCSTR versionName;
DWORD attrib;
} VERSION_DATA, *PVERSION_DATA;
VERSION_DATA verData [] = {{NULL, "COMPANYNAME", ATTR_COMPNAME},
{NULL, "FILEDESCRIPTION", ATTR_FILEDESC},
{NULL, "FILEVERSION", ATTR_FILEVER},
{NULL, "INTERNALNAME", ATTR_INTNAME},
{NULL, "LEGALCOPYRIGHT", ATTR_LEGAL},
{NULL, "ORIGINALFILENAME", ATTR_ORIGNAME},
{NULL, "PRODUCTNAME", ATTR_PRODNAME},
{NULL, "PRODUCTVERSION", ATTR_PRODVER},
{NULL, NULL, 0}};
extern PSTR g_ExeTypes[4];
BOOL
pCheckForPattern (
IN PCTSTR FileName,
PFILE_HELPER_PARAMS Params,
OUT PTSTR FileAttr,
IN OUT PGROWBUFFER AttrList
)
{
PPATTERN_FILE patternFile;
PMIGDB_ATTRIB migDbAttrib;
DBATTRIB_PARAMS attribParams;
BOOL fileSelected;
BOOL found;
TCHAR temp [MEMDB_MAX];
MULTISZ_ENUMA multiSzEnum;
BOOL first;
patternFile = g_AttrPatterns;
found = FALSE;
while (patternFile) {
if (IsPatternMatch (patternFile->Pattern, FileName)) {
fileSelected = TRUE;
migDbAttrib = patternFile->PatternAttr;
while (migDbAttrib) {
attribParams.FileParams = Params;
attribParams.ExtraData = NULL;
if (!CallAttribute (migDbAttrib, &attribParams)) {
fileSelected = FALSE;
break;
}
migDbAttrib = migDbAttrib->Next;
}
if (fileSelected) {
found = TRUE;
break;
}
}
patternFile = patternFile->Next;
}
if (found) {
migDbAttrib = patternFile->PatternAttr;
while (migDbAttrib) {
_tcscpy (temp, MigDb_GetAttributeName (migDbAttrib->AttribIndex));
first = TRUE;
if (EnumFirstMultiSz (&multiSzEnum, migDbAttrib->Arguments)) {
_tcscat (temp, TEXT("("));
do {
if (!first) {
_tcscat (FileAttr, TEXT(","));
_tcscat (FileAttr, temp);
if (AttrList) {
MultiSzAppend (AttrList, temp);
}
*temp = 0;
}
first = FALSE;
_tcscat (temp, TEXT("\""));
_tcscat (temp, multiSzEnum.CurrentString);
_tcscat (temp, TEXT("\""));
}
while (EnumNextMultiSz (&multiSzEnum));
_tcscat (temp, TEXT(")"));
}
_tcscat (FileAttr, TEXT(","));
_tcscat (FileAttr, temp);
if (AttrList) {
MultiSzAppend (AttrList, temp);
}
migDbAttrib = migDbAttrib->Next;
}
return TRUE;
}
return FALSE;
}
PSTR
MyQueryVersionEntry (
IN PCSTR FileName,
IN PCSTR VersionEntry
)
{
VERSION_STRUCTW Version;
PCWSTR CurrentStr;
PSTR ConvCurrentStr = NULL;
PSTR result = NULL;
PCWSTR ConvFileName = NULL;
PCWSTR ConvVerEntry = NULL;
MYASSERT (VersionEntry);
ConvFileName = ConvertAtoW (FileName);
ConvVerEntry = ConvertAtoW (VersionEntry);
if (CreateVersionStructW (&Version, ConvFileName)) {
__try {
CurrentStr = EnumFirstVersionValueW (&Version, ConvVerEntry);
if (CurrentStr) {
CurrentStr = SkipSpaceW (CurrentStr);
ConvCurrentStr = UnicodeToCcs (CurrentStr);
TruncateTrailingSpace ((PSTR) ConvCurrentStr);
result = ConvCurrentStr;
}
else {
__leave;
}
}
__finally {
DestroyVersionStructW (&Version);
}
}
if (ConvVerEntry) {
FreeConvertedStr (ConvVerEntry);
}
if (ConvFileName) {
FreeConvertedStr (ConvFileName);
}
return result;
}
BOOL
pPrintLine (
IN PTREE_ENUM e,
OUT PTSTR FileAttr,
IN OUT PGROWBUFFER AttrList
)
{
FILE_HELPER_PARAMS Params;
UINT checkSum;
DWORD exeType;
PCSTR fileDesc16;
INT numAttribs;
DWORD listedAttr;
TCHAR ekey [MEMDB_MAX];
TCHAR temp [MEMDB_MAX];
PVERSION_DATA p;
Params.Handled = 0;
Params.FullFileSpec = e->FullPath;
_tcsncpy (Params.DirSpec, e->RootPath, MAX_TCHAR_PATH);
Params.IsDirectory = FALSE;
Params.Extension = GetFileExtensionFromPath (e->Name);
Params.FindData = e->FindData;
Params.VirtualFile = FALSE;
Params.CurrentDirData = NULL;
FileAttr [0] = 0;
if (!StringIMatch (e->Name, TEXT("kernel32.dll"))) {
if (pCheckForPattern (e->Name, &Params, FileAttr, AttrList)) {
return TRUE;
}
}
numAttribs = 0;
MemDbBuildKey (ekey, MEMDB_CATEGORY_ATTRIBUTES, e->Name, NULL, NULL);
if (!MemDbGetPatternValue (ekey, &listedAttr)) {
listedAttr = ATTR_COMPNAME | ATTR_PRODVER;
}
if (listedAttr & ATTR_FILESIZE) {
_stprintf (
temp,
TEXT(",FILESIZE(0x%08lX)"),
e->FindData->nFileSizeLow);
_tcscat (FileAttr, temp);
if (AttrList) {
_stprintf (
temp,
TEXT("FILESIZE(0x%08lX)"),
e->FindData->nFileSizeLow);
MultiSzAppend (AttrList, temp);
}
numAttribs ++;
}
if (listedAttr & ATTR_CHECKSUM) {
checkSum = ComputeCheckSum (&Params);
_stprintf (
temp,
TEXT(",CHECKSUM(0x%08lX)"),
checkSum);
_tcscat (FileAttr, temp);
if (AttrList) {
_stprintf (
temp,
TEXT("CHECKSUM(0x%08lX)"),
checkSum);
MultiSzAppend (AttrList, temp);
}
numAttribs ++;
}
if (listedAttr & ATTR_EXETYPE) {
exeType = GetModuleType (e->FullPath);
_stprintf (
temp,
TEXT(",EXETYPE(\"%s\")"),
g_ExeTypes[exeType]);
_tcscat (FileAttr, temp);
if (AttrList) {
_stprintf (
temp,
TEXT("EXETYPE(%s)"),
g_ExeTypes[exeType]);
MultiSzAppend (AttrList, temp);
}
numAttribs ++;
}
if (listedAttr & ATTR_DESCR16) {
fileDesc16 = Get16ModuleDescription (e->FullPath);
if (fileDesc16 != NULL) {
_stprintf (
temp,
TEXT(",DESCRIPTION(\"%s\")"),
fileDesc16);
_tcscat (FileAttr, temp);
if (AttrList) {
_stprintf (
temp,
TEXT("DESCRIPTION(%s)"),
fileDesc16);
MultiSzAppend (AttrList, temp);
}
numAttribs ++;
FreePathString (fileDesc16);
}
}
p = verData;
while (p->versionName) {
if (listedAttr & p->attrib) {
p->versionValue = MyQueryVersionEntry (e->FullPath, p->versionName);
}
p++;
}
p = verData;
while (p->versionName) {
if ((listedAttr & p->attrib) && (p->versionValue)) {
_stprintf (
temp,
TEXT(",%s(\"%s\")"),
p->versionName,
p->versionValue);
_tcscat (FileAttr, temp);
if (AttrList) {
_stprintf (
temp,
TEXT("%s(%s)"),
p->versionName,
p->versionValue);
MultiSzAppend (AttrList, temp);
}
FreePathString (p->versionValue);
numAttribs ++;
}
p++;
}
if (numAttribs == 0) {
checkSum = ComputeCheckSum (&Params);
_stprintf (
temp,
TEXT(",FC(%ld,%lX)"),
e->FindData->nFileSizeLow,
checkSum
);
_tcscat (FileAttr, temp);
if (AttrList) {
_stprintf (
temp,
TEXT("FC(%ld"),
e->FindData->nFileSizeLow
);
MultiSzAppend (AttrList, temp);
_stprintf (
temp,
TEXT("%lX)"),
checkSum
);
MultiSzAppend (AttrList, temp);
}
}
return TRUE;
}
BOOL
pHandleAppFile (
IN PTREE_ENUM e,
IN PCTSTR Action,
IN PCTSTR Section,
IN PCTSTR Message,
IN PCTSTR SrcPath
)
{
TCHAR msgStr [MEMDB_MAX] = "";
FILE_HELPER_PARAMS Params;
TCHAR line [MEMDB_MAX];
TCHAR key [MEMDB_MAX] = "";
DWORD offset;
Params.Handled = 0;
Params.FullFileSpec = e->FullPath;
_tcsncpy (Params.DirSpec, SrcPath, MAX_TCHAR_PATH);
Params.IsDirectory = FALSE;
Params.Extension = GetFileExtensionFromPath (e->Name);
Params.FindData = e->FindData;
Params.VirtualFile = FALSE;
Params.CurrentDirData = NULL;
pPrintLine (e, line, NULL);
MemDbBuildKey (key, MEMDB_CATEGORY_RENAME_SRC, e->Name, NULL, NULL);
if (MemDbGetValue (key, &offset)) {
if (!MemDbBuildKeyFromOffset (offset, key, 1, NULL)) {
*key = 0;
}
} else {
*key = 0;
}
_stprintf (
msgStr,
TEXT("%s\\%s%s)"),
MEMDB_CATEGORY_SECTFILES,
*key?key:e->Name,
line);
MemDbSetValue (msgStr, 0);
return TRUE;
}
BOOL
pHandleSysFile (
IN PTREE_ENUM e,
IN PCTSTR Action,
IN PCTSTR Section,
IN PCTSTR Message,
IN PCTSTR SrcPath
)
{
TCHAR msgStr [MEMDB_MAX] = "";
FILE_HELPER_PARAMS Params;
HASHITEM stringId;
PMIGDB_FILE migDbFile;
FILE_LIST_STRUCT fileList;
PMIGDB_ATTRIB migDbAttrib;
DBATTRIB_PARAMS attribParams;
BOOL fileSelected = FALSE;
PCTSTR actionTmp;
TCHAR line [MEMDB_MAX];
TCHAR key [MEMDB_MAX] = "";
DWORD offset;
GROWBUFFER attrList = GROWBUF_INIT;
// this is not a cabinet file, let's do something with it.
Params.Handled = 0;
Params.FullFileSpec = e->FullPath;
_tcsncpy (Params.DirSpec, SrcPath, MAX_TCHAR_PATH);
Params.IsDirectory = FALSE;
Params.Extension = GetFileExtensionFromPath (e->Name);
Params.FindData = e->FindData;
Params.VirtualFile = FALSE;
Params.CurrentDirData = NULL;
pPrintLine (e, line, &attrList);
if (StringIMatch (e->Name, TEXT("kernel32.dll"))) {
_stprintf (
msgStr,
TEXT("%s\\%s%s"),
MEMDB_CATEGORY_REQFILES,
e->Name,
line);
MemDbSetValue (msgStr, fileSelected);
};
// first check if this file is in "known good" list or is already listed in migdb.inx
// with same action
stringId = HtFindString (g_FileTable, e->Name);
if (stringId) {
//The string table has extra data (a pointer to a FILE_LIST_STRUCT node)
HtCopyStringData (g_FileTable, stringId, &fileList);
migDbFile = fileList.First;
while (migDbFile) {
//check all attributes for this file
migDbAttrib = migDbFile->Attributes;
fileSelected = TRUE;
while (migDbAttrib != NULL) {
attribParams.FileParams = &Params;
attribParams.ExtraData = NULL;
if (!CallAttribute (migDbAttrib, &attribParams)) {
fileSelected = FALSE;
break;
}
migDbAttrib = migDbAttrib->Next;
}
if ((!fileSelected) &&
(migDbFile->Section == NULL)
) {
// there was a name collision with a "known good" file. We will send a message
_stprintf (msgStr, TEXT("%s\\%s"), MEMDB_CATEGORY_WARNFILES, e->Name);
MemDbSetValue (msgStr, 0);
}
if ((fileSelected) &&
(migDbFile->Section == NULL)
) {
// this file is "known good". We will send a message
_stprintf (msgStr, TEXT("%s\\%s"), MEMDB_CATEGORY_GOODFILES, e->Name);
MemDbSetValue (msgStr, 0);
break;
}
if ((fileSelected) && (!StringIMatch (Section, migDbFile->Section->Context->SectName))){
actionTmp = MigDb_GetActionName (migDbFile->Section->Context->ActionIndex);
if ((actionTmp != NULL) && StringIMatch (actionTmp, Action)) {
// this file was already listed in migdb.inx with the same action
_stprintf (
msgStr,
TEXT("%s\\%s\\%-14s%s"),
MEMDB_CATEGORY_DUPLFILES,
Action,
e->Name,
line);
MemDbSetValue (msgStr, 0);
break;
}
}
fileSelected = FALSE;
migDbFile = migDbFile->Next;
}
}
if (!fileSelected) {
// one more check. If this file is in FILELIST.DAT (but not in the EXCEPTED section)
// and COMPANYNAME attribute has Microsoft somewhere inside we'll put it in a different
// place
MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, e->Name, NULL, NULL);
if (MemDbGetValue (key, NULL)) {
MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES_EXCEPT, e->Name, NULL, NULL);
if (!MemDbGetValue (key, NULL)) {
if (GlobalVersionCheck (e->FullPath, "COMPANYNAME", "*MICROSOFT*")) {
fileSelected = TRUE;
}
}
}
// this file is not in the list or attributes do not match
// we will add in incompatibility list.
//creating MIGDB_FILE structure for current file
migDbFile = (PMIGDB_FILE) PoolMemGetMemory (g_MigDbPool, sizeof (MIGDB_FILE));
if (migDbFile != NULL) {
ZeroMemory (migDbFile, sizeof (MIGDB_FILE));
migDbFile->Section = g_ContextList->Sections;
migDbFile->Attributes = pLoadAttribData (attrList.Buf);
if (g_MigDbHook != NULL) {
migDbAttrib = migDbFile->Attributes;
while (migDbAttrib) {
g_MigDbHook (e->Name, g_ContextList, g_ContextList->Sections, migDbFile, migDbAttrib);
migDbAttrib = migDbAttrib->Next;
}
}
//adding this file into string table and create a MIGDB_FILE node. If file
//already exists in string table then just create another MIGDB_FILE node
//chained with already existing ones.
stringId = HtFindString (g_FileTable, e->Name);
if (stringId) {
HtCopyStringData (g_FileTable, stringId, &fileList);
fileList.Last->Next = migDbFile;
fileList.Last = migDbFile;
HtSetStringData (g_FileTable, stringId, &fileList);
}
else {
fileList.First = fileList.Last = migDbFile;
HtAddStringAndData (g_FileTable, e->Name, &fileList);
}
}
else {
DEBUGMSG ((DBG_ERROR, "Unable to allocate file node for %s", e->Name));
}
MemDbBuildKey (key, MEMDB_CATEGORY_RENAME_SRC, e->Name, NULL, NULL);
if (MemDbGetValue (key, &offset)) {
if (!MemDbBuildKeyFromOffset (offset, key, 1, NULL)) {
*key = 0;
}
} else {
*key = 0;
}
_stprintf (
msgStr,
TEXT("%s\\%s%s"),
MEMDB_CATEGORY_SECTFILES,
*key?key:e->Name,
line);
MemDbSetValue (msgStr, fileSelected);
}
FreeGrowBuffer (&attrList);
return TRUE;
}
BOOL
pCompressedFile (
IN PTREE_ENUM e
)
{
PCTSTR extPtr;
extPtr = GetFileExtensionFromPath (e->FullPath);
if (extPtr == NULL) {
return FALSE;
}
if (_tcslen (extPtr) != 3) {
return FALSE;
}
return (extPtr [2] == TEXT('_'));
}
BOOL
pExeFile (
IN PTREE_ENUM e
)
{
PCTSTR extPtr;
extPtr = GetFileExtensionFromPath (e->FullPath);
if ((extPtr != NULL) &&
(StringIMatch (extPtr, TEXT("EXE")))
) {
return TRUE;
}
return FALSE;
}
BOOL
pCopyAndHandleCabResource (
IN PVOID Source,
IN DWORD Size,
IN PCTSTR DirName
)
{
TCHAR cabDir [MAX_TCHAR_PATH] = "";
HANDLE hFile;
DWORD dontCare;
if (Size < 4) {
return TRUE;
}
if (*((PDWORD)Source) != 0x4643534D) {
return TRUE;
}
g_FileSequencer ++;
_stprintf (cabDir, TEXT("%s\\MIGDB%03u.CAB"), DirName, g_FileSequencer);
hFile = CreateFile (cabDir, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
DEBUGMSG ((DBG_ERROR, "Cannot create file %s", cabDir));
return FALSE;
}
if (!WriteFile (hFile, Source, Size, &dontCare, NULL)) {
DEBUGMSG ((DBG_ERROR, "Cannot write to file %s", cabDir));
return FALSE;
}
CloseHandle (hFile);
return TRUE;
}
BOOL CALLBACK
EnumResNameProc (
IN HANDLE hModule, // module handle
IN LPCTSTR lpszType, // pointer to resource type
IN LPTSTR lpszName, // pointer to resource name
IN LONG lParam // application-defined parameter
)
{
HRSRC hResource;
DWORD size;
HGLOBAL hGlobal;
PVOID srcBytes;
hResource = FindResource (hModule, lpszName, lpszType);
if (hResource) {
size = SizeofResource (hModule, hResource);
if (size) {
hGlobal = LoadResource (hModule, hResource);
if (hGlobal) {
srcBytes = LockResource (hGlobal);
if (srcBytes) {
pCopyAndHandleCabResource (srcBytes, size, (PCTSTR)lParam);
}
}
}
}
return TRUE;
}
BOOL CALLBACK
EnumResTypeProc (
IN HANDLE hModule, // resource-module handle
IN LPTSTR lpszType, // pointer to resource type
IN LONG lParam // application-defined parameter
)
{
if ((lpszType != RT_ACCELERATOR ) &&
(lpszType != RT_ANICURSOR ) &&
(lpszType != RT_ANIICON ) &&
(lpszType != RT_BITMAP ) &&
(lpszType != RT_CURSOR ) &&
(lpszType != RT_DIALOG ) &&
(lpszType != RT_FONT ) &&
(lpszType != RT_FONTDIR ) &&
(lpszType != RT_GROUP_CURSOR ) &&
(lpszType != RT_GROUP_ICON ) &&
(lpszType != RT_HTML ) &&
(lpszType != RT_ICON ) &&
(lpszType != RT_MENU ) &&
(lpszType != RT_MESSAGETABLE ) &&
(lpszType != RT_PLUGPLAY ) &&
(lpszType != RT_STRING ) &&
(lpszType != RT_VERSION ) &&
(lpszType != RT_VXD ) &&
(lpszType != RT_HTML )
) {
// we found an unknown type. Let's enumerate all resources of this type
if (EnumResourceNames (hModule, lpszType, EnumResNameProc, lParam) == 0) {
DEBUGMSG ((DBG_ERROR, "Error enumerating names:%ld", GetLastError ()));
}
}
return TRUE;
}
BOOL
pHandleAllFiles (
IN BOOL AppMode,
IN PCTSTR Action,
IN PCTSTR Section,
IN PCTSTR Message,
IN PCTSTR SrcPath
)
{
TCHAR tempDir [MAX_TCHAR_PATH] = "";
TCHAR cmdLine [MAX_TCHAR_PATH] = "";
TCHAR newName [MAX_TCHAR_PATH] = "";
TREE_ENUM e;
DWORD error;
HMODULE exeModule;
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
if (EnumFirstFileInTree (&e, SrcPath, TEXT("*"), FALSE)) {
do {
if (!e.Directory) {
if (pCabinetFile (e.Name)) {
if ((AppMode) ||
(!pSelected (e.Name))
) {
// cabinet file
g_DirSequencer++;
_stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer);
if (CreateDirectory (tempDir, NULL) == 0) {
error = GetLastError ();
if (error == ERROR_ALREADY_EXISTS) {
pDeleteAllFiles (tempDir);
}
ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir));
}
_tprintf (TEXT(" Extracting cabinet file ... %s"), e.Name);
// we need to expand the cabinet file
SetLastError (0);
if (!SetupIterateCabinet (e.FullPath, 0, pCabinetCallback, tempDir)) {
_tprintf (TEXT("...error %ld\n"), GetLastError());
DEBUGMSG((DBG_ERROR, "Could not iterate cabinet file:%s\nError:%ld", e.FullPath, GetLastError ()));
}
else {
_tprintf (TEXT("...done\n"));
}
if (!pHandleAllFiles (AppMode, Action, Section, Message, tempDir)) {
return FALSE;
}
pDeleteAllFiles (tempDir);
RemoveDirectory (tempDir);
g_DirSequencer--;
}
}
else if (pCompressedFile (&e)) {
if (AppMode) {
if (!pSpecialSelected (e.Name, newName)) {
continue;
}
}
else {
if (pSpecialSelected (e.Name, newName)) {
continue;
}
}
// compressed file
g_DirSequencer++;
_stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer);
if (CreateDirectory (tempDir, NULL) == 0) {
error = GetLastError ();
if (error == ERROR_ALREADY_EXISTS) {
pDeleteAllFiles (tempDir);
}
ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir));
}
_stprintf (cmdLine, TEXT("expand /r %s %s"), e.FullPath, tempDir);
ZeroMemory (&startupInfo, sizeof (STARTUPINFO));
startupInfo.cb = sizeof (STARTUPINFO);
if (CreateProcess (NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo)) {
WaitForSingleObject (processInfo.hProcess, INFINITE);
CloseHandle (processInfo.hProcess);
CloseHandle (processInfo.hThread);
if (!pHandleAllFiles (AppMode, Action, Section, Message, tempDir)) {
return FALSE;
}
pDeleteAllFiles (tempDir);
}
else {
DEBUGMSG ((DBG_ERROR, "Could not decompress:%s, Error:%ld", e.Name, GetLastError()));
}
RemoveDirectory (tempDir);
g_DirSequencer--;
}
else {
if (pExeFile (&e)) {
g_FileSequencer = 0;
g_DirSequencer++;
_stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer);
if (CreateDirectory (tempDir, NULL) == 0) {
error = GetLastError ();
if (error == ERROR_ALREADY_EXISTS) {
pDeleteAllFiles (tempDir);
}
ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir));
}
exeModule = LoadLibraryEx (e.FullPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
EnumResourceTypes (exeModule, EnumResTypeProc, (LONG)tempDir);
FreeLibrary (exeModule);
if (!pHandleAllFiles (AppMode, Action, Section, Message, tempDir)) {
return FALSE;
}
pDeleteAllFiles (tempDir);
RemoveDirectory (tempDir);
g_DirSequencer--;
}
if (AppMode) {
if (pSelected (e.Name)) {
if (!pHandleAppFile (&e, Action, Section, Message, SrcPath)) {
return FALSE;
}
}
}
else {
if (!pSelected (e.Name)) {
if (!pHandleSysFile (&e, Action, Section, Message, SrcPath)) {
return FALSE;
}
}
}
}
}
} while (EnumNextFileInTree (&e));
}
return TRUE;
}
BOOL
pHandleSection (
IN PCTSTR SectionName,
IN HINF ConfigHandle
)
{
PMIGDB_CONTEXT migDbContext = NULL;
INFCONTEXT context;
TCHAR action [MAX_TCHAR_PATH] = "";
TCHAR section [MAX_TCHAR_PATH] = "";
TCHAR message [MAX_TCHAR_PATH] = "";
TCHAR srcPath [MAX_TCHAR_PATH] = "";
TCHAR msgStr [MAX_TCHAR_PATH] = "";
TCHAR sectTmp [MAX_TCHAR_PATH] = "";
TCHAR renSect [MAX_TCHAR_PATH] = "";
TCHAR srcFile [MAX_TCHAR_PATH] = "";
TCHAR destFile[MAX_TCHAR_PATH] = "";
BOOL forced = FALSE;
INT field;
TCHAR excludePattern [MAX_TCHAR_PATH] = "";
BOOL appMode = FALSE;
TCHAR sectPatterns [MAX_TCHAR_PATH] = "";
DWORD offset;
_tprintf (TEXT("Processing section : %s ... "), SectionName);
if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("action"), &context)) {
_tprintf (TEXT("\nCannot find Action= line in %s.\n"), SectionName);
return FALSE;
}
if (!SetupGetStringField (&context, 1, action, MAX_TCHAR_PATH, NULL)) {
_tprintf (TEXT("\nCannot read action name in %s.\n"), SectionName);
return FALSE;
}
if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("section"), &context)) {
_tprintf (TEXT("\nCannot find Section= line in %s.\n"), SectionName);
return FALSE;
}
if (!SetupGetStringField (&context, 1, section, MAX_TCHAR_PATH, NULL)) {
_tprintf (TEXT("\nCannot read section name in %s.\n"), SectionName);
return FALSE;
}
if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("sourcepath"), &context)) {
_tprintf (TEXT("\nCannot find SourcePath= line in %s.\n"), SectionName);
return FALSE;
}
if (!SetupGetStringField (&context, 1, srcPath, MAX_TCHAR_PATH, NULL)) {
_tprintf (TEXT("\nCannot read source path name in %s.\n"), SectionName);
return FALSE;
}
if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("message"), &context)) {
SetupGetStringField (&context, 1, message, MAX_TCHAR_PATH, NULL);
}
if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("RenameSection"), &context)) {
SetupGetStringField (&context, 1, renSect, MAX_TCHAR_PATH, NULL);
}
g_SectFiles.Buf = NULL;
g_SectFiles.Size = 0;
g_SectFiles.End = 0;
g_SectFiles.GrowSize = 0;
g_SectFiles.UserIndex = 0;
if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("ExcludeFiles"), &context)) {
field = 1;
while (SetupGetStringField (&context, field, excludePattern, MAX_TCHAR_PATH, NULL)) {
MultiSzAppend (&g_SectFiles, excludePattern);
field ++;
}
appMode = FALSE;
}
if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("SpecifiedFiles"), &context)) {
field = 1;
while (SetupGetStringField (&context, field, excludePattern, MAX_TCHAR_PATH, NULL)) {
MultiSzAppend (&g_SectFiles, excludePattern);
field ++;
}
appMode = TRUE;
}
// let's try to find if this section was already processed in migdb.inx
if (SetupFindFirstLine (g_MigDbInf, action, NULL, &context)) {
do {
if (SetupGetStringField (&context, 1, sectTmp, MAX_TCHAR_PATH, NULL) &&
(StringIMatch (section, sectTmp))
) {
if ((!g_RescanFlag) ||
((g_RescanSect != NULL) && (!StringIMatch (g_RescanSect, section)))
) {
_tprintf (TEXT("skipped\n"));
return TRUE;
}
WritePrivateProfileString (section, NULL, NULL, g_MigdbDest);
WritePrivateProfileString (NULL, NULL, NULL, g_MigdbDest);
_tprintf (TEXT("forced ..."));
forced = TRUE;
}
}
while (SetupFindNextLine (&context, &context));
}
if (SetupFindFirstLine (ConfigHandle, renSect, NULL, &context)) {
do {
if (SetupGetStringField (&context, 0, srcFile, MAX_TCHAR_PATH, NULL) &&
SetupGetStringField (&context, 1, destFile, MAX_TCHAR_PATH, NULL)
) {
MemDbSetValueEx (MEMDB_CATEGORY_RENAME_DEST, destFile, NULL, NULL, 0, &offset);
MemDbSetValueEx (MEMDB_CATEGORY_RENAME_SRC, srcFile, NULL, NULL, offset, NULL);
}
} while (SetupFindNextLine (&context, &context));
}
_tprintf (TEXT("\n"));
migDbContext = (PMIGDB_CONTEXT) PoolMemGetMemory (g_MigDbPool, sizeof (MIGDB_CONTEXT));
if (migDbContext == NULL) {
DEBUGMSG ((DBG_ERROR, "Unable to create context for %s", action));
return FALSE;
}
ZeroMemory (migDbContext, sizeof (MIGDB_CONTEXT));
migDbContext->Next = g_ContextList;
g_ContextList = migDbContext;
// update ActionIndex with known value
migDbContext->ActionIndex = MigDb_GetActionIdx (action);
DEBUGMSG_IF(((migDbContext->ActionIndex == -1), DBG_ERROR, "Unable to identify action index for %s", action));
// update SectName field
migDbContext->SectName = PoolMemDuplicateString (g_MigDbPool, section);
if (!pHandleAllFiles (appMode, action, section, message, srcPath)) {
return FALSE;
}
FreeGrowBuffer (&g_SectFiles);
if (!forced) {
// now let's add the action section and the line within it
_stprintf (msgStr, TEXT("%s\\%s,%s"),
MEMDB_CATEGORY_ACTION,
section,
message);
MemDbSetValue (msgStr, 0);
pWriteMemdbSection (g_MigdbDest, MEMDB_CATEGORY_ACTION, action, FALSE);
}
pWriteMemdbSection (g_MigdbDest, MEMDB_CATEGORY_SECTFILES, section, TRUE);
pWriteMemdbSection (g_MigdbDest, MEMDB_CATEGORY_REQFILES, TEXT("Windows 9x Required Files"), TRUE);
MemDbDeleteTree (MEMDB_CATEGORY_SECTFILES);
MemDbDeleteTree (MEMDB_CATEGORY_ACTION);
MemDbDeleteTree (MEMDB_CATEGORY_RENAME_SRC);
MemDbDeleteTree (MEMDB_CATEGORY_RENAME_DEST);
MemDbDeleteTree (MEMDB_CATEGORY_REQFILES);
return TRUE;
}
BOOL
pWriteMemdbSection (
IN PCTSTR FileName,
IN PCTSTR MemDbCategory,
IN PCTSTR SectName,
IN BOOL WriteByValue
)
{
HANDLE fileHandle = INVALID_HANDLE_VALUE;
TCHAR line [MAX_TCHAR_PATH] = "";
DWORD dontCare;
MEMDB_ENUM e;
PCTSTR pattern;
fileHandle = CreateFile (FileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
_tprintf (TEXT("\nCannot open %s.\n"), FileName);
return FALSE;
}
SetFilePointer (fileHandle, 0, 0, FILE_END);
_stprintf (line, TEXT("[%s]\r\n"), SectName);
WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL);
pattern = JoinPaths (MemDbCategory, TEXT("\\*"));
if (MemDbEnumFirstValue (&e, pattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
do {
if (!WriteByValue || !e.dwValue) {
_stprintf (line, TEXT("%s\r\n"), e.szName);
if (!WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL)) {
DEBUGMSG ((DBG_ERROR, "Error while writing information."));
}
}
}
while (MemDbEnumNextValue (&e));
}
_stprintf (line, TEXT("\r\n\r\n"), SectName);
WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL);
if (!CloseHandle (fileHandle)) {
DEBUGMSG ((DBG_ERROR, "Error while closing file %s.", FileName));
}
if (WriteByValue) {
fileHandle = CreateFile (g_MigdbDump, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (fileHandle == INVALID_HANDLE_VALUE) {
_tprintf (TEXT("\nCannot open %s.\n"), g_MigdbDump);
return FALSE;
}
SetFilePointer (fileHandle, 0, 0, FILE_END);
_stprintf (line, TEXT("[\n%s.obsolete]\r\n"), SectName);
WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL);
if (MemDbEnumFirstValue (&e, pattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
do {
if (e.dwValue) {
_stprintf (line, TEXT("%s\r\n"), e.szName);
if (!WriteFile (fileHandle, line, GetEndOfString (line) - line, &dontCare, NULL)) {
DEBUGMSG ((DBG_ERROR, "Error while writing information."));
}
}
}
while (MemDbEnumNextValue (&e));
}
if (!CloseHandle (fileHandle)) {
DEBUGMSG ((DBG_ERROR, "Error while closing file %s.", FileName));
}
}
FreePathString (pattern);
return TRUE;
}
BOOL
pArrangeMigDbFile (
IN PCTSTR SrcFile,
IN PCTSTR DestFile
)
{
return CopyFile (SrcFile, DestFile, FALSE);
}