#include "pch.h" typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID); INITROUTINE_PROTOTYPE MigUtil_Entry; INITROUTINE_PROTOTYPE MemDb_Entry; INITROUTINE_PROTOTYPE FileEnum_Entry; #define DBG_MODULES "MODULES" #define FLAG_BAD_FUNCTION 1 #define FLAG_BAD_INDEX 2 HINSTANCE g_hInst; HANDLE g_hHeap; BOOL g_CancelFlag = FALSE; DWORD g_DirSequencer = 0; DWORD g_FileSequencer = 0; #ifdef DEBUG extern BOOL g_DoLog; #endif extern BOOL *g_CancelFlagPtr = &g_CancelFlag; extern POOLHANDLE g_PathsPool; BOOL WriteE95Only ( VOID ); BOOL ReadNtFilesEx ( IN PCSTR FileListName, //optional, if null default is opened IN BOOL ConvertPath ); BOOL pHandleFile ( IN PCTSTR FileName, IN BOOL Win95Side ); BOOL pHandleAllFiles ( IN PCTSTR SrcPath, IN BOOL Win95Side ); BOOL pDeleteAllFiles ( IN PCTSTR DirPath ); BOOL pProcessExportModule ( IN PCTSTR ModuleName, IN BOOL Win95Side ); BOOL pLoadKnownGoodExports ( IN HINF ConfigHandle ); BOOL pLoadIgnoredFiles ( IN HINF ConfigHandle ); BOOL pLocalLoadNTFilesData ( IN PCTSTR FilePath, IN HINF ConfigHandle ); BOOL pCompressedFile ( IN PTREE_ENUM e ); BOOL pWorkerFn ( IN HINF ConfigHandle ); BOOL pHandleSection ( IN PCTSTR SectionName, IN HINF ConfigHandle ); VOID pInitProgBarVars ( VOID ); VOID pUsage ( VOID ) { _tprintf (TEXT ("\nCommand line syntax:\n\n" "exports [/B:BaseDir] [/T:TempDir] [/F[:SectionName]]\n\n" "/B Specifies the base directory where all exports files are\n" " located. (e95only.dat, exports.cfg)\n" "/T Specifies the temporary directory used for unpacking\n" " cabinet files\n" "/F Forces rescanning a particular section or all sections\n" "/I Specifies path to NTFILES (default %NTTREE%)\n")); } PTSTR g_ConfigFile = NULL; PTSTR g_TempDir = NULL; PTSTR g_BaseDir = NULL; PTSTR g_ExportDest = NULL; PTSTR g_TxtSetupPath = NULL; PTSTR g_RescanSect = NULL; BOOL g_RescanFlag = FALSE; extern HINF g_MigDbInf; GROWBUFFER g_SectFiles = GROWBUF_INIT; #define MEMDB_CATEGORY_WNT_EXPORTS TEXT("WNtExports") #define MEMDB_CATEGORY_W95_SECTIONS TEXT("W95Sections") void __cdecl main ( int argc, CHAR *argv[] ) { INT argidx, index; INT nextArg = 0; HINF configHandle = INVALID_HANDLE_VALUE; TCHAR fileName [MAX_TCHAR_PATH] = ""; PTSTR dontCare; #ifdef DEBUG g_DoLog = TRUE; #endif g_hInst = GetModuleHandle (NULL); g_hHeap = GetProcessHeap(); if (!MigUtil_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) { _tprintf (TEXT("MigUtil failed initializing\n")); exit (1); } if (!MemDb_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) { _tprintf (TEXT("MemDb failed initializing\n")); exit(1); } for (argidx = 1; argidx < argc; argidx++) { if ((argv[argidx][0] != '-') && (argv[argidx][0] != '/') ) { if (nextArg == 0) { pUsage (); exit (1); } switch (nextArg) { case 1: index = 0; goto label1; case 2: index = 0; goto label2; case 3: index = 0; goto label3; case 4: index = 0; goto label4; } } switch (toupper(argv[argidx][1])) { case 'B': if (argv[argidx][2] == 0) { nextArg = 1; } else { if (argv[argidx][2] != ':') { index = 2; } else { index = 3; } label1: nextArg = 0; g_BaseDir = AllocPathString (MAX_TCHAR_PATH); #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_BaseDir, MAX_TCHAR_PATH); #else _tcsncpy (g_BaseDir, argv[argidx]+index, MAX_TCHAR_PATH); #endif } break; case 'T': if (argv[argidx][2] == 0) { nextArg = 2; } else { if (argv[argidx][2] != ':') { index = 2; } else { index = 3; } label2: nextArg = 0; g_TempDir = AllocPathString (MAX_TCHAR_PATH); #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_TempDir, MAX_TCHAR_PATH); #else _tcsncpy (g_TempDir, argv[argidx]+index, MAX_TCHAR_PATH); #endif } break; case 'I': if (argv[argidx][2] == 0) { nextArg = 3; } else { if (argv[argidx][2] != ':') { index = 2; } else { index = 3; } label3: nextArg = 0; g_TxtSetupPath = AllocPathString (MAX_TCHAR_PATH); #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_TxtSetupPath, MAX_TCHAR_PATH); #else _tcsncpy (g_TxtSetupPath, argv[argidx]+index, MAX_TCHAR_PATH); #endif } break; case 'F': g_RescanFlag = TRUE; if (argv[argidx][2] == 0) { nextArg = 4; } else { if (argv[argidx][2] != ':') { index = 2; } else { index = 3; } label4: nextArg = 0; g_RescanSect = AllocPathString (MAX_TCHAR_PATH); #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, argv[argidx]+index, -1, g_RescanSect, MAX_TCHAR_PATH); #else _tcsncpy (g_RescanSect, argv[argidx]+index, MAX_TCHAR_PATH); #endif } break; default: pUsage (); exit (1); } } if (g_BaseDir == NULL) { g_BaseDir = AllocPathString (MAX_TCHAR_PATH); _tcsncpy (g_BaseDir, TEXT(".\\"), MAX_TCHAR_PATH); } if (g_TempDir == NULL) { g_TempDir = AllocPathString (MAX_TCHAR_PATH); if (GetEnvironmentVariable (TEXT("TEMP"), g_TempDir, MAX_TCHAR_PATH) == 0) { _tcsncpy (g_TempDir, TEXT("C:\\TEMP"), MAX_TCHAR_PATH); } } if (g_TxtSetupPath == NULL) { g_TxtSetupPath = AllocPathString (MAX_TCHAR_PATH); if ((GetEnvironmentVariable (TEXT("_NTTREE" ), g_TxtSetupPath, MAX_TCHAR_PATH) == 0) && (GetEnvironmentVariable (TEXT("_NT386TREE"), g_TxtSetupPath, MAX_TCHAR_PATH) == 0) ) { _tcsncpy (g_TxtSetupPath, TEXT("."), MAX_TCHAR_PATH); } } g_ConfigFile = JoinPaths (g_BaseDir, TEXT("exports.cfg")); g_ExportDest = JoinPaths (g_BaseDir, TEXT("e95only.dat")); if (!DoesFileExist (g_ConfigFile)) { _tprintf (TEXT("\nConfiguration file not found. Exiting.\n")); exit (1); } if (SearchPath (NULL, TEXT("extract.exe"), NULL, 0, NULL, NULL) == 0) { _tprintf (TEXT("\nCannot find extract.exe. Exiting.\n")); exit (1); } configHandle = SetupOpenInfFile (g_ConfigFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); if (configHandle == INVALID_HANDLE_VALUE) { SearchPath (NULL, g_ConfigFile, NULL, MAX_TCHAR_PATH, fileName, &dontCare); configHandle = SetupOpenInfFile (fileName, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); if (configHandle == INVALID_HANDLE_VALUE) { _tprintf (TEXT("\nCannot open configuration file %s. Exiting.\n"), g_ConfigFile); exit (1); } } if (!pLoadKnownGoodExports (configHandle)) { _tprintf (TEXT("\nCannot load known good exports. Exiting.\n")); exit (1); } if (!pLocalLoadNTFilesData (g_TxtSetupPath, configHandle)) { _tprintf (TEXT("\nCannot load NT file list. Exiting.\n")); exit (1); } if (!pLoadIgnoredFiles (configHandle)) { _tprintf (TEXT("\nCannot load ignored files. Exiting.\n")); exit (1); } pWorkerFn (configHandle); WriteE95Only (); FreePathString (g_ConfigFile); FreePathString (g_TempDir); FreePathString (g_BaseDir); FreePathString (g_ExportDest); if (!MemDb_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) { _tprintf (TEXT("MemDb failed initializing\n")); exit(1); } if (!MigUtil_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) { _tprintf (TEXT("MigUtil failed initializing\n")); exit (1); } } BOOL WriteE95Only ( VOID ) { return MemDbExportA (MEMDB_CATEGORY_WIN9X_APIS, g_ExportDest, TRUE); } BOOL pLoadKnownGoodExports ( IN HINF ConfigHandle ) { INFCONTEXT context; TCHAR goodExport [MAX_TCHAR_PATH]; INT goodExportIdx; if (SetupFindFirstLine (ConfigHandle, TEXT("KnownGood"), NULL, &context)) { do { if (!SetupGetStringField (&context, 0, goodExport, MAX_TCHAR_PATH, NULL)) { _tprintf (TEXT("\nBad section [KnownGood] in %s. Exiting.\n"), g_ConfigFile); return FALSE; } if (!SetupGetIntField (&context, 1, &goodExportIdx)) { _tprintf (TEXT("\nBad section [KnownGood] in %s. Exiting.\n"), g_ConfigFile); return FALSE; } MemDbSetValueEx (MEMDB_CATEGORY_WNT_EXPORTS, goodExport, NULL, NULL, goodExportIdx, NULL); } while (SetupFindNextLine (&context, &context)); } return TRUE; } BOOL pLoadIgnoredFiles ( IN HINF ConfigHandle ) { INFCONTEXT context; TCHAR ignoredFile [MAX_TCHAR_PATH]; TCHAR key [MEMDB_MAX]; if (SetupFindFirstLine (ConfigHandle, TEXT("IgnoredFiles"), NULL, &context)) { do { if (!SetupGetStringField (&context, 0, ignoredFile, MAX_TCHAR_PATH, NULL)) { _tprintf (TEXT("\nBad section [IgnoredFiles] in %s. Exiting.\n"), g_ConfigFile); return FALSE; } MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, ignoredFile, NULL, NULL); MemDbDeleteTree (key); } while (SetupFindNextLine (&context, &context)); } return TRUE; } BOOL pLocalLoadNTFilesData ( IN PCTSTR FilePath, IN HINF ConfigHandle ) { PCSTR fileListName = NULL; PCSTR fileListNameTmp = NULL; //first let's read FILELIST.DAT fileListName = JoinPaths (g_TxtSetupPath, S_FILELIST_UNCOMPRESSED); if (!DoesFileExist (fileListName)) { fileListName = JoinPaths (g_TxtSetupPath, S_FILELIST_COMPRESSED); if (!DoesFileExist (fileListName)) { _tprintf (TEXT("Could not find FILELIST.DAT.")); FreePathString (fileListName); return FALSE; } fileListNameTmp = JoinPaths (g_TempDir, S_FILELIST_UNCOMPRESSED); if (SetupDecompressOrCopyFile (fileListName, fileListNameTmp, 0) != NO_ERROR) { _tprintf (TEXT("Could not decompress FILELIST.DAT.")); FreePathString (fileListName); FreePathString (fileListNameTmp); return FALSE; } FreePathString (fileListNameTmp); } if (!ReadNtFilesEx (fileListNameTmp?fileListNameTmp:fileListName, FALSE)) { _tprintf (TEXT("Could not read FILELIST.DAT.")); if (fileListName) { FreePathString (fileListName); } if (fileListNameTmp) { DeleteFile (fileListNameTmp); FreePathString (fileListNameTmp); } return FALSE; } if (fileListName) { FreePathString (fileListName); } if (fileListNameTmp) { DeleteFile (fileListNameTmp); FreePathString (fileListNameTmp); } _tprintf (TEXT("Processing NT files ... \n")); if (!pHandleAllFiles (FilePath, FALSE)) { return FALSE; } return TRUE; } UINT pCabinetCallback ( IN PVOID Context, //context used by the callback routine IN UINT Notification, //notification sent to callback routine IN UINT Param1, //additional notification information IN UINT Param2 //additional notification information ); ) { PCTSTR tempDir = Context; PCTSTR fileName = (PCTSTR)Param2 ; PFILE_IN_CABINET_INFO fileInfo = (PFILE_IN_CABINET_INFO)Param1; switch (Notification) { case SPFILENOTIFY_FILEEXTRACTED : case SPFILENOTIFY_NEEDNEWCABINET : return NO_ERROR; case SPFILENOTIFY_FILEINCABINET : _stprintf (fileInfo->FullTargetName, TEXT("%s\\%s"), tempDir, fileInfo->NameInCabinet); return FILEOP_DOIT; } return NO_ERROR; } BOOL pWorkerFn ( HINF ConfigHandle ) { INFCONTEXT context; TCHAR sectName [MAX_TCHAR_PATH]; if (SetupFindFirstLine (ConfigHandle, TEXT("sections"), NULL, &context)) { do { if (!SetupGetStringField (&context, 1, sectName, MAX_TCHAR_PATH, NULL)) { _tprintf (TEXT("\nBad section [SECTIONS] in %s. Exiting.\n"), g_ConfigFile); return FALSE; } if (!pHandleSection (sectName, ConfigHandle)) { return FALSE; } } while (SetupFindNextLine (&context, &context)); } return TRUE; } BOOL pDeleteAllFiles ( IN PCTSTR DirPath ) { TREE_ENUM e; TCHAR tempFile [MAX_TCHAR_PATH] = ""; BOOL dirsFirst = FALSE; if (EnumFirstFileInTree (&e, DirPath, TEXT("*"), dirsFirst)) { do { if (e.Directory) { DEBUGMSG((DBG_ERROR, "Unexpected directory in temporary area.")); return FALSE; } _stprintf (tempFile, TEXT("%s\\%s"), DirPath, e.Name); if (!DeleteFile (tempFile)) { return FALSE; } } while (EnumNextFileInTree (&e)); } return TRUE; } BOOL pSelected ( IN PCTSTR FileName ) { TCHAR key[MEMDB_MAX]; DWORD dontCare; MemDbBuildKey (key, MEMDB_CATEGORY_NT_FILES, FileName, NULL, NULL); return MemDbGetValue (key, &dontCare); } BOOL pCabinetFile ( IN PCTSTR FileName ) { PCTSTR extPtr; extPtr = GetFileExtensionFromPath (FileName); if ((extPtr != NULL) && (_tcsicmp (extPtr, TEXT("CAB")) == 0) ) { return TRUE; } return FALSE; } BOOL pHandleFile ( IN PCTSTR FileName, IN BOOL Win95Side ) { pProcessExportModule (FileName, Win95Side); return TRUE; } BOOL pCompressedFile ( IN PTREE_ENUM e ) { PCTSTR extPtr; extPtr = GetFileExtensionFromPath (e->FullPath); if (extPtr == NULL) { return FALSE; } if (_tcslen (extPtr) != 3) { return FALSE; } return (extPtr [2] == TEXT('_')); } BOOL pExeFile ( IN PTREE_ENUM e ) { PCTSTR extPtr; extPtr = GetFileExtensionFromPath (e->FullPath); if ((extPtr != NULL) && (StringIMatch (extPtr, TEXT("EXE"))) ) { return TRUE; } return FALSE; } BOOL pCopyAndHandleCabResource ( IN PVOID Source, IN DWORD Size, IN PCTSTR DirName ) { TCHAR cabDir [MAX_TCHAR_PATH] = ""; HANDLE hFile; DWORD dontCare; if (Size < 4) { return TRUE; } if (*((PDWORD)Source) != 0x4643534D) { return TRUE; } g_FileSequencer ++; _stprintf (cabDir, TEXT("%s\\MIGDB%03u.CAB"), DirName, g_FileSequencer); hFile = CreateFile (cabDir, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { DEBUGMSG ((DBG_ERROR, "Cannot create file %s", cabDir)); return FALSE; } if (!WriteFile (hFile, Source, Size, &dontCare, NULL)) { DEBUGMSG ((DBG_ERROR, "Cannot write to file %s", cabDir)); return FALSE; } CloseHandle (hFile); return TRUE; } BOOL CALLBACK EnumResNameProc ( IN HANDLE hModule, // module handle IN LPCTSTR lpszType, // pointer to resource type IN LPTSTR lpszName, // pointer to resource name IN LONG lParam // application-defined parameter ) { HRSRC hResource; DWORD size; HGLOBAL hGlobal; PVOID srcBytes; hResource = FindResource (hModule, lpszName, lpszType); if (hResource) { size = SizeofResource (hModule, hResource); if (size) { hGlobal = LoadResource (hModule, hResource); if (hGlobal) { srcBytes = LockResource (hGlobal); if (srcBytes) { pCopyAndHandleCabResource (srcBytes, size, (PCTSTR)lParam); } } } } return TRUE; } BOOL CALLBACK EnumResTypeProc ( IN HANDLE hModule, // resource-module handle IN LPTSTR lpszType, // pointer to resource type IN LONG lParam // application-defined parameter ) { if ((lpszType != RT_ACCELERATOR ) && (lpszType != RT_ANICURSOR ) && (lpszType != RT_ANIICON ) && (lpszType != RT_BITMAP ) && (lpszType != RT_CURSOR ) && (lpszType != RT_DIALOG ) && (lpszType != RT_FONT ) && (lpszType != RT_FONTDIR ) && (lpszType != RT_GROUP_CURSOR ) && (lpszType != RT_GROUP_ICON ) && (lpszType != RT_HTML ) && (lpszType != RT_ICON ) && (lpszType != RT_MENU ) && (lpszType != RT_MESSAGETABLE ) && (lpszType != RT_PLUGPLAY ) && (lpszType != RT_STRING ) && (lpszType != RT_VERSION ) && (lpszType != RT_VXD ) && (lpszType != RT_HTML ) ) { // we found an unknown type. Let's enumerate all resources of this type if (EnumResourceNames (hModule, lpszType, EnumResNameProc, lParam) == 0) { DEBUGMSG ((DBG_ERROR, "Error enumerating names:%ld", GetLastError ())); } } return TRUE; } BOOL pHandleAllFiles ( IN PCTSTR SrcPath, IN BOOL Win95Side ) { TCHAR tempDir [MAX_TCHAR_PATH] = ""; TCHAR cmdLine [MAX_TCHAR_PATH] = ""; TREE_ENUM e; DWORD error; HMODULE exeModule; PROCESS_INFORMATION processInfo; STARTUPINFO startupInfo; if (EnumFirstFileInTree (&e, SrcPath, TEXT("*"), FALSE)) { do { if (!e.Directory) { if (pCabinetFile (e.Name)) { // cabinet file g_DirSequencer++; _stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer); if (CreateDirectory (tempDir, NULL) == 0) { error = GetLastError (); if (error == ERROR_ALREADY_EXISTS) { pDeleteAllFiles (tempDir); } ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir)); } _tprintf (TEXT(" Extracting cabinet file ... %s"), e.Name); // we need to expand the cabinet file SetLastError (0); if (!SetupIterateCabinet (e.FullPath, 0, pCabinetCallback, tempDir)) { _tprintf (TEXT("...error %ld\n"), GetLastError()); DEBUGMSG((DBG_ERROR, "Could not iterate cabinet file:%s\nError:%ld", e.FullPath, GetLastError ())); } else { _tprintf (TEXT("...done\n")); } if (!pHandleAllFiles (tempDir, Win95Side)) { return FALSE; } pDeleteAllFiles (tempDir); RemoveDirectory (tempDir); g_DirSequencer--; } else if (pCompressedFile (&e)) { // compressed file g_DirSequencer++; _stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer); if (CreateDirectory (tempDir, NULL) == 0) { error = GetLastError (); if (error == ERROR_ALREADY_EXISTS) { pDeleteAllFiles (tempDir); } ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir)); } _stprintf (cmdLine, TEXT("expand /r %s %s"), e.FullPath, tempDir); ZeroMemory (&startupInfo, sizeof (STARTUPINFO)); startupInfo.cb = sizeof (STARTUPINFO); if (CreateProcess (NULL, cmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo)) { WaitForSingleObject (processInfo.hProcess, INFINITE); CloseHandle (processInfo.hProcess); CloseHandle (processInfo.hThread); if (!pHandleAllFiles (tempDir, Win95Side)) { return FALSE; } pDeleteAllFiles (tempDir); } else { DEBUGMSG ((DBG_ERROR, "Could not decompress:%s, Error:%ld", e.Name, GetLastError())); } RemoveDirectory (tempDir); g_DirSequencer--; } else { if (pExeFile (&e)) { g_FileSequencer = 0; g_DirSequencer++; _stprintf (tempDir, TEXT("%s\\MIGDB%03u"), g_TempDir, g_DirSequencer); if (CreateDirectory (tempDir, NULL) == 0) { error = GetLastError (); if (error == ERROR_ALREADY_EXISTS) { pDeleteAllFiles (tempDir); } ELSE_DEBUGMSG ((DBG_ERROR, "Cannot create directory %s", tempDir)); } exeModule = LoadLibraryEx (e.FullPath, NULL, LOAD_LIBRARY_AS_DATAFILE); EnumResourceTypes (exeModule, EnumResTypeProc, (LONG)tempDir); FreeLibrary (exeModule); if (!pHandleAllFiles (tempDir, Win95Side)) { return FALSE; } pDeleteAllFiles (tempDir); RemoveDirectory (tempDir); g_DirSequencer--; } if (pSelected (e.Name)) { if (!pHandleFile (e.FullPath, Win95Side)) { return FALSE; } } } } else { if (!Win95Side) { if ((StringIMatch (e.SubPath, TEXT("Win9xMig"))) || (StringIMatch (e.SubPath, TEXT("\\Win9xMig"))) || (StringIMatch (e.SubPath, TEXT("Winnt32"))) || (StringIMatch (e.SubPath, TEXT("\\Winnt32"))) || (StringIMatch (e.SubPath, TEXT("System32"))) || (StringIMatch (e.SubPath, TEXT("\\System32"))) ) { AbortEnumFileInTree (&e); } } } } while (EnumNextFileInTree (&e)); } return TRUE; } BOOL pHandleSection ( IN PCTSTR SectionName, IN HINF ConfigHandle ) { INFCONTEXT context; TCHAR srcPath [MAX_TCHAR_PATH] = ""; TCHAR key [MEMDB_MAX] = ""; BOOL forced = FALSE; INT field; TCHAR includePattern [MAX_TCHAR_PATH] = ""; DWORD dontCare; _tprintf (TEXT("Processing section : %s ... "), SectionName); if (!SetupFindFirstLine (ConfigHandle, SectionName, TEXT("sourcepath"), &context)) { _tprintf (TEXT("\nCannot find SourcePath= line in %s.\n"), SectionName); return FALSE; } if (!SetupGetStringField (&context, 1, srcPath, MAX_TCHAR_PATH, NULL)) { _tprintf (TEXT("\nCannot read source path name in %s.\n"), SectionName); return FALSE; } g_SectFiles.Buf = NULL; g_SectFiles.Size = 0; g_SectFiles.End = 0; g_SectFiles.GrowSize = 0; g_SectFiles.UserIndex = 0; if (SetupFindFirstLine (ConfigHandle, SectionName, TEXT("IncludeFiles"), &context)) { field = 1; while (SetupGetStringField (&context, field, includePattern, MAX_TCHAR_PATH, NULL)) { MultiSzAppend (&g_SectFiles, includePattern); field ++; } } // let's try to find if this section was already processed in migdb.inx MemDbBuildKey (key, MEMDB_CATEGORY_W95_SECTIONS, SectionName, NULL, NULL); if (MemDbGetValue (key, &dontCare)) { FreeGrowBuffer (&g_SectFiles); _tprintf (TEXT("skipped\n")); return TRUE; } _tprintf (TEXT("\n")); MemDbSetValue (key, 0); if (!pHandleAllFiles (srcPath, TRUE)) { FreeGrowBuffer (&g_SectFiles); return FALSE; } FreeGrowBuffer (&g_SectFiles); return TRUE; } //from here we are dealing with 16 bit and 32 bit modules decompiling code //since we are reading from a file we need that sizeof to give us the accurate result #pragma pack(push,1) typedef struct _NE_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; WORD EntryTableOff; WORD EntryTableLen; ULONG Reserved; WORD Flags; WORD NumberOfDataSeg; WORD SizeOfHeap; WORD SizeOfStack; ULONG CS_IP; ULONG SS_SP; WORD NumEntriesSegTable; WORD NumEntriesModuleTable; WORD NonResNameTableSize; WORD SegTableOffset; WORD ResTableOffset; WORD ResNameTableOffset; WORD ModuleTableOffset; WORD ImportedTableOffset; ULONG NonResNameTableOffset; WORD NumberOfMovableEntryPoints; WORD ShiftCount; WORD NumberOfResourceSegments; BYTE TargetOS; BYTE AdditionalInfo; WORD FastLoadOffset; WORD FastLoadSize; WORD Reserved1; WORD WinVersionExpected; } NE_HEADER, *PNE_HEADER; typedef struct _NE_SEGMENT_ENTRY { WORD SegmentOffset; WORD SegmentLen; WORD SegmentFlags; WORD SegMinAlloc; } NE_SEGMENT_ENTRY, *PNE_SEGMENT_ENTRY; typedef struct _NE_RELOC_ITEM { BYTE AddressType; BYTE RelocType; WORD RelocOffset; WORD ModuleOffset; WORD FunctionOffset; } NE_RELOC_ITEM, *PNE_RELOC_ITEM; #define SEG_CODE_MASK 0x0001 #define SEG_CODE 0x0000 #define SEG_PRELOAD_MASK 0x0040 #define SEG_PRELOAD 0x0040 #define SEG_RELOC_MASK 0x0100 #define SEG_RELOC 0x0100 #define RELOC_IMPORTED_ORDINAL 0x01 #define RELOC_IMPORTED_NAME 0x02 #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ #define IMAGE_NE_SIGNATURE 0x454E // NE #define IMAGE_PE_SIGNATURE 0x00004550l // PE00 #pragma pack(pop) typedef struct _EXPORT_ENUM32 { /*user area - BEGIN*/ PCSTR ExportFunction; DWORD ExportFunctionOrd; /*user area - END*/ PLOADED_IMAGE Image; PIMAGE_EXPORT_DIRECTORY ImageDescriptor; PDWORD ExportNamesAddr; PUSHORT ExportOrdAddr; DWORD CurrExportNr; } EXPORT_ENUM32, *PEXPORT_ENUM32; typedef struct _EXPORT_ENUM16 { /*user area - BEGIN*/ CHAR ExportFunction[MAX_MBCHAR_PATH]; PUSHORT ExportFunctionOrd; /*user area - END*/ BOOL ResTable; PCSTR Image; PDOS_HEADER DosHeader; PNE_HEADER NeHeader; PCSTR NamesEntry; } EXPORT_ENUM16, *PEXPORT_ENUM16; #define UNKNOWN_MODULE 0 #define DOS_MODULE 1 #define W16_MODULE 2 #define W32_MODULE 3 typedef struct _MODULE_IMAGE { UINT ModuleType; union { struct { LOADED_IMAGE Image; } W32Data; struct { PCSTR Image; HANDLE FileHandle; HANDLE MapHandle; } W16Data; } ModuleData; } MODULE_IMAGE, *PMODULE_IMAGE; BOOL pLoadModuleData ( IN PCSTR ModuleName, IN OUT PMODULE_IMAGE ModuleImage ) { HANDLE fileHandle; DWORD bytesRead; DOS_HEADER dh; DWORD sign; PWORD signNE = (PWORD)&sign; BOOL result = FALSE; ZeroMemory (ModuleImage, sizeof (MODULE_IMAGE)); fileHandle = CreateFile (ModuleName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (fileHandle == INVALID_HANDLE_VALUE) { ModuleImage->ModuleType = UNKNOWN_MODULE; return FALSE; } __try { __try { if ((!ReadFile (fileHandle, &dh, sizeof (DOS_HEADER), &bytesRead, NULL)) || (bytesRead != sizeof (DOS_HEADER)) ) { __leave; } result = TRUE; if (dh.e_magic != IMAGE_DOS_SIGNATURE) { ModuleImage->ModuleType = UNKNOWN_MODULE; __leave; } ModuleImage->ModuleType = DOS_MODULE; if (SetFilePointer (fileHandle, dh.e_lfanew, NULL, FILE_BEGIN) != (DWORD)dh.e_lfanew) { __leave; } if ((!ReadFile (fileHandle, &sign, sizeof (DWORD), &bytesRead, NULL)) || (bytesRead != sizeof (DWORD)) ) { __leave; } CloseHandle (fileHandle); fileHandle = INVALID_HANDLE_VALUE; if (sign == IMAGE_PE_SIGNATURE) { ModuleImage->ModuleType = W32_MODULE; result = MapAndLoad ((PSTR)ModuleName, NULL, &ModuleImage->ModuleData.W32Data.Image, FALSE, TRUE); } if (*signNE == IMAGE_NE_SIGNATURE) { ModuleImage->ModuleType = W16_MODULE; ModuleImage->ModuleData.W16Data.Image = MapFileIntoMemory ( ModuleName, &ModuleImage->ModuleData.W16Data.FileHandle, &ModuleImage->ModuleData.W16Data.MapHandle ); result = (ModuleImage->ModuleData.W16Data.Image != NULL); } } __finally { if (fileHandle != INVALID_HANDLE_VALUE) { CloseHandle (fileHandle); } } } __except (EXCEPTION_EXECUTE_HANDLER) { CloseHandle (fileHandle); } return result; } BOOL pUnloadModuleData ( IN OUT PMODULE_IMAGE ModuleImage ) { switch (ModuleImage->ModuleType) { case W32_MODULE: UnMapAndLoad (&ModuleImage->ModuleData.W32Data.Image); break; case W16_MODULE: UnmapFile ( (PVOID) ModuleImage->ModuleData.W16Data.Image, ModuleImage->ModuleData.W16Data.FileHandle, ModuleImage->ModuleData.W16Data.MapHandle ); break; default:; } return TRUE; } BOOL EnumNextExportFunction16 ( IN OUT PEXPORT_ENUM16 ModuleExports ) { ModuleExports->NamesEntry += ModuleExports->NamesEntry [0] + 3; if (ModuleExports->NamesEntry [0] == 0) { if (!ModuleExports->ResTable) { return FALSE; } else { ModuleExports->ResTable = FALSE; ModuleExports->NamesEntry = ModuleExports->Image + ModuleExports->NeHeader->NonResNameTableOffset; return EnumNextExportFunction16 (ModuleExports); } } strncpy (ModuleExports->ExportFunction, ModuleExports->NamesEntry + 1, ModuleExports->NamesEntry [0]); ModuleExports->ExportFunction [ModuleExports->NamesEntry [0]] = 0; ModuleExports->ExportFunctionOrd = (PUSHORT) (ModuleExports->NamesEntry + ModuleExports->NamesEntry [0] + 1); return TRUE; } BOOL EnumFirstExportFunction16 ( IN PCSTR ModuleImage, IN OUT PEXPORT_ENUM16 ModuleExports ) { ZeroMemory (ModuleExports, sizeof (EXPORT_ENUM16)); ModuleExports->Image = ModuleImage; ModuleExports->ResTable = TRUE; ModuleExports->DosHeader = (PDOS_HEADER) (ModuleExports->Image); ModuleExports->NeHeader = (PNE_HEADER) (ModuleExports->Image + ModuleExports->DosHeader->e_lfanew); ModuleExports->NamesEntry = ModuleExports->Image + ModuleExports->DosHeader->e_lfanew + ModuleExports->NeHeader->ResNameTableOffset; return EnumNextExportFunction16 (ModuleExports); } BOOL EnumNextExportFunction32 ( IN OUT PEXPORT_ENUM32 ModuleExports ) { if (ModuleExports->CurrExportNr >= ModuleExports->ImageDescriptor->NumberOfNames) { return FALSE; } if (*ModuleExports->ExportNamesAddr == 0) { return FALSE; } ModuleExports->ExportFunction = ImageRvaToVa ( ModuleExports->Image->FileHeader, ModuleExports->Image->MappedAddress, *ModuleExports->ExportNamesAddr, NULL ); ModuleExports->ExportFunctionOrd = *ModuleExports->ExportOrdAddr + ModuleExports->ImageDescriptor->Base; ModuleExports->ExportNamesAddr ++; ModuleExports->ExportOrdAddr ++; ModuleExports->CurrExportNr ++; return (ModuleExports->ExportFunction != NULL); } BOOL EnumFirstExportFunction32 ( IN PLOADED_IMAGE ModuleImage, IN OUT PEXPORT_ENUM32 ModuleExports ) { ULONG imageSize; ZeroMemory (ModuleExports, sizeof (EXPORT_ENUM32)); ModuleExports->Image = ModuleImage; ModuleExports->ImageDescriptor = (PIMAGE_EXPORT_DIRECTORY) ImageDirectoryEntryToData ( ModuleImage->MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_EXPORT, &imageSize ); if (!ModuleExports->ImageDescriptor) { DEBUGMSG((DBG_MODULES, ":Cannot load export directory for %s", ModuleImage->ModuleName)); return FALSE; } if (ModuleExports->ImageDescriptor->NumberOfNames == 0) { return FALSE; } ModuleExports->ExportNamesAddr = (PDWORD) ImageRvaToVa ( ModuleExports->Image->FileHeader, ModuleExports->Image->MappedAddress, ModuleExports->ImageDescriptor->AddressOfNames, NULL ); ModuleExports->ExportOrdAddr = (PUSHORT) ImageRvaToVa ( ModuleExports->Image->FileHeader, ModuleExports->Image->MappedAddress, ModuleExports->ImageDescriptor->AddressOfNameOrdinals, NULL ); ModuleExports->CurrExportNr = 0; return EnumNextExportFunction32 (ModuleExports); } DWORD pProcessPEModule ( IN PCSTR CurrentPath, IN PLOADED_IMAGE ModuleImage, IN BOOL Win95Side ) { EXPORT_ENUM32 e; CHAR key[MEMDB_MAX]; MEMDB_ENUM me; DWORD memDbValue; if (EnumFirstExportFunction32 (ModuleImage, &e)) { do { DEBUGMSG((DBG_MODULES, "%s 32exports %s", ModuleImage->ModuleName, e.ExportFunction)); if (Win95Side) { MemDbBuildKey (key, MEMDB_CATEGORY_WNT_EXPORTS, GetFileNameFromPath (ModuleImage->ModuleName), e.ExportFunction, NULL); if (!MemDbGetValue (key, &memDbValue)) { if (MemDbEnumFirstValue (&me, MEMDB_CATEGORY_WIN9X_APIS TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ALL_MATCHES)) { MemDbBuildKey (key, MEMDB_CATEGORY_WIN9X_APIS, GetFileNameFromPath (ModuleImage->ModuleName), e.ExportFunction, NULL); MemDbSetValue (key, 0); _stprintf (key, TEXT("%s\\%s\\%ld"), MEMDB_CATEGORY_WIN9X_APIS, GetFileNameFromPath (ModuleImage->ModuleName), e.ExportFunctionOrd); MemDbSetValue (key, 0); } } else { if ((USHORT)memDbValue != e.ExportFunctionOrd) { _stprintf (key, TEXT("%s\\%s\\%ld"), MEMDB_CATEGORY_WIN9X_APIS, GetFileNameFromPath (ModuleImage->ModuleName), e.ExportFunctionOrd); MemDbSetValue (key, 0); } } } else { MemDbBuildKey (key, MEMDB_CATEGORY_WNT_EXPORTS, GetFileNameFromPath (ModuleImage->ModuleName), e.ExportFunction, NULL); if (!MemDbGetValue (key, NULL)) { MemDbSetValue (key, e.ExportFunctionOrd); } } } while (EnumNextExportFunction32 (&e)); } return TRUE; } DWORD pProcessNEModule ( IN PCSTR ModuleName, IN PCSTR ModuleImage, IN BOOL Win95Side ) { EXPORT_ENUM16 e; CHAR key[MEMDB_MAX]; CHAR fileName[MEMDB_MAX]; PSTR extPtr; MEMDB_ENUM me; DWORD memDbValue; //since this is a NT module whenever some other module imports something from this one we will not have the //extension so let's get the extension out StringCopy (fileName, GetFileNameFromPath (ModuleName)); extPtr = (PSTR)GetFileExtensionFromPath (fileName); if (extPtr) { extPtr = _mbsdec (fileName, extPtr); if (extPtr) { *extPtr = 0; } } if (EnumFirstExportFunction16 (ModuleImage, &e)) { do { DEBUGMSG((DBG_MODULES, "%s 16exports %s", ModuleName, e.ExportFunction)); if (Win95Side) { MemDbBuildKey (key, MEMDB_CATEGORY_WNT_EXPORTS, fileName, e.ExportFunction, NULL); if (!MemDbGetValue (key, &memDbValue)) { if (MemDbEnumFirstValue (&me, MEMDB_CATEGORY_WIN9X_APIS TEXT("\\*"), MEMDB_ALL_SUBLEVELS, MEMDB_ALL_MATCHES)) { MemDbBuildKey (key, MEMDB_CATEGORY_WIN9X_APIS, fileName, e.ExportFunction, NULL); MemDbSetValue (key, 0); _stprintf (key, TEXT("%s\\%s\\%ld"), MEMDB_CATEGORY_WIN9X_APIS, fileName, *e.ExportFunctionOrd); MemDbSetValue (key, 0); } } else { if ((USHORT)memDbValue != (*e.ExportFunctionOrd)) { _stprintf (key, TEXT("%s\\%s\\%ld"), MEMDB_CATEGORY_WIN9X_APIS, fileName, *e.ExportFunctionOrd); MemDbSetValue (key, 0); } } } else { MemDbBuildKey (key, MEMDB_CATEGORY_WNT_EXPORTS, fileName, e.ExportFunction, NULL); if (!MemDbGetValue (key, NULL)) { MemDbSetValue (key, *e.ExportFunctionOrd); } } } while (EnumNextExportFunction16 (&e)); } return TRUE; } BOOL pProcessExportModule ( IN PCTSTR ModuleName, IN BOOL Win95Side ) { MODULE_IMAGE moduleImage; DWORD result = TRUE; PCSTR fileName = GetFileNameFromPath (ModuleName); if (_stricmp (fileName, "COMCTL32.DLL") == 0) { result = TRUE; } __try { if (!pLoadModuleData (ModuleName, &moduleImage)) { DEBUGMSG((DBG_MODULES, ":Cannot load image for %s. Error:%ld", ModuleName, GetLastError())); __leave; } __try { switch (moduleImage.ModuleType) { case DOS_MODULE: DEBUGMSG((DBG_MODULES, "Examining %s : DOS module.", ModuleName)); break; case W16_MODULE: DEBUGMSG((DBG_MODULES, "Examining %s : W16 module.", ModuleName)); result = pProcessNEModule (ModuleName, moduleImage.ModuleData.W16Data.Image, Win95Side); break; case W32_MODULE: DEBUGMSG((DBG_MODULES, "Examining %s : W32 module.", ModuleName)); result = pProcessPEModule (ModuleName, &moduleImage.ModuleData.W32Data.Image, Win95Side); break; default: DEBUGMSG((DBG_MODULES, "Examining %s : Unknown module type.", ModuleName)); } } __except (EXCEPTION_EXECUTE_HANDLER) { DEBUGMSG((DBG_WARNING, DBG_MODULES":Access violation while checking %s", ModuleName)); result = TRUE; } } __finally { pUnloadModuleData (&moduleImage); } return result; }