/*++ Copyright (c) 1997 Microsoft Corporation Module Name: filegen.c Abstract: This module creates a tool that generates filelist.dat and is executed for us by the NT build lab. It scans the INI files to build a list for all files that are going to be installed by NT Author: Calin Negreanu (calinn) 18-Feb-1998 Revision History: --*/ #include "pch.h" #include #ifdef UNICODE #error UNICODE not allowed #endif #define S_IGNORE_THIS_FILE TEXT("*") #define FILEGEN_VERSION 3 #define DIRS_FIELD 8 #define DISP_FIELD 9 #define DEST_FIELD 11 #define SRC_NEVER_COPY 0x01 BOOL CancelFlag = FALSE; BOOL *g_CancelFlagPtr = &CancelFlag; POOLHANDLE g_TempPool; #ifdef DEBUG extern BOOL g_DoLog; #endif typedef BOOL (*PSETUPGETINFSECTIONS) ( HINF,PTSTR,UINT,UINT*); PSETUPGETINFSECTIONS MypSetupGetInfSections; // this section is populated from the directories with either INF files or with compressed // INF files that were uncompressed in the temp directory. Two things: The value of every // key will have a checksum of the INF, if this is 0xFFFFFFFF it means that the INF file // has changed and all the other information about this INF file should be discarded. #define MEMDB_CATEGORY_INF_FILES TEXT("InfFiles") // this section needs no optimization. It will be created every time from the additional file #define MEMDB_CATEGORY_NT_KNOWN_FILES TEXT("NtKnownFiles") // this section needs no optimization. It will be created every time from the additional file #define MEMDB_CATEGORY_NT_HEADER_FILES TEXT("NtHeaderFiles") // this section needs no optimization. It will be created every time from the additional file #define MEMDB_CATEGORY_NT_CHECK_FILES TEXT("NtCheckFiles") #define MEMDB_CATEGORY_NT_FILES_DOUBLED_COPY "NtFilesDoubledCopy" #define MEMDB_CATEGORY_NT_FILES_DOUBLED_IDX_COPY "NtFilesDoubledIdxCopy" #define MEMDB_CATEGORY_NT_FILES_NODIR_COPY "NtFilesNoDirCopy" #define MEMDB_CATEGORY_NT_FILES_NODIR_OTHER_COPY "NtFilesNoDirOtherCopy" #define MEMDB_CATEGORY_NT_FILES_DOUBLED_DEL "NtFilesDoubledDel" #define MEMDB_CATEGORY_NT_FILES_DOUBLED_IDX_DEL "NtFilesDoubledIdxDel" #define MEMDB_CATEGORY_NT_FILES_NODIR_DEL "NtFilesNoDirDel" #define MEMDB_CATEGORY_NT_FILES_NODIR_OTHER_DEL "NtFilesNoDirOtherDel" #define MEMDB_CATEGORY_NT_SECT_NODIR "NtSectNoDir" #define MEMDB_CATEGORY_NT_SECT_BADDIR "NtSectBadDir" #define MEMDB_CATEGORY_NT_INSTALLED_INFS "NtInstalledInfs" #define MEMDB_CATEGORY_NT_FILES_NO_LAYOUT "NtFileNoLayout" #define MEMDB_CATEGORY_DEL_FILES "DelFiles" #define MEMDB_CATEGORY_SRC_INF_FILES_NR "Source INF Files\\Total Number" #define MEMDB_CATEGORY_SRC_INF_FILES "Source INF Files" #define MEMDB_CATEGORY_KNOWN_FILE_NAMES "KnownFileNames" #define SECT_KNOWN_LOCATION "NtFiles_KnownLocation" HANDLE g_hHeap; HINSTANCE g_hInst; extern POOLHANDLE g_TextPool; CHAR g_TempDirBuf[MAX_MBCHAR_PATH]; CHAR g_TempDirWackBuf[MAX_MBCHAR_PATH]; PSTR g_TempDir; PSTR g_TempDirWack; INT g_TempDirWackChars; PSTR g_WinDir; CHAR g_WinDirBuf[MAX_MBCHAR_PATH]; CHAR g_SourceDirectoryBuf[MAX_SOURCE_COUNT][MAX_MBCHAR_PATH]; PCSTR g_SourceDirectories[MAX_SOURCE_COUNT]; DWORD g_SourceDirectoryCount = 0; BOOL g_DoWarnings = FALSE; CHAR g_WarnFileBuf[MAX_MBCHAR_PATH]; PSTR g_WarnFile = NULL; BOOL g_DoHeader = FALSE; CHAR g_HeaderFileBuf[MAX_MBCHAR_PATH]; PSTR g_HeaderFile = NULL; PSTR g_AddnlFile = NULL; BOOL g_AddnlFileForced = FALSE; CHAR g_AddnlFileBuf[MAX_MBCHAR_PATH]; CHAR g_AddnlFileAlt[MAX_MBCHAR_PATH]; HINF g_AddnlInf = INVALID_HANDLE_VALUE; CHAR g_PlatformBuf[MAX_MBCHAR_PATH]; PSTR g_Platform = NULL; CHAR g_ProductBuf[MAX_MBCHAR_PATH]; PSTR g_Product = NULL; CHAR g_StructNameBuf[MAX_MBCHAR_PATH] = "Tier2Files"; PSTR g_StructName = NULL; BOOL g_StrictInfs = TRUE; #define LAYOUT_CACHE_SIZE 3 CHAR g_LastLayoutFile[LAYOUT_CACHE_SIZE][MAX_MBCHAR_PATH]; UINT g_LayoutRef[LAYOUT_CACHE_SIZE]; HINF g_LastLayoutHandle[LAYOUT_CACHE_SIZE]; BOOL g_NextAvailLayoutData = 0; BOOL g_ForceRescan = FALSE; PSTR g_InfDatabase = NULL; UINT g_TotalInfFiles = 0; typedef struct _EXCLUDED_FILES { PCSTR File; INT ExcludeType; struct _EXCLUDED_FILES *Next; } EXCLUDED_FILES, *PEXCLUDED_FILES; PEXCLUDED_FILES g_ExcludedFiles = NULL; typedef struct _FORCED_FILES { PCSTR FilePattern; struct _FORCED_FILES *Next; } FORCED_FILES, *PFORCED_FILES; PFORCED_FILES g_ForcedFiles = NULL; typedef struct _EXCLUDED_INF_FILES { PCSTR InfName; PCSTR CopySectName; struct _EXCLUDED_INF_FILES *Next; } EXCLUDED_INF_FILES, *PEXCLUDED_INF_FILES; HASHITEM g_ExcludedInfsTable; HASHITEM g_ExcludedDirsTable; typedef struct _RENAMED_DIRS { PCSTR SrcDir; PCSTR DestDir; struct _RENAMED_DIRS *Next; } RENAMED_DIRS, *PRENAMED_DIRS; PRENAMED_DIRS g_RenamedDirs = NULL; typedef struct _HEADER_FILES { PCSTR FilePattern; UINT Priority; struct _HEADER_FILES *Next; } HEADER_FILES, *PHEADER_FILES; PHEADER_FILES g_HeaderFiles; HASHITEM g_PrivateIdInfsTable; typedef struct _PRIVATE_ID_INFS { PCSTR PrivateId; PCSTR EquivalentId; struct _PRIVATE_ID_INFS *Next; } PRIVATE_ID_INFS, *PPRIVATE_ID_INFS; HASHITEM g_IgnoredDirsTable; BOOL WINAPI MigUtil_Entry ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ); BOOL WINAPI MemDb_Entry ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ); BOOL pCreateNtFileList ( IN PCSTR FileListDatPath ); BOOL LocalGetFileNames ( IN PCTSTR *InfDirs, IN UINT InfDirCount, IN BOOL QueryFlag ); BOOL pLocalGetFileNamesWorker ( IN PCTSTR InfDir, IN BOOL QueryFlag ); VOID LocalFreeFileNames ( IN BOOL QueryFlag ); BOOL pLocalReadNtFiles ( IN PCTSTR InfPath ); BOOL pFixDir ( IN PCSTR src, OUT PSTR dest ); BOOL pIsExcludedDir ( IN PCTSTR DirName ); BOOL pShouldRescanInfs ( IN PCTSTR *InfDirs, IN UINT InfDirCount ); VOID pProcessDelFileSpec ( IN PCSTR DestDirectory, IN PCSTR DestFile ); VOID HelpAndExit ( VOID ) { printf ("Command line syntax:\n\n" "filegen [-i:] [-o:] [-t:] [-w[:]]\n" " [-h:] [-a:] [-p:]\n" " [-d:] [-s:] [-b:] [-f] [-l]\n\n" "Optional Arguments:\n" " [-i:] - Specifies directory containing INF files.\n" " Default: %%_NTTREE%%\n" " [-o:] - Specifies path and file name of DAT file.\n" " Default: %%_NTTREE%%\\filelist.dat\n" " [-t:] - Specifies path for temporary files.\n" " Default: %%TEMP%%\n" " [-w[:]] - Specifies if warning file is generated and it's\n" " location. Default: %%_NTTREE%%\\dump\\filegen.wrn\n" " [-h:] - Specifies if header file is generated and it's\n" " location. Default: %%_NTTREE%%\\dump\\filegen.hdr\n" " [-a:] - Specifies full path name for FILEGEN.INF file\n" " [-p:] - Specifies platform (such as x86 or ia64)\n" " Default: x86\n" " [-d:] - Specifies product type (WKS, DTC, ENT, SRV)\n" " Default: WKS\n" " [-s:] - Specifies the structure name (for header file)\n" " Default: Tier2Files\n" " [-b:] - Specifies INF database file from the last run\n" " [-f] - Force rescanning all INFs\n" " [-l] - List content of existing output file\n" ); exit(255); } HINF pOpenInfWithCache ( IN PCSTR InfFile ) { HINF infHandle; INT index; for (index = 0 ; index < LAYOUT_CACHE_SIZE ; index++) { if (StringIMatch (InfFile, g_LastLayoutFile[index])) { infHandle = g_LastLayoutHandle[index]; g_LayoutRef[index] += 1; break; } } if (index == LAYOUT_CACHE_SIZE) { infHandle = InfOpenInfFile (InfFile); if (infHandle != INVALID_HANDLE_VALUE) { for (index = 0 ; index < LAYOUT_CACHE_SIZE ; index++) { if (g_LayoutRef[index] == 0) { break; } } if (index < LAYOUT_CACHE_SIZE) { if (g_LastLayoutFile[index][0]) { InfCloseInfFile (g_LastLayoutHandle[index]); } StringCopy (g_LastLayoutFile[index], InfFile); g_LastLayoutHandle[index] = infHandle; g_LayoutRef[index] = 1; } } } return infHandle; } VOID pCloseInfWithCache ( IN HINF Inf ) { INT i; for (i = 0 ; i < LAYOUT_CACHE_SIZE ; i++) { if (g_LastLayoutFile[i][0] && g_LastLayoutHandle[i] == Inf) { break; } } if (i < LAYOUT_CACHE_SIZE) { if (g_LayoutRef[i] == 0) { MYASSERT(FALSE); } else { g_LayoutRef[i] -= 1; } } else { InfCloseInfFile (Inf); } } VOID pCloseCachedHandles ( VOID ) { INT index; for (index = 0 ; index < LAYOUT_CACHE_SIZE ; index++) { if (g_LastLayoutFile[index][0]) { InfCloseInfFile (g_LastLayoutHandle[index]); g_LastLayoutHandle[index] = INVALID_HANDLE_VALUE; g_LastLayoutFile[index][0] = 0; g_LayoutRef[index] = 0; } } } PTSTR pGetNonEmptyField ( IN OUT PINFSTRUCT InfStruct, IN UINT Field ) { PTSTR result; result = InfGetStringField (InfStruct, Field); if (result && *result == 0) { result = NULL; } return result; } BOOL pIsForcedFile ( IN PCTSTR FileName ) { PFORCED_FILES forcedFile; forcedFile = g_ForcedFiles; while (forcedFile) { if (IsPatternMatch (forcedFile->FilePattern, FileName)) { return TRUE; } forcedFile = forcedFile->Next; } return FALSE; } INT pIsExcludedFile ( IN PCTSTR FileName ) { PEXCLUDED_FILES excludedFile; // // Test if a file referenced by an INF should be excluded from the file list // // Return value -1 means not excluded // Return value 0 means excluded // Return value 1 means not excluded, but include in excluded files section of filelist.dat // excludedFile = g_ExcludedFiles; while (excludedFile) { if (IsPatternMatch (excludedFile->File, FileName)) { if (!pIsForcedFile (FileName)) { return excludedFile->ExcludeType; } } excludedFile = excludedFile->Next; } return -1; } BOOL pIsExcludedInfSection ( IN PCTSTR InfFileName, IN PCTSTR InfSectionName ) { BOOL excluded = FALSE; PEXCLUDED_INF_FILES excludedInf; if (HtFindStringAndData (g_ExcludedInfsTable, InfFileName, &excludedInf)) { if (!excludedInf) { //this means that the whole INF is excluded excluded = TRUE; } else { while (excludedInf) { if (StringIMatch (excludedInf->CopySectName, InfSectionName)) { excluded = TRUE; break; } excludedInf = excludedInf->Next; } } } return excluded; } BOOL pLoadForcedFilesFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; PCSTR filePattern; PFORCED_FILES forcedFile; if (InfFindFirstLine (infHandle, SectName, NULL, &context)) { do { filePattern = pGetNonEmptyField (&context, 1); if (filePattern) { forcedFile = (PFORCED_FILES) PoolMemGetMemory (g_TextPool, sizeof (FORCED_FILES)); if (forcedFile) { forcedFile->FilePattern = PoolMemDuplicateString (g_TextPool, filePattern); forcedFile->Next = g_ForcedFiles; g_ForcedFiles = forcedFile; } } } while (InfFindNextLine (&context)); } InfCleanUpInfStruct (&context); return TRUE; } BOOL pLoadForcedFiles ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } StringCopy (sectTmp, TEXT("FILELIST.FORCEINCLUDE")); pLoadForcedFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadForcedFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadForcedFilesFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.FORCEINCLUDE")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadForcedFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadForcedFilesFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadExcludedFilesFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; PCSTR filePattern; PEXCLUDED_FILES excludedFile; if (InfFindFirstLine (infHandle, SectName, NULL, &context)) { do { filePattern = pGetNonEmptyField (&context, 1); if (filePattern) { excludedFile = (PEXCLUDED_FILES) PoolMemGetMemory (g_TextPool, sizeof (EXCLUDED_FILES)); if (excludedFile) { excludedFile->File = PoolMemDuplicateString (g_TextPool, filePattern); if (!InfGetIntField (&context, 2, &(excludedFile->ExcludeType))) { excludedFile->ExcludeType = 0; } excludedFile->Next = g_ExcludedFiles; g_ExcludedFiles = excludedFile; } } } while (InfFindNextLine (&context)); } InfCleanUpInfStruct (&context); return TRUE; } BOOL pLoadExcludedFiles ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } StringCopy (sectTmp, TEXT("FILELIST.EXCLUDE")); pLoadExcludedFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadExcludedFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadExcludedFilesFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.EXCLUDE")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadExcludedFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadExcludedFilesFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadRenamedDirsFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; PCSTR srcDir, destDir; PRENAMED_DIRS renamedDir; if (InfFindFirstLine (infHandle, SectName, NULL, &context)) { do { srcDir = pGetNonEmptyField (&context, 1); destDir = pGetNonEmptyField (&context, 2); if (srcDir && destDir) { renamedDir = (PRENAMED_DIRS) PoolMemGetMemory (g_TextPool, sizeof (RENAMED_DIRS)); if (renamedDir) { renamedDir->SrcDir = PoolMemDuplicateString (g_TextPool, srcDir); renamedDir->DestDir = PoolMemDuplicateString (g_TextPool, destDir); renamedDir->Next = g_RenamedDirs; g_RenamedDirs = renamedDir; } } } while (InfFindNextLine (&context)); } InfCleanUpInfStruct (&context); return TRUE; } BOOL pLoadRenamedDirs ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } StringCopy (sectTmp, TEXT("FILELIST.RENAMEDIRS")); pLoadRenamedDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadRenamedDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadRenamedDirsFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.RENAMEDIRS")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadRenamedDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadRenamedDirsFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadHeaderFilesFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; PCSTR filePattern; PHEADER_FILES headerFile; if (InfFindFirstLine (infHandle, SectName, NULL, &context)) { do { filePattern = pGetNonEmptyField (&context, 1); if (filePattern) { headerFile = (PHEADER_FILES) PoolMemGetMemory (g_TextPool, sizeof (HEADER_FILES)); if (headerFile) { headerFile->FilePattern = PoolMemDuplicateString (g_TextPool, filePattern); if (!InfGetIntField (&context, 2, &(headerFile->Priority))) { headerFile->Priority = 0xFFFFFFFF; } headerFile->Next = g_HeaderFiles; g_HeaderFiles = headerFile; } } } while (InfFindNextLine (&context)); } InfCleanUpInfStruct (&context); return TRUE; } BOOL pLoadHeaderFiles ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } StringCopy (sectTmp, TEXT("FILELIST.HEADERFILES")); pLoadHeaderFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadHeaderFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadHeaderFilesFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.HEADERFILES")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadHeaderFilesFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadHeaderFilesFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadExcludedInfsFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT is = INITINFSTRUCT_POOLHANDLE; PCTSTR InfFile, CopySect; PEXCLUDED_INF_FILES excludedInfFile; HASHITEM findIndex; if (InfFindFirstLine (infHandle, SectName, NULL, &is)) { do { InfFile = pGetNonEmptyField (&is, 1); CopySect = pGetNonEmptyField (&is, 2); if (InfFile) { if (CopySect) { excludedInfFile = (PEXCLUDED_INF_FILES) PoolMemGetMemory (g_TextPool, sizeof (EXCLUDED_INF_FILES)); excludedInfFile->InfName = PoolMemDuplicateString (g_TextPool, InfFile); excludedInfFile->CopySectName = PoolMemDuplicateString (g_TextPool, CopySect); findIndex = HtFindStringAndData (g_ExcludedInfsTable, InfFile, &(excludedInfFile->Next)); if (findIndex) { HtSetStringData (g_ExcludedInfsTable, findIndex, &excludedInfFile); } else { excludedInfFile->Next = NULL; HtAddStringAndData (g_ExcludedInfsTable, InfFile, &excludedInfFile); } } else { // the whole INF file is excluded findIndex = HtFindStringAndData (g_ExcludedInfsTable, InfFile, &excludedInfFile); if (findIndex) { excludedInfFile = NULL; HtSetStringData (g_ExcludedInfsTable, findIndex, &excludedInfFile); } else { excludedInfFile = NULL; HtAddStringAndData (g_ExcludedInfsTable, InfFile, &excludedInfFile); } } } InfResetInfStruct (&is); } while (InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); return TRUE; } BOOL pCreateExcludedInfsTable ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } g_ExcludedInfsTable = HtAllocWithData (sizeof (PCTSTR)); StringCopy (sectTmp, TEXT("FILELIST.EXCLUDEINF")); pLoadExcludedInfsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadExcludedInfsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadExcludedInfsFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.EXCLUDEINF")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadExcludedInfsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadExcludedInfsFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadPrivateIdInfsFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT is = INITINFSTRUCT_POOLHANDLE; PCTSTR InfFile, PrivateId, EquivalentId; PPRIVATE_ID_INFS privateIdInfFile; HASHITEM findIndex; if (InfFindFirstLine (infHandle, SectName, NULL, &is)) { do { InfFile = pGetNonEmptyField (&is, 1); PrivateId = pGetNonEmptyField (&is, 2); EquivalentId = pGetNonEmptyField (&is, 3); if (InfFile && PrivateId && EquivalentId) { privateIdInfFile = (PPRIVATE_ID_INFS) PoolMemGetMemory (g_TextPool, sizeof (PRIVATE_ID_INFS)); privateIdInfFile->PrivateId = PoolMemDuplicateString (g_TextPool, PrivateId); privateIdInfFile->EquivalentId = PoolMemDuplicateString (g_TextPool, EquivalentId); findIndex = HtFindStringAndData (g_PrivateIdInfsTable, InfFile, &(privateIdInfFile->Next)); if (findIndex) { HtSetStringData (g_PrivateIdInfsTable, findIndex, &privateIdInfFile); } else { privateIdInfFile->Next = NULL; HtAddStringAndData (g_PrivateIdInfsTable, InfFile, &privateIdInfFile); } } InfResetInfStruct (&is); } while (InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); return TRUE; } BOOL pCreatePrivateIdInfsTable ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } g_PrivateIdInfsTable = HtAllocWithData (sizeof (PCTSTR)); StringCopy (sectTmp, TEXT("FILELIST.PRIVATEIDDIR")); pLoadPrivateIdInfsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadPrivateIdInfsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadPrivateIdInfsFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.PRIVATEIDDIR")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadPrivateIdInfsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadPrivateIdInfsFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadExcludedDirsFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT is = INITINFSTRUCT_POOLHANDLE; PCTSTR DirId; if (InfFindFirstLine (infHandle, SectName, NULL, &is)) { do { DirId = pGetNonEmptyField (&is, 1); if (DirId) { HtAddString (g_ExcludedDirsTable, DirId); } InfResetInfStruct (&is); } while (InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); return TRUE; } BOOL pLoadExcludedDirs ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } g_ExcludedDirsTable = HtAlloc (); StringCopy (sectTmp, TEXT("FILELIST.EXCLUDEDIR")); pLoadExcludedDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadExcludedDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadExcludedDirsFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.EXCLUDEDIR")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadExcludedDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadExcludedDirsFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadIgnoredDirsFromSect ( IN HINF infHandle, IN PCSTR SectName ) { INFSTRUCT is = INITINFSTRUCT_POOLHANDLE; PCTSTR DirId; if (InfFindFirstLine (infHandle, SectName, NULL, &is)) { do { DirId = pGetNonEmptyField (&is, 1); if (DirId) { HtAddString (g_IgnoredDirsTable, DirId); } InfResetInfStruct (&is); } while (InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); return TRUE; } BOOL pLoadIgnoredDirs ( IN HINF infHandle ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } g_IgnoredDirsTable = HtAlloc (); StringCopy (sectTmp, TEXT("FILELIST.IGNOREDIR")); pLoadIgnoredDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadIgnoredDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadIgnoredDirsFromSect (infHandle, sectTmp); StringCopy (sectTmp, TEXT("FILELIST.IGNOREDIR")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadIgnoredDirsFromSect (infHandle, sectTmp); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadIgnoredDirsFromSect (infHandle, sectTmp); FreeText (sectTmp); return TRUE; } BOOL pLoadKnownFilesFromSect ( IN HINF infHandle, IN PCSTR SectName, IN BOOL CountPriority ) { INFSTRUCT is = INITINFSTRUCT_POOLHANDLE; PCTSTR SrcName; PCTSTR DestName; PCTSTR InfName; PCTSTR DirName; UINT Priority; DWORD offset; PTSTR key; key = AllocText (MEMDB_MAX); if (!key) { return FALSE; } if (InfFindFirstLine (infHandle, SectName, NULL, &is)) { do { DestName = pGetNonEmptyField (&is, 1); SrcName = pGetNonEmptyField (&is, 2); InfName = pGetNonEmptyField (&is, 3); DirName = pGetNonEmptyField (&is, 4); if (!InfGetIntField (&is, 5, &Priority)) { Priority = 0xFFFFFFFF; } if (DestName && DirName) { MemDbSetValueEx ( MEMDB_CATEGORY_NT_DIRS, DirName, NULL, NULL, 0, &offset ); if (CountPriority) { _stprintf (key, TEXT("%s\\%07ud\\%s\\%s\\%s"), MEMDB_CATEGORY_NT_KNOWN_FILES, Priority, DestName, SrcName, InfName); } else { _stprintf (key, TEXT("%s\\%s\\%s\\%s"), MEMDB_CATEGORY_NT_KNOWN_FILES, DestName, SrcName, InfName); } MemDbSetValue (key, offset); MemDbBuildKey (key, MEMDB_CATEGORY_KNOWN_FILE_NAMES, SrcName, NULL, NULL); MemDbSetValue (key, offset); } InfResetInfStruct (&is); } while (InfFindNextLine (&is)); } InfCleanUpInfStruct (&is); FreeText (key); return TRUE; } BOOL pIsKnownFile ( IN PCTSTR DestDir, IN PCTSTR DestFile ) { TCHAR testKey[MEMDB_MAX]; DWORD storedOffset; DWORD dirOffset; MemDbSetValueEx ( MEMDB_CATEGORY_NT_DIRS, DestDir, NULL, NULL, 0, &dirOffset ); MemDbBuildKey (testKey, MEMDB_CATEGORY_KNOWN_FILE_NAMES, DestFile, NULL, NULL); if (!MemDbGetValue (testKey, &storedOffset)) { return FALSE; } return storedOffset != dirOffset; } BOOL pLoadKnownFiles ( IN HINF InfHandle, IN BOOL CountPriority ) { PTSTR sectTmp; sectTmp = AllocText (256); if (!sectTmp) { return FALSE; } MemDbDeleteTree (MEMDB_CATEGORY_NT_KNOWN_FILES); StringCopy (sectTmp, TEXT("FILELIST.KNOWNFILES")); pLoadKnownFilesFromSect (InfHandle, sectTmp, CountPriority); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadKnownFilesFromSect (InfHandle, sectTmp, CountPriority); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadKnownFilesFromSect (InfHandle, sectTmp, CountPriority); StringCopy (sectTmp, TEXT("FILELIST.KNOWNFILES")); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Product); pLoadKnownFilesFromSect (InfHandle, sectTmp, CountPriority); StringCat (sectTmp, TEXT(".")); StringCat (sectTmp, g_Platform); pLoadKnownFilesFromSect (InfHandle, sectTmp, CountPriority); FreeText (sectTmp); return TRUE; } VOID pPrintWarningGroupPart ( IN HANDLE FileHandle, IN PCSTR Title, IN PCSTR MemDbPattern, IN INT Type, IN BOOL LastPartOfGroup, IN OUT PBOOL OneItem OPTIONAL ) { MEMDB_ENUM enumFiles; MEMDB_ENUM enumSubFiles; PSTR outptr; PSTR output; BOOL dummy = FALSE; PTSTR outputStr; PTSTR key; __try { outputStr = AllocText (MEMDB_MAX); key = AllocText (MEMDB_MAX); if (!key || !outputStr) { __leave; } if (!OneItem) { OneItem = &dummy; } if (MemDbEnumFirstValue ( &enumFiles, MemDbPattern, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { if (*OneItem == FALSE) { WriteFileString (FileHandle, Title); } do { switch (Type) { case 0: WriteFileString (FileHandle, enumFiles.szName); WriteFileString (FileHandle, "\r\n"); break; case 1: output = DuplicatePathString (enumFiles.szName, 0); outptr = _mbschr (output, '\\'); if (outptr) { *outptr = '='; } WriteFileString (FileHandle, output); WriteFileString (FileHandle, "\r\n"); FreePathString (output); break; case 2: output = DuplicatePathString (enumFiles.szName, 0); outptr = _mbschr (output, '\\'); if (outptr) { *outptr = '='; } outptr = _mbschr (outptr, '\\'); if (outptr) { *outptr = ','; } WriteFileString (FileHandle, output); WriteFileString (FileHandle, "\r\n"); FreePathString (output); break; case 3: WriteFileString (FileHandle, enumFiles.szName); WriteFileString (FileHandle, "="); MemDbBuildKeyFromOffset (enumFiles.dwValue, outputStr, 1, NULL); outptr = _mbschr (outputStr, '\\'); if (outptr) { *outptr = ','; } if (Type == 4) { outptr = _mbschr (outptr, '\\'); if (outptr) { *outptr = ','; } } WriteFileString (FileHandle, outputStr); WriteFileString (FileHandle, "\r\n"); break; case 4: case 5: if (Type == 4) { MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES_DOUBLED_COPY, enumFiles.szName, TEXT("*"), NULL); } else { MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES_DOUBLED_DEL, enumFiles.szName, TEXT("*"), NULL); } if (MemDbEnumFirstValue ( &enumSubFiles, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { WriteFileString (FileHandle, enumFiles.szName); WriteFileString (FileHandle, "="); output = DuplicatePathString (enumSubFiles.szName, 0); outptr = _mbschr (output, '\\'); if (outptr) { *outptr = ','; } WriteFileString (FileHandle, output); WriteFileString (FileHandle, "\r\n"); FreePathString (output); } while (MemDbEnumNextValue (&enumSubFiles)); } break; } } while (MemDbEnumNextValue (&enumFiles)); *OneItem = TRUE; } if (LastPartOfGroup) { if (*OneItem) { WriteFileString (FileHandle, "\r\n\r\n"); } *OneItem = FALSE; } } __finally { FreeText (outputStr); FreeText (key); } } VOID pPrintWarnings ( VOID ) { HANDLE fileHandle; MEMDB_ENUM enumFiles,enumFiles1; DWORD dontCare; PSTR output; PSTR outptr; PSTR outputStr; PSTR key; BOOL matchFound; __try { outputStr = AllocText (MEMDB_MAX); key = AllocText (MEMDB_MAX); if (!key || !outputStr) { __leave; } fileHandle = CreateFile (g_WarnFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); matchFound = FALSE; pPrintWarningGroupPart ( fileHandle, "Files with no directory information in LAYOUT.INF and INTL.INF:\r\n\r\n", MEMDB_CATEGORY_NT_FILES_NODIR_COPY "\\*", 0, FALSE, &matchFound ); pPrintWarningGroupPart ( fileHandle, "Files with no directory information in LAYOUT.INF and INTL.INF:\r\n\r\n", MEMDB_CATEGORY_NT_FILES_NODIR_DEL "\\*", 0, TRUE, &matchFound ); pPrintWarningGroupPart ( fileHandle, "INF files with section having no directory information:\r\n" "(=)\r\n\r\n", MEMDB_CATEGORY_NT_SECT_NODIR "\\*", 1, TRUE, NULL ); pPrintWarningGroupPart ( fileHandle, "INF files with section having unknown directory ID:\r\n" "(=,)\r\n\r\n", MEMDB_CATEGORY_NT_SECT_BADDIR "\\*", 2, TRUE, NULL ); pPrintWarningGroupPart ( fileHandle, "INF files with files having no source layout information:\r\n" "(=
,)\r\n\r\n", MEMDB_CATEGORY_NT_FILES_NO_LAYOUT "\\*", 2, TRUE, NULL ); pPrintWarningGroupPart ( fileHandle, "Files within copy sections with bad or non-existent dir ID:\r\n" "(=,
[,])\r\n\r\n", MEMDB_CATEGORY_NT_FILES_NODIR_OTHER_COPY "\\*", 3, FALSE, &matchFound ); pPrintWarningGroupPart ( fileHandle, "Files within copy sections with bad or non-existent dir ID:\r\n" "(=,
[,])\r\n\r\n", MEMDB_CATEGORY_NT_FILES_NODIR_OTHER_DEL "\\*", 3, TRUE, &matchFound ); pPrintWarningGroupPart ( fileHandle, "Duplicate files:\r\n" "(=,)\r\n\r\n", MEMDB_CATEGORY_NT_FILES_DOUBLED_IDX_COPY "\\*", 4, FALSE, &matchFound ); pPrintWarningGroupPart ( fileHandle, "Duplicate files:\r\n" "(=,)\r\n\r\n", MEMDB_CATEGORY_NT_FILES_DOUBLED_IDX_DEL "\\*", 5, TRUE, &matchFound ); CloseHandle (fileHandle); } __finally { FreeText (outputStr); FreeText (key); } } BOOL pIsHeaderFile ( IN PCTSTR FileName, OUT PUINT Priority ) { PHEADER_FILES headerFile; UINT priority = 0xFFFFFFFF; BOOL result = FALSE; headerFile = g_HeaderFiles; while (headerFile) { if (IsPatternMatch (headerFile->FilePattern, FileName)) { if (priority > headerFile->Priority) { priority = headerFile->Priority; } result = TRUE; } headerFile = headerFile->Next; } if (result && Priority) { *Priority = priority; } return result; } VOID pBuildHeaderFilesCategory ( VOID ) { MEMDB_ENUM enumFiles; PSTR key; PSTR dirName; PSTR priorStr; PSTR filePtr1 = NULL, filePtr2=NULL; PSTR destName; PSTR srcName; PCSTR infName = NULL; UINT Priority; INT ExcludeType; __try { key = AllocText (MEMDB_MAX); dirName = AllocText (MEMDB_MAX); priorStr = AllocText (MEMDB_MAX); destName = AllocText (MEMDB_MAX); srcName = AllocText (MEMDB_MAX); if (!key || !dirName || !priorStr || !destName || !srcName) { __leave; } MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, TEXT("*"), NULL, NULL); if (MemDbEnumFirstValue ( &enumFiles, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { MemDbBuildKeyFromOffset (enumFiles.dwValue, key, 1, NULL); filePtr1 = enumFiles.szName; filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (destName, filePtr1, filePtr2); filePtr1 = _mbsinc (filePtr2); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (srcName, filePtr1, filePtr2); infName = _mbsinc (filePtr2); pFixDir (key, dirName); ExcludeType = pIsExcludedFile (destName); if ((ExcludeType == -1) || (ExcludeType == 1)) { if (!pIsExcludedDir (key)) { if (pIsHeaderFile (destName, &Priority)) { _stprintf ( key, TEXT("%s\\%07ud\\%s\\%s\\%s\\%s"), MEMDB_CATEGORY_NT_HEADER_FILES, Priority, destName, srcName, infName, dirName ); MemDbSetValue (key, 0); } } } _stprintf ( key, TEXT("%s\\%s\\%s"), MEMDB_CATEGORY_NT_CHECK_FILES, srcName, destName ); MemDbSetValue (key, 0); } while (MemDbEnumNextValue (&enumFiles)); } MemDbBuildKey (key, MEMDB_CATEGORY_NT_KNOWN_FILES, TEXT("*"), NULL, NULL); if (MemDbEnumFirstValue ( &enumFiles, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { MemDbBuildKeyFromOffset (enumFiles.dwValue, key, 1, NULL); filePtr1 = enumFiles.szName; //let's skip priority number filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (priorStr, filePtr1, filePtr2); filePtr1 = _mbsinc (filePtr2); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (destName, filePtr1, filePtr2); filePtr1 = _mbsinc (filePtr2); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (srcName, filePtr1, filePtr2); infName = _mbsinc (filePtr2); pFixDir (key, dirName); _stprintf ( key, TEXT("%s\\%s\\%s\\%s\\%s\\%s"), MEMDB_CATEGORY_NT_HEADER_FILES, priorStr, destName, srcName, infName, dirName ); MemDbSetValue (key, 0); _stprintf ( key, TEXT("%s\\%s\\%s"), MEMDB_CATEGORY_NT_CHECK_FILES, srcName, destName ); MemDbSetValue (key, 0); } while (MemDbEnumNextValue (&enumFiles)); } } __finally { FreeText (key); FreeText (dirName); FreeText (priorStr); FreeText (destName); FreeText (srcName); } } VOID pPrintHeaderFileFromCategory ( IN HANDLE fileHandle, IN PCTSTR Category ) { MEMDB_ENUM enumFiles, e1; PSTR key; PCSTR dirName; PSTR filePtr1 = NULL, filePtr2=NULL; PSTR tempStr; PSTR string; PSTR string1; PSTR stringPtr, stringPtr1; DWORD dontCare; PSTR destName; PSTR srcName; PSTR infName; __try { key = AllocText (MEMDB_MAX); tempStr = AllocText (MAX_MBCHAR_PATH); string = AllocText (MAX_MBCHAR_PATH); string1 = AllocText (MEMDB_MAX); destName = AllocText (MEMDB_MAX); srcName = AllocText (MEMDB_MAX); infName = AllocText (MEMDB_MAX); if (!key || !tempStr || !string || !string1 || !destName || !srcName || !infName) { __leave; } MemDbBuildKey (key, Category, TEXT("*"), NULL, NULL); if (MemDbEnumFirstValue ( &enumFiles, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { filePtr2 = enumFiles.szName; //let's skip priority number filePtr1 = _mbschr (filePtr2, '\\'); if (filePtr1 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } filePtr1 = _mbsinc (filePtr1); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (destName, filePtr1, filePtr2); filePtr1 = _mbsinc (filePtr2); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (srcName, filePtr1, filePtr2); filePtr1 = _mbsinc (filePtr2); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles.szName)); continue; } StringCopyAB (infName, filePtr1, filePtr2); // // Now let's try to fix the infName if possible // MemDbBuildKey (key, MEMDB_CATEGORY_NT_CHECK_FILES, infName, TEXT("*"), NULL); if (MemDbEnumFirstValue (&e1, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) { StringCopy (infName, e1.szName); } dirName = _mbsinc (filePtr2); if (CountInstancesOfSubString (dirName, "%Platform%")) { INFCONTEXT context; GROWBUFFER platforms = GROWBUF_INIT; UINT index; CHAR field [MAX_MBCHAR_PATH]; MULTISZ_ENUMA platformsEnum; PCSTR newDir = NULL; if (SetupFindFirstLine (g_AddnlInf, TEXT("FILELIST.MULTIPLEPLATFORMS"), g_Platform, &context)) { index = 1; while (SetupGetStringField (&context, index, field, MAX_MBCHAR_PATH, NULL)) { MultiSzAppend (&platforms, field); index++; } } else { MultiSzAppend (&platforms, g_Platform); } if (EnumFirstMultiSz (&platformsEnum, platforms.Buf)) { do { newDir = StringSearchAndReplace (dirName, "%Platform%", platformsEnum.CurrentString); if (StringIMatch (destName, srcName)) { StringCopy (string, " {NULL, "); } else { sprintf (string, " {L\"%s\", ", srcName); } sprintf (tempStr, "L\"%s\\%s\", ", newDir, destName); StringCat (string, tempStr); if (StringIMatch (infName, "LAYOUT.INF") || StringIMatch (infName, "LAYOUT.INF") ) { StringCopy (tempStr, "NULL},\r\n"); } else { sprintf (tempStr, "L\"%s\"},\r\n", infName); } StringCat (string, tempStr); stringPtr = string; stringPtr1= string1; while (*stringPtr) { if (*stringPtr == '\\') { *stringPtr1 = *stringPtr; stringPtr1++; } *stringPtr1 = *stringPtr; if (IsLeadByte (*stringPtr)) { stringPtr ++; stringPtr1 ++; *stringPtr1 = *stringPtr; } stringPtr ++; stringPtr1 ++; } *stringPtr1 = 0; WriteFile (fileHandle, string1, GetEndOfStringA (string1) - string1, &dontCare, NULL); FreePathString (newDir); } while (EnumNextMultiSz (&platformsEnum)); } } else { if (StringIMatch (destName, srcName)) { StringCopy (string, " {NULL, "); } else { sprintf (string, " {L\"%s\", ", srcName); } sprintf (tempStr, "L\"%s\\%s\", ", dirName, destName); StringCat (string, tempStr); if (StringIMatch (infName, "LAYOUT.INF") || StringIMatch (infName, "LAYOUT.INF") ) { StringCopy (tempStr, "NULL},\r\n"); } else { sprintf (tempStr, "L\"%s\"},\r\n", infName); } StringCat (string, tempStr); stringPtr = string; stringPtr1= string1; while (*stringPtr) { if (*stringPtr == '\\') { *stringPtr1 = *stringPtr; stringPtr1++; } *stringPtr1 = *stringPtr; if (IsLeadByte (*stringPtr)) { stringPtr ++; stringPtr1 ++; *stringPtr1 = *stringPtr; } stringPtr ++; stringPtr1 ++; } *stringPtr1 = 0; WriteFile (fileHandle, string1, GetEndOfStringA (string1) - string1, &dontCare, NULL); } } while (MemDbEnumNextValue (&enumFiles)); } } __finally { FreeText (key); FreeText (tempStr); FreeText (string); FreeText (string1); FreeText (destName); FreeText (srcName); FreeText (infName); } } VOID pPrintHeaderFile ( VOID ) { HANDLE fileHandle; CHAR string [MAX_PATH]; DWORD dontCare; printf ("Writing %s...", g_HeaderFile); fileHandle = CreateFile (g_HeaderFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fileHandle == INVALID_HANDLE_VALUE) { return; } StringCopyA (string, "PROTECT_FILE_ENTRY "); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, g_StructName); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, "[] =\r\n"); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, "{\r\n"); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); pBuildHeaderFilesCategory (); pPrintHeaderFileFromCategory (fileHandle, MEMDB_CATEGORY_NT_HEADER_FILES); StringCopyA (string, "};\r\n\r\n"); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, "#define Count"); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, g_StructName); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, " (sizeof("); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, g_StructName); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, ")/sizeof("); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, g_StructName); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); StringCopyA (string, "[0]))\r\n\r\n"); WriteFile (fileHandle, string, GetEndOfStringA (string) - string, &dontCare, NULL); CloseHandle (fileHandle); printf ("done\n"); } BOOL pGetProperLayoutInf ( VOID ) { DWORD index = 0; PCTSTR layoutInfName = NULL; PCTSTR partialName = NULL; INFCONTEXT context; TCHAR productInfDir [MAX_PATH]; TCHAR UncompressedFile[MAX_PATH]; if (!SetupFindFirstLine (g_AddnlInf, TEXT("FILELIST.PRODUCTS"), g_Product, &context)) { return FALSE; } if (!SetupGetStringField (&context, 1, productInfDir, MAX_TCHAR_PATH, NULL)) { return FALSE; } partialName = JoinPaths (productInfDir, TEXT("layout.inf")); while (index < g_SourceDirectoryCount) { layoutInfName = JoinPaths (g_SourceDirectories [index], partialName); if (DoesFileExist (layoutInfName)) { // // copy the file to temporary directory // StringCopy (UncompressedFile, g_TempDir); StringCopy (AppendWack (UncompressedFile), TEXT("layout.inf")); CopyFile (layoutInfName, UncompressedFile, FALSE); } index ++; } FreePathString (partialName); return TRUE; } DWORD pComputeChecksum ( PCTSTR FullPath ) { HANDLE File; HANDLE Map; PBYTE Data; UINT Size; UINT u; DWORD Checksum = 0; Data = MapFileIntoMemory (FullPath, &File, &Map); if (!Data) { return 0xFFFFFFFF; } Size = GetFileSize (File, NULL); for (u = 0 ; u < Size ; u++) { Checksum = _rotl (Checksum, 3); Checksum ^= Data[u]; } UnmapFile (Data, Map, File); return Checksum; } VOID pDumpFileListDat ( IN PCSTR DatFile ) { HANDLE datHandle; PDWORD versionPtr; DWORD dontCare; BOOL error = TRUE; HANDLE datMapping; PCSTR p; if (!DatFile) { fprintf (stderr, "No output file to dump.\n"); return; } versionPtr = (PDWORD) MapFileIntoMemory (DatFile, &datHandle, &datMapping); if (!versionPtr) { fprintf (stderr, "Can't open %s. Error=%u (0x%08X).\n", DatFile, GetLastError(), GetLastError()); return; } __try { __try { if (*versionPtr == 0 || *versionPtr > 3) { fprintf (stderr, "Unsupported file format: %s\n", DatFile); __leave; } printf ("Version: %u\n\n", *versionPtr); // // Version 1: Dump out the normal files // p = (PCSTR) (&versionPtr[1]); if (*p) { printf ("Files:\n"); do { printf (" %s", p); p = GetEndOfString (p) + 1; printf ("\\%s\n", p); p = GetEndOfString (p) + 1; } while (*p); printf ("\n"); } else { printf ("No files to list.\n"); } p++; // // Version 2: Dump out the excluded files // if (*versionPtr >= 2 && *p) { printf ("Excluded Files:\n"); do { printf (" %s", p); p = GetEndOfString (p) + 1; printf ("\\%s\n", p); p = GetEndOfString (p) + 1; } while (*p); printf ("\n"); } else { printf ("No excluded files to list.\n"); } p++; // // Version 3: Dump out the deleted files // if (*versionPtr >= 3 && *p) { printf ("Deleted Files:\n"); do { printf (" %s", p); p = GetEndOfString (p) + 1; printf ("\\%s\n", p); p = GetEndOfString (p) + 1; } while (*p); printf ("\n"); } else { printf ("No deleted files to list.\n"); } error = FALSE; } __except (TRUE) { fprintf (stderr, "Invalid file format: %s\n", DatFile); } } __finally { UnmapFile (versionPtr, datMapping, datHandle); } return; } INT __cdecl main ( INT argc, CHAR *argv[] ) { CHAR NtTree[MAX_MBCHAR_PATH]; CHAR OutputFileBuf[MAX_MBCHAR_PATH]; CHAR key [MEMDB_MAX]; DWORD value; PSTR OutputFile; PSTR p; INT i; LONG rc; PSTR AddnlPtr; INFCONTEXT context; PCSTR infPath; BOOL listSwitch = FALSE; MypSetupGetInfSections = (PSETUPGETINFSECTIONS) GetProcAddress(GetModuleHandle("setupapi.dll"), "pSetupGetInfSections"); if (!MypSetupGetInfSections) MypSetupGetInfSections = (PSETUPGETINFSECTIONS) GetProcAddress(GetModuleHandle("setupapi.dll"), "SetupGetInfSections"); #ifdef DEBUG //g_DoLog = TRUE; #endif // // Get environment variables // p = getenv ("_NT386TREE"); if (!p || !(*p)) { p = getenv ("_NTTREE"); } if (p && *p) { StringCopyA (NtTree, p); } else { StringCopyA (NtTree, "."); } // // Set defaults // g_TempDir = NULL; g_TempDirWack = g_TempDirWackBuf; g_WinDir = g_WinDirBuf; StringCopyA (OutputFileBuf, NtTree); AppendPathWack (OutputFileBuf); StringCatA (OutputFileBuf, "filelist.dat"); OutputFile = OutputFileBuf; StringCopyA (g_WarnFileBuf, NtTree); AppendPathWack (g_WarnFileBuf); StringCatA (g_WarnFileBuf, "DUMP\\FILELIST.WRN"); g_WarnFile = g_WarnFileBuf; StringCopyA (g_HeaderFileBuf, NtTree); AppendPathWack (g_HeaderFileBuf); StringCatA (g_HeaderFileBuf, "DUMP\\FILELIST.HDR"); g_HeaderFile = g_HeaderFileBuf; StringCopyA (g_PlatformBuf, "X86"); g_Platform = g_PlatformBuf; StringCopyA (g_ProductBuf, "WKS"); g_Product = g_ProductBuf; GetModuleFileName (g_hInst, g_AddnlFileBuf, MAX_MBCHAR_PATH); AddnlPtr = (PSTR)GetFileExtensionFromPath (g_AddnlFileBuf); if (AddnlPtr) { StringCopyA (AddnlPtr, "INF"); } g_AddnlFile = g_AddnlFileBuf; // // Parse command line // for (i = 1 ; i < argc ; i++) { if (argv[i][0] == '-' || argv[i][0] == '/') { switch (tolower (argv[i][1])) { case 'i': if (argv[i][2] == ':') { if (g_SourceDirectoryCount < MAX_SOURCE_COUNT) { StringCopy (g_SourceDirectoryBuf[g_SourceDirectoryCount], &argv[i][3]); g_SourceDirectories[g_SourceDirectoryCount] = g_SourceDirectoryBuf[g_SourceDirectoryCount]; g_SourceDirectoryCount++; } } else if (i + 1 < argc) { i++; if (g_SourceDirectoryCount < MAX_SOURCE_COUNT) { StringCopy (g_SourceDirectoryBuf[g_SourceDirectoryCount], argv[i]); g_SourceDirectories[g_SourceDirectoryCount] = g_SourceDirectoryBuf[g_SourceDirectoryCount]; g_SourceDirectoryCount++; } } else { HelpAndExit(); } break; case 'a': g_AddnlFileForced = TRUE; if (argv[i][2] == ':') { g_AddnlFile = &argv[i][3]; } else if (i + 1 < argc) { i++; g_AddnlFile = argv[i]; } else { HelpAndExit(); } break; case 'o': if (argv[i][2] == ':') { OutputFile = &argv[i][3]; } else if (i + 1 < argc) { i++; OutputFile = argv[i]; } else { HelpAndExit(); } break; case 'w': g_DoWarnings = TRUE; if (argv[i][2] == ':') { g_WarnFile = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_WarnFile = argv[i]; } break; case 'h': g_DoHeader = TRUE; if (argv[i][2] == ':') { g_HeaderFile = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_HeaderFile = argv[i]; } break; case 'p': if (argv[i][2] == ':') { g_Platform = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_Platform = argv[i]; } break; case 'd': if (argv[i][2] == ':') { g_Product = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_Product = argv[i]; } break; case 't': if (argv[i][2] == ':') { g_TempDir = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_TempDir = argv[i]; } break; case 's': if (argv[i][2] == ':') { g_StructName = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_StructName = argv[i]; } break; case 'b': if (argv[i][2] == ':') { g_InfDatabase = &argv[i][3]; } else if ((i + 1 < argc) && (argv[i][0] != '/') && (argv[i][0] != '-')) { i++; g_InfDatabase = argv[i]; } break; case 'f': g_ForceRescan = TRUE; break; case 'l': listSwitch = TRUE; break; default: HelpAndExit(); } } else { HelpAndExit(); } } // // Init libs // g_hHeap = GetProcessHeap(); g_hInst = GetModuleHandle (NULL); GetWindowsDirectoryA (g_WinDir, MAX_MBCHAR_PATH); if (!MigUtil_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) { fprintf (stderr, "Initialization error!\n"); return 254; } if (!MemDb_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) { fprintf (stderr, "Initialization error!\n"); return 254; } // // List mode -- skip right to dumping filelist.dat // if (listSwitch && g_SourceDirectoryCount == 0) { pDumpFileListDat (OutputFile); return 0; } if (g_SourceDirectoryCount == 0) { StringCopyA (g_SourceDirectoryBuf[0], NtTree); g_SourceDirectories[0] = g_SourceDirectoryBuf[0]; g_SourceDirectoryCount = 1; } if (g_InfDatabase && DoesFileExist (g_InfDatabase)) { MemDbImport (g_InfDatabase); } if (!g_AddnlFileForced) { // now let's try and find the newest additional file // we want to compare time stamps for the one that's in the same dir // with filegen.exe and for the one that's on NTTREE\mstools WIN32_FIND_DATAA findData1, findData2; ULARGE_INTEGER time1, time2; StringCopyA (g_AddnlFileAlt, NtTree); AppendPathWackA (g_AddnlFileAlt); StringCatA (g_AddnlFileAlt, "MSTOOLS\\FILEGEN.INF"); if (DoesFileExistExA (g_AddnlFileAlt, &findData2)) { if (DoesFileExistExA (g_AddnlFileBuf, &findData1)) { time1.LowPart = findData1.ftLastWriteTime.dwLowDateTime; time1.HighPart = findData1.ftLastWriteTime.dwHighDateTime; time2.LowPart = findData2.ftLastWriteTime.dwLowDateTime; time2.HighPart = findData2.ftLastWriteTime.dwHighDateTime; if (time1.QuadPart < time2.QuadPart) { g_AddnlFile = g_AddnlFileAlt; } } else { g_AddnlFile = g_AddnlFileAlt; } } } // let's try to see if the additional file changed since our last run if (!g_ForceRescan) { MemDbBuildKey (key, MEMDB_CATEGORY_SRC_INF_FILES, g_AddnlFile, NULL, NULL); if (MemDbGetValue (key, &value)) { if (value != pComputeChecksum (g_AddnlFile)) { printf ("INF changed -- rescanning\n"); g_ForceRescan = TRUE; } } } if (g_DoHeader) { if (!g_StructName) { g_StructName = g_StructNameBuf; } } if (g_AddnlFile == NULL) { HelpAndExit(); } else { g_AddnlInf = SetupOpenInfFile (g_AddnlFile, NULL, INF_STYLE_OLDNT|INF_STYLE_WIN4, NULL); if (g_AddnlInf == INVALID_HANDLE_VALUE) { fprintf (stderr, "Could not open %s, error:%d", g_AddnlFile, GetLastError()); return 254; } } // validate platform if (!SetupFindFirstLine (g_AddnlInf, TEXT("FILELIST.PLATFORMS"), g_Platform, &context)) { fprintf (stderr, "Invalid platform: %s", g_Platform); return 254; } // validate product if (!SetupFindFirstLine (g_AddnlInf, TEXT("FILELIST.PRODUCTS"), g_Product, &context)) { fprintf (stderr, "Invalid product type: %s", g_Product); return 254; } // // get Temp dir // if (g_TempDir) { StringCopyA (g_TempDirBuf, g_TempDir); g_TempDir = g_TempDirBuf; } else { g_TempDir = g_TempDirBuf; GetTempPathA (MAX_MBCHAR_PATH, g_TempDir); StringCopy (AppendWack (g_TempDirBuf), g_Product); } StringCopyA (g_TempDirWack, g_TempDir); AppendWack (g_TempDirWack); g_TempDirWackChars = CharCountA (g_TempDirWack); if (!CreateDirectory (g_TempDir, NULL)) { DWORD error; error = GetLastError (); if (error != ERROR_ALREADY_EXISTS) { fprintf (stderr, "Cannot create temporary directory. Error: %d", error); return 254; } } printf ("Input path(s) : "); { DWORD index = 0; while (index < g_SourceDirectoryCount) { if (index == 0) { printf ("'%s'\n", g_SourceDirectories [index]); } else { printf (" '%s'\n", g_SourceDirectories [index]); } index ++; } } printf ("Output file : '%s'\n", OutputFile); printf ("Temporary dir : '%s'\n", g_TempDir); if (g_DoWarnings) { printf ("Warnings : '%s'\n", g_WarnFile); } if (g_DoHeader) { printf ("Header file : '%s'\n", g_HeaderFile); } printf ("Additional file : '%s'\n", g_AddnlFile); printf ("Platform : '%s'\n", g_Platform); printf ("Product : '%s'\n", g_Product); if (g_InfDatabase) { printf ("Rescan database : '%s'\n", g_InfDatabase); } printf ("\n"); // // Build filelist.dat // DISABLETRACKCOMMENT(); g_TempPool = PoolMemInitNamedPool ("filegen"); PoolMemDisableTracking (g_TempPool); if (!pLoadExcludedFiles (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pLoadForcedFiles (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pLoadRenamedDirs (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pLoadHeaderFiles (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pCreateExcludedInfsTable (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pCreatePrivateIdInfsTable (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pLoadExcludedDirs (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } if (!pLoadIgnoredDirs (g_AddnlInf)) { rc = GetLastError(); fprintf (stderr, "Could not read %s. Win32 Error Code: %x\n", g_AddnlFile, rc); return 2; } // let's try to see if any INF files changed since our last run if (!g_ForceRescan) { printf ("Checking INF changes\n"); if (!pShouldRescanInfs (g_SourceDirectories, g_SourceDirectoryCount)) { printf ("No INF file changes. Tool will not run\n"); return 0; } } MemDbDeleteTree (MEMDB_CATEGORY_SRC_INF_FILES); MemDbBuildKey (key, MEMDB_CATEGORY_SRC_INF_FILES, g_AddnlFile, NULL, NULL); MemDbSetValue (key, pComputeChecksum (g_AddnlFile)); // // load the INFs // printf ("Finding all INFs\n"); if (!LocalGetFileNames (g_SourceDirectories, g_SourceDirectoryCount, FALSE)) { fprintf (stderr, "ERROR: Cannot get INF file list\n"); DEBUGMSG ((DBG_WARNING, "NTFILELIST: Can't get INF file names")); LocalFreeFileNames (FALSE); return 3; } SetFileAttributes (OutputFile, FILE_ATTRIBUTE_NORMAL); if (!DeleteFile (OutputFile)) { if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND) ) { fprintf (stderr, "DeleteFile failed for %s. Win32 Error Code: %x\n", OutputFile, GetLastError ()); LocalFreeFileNames (FALSE); return 252; } } if (g_DoWarnings) { SetFileAttributes (g_WarnFile, FILE_ATTRIBUTE_NORMAL); if (!DeleteFile (g_WarnFile)) { if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND) ) { fprintf (stderr, "DeleteFile failed for %s. Win32 Error Code: %x\n", g_WarnFile, GetLastError ()); LocalFreeFileNames (FALSE); return 252; } } } if (g_DoHeader) { SetFileAttributes (g_HeaderFile, FILE_ATTRIBUTE_NORMAL); if (!DeleteFile (g_HeaderFile)) { if ((GetLastError() != ERROR_FILE_NOT_FOUND) && (GetLastError() != ERROR_PATH_NOT_FOUND) ) { fprintf (stderr, "DeleteFile failed for %s. Win32 Error Code: %x\n", g_HeaderFile, GetLastError ()); LocalFreeFileNames (FALSE); return 252; } } } // // now let's try to find the proper layout.inf // We will look into all source directories for a subdir with the name of the // product we are processing (for ENT is ENTINF etc.) and try to find layout.inf // there. // pGetProperLayoutInf (); printf ("Reading NT file list (layout.inf)\n"); infPath = JoinPaths (g_TempDir, "layout.inf"); if (!pLocalReadNtFiles (infPath)) { rc = GetLastError(); printf ("Could not read %s. Win32 Error Code: %x\n", infPath, rc); LocalFreeFileNames (FALSE); return 3; } FreePathString (infPath); printf ("Reading NT file list (intl.inf)\n"); infPath = JoinPaths (g_TempDir, "intl.inf"); if (!pLocalReadNtFiles (infPath)) { rc = GetLastError(); printf ("Could not read %s. Win32 Error Code: %x\n", infPath, rc); LocalFreeFileNames (FALSE); return 3; } FreePathString (infPath); if (!pCreateNtFileList (OutputFile)) { rc = GetLastError(); printf ("Could not build complete filelist. Win32 Error Code: %x\n", rc); LocalFreeFileNames (FALSE); return 3; } else { printf ("%s was built successfully.\n", OutputFile); if (listSwitch) { pDumpFileListDat (OutputFile); } } if (g_DoWarnings) { pPrintWarnings (); } if (g_DoHeader) { pLoadKnownFiles (g_AddnlInf, TRUE); pPrintHeaderFile (); } HtFree (g_ExcludedInfsTable); if (g_AddnlInf != INVALID_HANDLE_VALUE) { SetupCloseInfFile (g_AddnlInf); } LocalFreeFileNames (FALSE); ENABLETRACKCOMMENT(); // // Terminate libs // PoolMemEmptyPool (g_TempPool); PoolMemDestroyPool (g_TempPool); if (!MemDb_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) { fprintf (stderr, "Termination error!\n"); return 253; } if (!MigUtil_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) { fprintf (stderr, "Termination error!\n"); return 253; } return 0; } typedef struct _KNOWN_DIRS { PCSTR DirId; PCSTR DirValue; } KNOWN_DIRS, *PKNOWN_DIRS; KNOWN_DIRS g_LocalKnownDirs [] = { {"10" , "%systemroot%"}, {"11" , "%systemroot%\\system32"}, {"12" , "%systemroot%\\system32\\drivers"}, {"17" , "%systemroot%\\inf"}, {"18" , "%systemroot%\\help"}, {"20" , "%systemroot%\\fonts"}, {"21" , "%systemroot%\\system32\\viewers"}, {"23" , "%systemroot%\\system32\\spool\\drivers\\color"}, {"24" , "%systemdrive%"}, {"25" , "%systemroot%"}, {"30" , "%systemdrive%"}, {"50" , "%systemroot%\\system"}, {"51" , "%systemroot%\\system32\\spool"}, {"52" , "%systemroot%\\system32\\spool\\drivers"}, {"53" , "%systemdrive%\\Documents and Settings"}, {"54" , "%systemdrive%"}, {"55" , "%systemroot%\\system32\\spool\\prtprocs"}, {"16422", "%ProgramFiles%"}, {"16427", "%commonprogramfiles%"}, {"16428", "%commonprogramfiles(x86)%"}, {"XX001", "%ProgramFilesX86%"}, {"66000", "%systemroot%\\system32\\spool\\drivers\\W32%Platform%\\3"}, {"66002", "%systemroot%\\system32"}, {"66003", "%systemroot%\\system32\\spool\\drivers\\color"}, {NULL, NULL} }; typedef struct _CONVERT_DIRS { PCSTR SifDir; PCSTR SetupDir; } CONVERT_DIRS, *PCONVERT_DIRS; CONVERT_DIRS g_LocalConvertDirs [] = { {"1", "10"}, {"2", "11"}, {"3", "11\\config"}, {"4", "12"}, {"5", "50"}, {"6", "11\\os2"}, {"7", "11\\ras"}, {"8", "11\\os2\\dll"}, {"9", "51"}, {"10", "52"}, {"11", "66000"}, {"12", "55"}, {"14", "11\\wins"}, {"15", "11\\dhcp"}, {"16", "10\\repair"}, {"17", "12\\etc"}, {"20", "17"}, {"21", "18"}, {"22", "20"}, {"23", "10\\config"}, {"24", "10\\msagent\\intl"}, {"25", "10\\Cursors"}, {"26", "10\\Media"}, {"27", "10\\java"}, {"28", "10\\java\\classes"}, {"29", "10\\java\\trustlib"}, {"30", "11\\ShellExt"}, {"31", "10\\Web"}, {"32", "11\\Setup"}, {"33", "10\\Web\\printers"}, {"34", "66003"}, {"35", "11\\wbem"}, {"36", "11\\wbem\\Repository"}, {"37", "10\\addins"}, {"38", "10\\Connection Wizard"}, {"40", "10\\security"}, {"41", "10\\security\\templates"}, {"42", "11\\npp"}, {"43", "11\\ias"}, {"44", "11\\dllcache"}, {"45", "10\\Temp"}, {"46", "10\\Web\\printers\\images"}, {"47", "11\\export"}, {"48", "11\\wbem\\mof\\good"}, {"49", "11\\wbem\\mof\\bad"}, {"50", "10\\twain_32"}, {"51", "10\\msapps\\msinfo"}, {"52", "10\\msagent"}, {"53", "10\\msagent\\chars"}, {"54", "10\\security\\logs"}, {NULL, NULL} }; VOID pConvertSIFDir ( IN OUT PSTR Dir ) { PCONVERT_DIRS p = g_LocalConvertDirs; while (p->SifDir) { if (StringIMatch (Dir, p->SifDir)) { StringCopy (Dir, p->SetupDir); return; } p++; } } typedef struct _INF_DIRS { PCSTR InfName; PCSTR DirId; PCSTR DirValue; } INF_DIRS, *PINF_DIRS; BOOL pCheckIdDir ( IN PCSTR IdDir ) { PKNOWN_DIRS currDir = g_LocalKnownDirs; while (currDir->DirId) { if (StringIMatch (currDir->DirId, IdDir)) { return TRUE; } currDir++; } return FALSE; } BOOL pCheckInfIdDir ( IN PCSTR InfName, OUT PSTR IdDir ) { PPRIVATE_ID_INFS privateIdInfs; if (HtFindStringAndData (g_PrivateIdInfsTable, InfName, &privateIdInfs)) { while (privateIdInfs) { if (StringIMatch (privateIdInfs->PrivateId, IdDir)) { StringCopy (IdDir, privateIdInfs->EquivalentId); return TRUE; } privateIdInfs = privateIdInfs->Next; } } return FALSE; } VOID pMinimizeIdPath ( IN PCSTR SourceDirectoryWithLdirId, OUT PSTR DestDirectoryWithLdirId ) { PSTR temp; PKNOWN_DIRS knownDir; UINT thisSize; UINT bestSize = 0; PKNOWN_DIRS bestMatch = NULL; PCSTR end; __try { temp = AllocText (MAX_PATH); if (!temp) { __leave; } // // Search for the longest match // pFixDir (SourceDirectoryWithLdirId, temp); knownDir = g_LocalKnownDirs; while (knownDir->DirId) { thisSize = TcharCount (knownDir->DirValue); if (thisSize > bestSize) { end = temp + thisSize; if (*end == 0 || *end == '\\') { if (StringIPrefix (temp, knownDir->DirValue)) { bestMatch = knownDir; bestSize = thisSize; } } } knownDir++; } // // Copy the shortest path to the caller's buffer // if (bestMatch) { end = temp + bestSize; StringCopy (DestDirectoryWithLdirId, bestMatch->DirId); if (end) { StringCat (DestDirectoryWithLdirId, end); } } else { StringCopy (DestDirectoryWithLdirId, SourceDirectoryWithLdirId); } } __finally { FreeText (temp); } } PSTR pReadDestDir ( IN PCSTR FileName, IN PCSTR Section, IN HINF FileHandle, IN PGROWBUFFER LayoutFiles, OUT PDWORD badOffset ) { INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; MULTISZ_ENUMA layoutFilesEnum; PCSTR localLayoutFile = NULL; HINF infHandle; PSTR idDir; PSTR idDirPtr; PSTR subDir; PSTR result = NULL; PSTR srcDir, destDir, wildCharPtr; PSTR resultTmp = NULL; PRENAMED_DIRS renamedDir; BOOL found; *badOffset = 0; __try { idDir = AllocText (MEMDB_MAX); if (!idDir) { __leave; } if (InfFindFirstLine (FileHandle, "DestinationDirs", (Section[0]=='@')?(Section+1):Section, &context) || InfFindFirstLine (FileHandle, "DestinationDirs", "DefaultDestDir", &context) ) { idDirPtr = pGetNonEmptyField (&context, 1); if (idDirPtr) { StringCopy (idDir, idDirPtr); } else { idDir [0] = 0; } subDir = pGetNonEmptyField (&context, 2); if (!pCheckIdDir (idDir)) { if (!pCheckInfIdDir (GetFileNameFromPath (FileName), idDir)) { DEBUGMSG ((DBG_WARNING, "Directory ID not found for %s in %s", Section, GetFileNameFromPath (FileName))); if (g_DoWarnings) { MemDbSetValueEx (MEMDB_CATEGORY_NT_SECT_BADDIR, GetFileNameFromPath (FileName), Section, idDir, 0, badOffset); } result = NULL; __leave; } } if (subDir != NULL) { result = JoinPaths (idDir, subDir); } else { result = DuplicatePathString (idDir, 0); } __leave; } if (LayoutFiles) { if (EnumFirstMultiSz (&layoutFilesEnum, LayoutFiles->Buf)) { do { localLayoutFile = JoinPaths (g_TempDir, layoutFilesEnum.CurrentString); infHandle = pOpenInfWithCache (localLayoutFile); if (infHandle != INVALID_HANDLE_VALUE) { result = pReadDestDir (FileName, Section, infHandle, NULL, badOffset); pCloseInfWithCache (infHandle); if (result != NULL) { FreePathString (localLayoutFile); __leave; } } FreePathString (localLayoutFile); } while (EnumNextMultiSz (&layoutFilesEnum)); } } DEBUGMSG ((DBG_WARNING, "No directory found for %s in %s", Section, GetFileNameFromPath (FileName))); if (g_DoWarnings) { MemDbSetValueEx (MEMDB_CATEGORY_NT_SECT_NODIR, GetFileNameFromPath (FileName), Section, NULL, 0, badOffset); } } __finally { if (result != NULL) { // let's do some dir replacement here found = TRUE; while (found) { renamedDir = g_RenamedDirs; found = FALSE; while ((!found) && renamedDir) { if (IsPatternMatch (renamedDir->SrcDir, result)) { srcDir = DuplicatePathString (renamedDir->SrcDir, 0); destDir = DuplicatePathString (renamedDir->DestDir, 0); wildCharPtr = _tcschr (srcDir, TEXT('*')); if (wildCharPtr) { *wildCharPtr = 0; } wildCharPtr = _tcschr (destDir, TEXT('*')); if (wildCharPtr) { *wildCharPtr = 0; } MYASSERT (!StringIPrefix (srcDir, destDir)); MYASSERT (!StringIPrefix (destDir, srcDir)); resultTmp = (PSTR)StringSearchAndReplace (result, srcDir, destDir); if (resultTmp) { FreePathString (result); result = resultTmp; found = TRUE; } FreePathString (destDir); FreePathString (srcDir); } renamedDir = renamedDir->Next; } } } InfCleanUpInfStruct (&context); FreeText (idDir); } return result; } PTSTR pGetAdditionalLocation ( IN PCTSTR DestFile ) { INFCONTEXT context; TCHAR field [MAX_MBCHAR_PATH]; if (g_AddnlInf == INVALID_HANDLE_VALUE) { return NULL; } if (SetupFindFirstLine (g_AddnlInf, SECT_KNOWN_LOCATION, DestFile, &context)) { if (SetupGetStringField (&context, 1, field, MAX_MBCHAR_PATH, NULL)) { return (DuplicatePathString (field, 0)); } } return NULL; } BOOL pFixDir ( IN PCSTR src, OUT PSTR dest ) { PSTR tempPtr; PKNOWN_DIRS knownDir; BOOL result = FALSE; PSTR temp; __try { temp = AllocText (MEMDB_MAX); if (!temp) { __leave; } *dest = 0; tempPtr = _mbschr (src, '\\'); if (tempPtr) { StringCopyABA (temp, src, tempPtr); } else { StringCopy (temp, src); } knownDir = g_LocalKnownDirs; while (knownDir->DirId) { if (StringIMatch (temp, knownDir->DirId)) { StringCopy (dest, knownDir->DirValue); break; } knownDir ++; } if (*dest == 0) { __leave; } if (tempPtr) { StringCat (dest, tempPtr); } result = TRUE; } __finally { FreeText (temp); } return result; } BOOL DoDirsMatch ( IN DWORD Offset1, IN DWORD Offset2 ) { PSTR dir1; PSTR fixedDir1; PSTR dir2; PSTR fixedDir2; BOOL result = FALSE; dir1 = AllocText (MEMDB_MAX); fixedDir1 = AllocText (MEMDB_MAX); dir2 = AllocText (MEMDB_MAX); fixedDir2 = AllocText (MEMDB_MAX); if (dir1 && fixedDir1 && dir2 && fixedDir2) { if (MemDbBuildKeyFromOffset (Offset1, dir1, 1, NULL) && MemDbBuildKeyFromOffset (Offset2, dir2, 1, NULL) && pFixDir (dir1, fixedDir1) && pFixDir (dir2, fixedDir1) ) { result = StringIMatch (fixedDir1, fixedDir2); } } FreeText (dir1); FreeText (fixedDir1); FreeText (dir2); FreeText (fixedDir2); return result; } PCSTR pGetLayoutInfFile ( IN PCSTR FileName, IN HINF FileHandle, IN PGROWBUFFER LayoutFiles, IN PCSTR SrcName ) { INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; MULTISZ_ENUMA layoutFilesEnum; HINF layoutHandle; CHAR sectName [MAX_PATH]; PCSTR result = NULL; PCSTR layoutFile = NULL; PCSTR localLayoutFile = NULL; GROWBUFFER layoutFiles = GROWBUF_INIT; UINT fieldIdx = 0; StringCopy (sectName, "SourceDisksFiles"); if (InfFindFirstLine (FileHandle, sectName, SrcName, &context)) { InfCleanUpInfStruct (&context); result = DuplicatePathString (GetFileNameFromPath (FileName), 0); } if (!result) { StringCat (sectName, "."); StringCat (sectName, g_Platform); if (InfFindFirstLine (FileHandle, sectName, SrcName, &context)) { InfCleanUpInfStruct (&context); result = DuplicatePathString (GetFileNameFromPath (FileName), 0); } } if (!result) { if (LayoutFiles) { if (EnumFirstMultiSz (&layoutFilesEnum, LayoutFiles->Buf)) { do { localLayoutFile = JoinPaths (g_TempDir, layoutFilesEnum.CurrentString); layoutHandle = pOpenInfWithCache (localLayoutFile); if (layoutHandle != INVALID_HANDLE_VALUE) { // get all layout files in a multisz if (InfFindFirstLine (layoutHandle, "Version", "LayoutFile", &context)) { fieldIdx = 1; layoutFile = pGetNonEmptyField (&context, fieldIdx); while (layoutFile) { MultiSzAppend (&layoutFiles, layoutFile); fieldIdx ++; layoutFile = pGetNonEmptyField (&context, fieldIdx); } InfCleanUpInfStruct (&context); } result = pGetLayoutInfFile (layoutFilesEnum.CurrentString, layoutHandle, &layoutFiles, SrcName); pCloseInfWithCache (layoutHandle); if (result != NULL) { FreeGrowBuffer (&layoutFiles); FreePathString (localLayoutFile); break; } FreeGrowBuffer (&layoutFiles); } else { //MessageBox (NULL, "Layout", "Layout", MB_OK); } FreePathString (localLayoutFile); } while (EnumNextMultiSz (&layoutFilesEnum)); } } } InfCleanUpInfStruct (&context); return result; } // // Use globals for highly used memory allocations (to avoid reallocs) // typedef enum { ST_COPYFILES, ST_DELFILES } SECTIONTYPE; VOID pProcessCopyFileSpec ( IN PCSTR InfFileName, IN HINF InfFileHandle, IN PCSTR InfSection, IN PCSTR SrcFile, OPTIONAL IN PCSTR DestDirectory, IN PCSTR DestFile, IN BOOL NoDestDirSpec, IN DWORD NoDirOffset, IN PGROWBUFFER LayoutFilesBuf ) { BOOL twice = FALSE; BOOL removeExistingEntry = FALSE; BOOL outputFile = TRUE; PSTR key; MEMDB_ENUM enumFiles; DWORD offset; PCSTR layoutInfFile; PCSTR finalDestDir; PSTR tmpDest; __try { key = AllocText (MEMDB_MAX); if (!key) { __leave; } // // If DestFile has a subpath, join it with DestDirectory // if (_mbschr (DestFile, '\\')) { // // This dest file has a dir in it. Join it with the root, // then recompute the file name ptr. // finalDestDir = JoinPaths (DestDirectory, DestFile); tmpDest = _mbsrchr (finalDestDir, '\\'); *tmpDest = 0; DestFile = tmpDest + 1; } else { finalDestDir = DestDirectory; } // // Make SrcFile non-NULL // if (!SrcFile || !(*SrcFile)) { SrcFile = DestFile; } else { if (_mbschr (SrcFile, '\\')) { // // This src file has a dir in it -- skip the // dir specification // SrcFile = GetFileNameFromPath (SrcFile); } } // // Now add the file spec (if it does not already exist) // if (NoDestDirSpec) { MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, DestFile, SrcFile, "*"); if (!MemDbEnumFirstValue (&enumFiles, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) { if (g_DoWarnings) { // // Record a "no directory spec" warning because this file is not // listed in a section that is also listed in [DestinationDirs] // MemDbSetValueEx ( MEMDB_CATEGORY_NT_FILES_NODIR_OTHER_COPY, DestFile, NULL, NULL, NoDirOffset, NULL ); } } else { // // Already listed properly -- ignore this bad spec // return; } } // // Add the destination directory to the NtDirs category. // MemDbSetValueEx ( MEMDB_CATEGORY_NT_DIRS, finalDestDir, NULL, NULL, 0, &offset ); // // Now write the file to the caller-specified category. // MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, DestFile, SrcFile, "*"); if (MemDbEnumFirstValue (&enumFiles, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) { removeExistingEntry = TRUE; do { // // If file is marked in layout.inf as "never copy" then skip keep this file. // if (!(enumFiles.UserFlags & SRC_NEVER_COPY)) { // // Is there a non-identical match already in memdb? // if (offset != enumFiles.dwValue && !DoDirsMatch (offset, enumFiles.dwValue)) { twice = TRUE; removeExistingEntry = TRUE; outputFile = TRUE; // // Add the first duplicate to the del list, so that // uninstall backs it up. // MemDbBuildKeyFromOffset (enumFiles.dwValue, key, 1, NULL); pProcessDelFileSpec (key, DestFile); break; } else { // ignore identical duplicate removeExistingEntry = FALSE; outputFile = FALSE; } } } while (MemDbEnumNextValue (&enumFiles)); } // // Provide a warning when a file is listed in multiple INFs, or the // same INF twice. It must have a different dest directory. // if (twice) { DEBUGMSG ((DBG_WARNING, "File %s is listed in more that one directory.", DestFile)); if (g_DoWarnings) { MemDbSetValueEx (MEMDB_CATEGORY_NT_FILES_DOUBLED_IDX_COPY, DestFile, NULL, NULL, 0, NULL); } } // // Always use the last file spec, ignoring the early dups. // if (removeExistingEntry) { MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, DestFile, SrcFile, NULL); MemDbDeleteTree (key); } if (outputFile) { layoutInfFile = pGetLayoutInfFile ( InfFileName, InfFileHandle, LayoutFilesBuf, SrcFile ); if (layoutInfFile) { MemDbSetValueEx ( MEMDB_CATEGORY_NT_FILES, DestFile, SrcFile, layoutInfFile, offset, NULL ); FreePathString (layoutInfFile); } else { if (g_DoWarnings) { MemDbSetValueEx ( MEMDB_CATEGORY_NT_FILES_NO_LAYOUT, GetFileNameFromPath (InfFileName), InfSection, DestFile, 0, NULL ); } } } // // Write the file to keep track of dups // MemDbSetValueEx ( MEMDB_CATEGORY_NT_FILES_DOUBLED_COPY, DestFile, GetFileNameFromPath (InfFileName), finalDestDir, 0, NULL ); // // Remove directory warning keys when a [DestinationDirs] // specification exists. // if (!NoDestDirSpec) { MemDbBuildKey(key, MEMDB_CATEGORY_NT_FILES_NODIR_COPY, DestFile, NULL, NULL); MemDbDeleteTree (key); MemDbBuildKey(key, MEMDB_CATEGORY_NT_FILES_NODIR_OTHER_COPY, DestFile, NULL, NULL); MemDbDeleteValue (key); } } __finally { // // Clean up // if (finalDestDir != DestDirectory) { FreePathString (finalDestDir); } FreeText (key); } } VOID pProcessDelFileSpec ( IN PCSTR DestDirectory, IN PCSTR DestFile ) { PSTR key; PCSTR p; PCSTR finalDestDir; PSTR tmpDest; CHAR fixedFullPath[MAX_PATH]; __try { key = AllocText (MEMDB_MAX); if (!key) { __leave; } // // If DestFile has a subpath, join it with DestDirectory // if (_mbschr (DestFile, '\\')) { // // This dest file has a dir in it. Join it with the root, // then recompute the file name ptr. // finalDestDir = JoinPaths (DestDirectory, DestFile); tmpDest = _mbsrchr (finalDestDir, '\\'); *tmpDest = 0; DestFile = tmpDest + 1; } else { finalDestDir = DestDirectory; } // // Minimize the destination path // pMinimizeIdPath (DestDirectory, fixedFullPath); // // Record the spec in the DelFiles category // MemDbBuildKey (key, MEMDB_CATEGORY_DEL_FILES, fixedFullPath, DestFile, NULL); MemDbSetValue (key, 0); } __finally { if (finalDestDir != DestDirectory) { FreePathString (finalDestDir); } FreeText (key); } } VOID pProcessFileSpec ( IN PCSTR InfFileName, IN HINF InfFileHandle, IN PCSTR InfSection, IN SECTIONTYPE SectionType, IN PCSTR SrcFile, OPTIONAL IN PCSTR DestDirectory, IN PCSTR DestFile, IN BOOL NoDestDirSpec, IN DWORD NoDirOffset, IN PGROWBUFFER LayoutFilesBuf ) { if (SectionType == ST_COPYFILES) { pProcessCopyFileSpec ( InfFileName, InfFileHandle, InfSection, SrcFile, DestDirectory, DestFile, NoDestDirSpec, NoDirOffset, LayoutFilesBuf ); } else if (SectionType == ST_DELFILES) { if (!NoDestDirSpec) { pProcessDelFileSpec (DestDirectory, DestFile); } } } BOOL pProcessInfCommand ( IN PCSTR InfFileName, IN PCSTR SectionMultiSz, IN HINF InfFileHandle, IN SECTIONTYPE SectionType, IN PGROWBUFFER LayoutFilesBuf ) { MULTISZ_ENUM multiSz; BOOL done; PCSTR destDirectory; PCSTR knownDestDir; PCSTR srcFile; PCSTR destFile; DWORD noDirOffset; INFSTRUCT context; // // Evaluate the INF section // if (EnumFirstMultiSz (&multiSz, SectionMultiSz)) { do { // // If this section is excluded, continue without processing it. // if (pIsExcludedInfSection (GetFileNameFromPath (InfFileName), multiSz.CurrentString)) { continue; } // // Read destination directory for this particular copy section. This comes // from the INF's [DestinationDirs] section. // destDirectory = pReadDestDir ( InfFileName, multiSz.CurrentString, InfFileHandle, LayoutFilesBuf, &noDirOffset ); // // read all the lines that contain destination file name and source file name // InitInfStruct (&context, NULL, g_TempPool); if (multiSz.CurrentString[0] == '@' || InfFindFirstLine (InfFileHandle, multiSz.CurrentString, NULL, &context) ) { done = FALSE; do { // // Get the dest and src file names // if (multiSz.CurrentString[0]=='@') { destFile = multiSz.CurrentString + 1; } else { destFile = pGetNonEmptyField (&context, 1); } if (multiSz.CurrentString[0]=='@') { srcFile = NULL; } else { srcFile = pGetNonEmptyField (&context, 2); } if (destDirectory) { // // Perform processing to ensure that the file spec is // unique, that it is fully formed, and that it gets // written to filelist.dat. // pProcessFileSpec ( InfFileName, InfFileHandle, multiSz.CurrentString, SectionType, srcFile, destDirectory, destFile, FALSE, noDirOffset, LayoutFilesBuf ); } else if (destFile) { knownDestDir = pGetAdditionalLocation (GetFileNameFromPath (destFile)); if (knownDestDir) { pProcessFileSpec ( InfFileName, InfFileHandle, multiSz.CurrentString, SectionType, srcFile, knownDestDir, destFile, TRUE, noDirOffset, LayoutFilesBuf ); FreePathString (knownDestDir); } } if (multiSz.CurrentString[0]=='@') { done = TRUE; } else if (!InfFindNextLine (&context)) { done = TRUE; } } while (!done); InfCleanUpInfStruct (&context); } if (destDirectory != NULL) { FreePathString (destDirectory); } } while (EnumNextMultiSz (&multiSz)); } return TRUE; } BOOL pProcessFile ( IN PCSTR FileName ) { GROWBUFFER sectionNamesBuf = GROWBUF_INIT; PWSTR sectBuffer = NULL; PWSTR currentSect; HINF fileHandle; UINT sizeNeeded = 0; UINT fieldIdx = 0; CHAR section[MAX_MBCHAR_PATH]; MULTISZ_ENUMA sectionEnum; PCSTR layoutFile; PCSTR cmdSection; INFSTRUCT context = INITINFSTRUCT_POOLHANDLE; GROWBUFFER layoutFilesBuf = GROWBUF_INIT; fileHandle = InfOpenInfFile (FileName); if (fileHandle == INVALID_HANDLE_VALUE) { fprintf (stderr, "WARNING: Cannot open inf file:%s\n", FileName); return TRUE; } __try { // // get all layout files in a multisz // if (InfFindFirstLine (fileHandle, "Version", "LayoutFile", &context)) { fieldIdx = 1; layoutFile = pGetNonEmptyField (&context, fieldIdx); while (layoutFile) { MultiSzAppend (&layoutFilesBuf, layoutFile); fieldIdx ++; layoutFile = pGetNonEmptyField (&context, fieldIdx); } } else { // put layout.inf in the list, because it is the default layout file MultiSzAppend (&layoutFilesBuf, "layout.inf"); } InfResetInfStruct (&context); // // get all the sections // if (!(*MypSetupGetInfSections) (fileHandle, NULL, 0, &sizeNeeded)) { fprintf (stderr, "WARNING: Error processing inf file:%s\n", FileName); __leave; } if (sizeNeeded == 0) { __leave; } sectBuffer = AllocPathStringW (sizeNeeded + 1); if (!(*MypSetupGetInfSections) (fileHandle, (PSTR)sectBuffer, sizeNeeded, NULL)) { fprintf (stderr, "WARNING: Error processing inf file:%s\n", FileName); __leave; } // // enumerate all sections looking for CopyFiles key // currentSect = sectBuffer; while (*currentSect) { sprintf (section, "%S", currentSect); // // get all sections that copy files in a multisz // if (InfFindFirstLine (fileHandle, section, "CopyFiles", &context)) { do { fieldIdx = 1; cmdSection = pGetNonEmptyField (&context, fieldIdx); while (cmdSection) { MultiSzAppend (§ionNamesBuf, cmdSection); fieldIdx ++; cmdSection = pGetNonEmptyField (&context, fieldIdx); } // // enumerate all sections that copy files // if (EnumFirstMultiSz (§ionEnum, sectionNamesBuf.Buf)) { do { if (!pProcessInfCommand ( FileName, sectionEnum.CurrentString, fileHandle, ST_COPYFILES, &layoutFilesBuf )) { __leave; } } while (EnumNextMultiSz (§ionEnum)); } FreeGrowBuffer (§ionNamesBuf); } while (InfFindNextLine (&context)); } InfResetInfStruct (&context); // // get all sections that delete files in a multisz // if (InfFindFirstLine (fileHandle, section, "DelFiles", &context)) { do { fieldIdx = 1; cmdSection = pGetNonEmptyField (&context, fieldIdx); while (cmdSection) { MultiSzAppend (§ionNamesBuf, cmdSection); fieldIdx ++; cmdSection = pGetNonEmptyField (&context, fieldIdx); } // // enumerate all sections that delete files // if (EnumFirstMultiSz (§ionEnum, sectionNamesBuf.Buf)) { do { if (!pProcessInfCommand ( FileName, sectionEnum.CurrentString, fileHandle, ST_DELFILES, &layoutFilesBuf )) { __leave; } } while (EnumNextMultiSz (§ionEnum)); } FreeGrowBuffer (§ionNamesBuf); } while (InfFindNextLine (&context)); } InfResetInfStruct (&context); currentSect = GetEndOfStringW (currentSect) + 1; } } __finally { FreePathStringW (sectBuffer); FreeGrowBuffer (&layoutFilesBuf); InfCleanUpInfStruct (&context); InfCloseInfFile (fileHandle); } return TRUE; } typedef struct { CHAR FilePath[MAX_PATH]; UINT ThreadNumber; HANDLE GoEvent; HANDLE DoneEvent; } THREADARGS, *PTHREADARGS; HANDLE g_Semaphores[4]; HANDLE g_FileThreads[4]; THREADARGS g_FileThreadInfo[4]; HANDLE g_DoneEvent; DWORD WINAPI pProcessFileThread ( IN PVOID ThreadInfo ) { HANDLE array[2]; PTHREADARGS threadInfo = (PTHREADARGS) ThreadInfo; DWORD rc; array[0] = threadInfo->GoEvent; array[1] = threadInfo->DoneEvent; for (;;) { rc = WaitForMultipleObjects (2, array, FALSE, INFINITE); if (rc == WAIT_OBJECT_0) { pProcessFile (threadInfo->FilePath); ReleaseSemaphore (g_Semaphores[threadInfo->ThreadNumber], 1, NULL); } else { break; } } return 0; } BOOL pProcessFileDispatcher ( IN PCSTR FileName ) { DWORD rc; // // Wait for a thread to become availble // rc = WaitForMultipleObjects (4, g_Semaphores, FALSE, INFINITE); if (rc <= WAIT_OBJECT_0 + 3) { } else { fprintf (stderr, "Failed to acquire thread\n"); exit (1); } // // Put file name in thread's struct // rc -= WAIT_OBJECT_0; StringCopy (g_FileThreadInfo[rc].FilePath, FileName); // // Start the thread // SetEvent (g_FileThreadInfo[rc].GoEvent); return TRUE; } VOID pInitFileThreads ( VOID ) { UINT u; g_DoneEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (!g_DoneEvent) { fprintf (stderr, "Failed to init completion event\n"); } for (u = 0 ; u < 4 ; u++) { g_Semaphores[u] = CreateSemaphore (NULL, 1, 1, NULL); if (!g_Semaphores[u]) { fprintf (stderr, "Failed to init semaphores\n"); exit (1); } g_FileThreadInfo[u].ThreadNumber = u; g_FileThreadInfo[u].GoEvent = CreateEvent (NULL, FALSE, FALSE, NULL); g_FileThreadInfo[u].DoneEvent = g_DoneEvent; if (!g_FileThreadInfo[u].GoEvent) { fprintf (stderr, "Failed to init thread info\n"); exit (1); } g_FileThreads[u] = CreateThread (NULL, 0, pProcessFileThread, &g_FileThreadInfo[u], 0, NULL); if (!g_FileThreads[u]) { fprintf (stderr, "Failed to init threads\n"); exit (1); } } } VOID pStopFileThreads ( VOID ) { SetEvent (g_DoneEvent); WaitForMultipleObjects (4, g_FileThreads, TRUE, INFINITE); } BOOL pIsExcludedDir ( IN PCTSTR DirName ) { TCHAR DirId [MAX_PATH]; PCTSTR NextPtr = NULL; NextPtr = _mbschr (DirName, '\\'); if (!NextPtr) { NextPtr = GetEndOfString (DirName); } StringCopyAB (DirId, DirName, NextPtr); return (HtFindString (g_ExcludedDirsTable, DirId) != NULL); } BOOL pCreateNtFileList ( IN PCSTR FileListDatPath ) { MEMDB_ENUM enumFiles; PSTR currentFile; BOOL result = FALSE; PSTR filePtr1 = NULL, filePtr2 = NULL; DWORD version = FILEGEN_VERSION; INT ExcludeType; INFCONTEXT context; BOOL found = FALSE; PSTR platform; PSTR product; PSTR destName; PSTR srcName; PSTR temp; PSTR key2; PSTR key3; PSTR extPtr; BOOL process = TRUE; DWORD offset; BOOL b; HANDLE fileHandle = INVALID_HANDLE_VALUE; MEMDB_ENUM enumFiles2; CHAR string [MAX_MBCHAR_PATH]; DWORD dontCare; PSTR fileSpec; HASHTABLE dupTable; __try { platform = AllocText (MAX_PATH); product = AllocText (MAX_PATH); destName = AllocText (MEMDB_MAX); srcName = AllocText (MEMDB_MAX); temp = AllocText (MEMDB_MAX); key2 = AllocText (MEMDB_MAX); key3 = AllocText (MEMDB_MAX); dupTable = HtAlloc(); if (!platform || !product || !destName || !srcName || !temp || !key2 || !key3 || !dupTable) { __leave; } //pInitFileThreads(); if (MemDbEnumFirstValue ( &enumFiles, MEMDB_CATEGORY_INF_FILES TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { currentFile = enumFiles.szName; if (!StringMatch (currentFile, S_IGNORE_THIS_FILE)) { process = TRUE; if (g_StrictInfs) { StringCopy (srcName, GetFileNameFromPath (currentFile)); extPtr = (PSTR)GetFileExtensionFromPath (srcName); if (!StringIMatch (extPtr, "INF")) { extPtr = _mbsdec (srcName, extPtr); if (extPtr) { *extPtr = 0; } } MemDbBuildKey (temp, MEMDB_CATEGORY_NT_INSTALLED_INFS, srcName, NULL, NULL); if (!MemDbGetValue (temp, NULL)) { process = FALSE; } } if (process) { PEXCLUDED_INF_FILES excludedInf; if (HtFindStringAndData (g_ExcludedInfsTable, currentFile, &excludedInf)) { if (!excludedInf) { //this means that the whole INF is excluded printf ("Excluded: %s\n", currentFile); process = FALSE; } } } if (process) { printf ("Processing file : %s", currentFile); //if (!pProcessFileDispatcher (currentFile)) { if (!pProcessFile (currentFile)) { DEBUGMSG ((DBG_ERROR, "Error while processing: %s", currentFile)); } printf("\n"); } } } while (MemDbEnumNextValue (&enumFiles)); } //pStopFileThreads(); pLoadKnownFiles (g_AddnlInf, FALSE); // now let's write the filelist.dat file if we are on the right platform and product found = FALSE; if (SetupFindFirstLine (g_AddnlInf, TEXT("FILELIST.GENERATE"), NULL, &context)) { do { if (SetupGetStringField (&context, 1, platform, MAX_TCHAR_PATH, NULL) && SetupGetStringField (&context, 2, product, MAX_TCHAR_PATH, NULL) && StringIMatch (g_Platform, platform) && StringIMatch (g_Product, product) ) { found = TRUE; break; } } while (SetupFindNextLine (&context, &context)); } if (found) { fileHandle = CreateFile ( FileListDatPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (fileHandle == INVALID_HANDLE_VALUE) { fprintf (stderr, "Cannot create output file : %s\n", FileListDatPath); __leave; } if (!WriteFile (fileHandle, &version, sizeof (DWORD), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } if (MemDbEnumFirstValue ( &enumFiles2, MEMDB_CATEGORY_NT_KNOWN_FILES TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { MemDbBuildKeyFromOffset (enumFiles2.dwValue, key3, 1, NULL); if (!pIsExcludedDir (key3)) { filePtr1 = enumFiles2.szName; //let's skip priority number filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles2.szName)); continue; } filePtr1 = _mbsinc (filePtr2); filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { DEBUGMSG ((DBG_WARNING, "Bogus name found in NT_FILES: %S", enumFiles2.szName)); continue; } StringCopyAB (destName, filePtr1, filePtr2); ExcludeType = pIsExcludedFile (destName); if ((ExcludeType == -1) || (ExcludeType == 1)){ wsprintf (temp, "%s\\%s", key3, destName); if (!HtFindString (dupTable, temp)) { if (!WriteFile (fileHandle, key3, SizeOfString (key3), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } if (!WriteFile (fileHandle, destName, SizeOfString (destName), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } HtAddString (dupTable, temp); } } } } while (MemDbEnumNextValue (&enumFiles2)); } if (MemDbEnumFirstValue ( &enumFiles2, TEXT(MEMDB_CATEGORY_NT_FILESA)TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { MemDbBuildKeyFromOffset (enumFiles2.dwValue, key3, 1, NULL); if (!pIsExcludedDir (key3)) { filePtr1 = enumFiles2.szName; filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { StringCopy (destName, filePtr1); } else { StringCopyAB (destName, filePtr1, filePtr2); } ExcludeType = pIsExcludedFile (destName); if ((ExcludeType == -1) || (ExcludeType == 1)){ if (!pIsKnownFile (key3, destName)) { wsprintf (temp, "%s\\%s", key3, destName); if (!HtFindString (dupTable, temp)) { // // Write file to list // if (!WriteFile (fileHandle, key3, SizeOfString (key3), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } if (!WriteFile (fileHandle, destName, SizeOfString (destName), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } HtAddString (dupTable, temp); } } else { // // Put overridden location in DelFiles list // pProcessDelFileSpec (key3, destName); } } } } while (MemDbEnumNextValue (&enumFiles2)); } * string = 0; if (!WriteFile (fileHandle, string, 1, &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } // now it's the time to write the excluded files if (MemDbEnumFirstValue ( &enumFiles2, TEXT(MEMDB_CATEGORY_NT_FILESA)TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { filePtr1 = enumFiles2.szName; filePtr2 = _mbschr (filePtr1, '\\'); if (filePtr2 == NULL) { StringCopy (destName, filePtr1); } else { StringCopyAB (destName, filePtr1, filePtr2); } ExcludeType = pIsExcludedFile (destName); if (ExcludeType == 1) { if (!WriteFile (fileHandle, destName, SizeOfString (destName), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } } } while (MemDbEnumNextValue (&enumFiles2)); } * string = 0; if (!WriteFile (fileHandle, string, 1, &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } // now it's the time to write the deleted files if (MemDbEnumFirstValue ( &enumFiles2, MEMDB_CATEGORY_DEL_FILES TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { if (HtFindString (dupTable, enumFiles2.szName)) { continue; } StringCopy (key3, enumFiles2.szName); fileSpec = (PSTR) GetFileNameFromPath (key3); if (!fileSpec) { continue; } *_mbsdec (key3, fileSpec) = 0; if (!WriteFile (fileHandle, key3, SizeOfString (key3), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } if (!WriteFile (fileHandle, fileSpec, SizeOfString (fileSpec), &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } } while (MemDbEnumNextValue (&enumFiles2)); } *string = 0; if (!WriteFile (fileHandle, string, 1, &dontCare, NULL)) { printf ("Error writing to %s. Error=%u\n", FileListDatPath, GetLastError()); __leave; } } else { fprintf ( stderr, "Not generating %s.\nDid not find %s,%s in [FileList.Generate] section of %s.\n", FileListDatPath, g_Platform, g_Product, g_AddnlFile ); // assume success } result = TRUE; } __finally { FreeText (platform); FreeText (product); FreeText (destName); FreeText (srcName); FreeText (temp); FreeText (key2); FreeText (key3); HtFree (dupTable); pCloseCachedHandles(); if (fileHandle != INVALID_HANDLE_VALUE) { CloseHandle (fileHandle); } } return result; } BOOL pLocalReadNtFileSection ( IN PCTSTR InfPath, IN HINF InfHandle, IN HASHTABLE DirsTable, IN PCTSTR SectName ) { INFCONTEXT context; PSTR fileName; PSTR dirNumber; PSTR destName; PSTR key; INT dispNumber; WORD userFlags; DWORD offset; BOOL result = TRUE; __try { fileName = AllocText (MAX_PATH); dirNumber = AllocText (MAX_PATH); destName = AllocText (MAX_PATH); key = AllocText (MEMDB_MAX); if (!fileName || !dirNumber || !destName || !key) { __leave; } if (SetupFindFirstLine (InfHandle, SectName, NULL, &context)) { do { if (!SetupGetOemStringField (&context, 0, fileName, MAX_TCHAR_PATH, NULL)) { return result; } if (!SetupGetStringField (&context, DIRS_FIELD, dirNumber, MAX_TCHAR_PATH, NULL)) { return result; } if (!SetupGetIntField (&context, DISP_FIELD, &dispNumber)) { dispNumber = 3; } if (!SetupGetStringField (&context, DEST_FIELD, destName, MAX_TCHAR_PATH, NULL)) { StringCopy (destName, fileName); } if (destName [0] == 0) { StringCopy (destName, fileName); } if (dispNumber!=3) { if (HtFindStringAndData (DirsTable, dirNumber, &offset)) { userFlags = (dispNumber == 3) ? SRC_NEVER_COPY : 0; pConvertSIFDir (dirNumber); MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, destName, fileName, GetFileNameFromPath (InfPath)); MemDbSetValueAndFlags (key, offset, userFlags, 0); MemDbSetValueEx ( MEMDB_CATEGORY_NT_FILES_DOUBLED_COPY, fileName, GetFileNameFromPath (InfPath), //TEXT("LAYOUT.INF"), dirNumber, 0, NULL ); if (g_StrictInfs) { MemDbSetValueEx ( MEMDB_CATEGORY_NT_INSTALLED_INFS, fileName, NULL, NULL, 0, NULL ); } } else { if (g_DoWarnings) { MemDbSetValueEx (MEMDB_CATEGORY_NT_FILES_NODIR_COPY, fileName, NULL, NULL, 0, NULL); } } } } while (SetupFindNextLine (&context, &context)); } } __finally { FreeText (fileName); FreeText (dirNumber); FreeText (destName); FreeText (key); } return result; } BOOL pLocalReadNtDirs ( IN HINF InfHandle, IN OUT HASHTABLE DirsTable ) { INFCONTEXT context; TCHAR dirNumber[MAX_TCHAR_PATH]; TCHAR dirString[MAX_TCHAR_PATH]; PCTSTR dirStringPtr; PCTSTR fullPath; DWORD offset; BOOL result = TRUE; PSTR srcDir, destDir, wildCharPtr; PSTR resultTmp = NULL; PRENAMED_DIRS renamedDir; BOOL found; if (SetupFindFirstLine (InfHandle, TEXT("WinntDirectories"), NULL, &context)) { do { if (!SetupGetOemStringField (&context, 0, dirNumber, MAX_TCHAR_PATH, NULL)) { return result; } if (!SetupGetOemStringField (&context, 1, dirString, MAX_TCHAR_PATH, NULL)) { return result; } if (_tcsnextc (dirString) == TEXT('\\')) { dirStringPtr = _tcsinc (dirString); } else { dirStringPtr = dirString; } if (*dirStringPtr) { fullPath = JoinPaths ("10", dirStringPtr); } else { fullPath = DuplicatePathString ("10", 0); } // let's do some dir replacement here found = TRUE; while (found) { renamedDir = g_RenamedDirs; found = FALSE; while ((!found) && renamedDir) { if (IsPatternMatch (renamedDir->SrcDir, fullPath)) { srcDir = DuplicatePathString (renamedDir->SrcDir, 0); destDir = DuplicatePathString (renamedDir->DestDir, 0); wildCharPtr = _tcschr (srcDir, TEXT('*')); if (wildCharPtr) { *wildCharPtr = 0; } wildCharPtr = _tcschr (destDir, TEXT('*')); if (wildCharPtr) { *wildCharPtr = 0; } resultTmp = (PSTR)StringSearchAndReplace (fullPath, srcDir, destDir); if (resultTmp) { FreePathString (fullPath); fullPath = resultTmp; found = TRUE; } FreePathString (destDir); FreePathString (srcDir); } renamedDir = renamedDir->Next; } } MemDbSetValueEx ( MEMDB_CATEGORY_NT_DIRS, fullPath, NULL, NULL, 0, &offset ); HtAddStringAndData (DirsTable, dirNumber, &offset); FreePathString (fullPath); } while (SetupFindNextLine (&context, &context)); } return result; } HASHTABLE g_DirsTable; BOOL pLocalReadNtFiles ( IN PCTSTR InfPath ) { BOOL result = TRUE; HINF infHandle; PCTSTR platformSect = NULL; infHandle = SetupOpenInfFile (InfPath, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); if (infHandle == INVALID_HANDLE_VALUE) { return FALSE; } __try { if (!g_DirsTable) { g_DirsTable = HtAllocWithData (sizeof (DWORD)); } if (g_DirsTable == NULL) { result = FALSE; __leave; } if (!pLocalReadNtDirs (infHandle, g_DirsTable)) { result = FALSE; __leave; } if (!pLocalReadNtFileSection (InfPath, infHandle, g_DirsTable, TEXT("SourceDisksfiles"))) { result = FALSE; __leave; } platformSect = JoinTextEx (NULL, TEXT("SourceDisksfiles"), g_Platform, TEXT("."), 0, NULL); if (!pLocalReadNtFileSection (InfPath, infHandle, g_DirsTable, platformSect)) { result = FALSE; __leave; } } __finally { if (platformSect) { FreeText (platformSect); platformSect = NULL; } SetupCloseInfFile (infHandle); } return result; } // the following functions are copied from hwcomp.c and slightly modified to allow recursive search // and to bypass the exclusion list. BOOL LocalGetFileNames ( IN PCTSTR *InfDirs, IN UINT InfDirCount, IN BOOL QueryFlag ) /*++ Routine Description: LocalGetFileNames searches InfDirs for any file that ends with .INF or .IN_. It builds a MULTI_SZ list of file names that may contain PNP IDs. All compressed INFs are decompressed into a temporary directory. If the QueryFlag is set, the file name list is prepared but no files are decompressed. Arguments: InfDirs - A list of paths to the directory containing INFs, either compressed or non-compressed. InfDirCount - Specifies the number of dirs in the InfDirs array. QueryFlag - QUERYONLY if the function should build the file list but should not decompress; PERFORMCOMPLETEOP if the function should build the file list and decompress as needed. Return Value: TRUE if successfull, FALSE if not. Call GetLastError for an error code. --*/ { UINT u; // // Add list of files for each directory // g_TotalInfFiles = 0; for (u = 0 ; u < InfDirCount ; u++) { if (!pLocalGetFileNamesWorker (InfDirs[u], QueryFlag)) { return FALSE; } } MemDbSetValue (MEMDB_CATEGORY_SRC_INF_FILES_NR, g_TotalInfFiles); if (g_InfDatabase) { MemDbExport (MEMDB_CATEGORY_SRC_INF_FILES, g_InfDatabase, TRUE); } return TRUE; } BOOL pIsDirectorySuppressed ( IN PCTSTR SubDirName ) { return (HtFindString (g_IgnoredDirsTable, SubDirName) != NULL); } BOOL pSameInfFiles ( IN PCTSTR InfDir ) { TREE_ENUM e; PSTR key; PTSTR p; DWORD value; DWORD totalInfFiles = 0; BOOL result = TRUE; __try { key = AllocText (MEMDB_MAX); if (!key) { __leave; } if (EnumFirstFileInTreeEx (&e, InfDir, TEXT("*.in?"), FALSE, FALSE, 1)) { do { if (e.Directory) { if (pIsDirectorySuppressed (e.SubPath)) { AbortEnumCurrentDir (&e); } } else if (IsPatternMatch (TEXT("*.in?"), e.Name)) { // // Make sure file has _ or f at the end. // p = GetEndOfString (e.FindData->cFileName); MYASSERT (p != e.FindData->cFileName); p = _tcsdec2 (e.FindData->cFileName, p); MYASSERT (p); if (!p) { continue; } if (*p != TEXT('_') && _totlower (*p) != TEXT('f')) { continue; } g_TotalInfFiles ++; MemDbBuildKey (key, MEMDB_CATEGORY_SRC_INF_FILES, e.FullPath, NULL, NULL); if (MemDbGetValue (key, &value)) { if (*p == TEXT('_')) { result = (value == e.FindData->nFileSizeLow); } else { result = (value == pComputeChecksum (e.FullPath)); } if (!result) { AbortEnumFileInTree (&e); break; } } else { result = FALSE; AbortEnumFileInTree (&e); break; } } } while (EnumNextFileInTree (&e)); } } __finally { FreeText (key); } return result; } BOOL pShouldRescanInfs ( IN PCTSTR *InfDirs, IN UINT InfDirCount ) { UINT u; DWORD value; BOOL result = FALSE; g_TotalInfFiles = 0; for (u = 0 ; u < InfDirCount ; u++) { if (!pSameInfFiles (InfDirs[u])) { return TRUE; } } if (MemDbGetValue (MEMDB_CATEGORY_SRC_INF_FILES_NR, &value)) { result = (value != g_TotalInfFiles); } else { result = TRUE; } return result; } BOOL pLocalGetFileNamesWorker ( IN PCTSTR InfDir, IN BOOL QueryFlag ) /*++ Routine Description: pLocalGetFileNamesWorker gets the file names for a single directory. See LocalGetFileNames for more details. Arguments: InfDir - Specifies directory holding zero or more INFs (either compressed or non-compressed). QueryFlag - Specifies TRUE if INF list is to be queried, or FALSE if the list is to be fully processed. When QueryFlag is TRUE, files are not decompressed or opened. Return Value: TRUE if the function completes successfully, or FALSE if it fails. Call GetLastError for additional failure information. --*/ { TREE_ENUM e; PSTR key; PTSTR p; PSTR ActualFile; PSTR AnsiFileName; PTSTR FileNameOnDisk; HANDLE hFile; DWORD BytesRead; PSTR UncompressedFile; PSTR CompressedFile; BOOL DecompressFlag; DWORD rc = ERROR_SUCCESS; BYTE BufForSp[2048]; PSP_INF_INFORMATION psp; BOOL result = FALSE; __try { key = AllocText (MEMDB_MAX); ActualFile = AllocText (MAX_PATH); AnsiFileName = AllocText (MAX_PATH); UncompressedFile = AllocText (MAX_PATH); CompressedFile = AllocText (MAX_PATH); if (!key || !ActualFile || !AnsiFileName || !UncompressedFile || !CompressedFile) { __leave; } psp = (PSP_INF_INFORMATION) BufForSp; DEBUGMSG ((DBG_WARNING, "Enumerating %s", InfDir)); // // Get file names // if (EnumFirstFileInTreeEx (&e, InfDir, TEXT("*.in?"), FALSE, FALSE, 1)) { rc = ERROR_SUCCESS; do { if (e.Directory) { if (pIsDirectorySuppressed (e.SubPath)) { AbortEnumCurrentDir (&e); } } else if (IsPatternMatch (TEXT("*.in?"), e.Name)) { // // Make sure file has _ or f at the end. // p = GetEndOfString (e.FindData->cFileName); MYASSERT (p != e.FindData->cFileName); p = _tcsdec2 (e.FindData->cFileName, p); MYASSERT (p); if (!p) { continue; } if (*p != TEXT('_') && _totlower (*p) != TEXT('f')) { continue; } // // add the file to the database list // g_TotalInfFiles ++; MemDbBuildKey (key, MEMDB_CATEGORY_SRC_INF_FILES, e.FullPath, NULL, NULL); if (*p == TEXT('_')) { MemDbSetValue (key, e.FindData->nFileSizeLow); } else { MemDbSetValue (key, pComputeChecksum (e.FullPath)); } // // Default actual file to uncompressed name // StringCopy (ActualFile, e.FindData->cFileName); // // Build source file (CompressedFile) // StringCopy (CompressedFile, InfDir); StringCopy (AppendWack (CompressedFile), e.SubPath); // // Build destination file (UncompressedFile) and detect collisions // StringCopy (UncompressedFile, g_TempDir); // // Create uncompressed file path // if (*p == TEXT('_')) { // // Extract real name from INF file at offset 0x3c // ActualFile[0] = 0; hFile = CreateFile ( CompressedFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile != INVALID_HANDLE_VALUE) { if (0xffffffff != SetFilePointer (hFile, 0x3c, NULL, FILE_BEGIN)) { if (ReadFile ( hFile, AnsiFileName, MAX_PATH, &BytesRead, NULL )) { if (BytesRead >= SizeOfString (e.FindData->cFileName)) { FileNameOnDisk = ConvertAtoT (AnsiFileName); if (StringIMatchCharCount ( e.FindData->cFileName, FileNameOnDisk, CharCount (e.FindData->cFileName) - 1 )) { // // Real name found -- use it as ActualFile // StringCopy (ActualFile, FileNameOnDisk); StringCopy (AppendWack (UncompressedFile), ActualFile); } FreeAtoT (FileNameOnDisk); } } } CloseHandle (hFile); } // // If file name could not be found, discard this file // if (!ActualFile[0]) { DEBUGMSG ((DBG_WARNING, "%s is not an INF file", e.FindData->cFileName)); continue; } DecompressFlag = TRUE; } else { StringCopy (AppendWack (UncompressedFile), ActualFile); DecompressFlag = FALSE; } // // Skip excluded files // if (!QueryFlag) { // // Uncompress file if necessary // /* DEBUGMSG_IF (( DoesFileExist (UncompressedFile), DBG_WARNING, "%s already exists and will be deleted", UncompressedFile )); */ if (DecompressFlag) { SetFileAttributes (UncompressedFile, FILE_ATTRIBUTE_NORMAL); DeleteFile (UncompressedFile); rc = SetupDecompressOrCopyFile (CompressedFile, UncompressedFile, 0); if (rc != ERROR_SUCCESS) { DEBUGMSG ((DBG_WARNING, "pLocalGetFileNamesWorker: Could not decompress %s to %s", CompressedFile, UncompressedFile)); fprintf ( stderr, "Could not copy %s to %s. Error %u.", CompressedFile, UncompressedFile, GetLastError() ); break; } } else { CopyFile (CompressedFile, UncompressedFile, FALSE); } // // Determine if this is an NT 4 INF // if (!SetupGetInfInformation ( UncompressedFile, INFINFO_INF_NAME_IS_ABSOLUTE, psp, sizeof (BufForSp), NULL) || psp->InfStyle != INF_STYLE_WIN4 ) { //DEBUGMSG ((DBG_WARNING, "%s is not a WIN4 INF file", UncompressedFile)); if (!QueryFlag) { DeleteFile (UncompressedFile); } StringCopy (UncompressedFile, S_IGNORE_THIS_FILE); } } // // Add file to grow buffer // MemDbSetValueEx (MEMDB_CATEGORY_INF_FILES, UncompressedFile, NULL, NULL, 0, NULL); } MYASSERT (rc == ERROR_SUCCESS); } while (EnumNextFileInTree (&e)); } if (rc != ERROR_SUCCESS) { SetLastError (rc); DEBUGMSG ((DBG_WARNING, "pLocalGetFileNamesWorker: Error encountered in loop")); __leave; } result = TRUE; } __finally { FreeText (key); FreeText (ActualFile); FreeText (AnsiFileName); FreeText (UncompressedFile); FreeText (CompressedFile); } return result; } VOID LocalFreeFileNames ( IN BOOL QueryFlag ) /*++ Routine Description: LocalFreeFileNames cleans up the list generated by LocalGetFileNames. If QueryFlag is set to PERFORMCOMPLETEOP, all temporary decompressed files are deleted. Arguments: FileNames - The same grow buffer passed to LocalGetFileNames QueryFlag - The same flag passed to LocalGetFileNames Return Value: none --*/ { MEMDB_ENUM enumFiles; if (MemDbEnumFirstValue ( &enumFiles, MEMDB_CATEGORY_INF_FILES TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { do { if (StringIMatchCharCount (enumFiles.szName, g_TempDirWack, g_TempDirWackChars)) { SetFileAttributes (enumFiles.szName, FILE_ATTRIBUTE_NORMAL); DeleteFile (enumFiles.szName); } } while (MemDbEnumNextValue (&enumFiles)); } MemDbDeleteTree (MEMDB_CATEGORY_INF_FILES); }