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