510 lines
14 KiB
C
510 lines
14 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bind.c
|
|
|
|
Abstract:
|
|
|
|
Author:
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <private.h>
|
|
|
|
#define STANDALONE_BIND
|
|
|
|
BOOL
|
|
Match(
|
|
char *Pattern,
|
|
char *Text
|
|
)
|
|
{
|
|
switch (*Pattern) {
|
|
case '\0':
|
|
return *Text == '\0';
|
|
|
|
case '?':
|
|
return *Text != '\0' && Match( Pattern + 1, Text + 1 );
|
|
|
|
case '*':
|
|
do {
|
|
if (Match( Pattern + 1, Text ))
|
|
return TRUE;
|
|
}
|
|
while (*Text++);
|
|
return FALSE;
|
|
|
|
default:
|
|
return toupper( *Text ) == toupper( *Pattern ) && Match( Pattern + 1, Text + 1 );
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
AnyMatches(
|
|
char *Name,
|
|
int *NumList,
|
|
int Length,
|
|
char **StringList
|
|
)
|
|
{
|
|
if (Length == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
return (Match( StringList[ NumList[ 0 ] ], Name ) ||
|
|
AnyMatches( Name, NumList + 1, Length - 1, StringList )
|
|
);
|
|
}
|
|
|
|
BOOL
|
|
BindStatusRoutine(
|
|
IMAGEHLP_STATUS_REASON Reason,
|
|
LPSTR ImageName,
|
|
LPSTR DllName,
|
|
ULONG64 Va,
|
|
ULONG_PTR Parameter
|
|
);
|
|
|
|
#define BIND_ERR 99
|
|
#define BIND_OK 0
|
|
|
|
PCHAR SymbolPath;
|
|
|
|
BOOL fVerbose;
|
|
BOOL fNoUpdate = TRUE;
|
|
BOOL fDisableNewImports;
|
|
BOOL fNoCacheImportDlls;
|
|
BOOL fBindSysImages;
|
|
DWORD BindFlags;
|
|
|
|
#ifndef _WIN64
|
|
BOOL
|
|
BindStatusRoutine32(
|
|
IMAGEHLP_STATUS_REASON Reason,
|
|
LPSTR ImageName,
|
|
LPSTR DllName,
|
|
ULONG Va,
|
|
ULONG Parameter
|
|
)
|
|
{
|
|
return BindStatusRoutine(Reason, ImageName, DllName, Va, Parameter);
|
|
}
|
|
#endif
|
|
|
|
int ExcludeList[256];
|
|
int ExcludeListLength = 0;
|
|
|
|
LPSTR DllPath;
|
|
LPSTR CurrentImageName;
|
|
char **ArgList;
|
|
DWORD dwVersion;
|
|
|
|
void DoBind(char *p);
|
|
|
|
int __cdecl
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
{
|
|
char c, *p;
|
|
|
|
BOOL fUsage = FALSE;
|
|
|
|
int ArgNumber = argc;
|
|
|
|
ArgList = argv;
|
|
|
|
DllPath = NULL;
|
|
CurrentImageName = NULL;
|
|
|
|
if (argc < 2) {
|
|
goto usage;
|
|
}
|
|
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
setvbuf(stderr, NULL, _IONBF, 0);
|
|
|
|
while (--argc) {
|
|
p = *++argv;
|
|
if (*p == '/' || *p == '-') {
|
|
while (c = *++p)
|
|
switch (toupper( c )) {
|
|
case '?':
|
|
fUsage = TRUE;
|
|
break;
|
|
|
|
case 'C':
|
|
fNoCacheImportDlls = TRUE;
|
|
break;
|
|
|
|
case 'O':
|
|
fDisableNewImports = TRUE;
|
|
break;
|
|
|
|
case 'P':
|
|
if (--argc) {
|
|
DllPath = *++argv;
|
|
} else {
|
|
fprintf( stderr, "BIND: Parameter missing for /%c\n", c );
|
|
fUsage = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'S':
|
|
if (--argc) {
|
|
SymbolPath = *++argv;
|
|
} else {
|
|
fprintf( stderr, "BIND: Parameter missing for /%c\n", c );
|
|
fUsage = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'U':
|
|
fNoUpdate = FALSE;
|
|
break;
|
|
|
|
case 'V':
|
|
fVerbose = TRUE;
|
|
break;
|
|
|
|
case 'X' :
|
|
if (--argc) {
|
|
++argv;
|
|
ExcludeList[ExcludeListLength] = ArgNumber - argc;
|
|
ExcludeListLength++;
|
|
} else {
|
|
fprintf( stderr, "BIND: Parameter missing for /%c\n", c );
|
|
fUsage = TRUE;
|
|
}
|
|
break;
|
|
|
|
case 'Y':
|
|
fBindSysImages = TRUE;
|
|
break;
|
|
|
|
default:
|
|
fprintf( stderr, "BIND: Invalid switch - /%c\n", c );
|
|
fUsage = TRUE;
|
|
break;
|
|
}
|
|
if (fUsage) {
|
|
usage:
|
|
fputs("usage: BIND [switches] image-names... \n"
|
|
" [-?] display this message\n"
|
|
" [-c] no caching of import dlls\n"
|
|
" [-o] disable new import descriptors\n"
|
|
" [-p dll search path]\n"
|
|
" [-s Symbol directory] update any associated .DBG file\n"
|
|
" [-u] update the image\n"
|
|
" [-v] verbose output\n"
|
|
" [-x image name] exclude this image from binding\n"
|
|
" [-y] allow binding on images located above 2G",
|
|
stderr
|
|
);
|
|
return BIND_ERR;
|
|
}
|
|
} else {
|
|
BindFlags = 0;
|
|
|
|
if (!fNoCacheImportDlls) {
|
|
// Always cache across calls unless the user indicates otherwise.
|
|
BindFlags |= BIND_CACHE_IMPORT_DLLS;
|
|
}
|
|
if (fNoUpdate) {
|
|
BindFlags |= BIND_NO_UPDATE;
|
|
}
|
|
if (fDisableNewImports) {
|
|
BindFlags |= BIND_NO_BOUND_IMPORTS;
|
|
}
|
|
if (fBindSysImages) {
|
|
BindFlags |= BIND_ALL_IMAGES;
|
|
}
|
|
|
|
dwVersion = GetVersion();
|
|
#if !defined(_WIN64) && !defined(STANDALONE_BIND)
|
|
if ((HIWORD(dwVersion) & 0x3fff) > 3600) {
|
|
// NT build > 3600 - supports 64-bit VA's on X86
|
|
BindFlags |= BIND_REPORT_64BIT_VA;
|
|
}
|
|
#endif
|
|
|
|
if (*p == '@') {
|
|
FILE *hFiles;
|
|
int ScanRet;
|
|
CHAR pchFileName[_MAX_PATH];
|
|
|
|
p++;
|
|
|
|
hFiles=fopen(p, "rt");
|
|
if (hFiles == NULL) {
|
|
fprintf( stderr, "BIND: fopen %s failed %d\n", p, errno );
|
|
ExitProcess( BIND_ERR );
|
|
}
|
|
|
|
ScanRet = fscanf( hFiles, "%s", pchFileName);
|
|
while (ScanRet && ScanRet != EOF) {
|
|
DoBind(pchFileName);
|
|
ScanRet = fscanf( hFiles, "%s", pchFileName );
|
|
}
|
|
} else {
|
|
DoBind(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
return BIND_OK;
|
|
}
|
|
|
|
void
|
|
DoBind(char *p)
|
|
{
|
|
CurrentImageName = p;
|
|
if (fVerbose) {
|
|
fprintf( stdout,
|
|
"BIND: binding %s using DllPath %s\n",
|
|
CurrentImageName,
|
|
DllPath ? DllPath : "Default"
|
|
);
|
|
}
|
|
|
|
if (AnyMatches( CurrentImageName, ExcludeList, ExcludeListLength, ArgList )) {
|
|
if (fVerbose) {
|
|
fprintf( stdout, "BIND: skipping %s\n", CurrentImageName );
|
|
}
|
|
} else {
|
|
#if !defined(_WIN64) && !defined(STANDALONE_BIND)
|
|
{
|
|
if ((HIWORD(dwVersion) & 0x3fff) > 3600) {
|
|
// NT build > 3600 - supports 64-bit VA's on X86
|
|
|
|
BindImageEx( BindFlags,
|
|
CurrentImageName,
|
|
DllPath,
|
|
SymbolPath,
|
|
(PIMAGEHLP_STATUS_ROUTINE)BindStatusRoutine
|
|
);
|
|
} else {
|
|
BindImageEx( BindFlags,
|
|
CurrentImageName,
|
|
DllPath,
|
|
SymbolPath,
|
|
(PIMAGEHLP_STATUS_ROUTINE)BindStatusRoutine32
|
|
);
|
|
}
|
|
}
|
|
#else
|
|
BindFlags |= BIND_REPORT_64BIT_VA;
|
|
|
|
BindImageEx( BindFlags,
|
|
CurrentImageName,
|
|
DllPath,
|
|
SymbolPath,
|
|
(PIMAGEHLP_STATUS_ROUTINE)BindStatusRoutine
|
|
);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
BindStatusRoutine(
|
|
IMAGEHLP_STATUS_REASON Reason,
|
|
LPSTR ImageName,
|
|
LPSTR DllName,
|
|
ULONG64 Va,
|
|
ULONG_PTR Parameter
|
|
)
|
|
{
|
|
PIMAGE_BOUND_IMPORT_DESCRIPTOR NewImports, NewImport;
|
|
PIMAGE_BOUND_FORWARDER_REF NewForwarder;
|
|
UINT i;
|
|
|
|
switch( Reason ) {
|
|
case BindOutOfMemory:
|
|
fprintf( stderr, "BIND: Out of memory - needed %u bytes.\n", Parameter );
|
|
ExitProcess( 1 );
|
|
|
|
case BindRvaToVaFailed:
|
|
fprintf( stderr, "BIND: %s contains invalid Rva - %08.8X\n", ImageName, (ULONG)Va );
|
|
break;
|
|
|
|
case BindNoRoomInImage:
|
|
fprintf( stderr,
|
|
"BIND: Not enough room for new format import table. Defaulting to unbound image.\n"
|
|
);
|
|
break;
|
|
|
|
case BindImportModuleFailed:
|
|
fprintf( stderr,"BIND: %s - Unable to find %s\n", ImageName, DllName );
|
|
break;
|
|
|
|
case BindImportProcedureFailed:
|
|
fprintf( stderr,
|
|
"BIND: %s - %s entry point not found in %s\n",
|
|
ImageName,
|
|
(char *)Parameter,
|
|
DllName
|
|
);
|
|
break;
|
|
|
|
case BindImportModule:
|
|
if (fVerbose) {
|
|
fprintf( stderr,"BIND: %s - Imports from %s\n", ImageName, DllName );
|
|
}
|
|
break;
|
|
|
|
case BindImportProcedure64:
|
|
#ifdef _WIN64
|
|
case BindImportProcedure:
|
|
#endif
|
|
if (fVerbose) {
|
|
fprintf( stderr,
|
|
"BIND: %s - %s Bound to %16.16I64X\n",
|
|
ImageName,
|
|
(char *)Parameter,
|
|
Va
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindImportProcedure32:
|
|
#ifndef _WIN64
|
|
case BindImportProcedure:
|
|
#endif
|
|
if (fVerbose) {
|
|
fprintf( stderr,
|
|
"BIND: %s - %s Bound to %08.8X\n",
|
|
ImageName,
|
|
(char *)Parameter,
|
|
(ULONG)Va
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindForwarder64:
|
|
#ifdef _WIN64
|
|
case BindForwarder:
|
|
#endif
|
|
if (fVerbose) {
|
|
fprintf( stderr, "BIND: %s - %s forwarded to %s [%16.16I64X]\n",
|
|
ImageName,
|
|
DllName,
|
|
(char *)Parameter,
|
|
Va
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindForwarder32:
|
|
#ifndef _WIN64
|
|
case BindForwarder:
|
|
#endif
|
|
if (fVerbose) {
|
|
fprintf( stderr, "BIND: %s - %s forwarded to %s [%08.8X]\n",
|
|
ImageName,
|
|
DllName,
|
|
(char *)Parameter,
|
|
Va
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindForwarderNOT64:
|
|
#ifdef _WIN64
|
|
case BindForwarderNOT:
|
|
#endif
|
|
if (fVerbose) {
|
|
fprintf( stderr,
|
|
"BIND: %s - Forwarder %s not snapped [%16.16I64X]\n",
|
|
ImageName,
|
|
(char *)Parameter,
|
|
Va
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindForwarderNOT32:
|
|
#ifndef _WIN64
|
|
case BindForwarderNOT:
|
|
#endif
|
|
if (fVerbose) {
|
|
fprintf( stderr,
|
|
"BIND: %s - Forwarder %s not snapped [%08.8X]\n",
|
|
ImageName,
|
|
(char *)Parameter,
|
|
Va
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindImageModified:
|
|
fprintf( stdout, "BIND: binding %s\n", ImageName );
|
|
break;
|
|
|
|
|
|
case BindExpandFileHeaders:
|
|
if (fVerbose) {
|
|
fprintf( stderr,
|
|
" Expanded %s file headers to %x\n",
|
|
ImageName,
|
|
Parameter
|
|
);
|
|
}
|
|
break;
|
|
|
|
case BindMismatchedSymbols:
|
|
fprintf(stderr, "BIND: Warning: %s checksum did not match %s\n",
|
|
ImageName,
|
|
(LPSTR)Parameter);
|
|
break;
|
|
|
|
case BindSymbolsNotUpdated:
|
|
fprintf(stderr, "BIND: Warning: symbol file %s not updated.\n",
|
|
(LPSTR)Parameter);
|
|
break;
|
|
|
|
case BindImageComplete:
|
|
if (fVerbose) {
|
|
fprintf(stderr, "BIND: Details of binding of %s\n", ImageName );
|
|
NewImports = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)Va;
|
|
NewImport = NewImports;
|
|
while (NewImport->OffsetModuleName) {
|
|
fprintf( stderr, " Import from %s [%x]",
|
|
(LPSTR)NewImports + NewImport->OffsetModuleName,
|
|
NewImport->TimeDateStamp
|
|
);
|
|
if (NewImport->NumberOfModuleForwarderRefs != 0) {
|
|
fprintf( stderr, " with %u forwarders", NewImport->NumberOfModuleForwarderRefs );
|
|
}
|
|
fprintf( stderr, "\n" );
|
|
NewForwarder = (PIMAGE_BOUND_FORWARDER_REF)(NewImport+1);
|
|
for ( i=0; i<NewImport->NumberOfModuleForwarderRefs; i++ ) {
|
|
fprintf( stderr, " Forward to %s [%x]\n",
|
|
(LPSTR)NewImports + NewForwarder->OffsetModuleName,
|
|
NewForwarder->TimeDateStamp
|
|
);
|
|
NewForwarder += 1;
|
|
}
|
|
NewImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewForwarder;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#include <bindi.c>
|
|
|
|
#define STANDALONE_MAP
|
|
#include <mapi.c>
|