/*++ Copyright (c) 1992 Microsoft Corporation Module Name: bind.c Abstract: Author: Revision History: --*/ #include 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, PVOID 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; int __cdecl main( int argc, char *argv[], char *envp[] ) { char c, *p; int ExcludeList[256]; int ExcludeListLength = 0; BOOL fUsage = FALSE; LPSTR DllPath; LPSTR CurrentImageName; int ArgNumber = argc; char **ArgList = argv; envp; DllPath = NULL; CurrentImageName = NULL; if (argc < 2) { goto usage; } 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 { 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 { 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; } BindImageEx( BindFlags, CurrentImageName, DllPath, SymbolPath, (PIMAGEHLP_STATUS_ROUTINE)BindStatusRoutine ); } } } return BIND_OK; } BOOL BindStatusRoutine( IMAGEHLP_STATUS_REASON Reason, LPSTR ImageName, LPSTR DllName, PVOID 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 - %p\n", ImageName, 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, Parameter, DllName ); break; case BindImportModule: if (fVerbose) { fprintf( stderr,"BIND: %s - Imports from %s\n", ImageName, DllName ); } break; case BindImportProcedure: if (fVerbose) { fprintf( stderr, "BIND: %s - %s Bound to %p\n", ImageName, Parameter, Va ); } break; case BindForwarder: if (fVerbose) { fprintf( stderr, "BIND: %s - %s forwarded to %s [%p]\n", ImageName, DllName, Parameter, Va ); } break; case BindForwarderNOT: if (fVerbose) { fprintf( stderr, "BIND: %s - Forwarder %s not snapped [%p]\n", ImageName, 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; iNumberOfModuleForwarderRefs; i++ ) { fprintf( stderr, " Forward to %s [%x]\n", (LPSTR)NewImports + NewForwarder->OffsetModuleName, NewForwarder->TimeDateStamp ); NewForwarder += 1; } NewImport = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewForwarder; } } break; } return TRUE; }