Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2237 lines
88 KiB

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <private.h>
#include <crt\io.h>
#include <share.h>
#include <time.h>
#include <setupapi.h>
#include "splitsymx.h"
#include <string.h>
#include "wppfmt.h"
#include <VerifyFinalImage.h>
#include <GetNextArg.h>
#include <strsafe.h>
#ifndef MOVEFILE_CREATE_HARDLINK
#define MOVEFILE_CREATE_HARDLINK 0x00000010
#endif
#define BINPLACE_ERR 77
#define BINPLACE_OK 0
// begin from PlaceFileMatch.c
#define BINPLACE_FULL_MAX_PATH 4096 // keep in sync with value in PlaceFileMatch.c
BOOL
PlaceFileMatch(
IN LPCSTR FullFileName,
IN OUT LPSTR PlaceFileEntry, // May be modified by env. var expansion
OUT LPSTR PlaceFileClass, // assumed CHAR[BINPLACE_MAX_FULL_PATH]
OUT LPSTR *PlaceFileNewName);
// end
BOOL fUpDriver;
BOOL fBypassSplitSymX;
BOOL fUsage;
BOOL fVerbose;
BOOL fSymChecking;
BOOL fTestMode;
BOOL fSplitSymbols;
BOOL fPatheticOS;
BOOL fKeepAttributes;
BOOL fDigitalSign;
BOOL fHardLinks;
BOOL fIgnoreHardLinks;
BOOL fDontLog;
BOOL fPlaceWin95SymFile;
BOOL fNoClassInSymbolsDir;
BOOL fMakeErrorOnDumpCopy;
BOOL fDontExit;
BOOL fForcePlace;
BOOL fSignCode;
BOOL fVerifyLc;
BOOL fWppFmt;
BOOL fCheckDelayload;
BOOL fChangeAsmsToRetailForSymbols;
BOOL fSrcControl;
BOOL fDbgControl;
BOOL fLogPdbPaths;
HINSTANCE hSetupApi;
HINSTANCE hLcManager;
PVLCA pVerifyLocConstraintA; // PVLCA defined in VerifyFinalImage.h
BOOL (WINAPI * pSetupGetIntField) (IN PINFCONTEXT Context, IN DWORD FieldIndex, OUT PINT IntegerValue);
BOOL (WINAPI * pSetupFindFirstLineA) (IN HINF InfHandle, IN PCSTR Section, IN PCSTR Key, OPTIONAL OUT PINFCONTEXT Context );
BOOL (WINAPI * pSetupGetStringFieldA) (IN PINFCONTEXT Context, IN DWORD FieldIndex, OUT PSTR ReturnBuffer, OPTIONAL IN DWORD ReturnBufferSize, OUT PDWORD RequiredSize);
HINF (WINAPI * pSetupOpenInfFileA) ( IN PCSTR FileName, IN PCSTR InfClass, OPTIONAL IN DWORD InfStyle, OUT PUINT ErrorLine OPTIONAL );
HINF (WINAPI * pSetupOpenMasterInf) (VOID);
ULONG SplitFlags = 0;
LPSTR CurrentImageName;
LPSTR PlaceFileName;
LPSTR PlaceRootName;
LPSTR ExcludeFileName;
LPSTR DumpOverride = NULL;
LPSTR NormalPlaceSubdir;
LPSTR CommandScriptName;
LPSTR SymbolFilePath = NULL;
LPSTR DestinationPath = NULL;
LPSTR PrivateSymbolFilePath = NULL;
LPSTR BinplaceLcDir;
LPSTR LcFilePart;
LPSTR szRSDSDllToLoad;
LPSTR gNewFileName;
LPSTR gPrivatePdbFullPath=NULL;
LPSTR gPublicPdbFullPath=NULL;
HINF LayoutInf;
FILE *PlaceFile;
FILE *LogFile;
FILE *CommandScriptFile;
CHAR* gDelayLoadModule;
CHAR* gDelayLoadHandler;
CHAR gFullFileName[MAX_PATH+1];
CHAR gDestinationFile[MAX_PATH+1];
UCHAR SetupFilePath[ MAX_PATH+1 ];
UCHAR DebugFilePath[ MAX_PATH+1 ];
UCHAR PlaceFilePath[ MAX_PATH+1 ];
UCHAR ExcludeFilePath[ MAX_PATH+1 ];
UCHAR DefaultSymbolFilePath[ MAX_PATH+1 ];
UCHAR szAltPlaceRoot[ MAX_PATH+1 ];
UCHAR LcFullFileName[ MAX_PATH+1 ];
UCHAR szExtraInfo[4096];
UCHAR TraceFormatFilePath[ MAX_PATH+1 ] ;
UCHAR LastPdbName[ MAX_PATH+1 ] ;
UCHAR TraceDir[ MAX_PATH+1 ] ;
#define DEFAULT_PLACE_FILE "\\tools\\placefil.txt"
#define DEFAULT_NTROOT "\\nt"
#define DEFAULT_NTDRIVE "c:"
#define DEFAULT_DUMP "dump"
#define DEFAULT_LCDIR "LcINF"
#define DEFAULT_EXCLUDE_FILE "\\tools\\symbad.txt"
#define DEFAULT_TRACEDIR "TraceFormat"
#define DEFAULT_DELAYLOADDIR "delayload"
typedef struct _CLASS_TABLE {
LPSTR ClassName;
LPSTR ClassLocation;
} CLASS_TABLE, *PCLASS_TABLE;
BOOL
PlaceTheFile();
BOOL BinplaceGetSourcePdbName(LPTSTR SourceFileName, DWORD BufferSize, CHAR* SourcePdbName, DWORD* PdbSig);
//BOOL FileExists(LPTSTR Filename);
BOOL StripCVSymbolPath (LPSTR DestinationFile); // in StripCVSymbolPath.c
// concat 3 paths together handling the case where the second may be relative to the first
// or may be absolute
BOOL ConcatPaths( LPTSTR pszDest, size_t cbDest, LPCTSTR Root, LPCTSTR Symbols, LPCTSTR Ext);
typedef
BOOL
(WINAPI *PCREATEHARDLINKA)(
LPCSTR lpFileName,
LPCSTR lpExistingFileName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
PCREATEHARDLINKA pCreateHardLinkA;
// Symbol checking
#define MAX_SYM_ERR 500
BOOL
CheckSymbols( // in CheckSymbols.c
LPSTR SourceFileName,
LPSTR TmpPath,
LPSTR ExcludeFileName,
BOOL SymbolFlag,
LPSTR ErrMsg,
size_t ErrMsgLen
);
BOOL
CopyTheFile(
LPSTR SourceFileName,
LPSTR SourceFilePart,
LPSTR DestinationSubdir,
LPSTR DestinationFilePart
);
BOOL
BinplaceCopyPdb (
LPSTR DestinationFile,
LPSTR SourceFileName, // Used for redist case
BOOL CopyFromSourceOnly,
BOOL StripPrivate
);
BOOL
SourceIsNewer( // in SourceIsNewer.c
IN LPSTR SourceFile,
IN LPSTR TargetFile,
IN BOOL fIsWin9x);
/* This is no longer used
__inline BOOL
SearchOneDirectory(
IN LPSTR Directory,
IN LPSTR FileToFind,
IN LPSTR SourceFullName,
IN LPSTR SourceFilePart,
OUT PBOOL FoundInTree
)
{
//
// This was way too slow. Just say we didn't find the file.
//
*FoundInTree = FALSE;
return(TRUE);
}
*/
BOOL SignWithIDWKey(IN LPCSTR FileName, IN BOOL fVerbose); // in SignWithIDWKey.c
CLASS_TABLE CommonClassTable[] = {
{"retail", "."},
{"system", "system32"},
{"system16","system"},
{"windows", "."},
{"drivers", "system32\\drivers"},
{"drvetc", "system32\\drivers\\etc"},
{"config", "system32\\config"},
{NULL,NULL}
};
CLASS_TABLE i386SpecificClassTable[] = {
{"hal","system32"},
{"printer","system32\\spool\\drivers\\w32x86"},
{"prtprocs","system32\\spool\\prtprocs\\w32x86"},
{NULL,NULL}
};
CLASS_TABLE Amd64SpecificClassTable[] = {
{"hal",".."},
{"printer","system32\\spool\\drivers\\w32amd64"},
{"prtprocs","system32\\spool\\prtprocs\\w32amd64"},
{NULL,NULL}
};
CLASS_TABLE ia64SpecificClassTable[] = {
{"hal",".."},
{"printer","system32\\spool\\drivers\\w32ia64"},
{"prtprocs","system32\\spool\\prtprocs\\w32ia64"},
{NULL,NULL}
};
DWORD GetAndLogNextArg( OUT TCHAR* Buffer, // local wrapper for GetNextArg()
IN DWORD BufferSize,
OPTIONAL OUT DWORD* RequiredSize);
BOOL PrintMessageLogBuffer(FILE* fLogHandle); // write the buffer to fLogHandle
BOOL FreeMessageLogBuffer(void); // free global arg buffer
int __cdecl
main(
int argc,
char *argv[],
char *envp[]
)
{
BOOL gOnlyCopyArchiveFiles = FALSE;
BOOL fBypassSplitSymX = FALSE;
char c, *p, *OverrideFlags, *s, **newargv=NULL;
LPSTR LcFileName = NULL;
int i, n;
BOOL NoPrivateSplit = FALSE;
OSVERSIONINFO VersionInformation;
LPTSTR platform;
FILE * MsgLogFile;
CHAR * MsgLogFileName;
HANDLE hMutex;
CHAR ArgBuffer[MAX_PATH+1];
DWORD ArgSize = sizeof(ArgBuffer);
DWORD ArgSizeNeeded;
CHAR* PlaceFileNameBuffer = NULL;
CHAR* PlaceRootNameBuffer = NULL;
CHAR CommonTempBuffer[MAX_PATH+1];
CHAR* CommonTempPtr;
gNewFileName = NULL;
ImageCheck.Argv = NULL;
fLogPdbPaths = FALSE;
gPrivatePdbFullPath= (CHAR*)malloc(sizeof(CHAR)*(MAX_PATH+1));
gPublicPdbFullPath = (CHAR*)malloc(sizeof(CHAR)*(MAX_PATH+1));
if (gPrivatePdbFullPath==NULL||gPublicPdbFullPath==NULL) {
fprintf( stderr, "BINPLACE : error BNP0273: out of memory\n");
exit(BINPLACE_ERR);
}
//
// Win 95 can't compare file times very well, this hack neuters the SourceIsNewer function
// on Win 95
//
VersionInformation.dwOSVersionInfoSize = sizeof( VersionInformation );
if (GetVersionEx( &VersionInformation ) && VersionInformation.dwPlatformId != VER_PLATFORM_WIN32_NT) {
fPatheticOS = TRUE;
}
envp;
fUpDriver = FALSE;
fUsage = FALSE;
fVerbose = FALSE;
fSymChecking = FALSE;
fTestMode = FALSE;
fSplitSymbols = FALSE;
fKeepAttributes = FALSE;
fDigitalSign = FALSE;
fHardLinks = FALSE;
fIgnoreHardLinks = FALSE;
fDontExit = FALSE;
fForcePlace = FALSE;
fSignCode = FALSE;
fVerifyLc = FALSE;
fWppFmt = FALSE ;
fSrcControl = FALSE;
fDbgControl = FALSE;
NormalPlaceSubdir = NULL;
pVerifyLocConstraintA = NULL;
if (argc < 2) {
goto showUsage;
}
if ( (szRSDSDllToLoad = (LPSTR) malloc((MAX_PATH+1) * sizeof(CHAR))) == NULL ) {
fprintf( stderr, "BINPLACE : error BNP0322: Out of memory\n");
exit(BINPLACE_ERR);
}
StringCbCopy( szRSDSDllToLoad, (MAX_PATH+1) * sizeof(CHAR), "mspdb70.dll");
setvbuf(stderr, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
if (!(PlaceFileName = getenv( "BINPLACE_PLACEFILE" )) &&
!(PlaceFileName = getenv( "BINPLACE_PLACEFILE_DEFAULT" ))) {
if ((PlaceFileName = getenv("_NTDRIVE")) == NULL) {
PlaceFileName = DEFAULT_NTDRIVE;
}
StringCbCopy((PCHAR) PlaceFilePath, sizeof(PlaceFilePath), PlaceFileName);
if ((PlaceFileName = getenv("_NTROOT")) == NULL) {
PlaceFileName = DEFAULT_NTROOT;
}
StringCbCat((PCHAR) PlaceFilePath, sizeof(PlaceFilePath), PlaceFileName);
StringCbCat((PCHAR) PlaceFilePath, sizeof(PlaceFilePath), DEFAULT_PLACE_FILE);
PlaceFileName = (PCHAR) PlaceFilePath;
}
if (!(ExcludeFileName = getenv( "BINPLACE_EXCLUDE_FILE" ))) {
if ((ExcludeFileName = getenv("_NTDRIVE")) == NULL) {
ExcludeFileName = DEFAULT_NTDRIVE;
}
StringCbCopy((PCHAR) ExcludeFilePath, sizeof(ExcludeFilePath), ExcludeFileName);
if ((ExcludeFileName = getenv("_NTROOT")) == NULL) {
ExcludeFileName = DEFAULT_NTROOT;
}
StringCbCat((PCHAR) ExcludeFilePath, sizeof(ExcludeFilePath), ExcludeFileName);
StringCbCat((PCHAR) ExcludeFilePath, sizeof(ExcludeFilePath), DEFAULT_EXCLUDE_FILE);
ExcludeFileName = (PCHAR) ExcludeFilePath;
}
if (!(BinplaceLcDir = getenv( "BINPLACE_LCDIR" ))) {
BinplaceLcDir = DEFAULT_LCDIR;
}
if ( getenv("NT_SIGNCODE") != NULL ) {
fSignCode=TRUE;
}
//
// Support Cross compile as well
//
#if defined(_AMD64_)
ImageCheck.Machine = IMAGE_FILE_MACHINE_AMD64;
PlaceRootName = getenv( "_NTAMD64TREE" );
#elif defined(_IA64_)
ImageCheck.Machine = IMAGE_FILE_MACHINE_IA64;
PlaceRootName = getenv( "_NTIA64TREE" );
#else // defined(_X86_)
if ((platform = getenv("AMD64")) != NULL) {
ImageCheck.Machine = IMAGE_FILE_MACHINE_AMD64;
PlaceRootName = getenv( "_NTAMD64TREE" );
} else if ((platform = getenv("IA64")) != NULL) {
ImageCheck.Machine = IMAGE_FILE_MACHINE_IA64;
PlaceRootName = getenv( "_NTIA64TREE" );
} else {
ImageCheck.Machine = IMAGE_FILE_MACHINE_I386;
PlaceRootName = getenv( "_NT386TREE" );
if (!PlaceRootName)
PlaceRootName = getenv( "_NTx86TREE" );
}
#endif
CurrentImageName = NULL;
OverrideFlags = getenv( "BINPLACE_OVERRIDE_FLAGS" );
if (OverrideFlags != NULL) {
s = OverrideFlags;
n = 0;
while (*s) {
while (*s && *s <= ' ')
s += 1;
if (*s) {
n += 1;
while (*s > ' ')
s += 1;
if (*s)
*s++ = '\0';
}
}
if (n) {
newargv = malloc( (argc + n + 1) * sizeof( char * ) );
memcpy( &newargv[n], argv, argc * sizeof( char * ) );
argv = newargv;
argv[ 0 ] = argv[ n ];
argc += n;
s = OverrideFlags;
for (i=1; i<=n; i++) {
while (*s && *s <= ' ')
s += 1;
argv[ i ] = s;
while (*s++)
;
}
__argv = argv; // required for GetNextArg()
__argc = argc;
}
}
// skip past exe name and don't log it
GetNextArg(CommonTempBuffer, sizeof(CommonTempBuffer), NULL);
while ( (ArgSizeNeeded = GetAndLogNextArg(ArgBuffer, ArgSize, NULL)) != 0 ) {
p = ArgBuffer;
if (*p == '/' || *p == '-') {
if (_stricmp(p + 1, "ChangeAsmsToRetailForSymbols") == 0) {
fChangeAsmsToRetailForSymbols = TRUE;
} else {
while (c = *++p)
switch (toupper( c )) {
case '?':
fUsage = TRUE;
break;
case 'A':
SplitFlags |= SPLITSYM_EXTRACT_ALL;
break;
case 'B':
CommonTempPtr = (CHAR*)realloc(NormalPlaceSubdir, GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
NormalPlaceSubdir = CommonTempPtr;
GetAndLogNextArg(NormalPlaceSubdir, _msize(NormalPlaceSubdir), NULL);
break;
case 'C':
if (*(p+1) == 'I' || *(p+1) == 'i') {
char *q;
GetAndLogNextArg(CommonTempBuffer, sizeof(CommonTempBuffer), NULL);
p = CommonTempBuffer;
ImageCheck.RC = atoi(p);
if (!ImageCheck.RC) {
fprintf( stderr, "BINPLACE : error BNP0000: Invalid return code for -CI option\n");
fUsage = TRUE;
}
while (*p++ != ',');
q = p;
ImageCheck.Argc = 0;
while (*p != '\0')
if (*p++ == ',') ImageCheck.Argc++;
// last option plus extra args for Image file and Argv NULL
ImageCheck.Argc += 3;
ImageCheck.Argv = malloc( ImageCheck.Argc * sizeof( void * ) );
for ( i = 0; i <= ImageCheck.Argc - 3; i++) {
ImageCheck.Argv[i] = q;
while (*q != ',' && *q != '\0') q++;
*q++ = '\0';
}
p--;
ImageCheck.Argv[ImageCheck.Argc-1] = NULL;
} else {
fDigitalSign = TRUE;
}
break;
case 'D':
if (*(p+1) == 'L' || *(p+1) == 'l')
{
GetAndLogNextArg(CommonTempBuffer, sizeof(CommonTempBuffer), NULL);
p = CommonTempBuffer;
gDelayLoadModule = p;
while (*p != ',')
{
p++;
}
*p = '\0';
p++;
gDelayLoadHandler = p;
while (*p != '\0')
{
p++;
}
p--;
if (gDelayLoadModule[0] == '\0' ||
gDelayLoadHandler[0] == '\0')
{
fprintf(stderr, "BINPLACE : error BNP0000: Invalid switch for -dl option\n");
fUsage = TRUE;
}
else
{
fCheckDelayload = TRUE;
}
}
else
{
CommonTempPtr = (CHAR*)realloc(DumpOverride,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
DumpOverride = CommonTempPtr;
GetAndLogNextArg(DumpOverride, _msize(DumpOverride), NULL);
}
break;
case 'E':
fDontExit = TRUE;
break;
case 'F':
fForcePlace = TRUE;
break;
case 'G':
CommonTempPtr = (CHAR*)realloc(LcFileName,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
LcFileName = CommonTempPtr;
GetAndLogNextArg(LcFileName, _msize(LcFileName), NULL);
break;
case 'H':
if ((VersionInformation.dwPlatformId != VER_PLATFORM_WIN32_NT) ||
(VersionInformation.dwMajorVersion < 5) ||
(pCreateHardLinkA = (PCREATEHARDLINKA)GetProcAddress( GetModuleHandle( "KERNEL32" ),
"CreateHardLinkA"
)
) == NULL
) {
fprintf( stderr, "BINPLACE: Hard links not supported. Defaulting to CopyFile\n" );
fHardLinks = FALSE;
} else {
fHardLinks = TRUE;
}
break;
case 'J':
fSymChecking = TRUE;
break;
case 'K':
fKeepAttributes = TRUE;
break;
case 'L':
break;
case 'M':
fMakeErrorOnDumpCopy = TRUE;
break;
case 'N':
CommonTempPtr = (CHAR*)realloc(PrivateSymbolFilePath,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
PrivateSymbolFilePath = CommonTempPtr;
GetAndLogNextArg(PrivateSymbolFilePath, _msize(PrivateSymbolFilePath), NULL);
break;
case 'O':
if (PlaceRootName != NULL) {
StringCbCopy(szAltPlaceRoot, sizeof(szAltPlaceRoot), PlaceRootName);
StringCbCat( szAltPlaceRoot, sizeof(szAltPlaceRoot), "\\");
// concat next arg to the end of szAltPlaceRoot
GetAndLogNextArg( &szAltPlaceRoot[strlen(szAltPlaceRoot)],
(sizeof(szAltPlaceRoot)/sizeof(CHAR)) - strlen(szAltPlaceRoot),
NULL);
PlaceRootName = szAltPlaceRoot;
}
break;
case 'P':
CommonTempPtr = (CHAR*)realloc(PlaceFileNameBuffer,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
PlaceFileNameBuffer = CommonTempPtr;
GetAndLogNextArg(PlaceFileNameBuffer, _msize(PlaceFileNameBuffer), NULL);
PlaceFileName = PlaceFileNameBuffer;
break;
case 'Q':
fDontLog = TRUE;
break;
case 'R':
CommonTempPtr = (CHAR*)realloc(PlaceRootNameBuffer,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
PlaceRootNameBuffer = CommonTempPtr;
GetAndLogNextArg(PlaceRootNameBuffer, _msize(PlaceRootNameBuffer), NULL);
PlaceRootName = PlaceRootNameBuffer;
break;
case 'S':
CommonTempPtr = (CHAR*)realloc(SymbolFilePath,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
SymbolFilePath = CommonTempPtr;
GetAndLogNextArg(SymbolFilePath, _msize(SymbolFilePath), NULL);
fSplitSymbols = TRUE;
fIgnoreHardLinks = TRUE;
break;
case 'T':
fTestMode = TRUE;
break;
case 'U':
fBypassSplitSymX = TRUE;
fUpDriver = TRUE;
break;
case 'V':
fVerbose = TRUE;
break;
case 'W':
fPlaceWin95SymFile = TRUE;
break;
case 'X':
SplitFlags |= SPLITSYM_REMOVE_PRIVATE;
break;
case 'Y':
fNoClassInSymbolsDir = TRUE;
break;
case 'Z':
NoPrivateSplit = TRUE;
break;
case ':': // Simple (== crude) escape mechanism as all the letters are used
// -:XXX can add extra options if need be
// For now just handle TMF, Trace Message Format processing of PDB's
if ((strlen(p) >= 3) && ((toupper(*(p+1)) == 'T') && (toupper(*(p+2)) == 'M') && (toupper(*(p+3))) == 'F')) {
LPSTR tfile ;
// If the RUNWPP operation ran this option will be automatically added
p += 3 ; // Gobble up the TMF
fBypassSplitSymX = TRUE; // SplitSymbolsX() causes problems when used with -:TMF
fWppFmt = TRUE ; // Need to package up the Software Tracing Formats
strncpy(TraceDir,DEFAULT_TRACEDIR,MAX_PATH) ; //Append to PrivateSymbolsPath
//If no default override.
tfile = getenv("TRACE_FORMAT_PATH"); //Has Path been overriden?
if (tfile != NULL) {
StringCbPrintfA(TraceFormatFilePath, sizeof(TraceFormatFilePath), "%s", tfile);
if (fVerbose) {
fprintf( stdout, "BINPLACE : warning BNP0000: Trace Formats file path set to %s\n", TraceFormatFilePath ) ;
}
} else {
TraceFormatFilePath[0] = '\0' ;
}
} else if ((strlen(p) >= 3) && ((toupper(*(p+1)) == 'S') && (toupper(*(p+2)) == 'R') && (toupper(*(p+3))) == 'C')) {
// This is the option for turning on creating a cvdump for the pdb for
// source control.
p += 3;
fSrcControl=TRUE;
} else if ((strlen(p) >= 3) && ((toupper(*(p+1)) == 'R') && (toupper(*(p+2)) == 'E') && (toupper(*(p+3))) == 'N')) {
// cmdline file renaming
p += 3;
CommonTempPtr = (CHAR*)realloc(gNewFileName,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
gNewFileName = CommonTempPtr;
GetAndLogNextArg(gNewFileName, _msize(gNewFileName), NULL);
} else if ((strlen(p) >= 3) && ((toupper(*(p+1)) == 'D') && (toupper(*(p+2)) == 'B') && (toupper(*(p+3))) == 'G')) {
// This is the option for turning on creating a cvdump for the pdb for
// source control.
p += 3;
fDbgControl=TRUE;
} else if ((strlen(p) >= 3) && ((toupper(*(p+1)) == 'A') && (toupper(*(p+2)) == 'R') && (toupper(*(p+3))) == 'C')) {
// only binplace the file if the ARCHIVE attribute is set
p += 3;
gOnlyCopyArchiveFiles=TRUE;
} else if ((strlen(p) == 5) && ((toupper(*(p+1)) == 'D') &&
(toupper(*(p+2)) == 'E') &&
(toupper(*(p+3)) == 'S') &&
(toupper(*(p+4)) == 'T'))) {
p += 4;
CommonTempPtr = (CHAR*)realloc(DestinationPath,GetNextArgSize()*sizeof(CHAR));
if (CommonTempPtr==NULL) {
exit(BINPLACE_ERR);
}
DestinationPath = CommonTempPtr;
GetAndLogNextArg(DestinationPath, _msize(DestinationPath), NULL);
} else if ((strlen(p) == 7) && ((toupper(*(p+1)) == 'L') &&
(toupper(*(p+2)) == 'O') &&
(toupper(*(p+3)) == 'G') &&
(toupper(*(p+4)) == 'P') &&
(toupper(*(p+5)) == 'D') &&
(toupper(*(p+6)) == 'B'))) {
fLogPdbPaths = TRUE;
p+=6;
}
break;
default:
fprintf( stderr, "BINPLACE : error BNP0000: Invalid switch - /%c\n", c );
fUsage = TRUE;
break;
}
}
if ( fUsage ) {
showUsage:
fputs(
"usage: binplace [switches] image-names... \n"
"where: [-?] display this message\n"
" [-a] Used with -s, extract all symbols\n"
" [-b subdir] put file in subdirectory of normal place\n"
" [-c] digitally sign image with IDW key\n"
" [-d dump-override]\n"
" [-:DBG] Don't binplace DBG files. If -j is present, don't binplace \n"
" binaries that point to DBG files.\n"
" [-:DEST <class>] Don't bother with placefil.txt - just put the\n"
" file(s) in the destination specified\n"
" [-e] don't exit if a file in list could not be binplaced\n"
" [-f] force placement by disregarding file timestamps\n"
" [-g lc-file] verify image with localization constraint file\n"
" [-h] modifies behavior to use hard links instead of CopyFile.\n"
" (ignored if -s is present)\n"
" [-j] verify proper symbols exist before copying\n"
" [-k] keep attributes (don't turn off archive)\n"
" [-:LOGPDB] include PDB paths in binplace.log\n"
" [-m] binplace files to dump (generates an error also)\n"
" [-n <Path>] Used with -x - Private pdb symbol path\n"
" [-o place-root-subdir] alternate project subdirectory\n"
" [-p place-file]\n"
" [-q] suppress writing to log file %BINPLACE_LOG%\n"
" [-r place-root]\n"
" [-s Symbol file path] split symbols from image files\n"
" [-:SRC] Process the PDB for source indexing\n"
" [-t] test mode\n"
" [-:TMF] Process the PDB for Trace Format files\n"
" [-u] UP driver\n"
" [-v] verbose output\n"
" [-w] copy the Win95 Sym file to the symbols tree\n"
" [-x] Used with -s, delete private symbolic when splitting\n"
" [-y] Used with -s, don't create class subdirs in the symbols tree\n"
" [-z] ignore -x if present\n"
" [-ci <rc,app,-arg0,-argv1,-argn>]\n"
" rc=application error return code,\n"
" app=application used to check images,\n"
" -arg0..-argn=application options\n"
" [-dl <modulename,delay-load handler>] (run dlcheck on this file)\n"
"\n"
"BINPLACE looks for the following environment variable names:\n"
" BINPLACE_EXCLUDE_FILE - full path name to symbad.txt\n"
" BINPLACE_OVERRIDE_FLAGS - may contain additional switches\n"
" BINPLACE_PLACEFILE - default value for -p flag\n"
" _NT386TREE - default value for -r flag on x86 platform\n"
" _NTAMD64TREE - default value for -r flag on AMD64 platform\n"
" _NTIA64TREE - default value for -r flag on IA64 platform\n"
" TRACE_FORMAT_PATH - set the path for Trace Format Files\n"
"\n"
,stderr
);
exit(BINPLACE_ERR);
}
} else {
WIN32_FIND_DATA FindData;
HANDLE h;
gPrivatePdbFullPath[0]= '\0';
gPublicPdbFullPath[0] = '\0';
if (!PlaceRootName) {
// If there's no root, just exit.
exit(BINPLACE_OK);
}
//
// Workaround for bogus setargv: ignore directories
//
if (NoPrivateSplit) {
SplitFlags &= ~SPLITSYM_REMOVE_PRIVATE;
}
h = FindFirstFile(p,&FindData);
if (h != INVALID_HANDLE_VALUE) {
FindClose(h);
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if ( fVerbose ) {
fprintf(stdout,"BINPLACE : warning BNP0000: ignoring directory %s\n",p);
}
continue;
}
if (gOnlyCopyArchiveFiles) {
if (! (FindData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ) {
if ( fVerbose ) {
fprintf(stdout,"BINPLACE : warning BNP1009: ignoring file without archive attribute %s\n",p);
}
continue;
}
}
}
CurrentImageName = p;
// If this is a dbg, don't binplace it
if ( fDbgControl && (strlen(p) > 4) &&
(strcmp(p+strlen(p)-4, ".dbg")== 0 ) ) {
fprintf(stderr, "BINPLACE : warning BNP0000: Dbg files not allowed. Use dbgtopdb.exe to remove %s.\n",p);
// exit(BINPLACE_ERR);
}
//
// If the master place file has not been opened, open
// it up.
//
if ( !PlaceFile && !DestinationPath) {
PlaceFile = fopen(PlaceFileName, "rt");
if (!PlaceFile) {
fprintf(stderr,"BINPLACE : fatal error BNP0000: fopen of placefile %s failed %d\n",PlaceFileName,GetLastError());
exit(BINPLACE_ERR);
}
}
//
// Check for bogus -g lc-file switch
//
if ( LcFileName != NULL ) {
h = FindFirstFile(LcFileName, &FindData);
if (h == INVALID_HANDLE_VALUE ||
(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
if (fVerbose ) {
fprintf(stdout,"BINPLACE : warning BNP0000: invalid file %s. Ignoring -G switch.\n", LcFileName);
}
LcFileName = NULL;
}
if (h != INVALID_HANDLE_VALUE) {
FindClose(h);
}
}
if ( LcFileName != NULL ) {
DWORD cb = GetFullPathName(LcFileName,MAX_PATH+1,LcFullFileName,&LcFilePart);
if (!cb || cb > MAX_PATH+1) {
fprintf(stderr,"BINPLACE : fatal error BNP0000: GetFullPathName %s failed %d\n",LcFileName, GetLastError());
exit(BINPLACE_ERR);
}
hLcManager = LoadLibraryA("lcman.DLL");
if (hLcManager != NULL) {
(VOID *) pVerifyLocConstraintA = GetProcAddress(hLcManager, "VerifyLocConstraintA");
}
if (pVerifyLocConstraintA != NULL) {
fVerifyLc = TRUE;
} else {
fprintf(stdout,"BINPLACE : warning BNP0000: Unable to bind to the necessary LCMAN.DLL functions... Ignoring -G switch\n");
}
}
if (PlaceRootName == NULL) {
fprintf(stderr,"BINPLACE : fatal error BNP0000: Place Root not defined - exiting.\n");
exit(BINPLACE_ERR);
}
// If the SymbolFilePath has not been set, make a default value.
if (!SymbolFilePath) {
StringCbCopy(DefaultSymbolFilePath, sizeof(DefaultSymbolFilePath), PlaceRootName);
StringCbCat( DefaultSymbolFilePath, sizeof(DefaultSymbolFilePath), "\\symbols");
SymbolFilePath = DefaultSymbolFilePath;
}
if ( !PlaceTheFile() ) {
if (fDontExit) {
fprintf(stderr,"BINPLACE : error BNP0000: Unable to place file %s.\n",CurrentImageName);
} else {
fprintf(stderr,"BINPLACE : fatal error BNP0000: Unable to place file %s - exiting.\n",CurrentImageName);
exit(BINPLACE_ERR);
}
} else {
}
}
}
if ( (MsgLogFileName = getenv("BINPLACE_MESSAGE_LOG")) != NULL) {
if (!MakeSureDirectoryPathExists(MsgLogFileName)) {
fprintf(stderr,"BINPLACE : error BNP0108: Unable to make directory to \"%s\"\n", MsgLogFileName);
} else {
hMutex = CreateMutex(NULL, FALSE, "WRITE_BINPLACE_MESSAGE_LOG");
if (hMutex != NULL) {
if ( WaitForSingleObject(hMutex, INFINITE) != WAIT_FAILED ) {
MsgLogFile = fopen(MsgLogFileName, "a");
if ( !MsgLogFile ) {
fprintf(stderr,"BINPLACE : error BNP0109: fopen of log file %s failed %d\n", MsgLogFileName,GetLastError());
} else {
setvbuf(MsgLogFile, NULL, _IONBF, 0);
PrintMessageLogBuffer(MsgLogFile);
fclose(MsgLogFile);
}
ReleaseMutex(hMutex);
CloseHandle(hMutex);
} else {
fprintf(stderr,"BINPLACE : error BNP0997: failed to acquire mutex (error code 0x%x)\n", GetLastError());
}
} // hMutex != NULL
}
} // getenv("BINPLACE_MESSAGE_LOG")
FreeMessageLogBuffer();
#define SafeFree(a) if (a!=NULL) { free(a); a=NULL; }
SafeFree(NormalPlaceSubdir);
SafeFree(DestinationPath);
SafeFree(gNewFileName);
SafeFree(PrivateSymbolFilePath);
SafeFree(LcFileName);
SafeFree(PlaceRootNameBuffer);
SafeFree(PlaceFileNameBuffer);
SafeFree(DumpOverride);
SafeFree(szRSDSDllToLoad);
SafeFree(ImageCheck.Argv);
SafeFree(newargv);
if (SymbolFilePath != DefaultSymbolFilePath) {
SafeFree(SymbolFilePath);
}
if (PlaceFile)
fclose(PlaceFile);
exit(BINPLACE_OK);
return BINPLACE_OK;
}
CHAR PlaceFileDir[ BINPLACE_FULL_MAX_PATH];
CHAR PlaceFileClass[BINPLACE_FULL_MAX_PATH];
CHAR PlaceFileEntry[BINPLACE_FULL_MAX_PATH];
BOOL
PlaceTheFile()
{
CHAR FullFileName[MAX_PATH+1];
LPSTR PlaceFileNewName;
LPSTR FilePart;
LPSTR Separator;
LPSTR PlaceFileClassPart;
DWORD cb;
int cfield;
PCLASS_TABLE ClassTablePointer;
BOOLEAN ClassMatch;
BOOL fCopyResult;
LPSTR Extension;
BOOL PutInDump;
BOOL PutInDebug = FALSE;
BOOL PutInLcDir = FALSE;
cb = GetFullPathName(CurrentImageName,MAX_PATH+1,FullFileName,&FilePart);
if (!cb || cb > MAX_PATH+1) {
fprintf(stderr,"BINPLACE : fatal error BNP0000: GetFullPathName failed %d\n",GetLastError());
return FALSE;
}
if (!fDontLog) {
StringCbCopy(gFullFileName,sizeof(gFullFileName),FullFileName);
}
if (fVerbose) {
fprintf(stdout,"BINPLACE : warning BNP0000: Looking at file %s\n",FilePart);
}
Extension = strrchr(FilePart,'.');
if (Extension) {
if (!_stricmp(Extension,".DBG")) {
PutInDebug = TRUE;
}
else if (!_stricmp(Extension,".LC")) {
PutInLcDir = TRUE;
}
}
if (!DumpOverride) {
if (DestinationPath) {
StringCbCopy(PlaceFileClass, sizeof(PlaceFileClass), DestinationPath);
if (gNewFileName!=NULL) {
PlaceFileNewName=gNewFileName;
} else {
PlaceFileNewName=NULL;
}
goto DoTheWork;
}
if (fseek(PlaceFile,0,SEEK_SET)) {
fprintf(stderr,"BINPLACE : fatal error BNP0000: fseek(PlaceFile,0,SEEK_SET) failed %d\n",GetLastError());
return FALSE;
}
while (fgets(PlaceFileEntry,sizeof(PlaceFileDir),PlaceFile)) {
PlaceFileClass[0] = '\0';
if( PlaceFileMatch( FullFileName, // IN
PlaceFileEntry, // INOUT
PlaceFileClass, // OUT, assumed CHAR[BINPLACE_MAX_FULL_PATH]
&PlaceFileNewName // OUT
)) {
DoTheWork:
//
// now that we have the file and class, search the
// class tables for the directory.
//
Separator = PlaceFileClass - 1;
while (Separator) {
PlaceFileClassPart = Separator+1;
Separator = strchr(PlaceFileClassPart,':');
if (Separator) {
*Separator = '\0';
}
//
// If the class is "retail" and we're in Setup mode,
// handle this file specially. Setup mode is used to
// incrementally binplace files into an existing installation.
//
SetupFilePath[0] = '\0';
PlaceFileDir[0]='\0';
ClassMatch = FALSE;
ClassTablePointer = &CommonClassTable[0];
while (ClassTablePointer->ClassName) {
if (!_stricmp(ClassTablePointer->ClassName,PlaceFileClassPart)) {
StringCbCopy(PlaceFileDir,sizeof(PlaceFileDir),ClassTablePointer->ClassLocation);
ClassMatch = TRUE;
//
// If the class is a driver and a UP driver is
// specified, then put the driver in the UP
// subdirectory.
//
// Do the same for retail. We assume the -u switch is passed
// only when actually needed.
//
if (fUpDriver
&& ( !_stricmp(PlaceFileClass,"drivers")
|| !_stricmp(PlaceFileClass,"retail"))) {
StringCbCat(PlaceFileDir,sizeof(PlaceFileDir),"\\up");
}
break;
}
ClassTablePointer++;
}
if (!ClassMatch) {
//
// Search Specific classes
//
// We need to support cross compiling here.
LPTSTR platform;
#if defined(_AMD64_)
ClassTablePointer = &Amd64SpecificClassTable[0];
#elif defined(_IA64_)
ClassTablePointer = &ia64SpecificClassTable[0];
#else // defined(_X86_)
ClassTablePointer = &i386SpecificClassTable[0];
if ((platform = getenv("AMD64")) != NULL) {
ClassTablePointer = &Amd64SpecificClassTable[0];
} else if ((platform = getenv("IA64")) != NULL) {
ClassTablePointer = &ia64SpecificClassTable[0];
}
#endif
while (ClassTablePointer->ClassName) {
if (!_stricmp(ClassTablePointer->ClassName,PlaceFileClassPart)) {
StringCbCopy(PlaceFileDir,sizeof(PlaceFileDir),ClassTablePointer->ClassLocation);
ClassMatch = TRUE;
break;
}
ClassTablePointer++;
}
}
if (!ClassMatch) {
char * asterisk;
//
// Still not found in class table. Use the class as the
// directory
//
if ( fVerbose ) {
fprintf(stderr,"BINPLACE : warning BNP0000: Class %s Not found in Class Tables\n",PlaceFileClassPart);
}
if ( asterisk = strchr( PlaceFileClassPart, '*')) {
//
// Expand * to platform
//
LPTSTR platform;
ULONG PlatformSize;
LPTSTR PlatformPath;
#if defined(_AMD64_)
PlatformSize = 5;
PlatformPath = TEXT("amd64");
#elif defined(_IA64_)
PlatformSize = 4;
PlatformPath = TEXT("ia64");
#else // defined(_X86_)
PlatformSize = 4;
PlatformPath = TEXT("i386");
if ((platform = getenv("IA64")) != NULL) {
PlatformPath = TEXT("ia64");
} else if ((platform = getenv("AMD64")) != NULL) {
PlatformSize = 5;
PlatformPath = TEXT("amd64");
}
#endif
*asterisk = '\0';
StringCbCopy(PlaceFileDir, sizeof(PlaceFileDir), PlaceFileClassPart);
*asterisk = '*';
StringCbCat( PlaceFileDir, sizeof(PlaceFileDir), PlatformPath);
StringCbCat( PlaceFileDir, sizeof(PlaceFileDir), asterisk + 1);
} else {
StringCbCopy(PlaceFileDir, sizeof(PlaceFileDir), PlaceFileClassPart);
}
}
if (SetupFilePath[0] == '\0') {
StringCbCopy(SetupFilePath, sizeof(SetupFilePath), PlaceFileDir);
StringCbCat( SetupFilePath, sizeof(SetupFilePath), "\\");
StringCbCat( SetupFilePath, sizeof(SetupFilePath), FilePart);
}
if (NormalPlaceSubdir) {
StringCbCat(PlaceFileDir, sizeof(PlaceFileDir), "\\");
StringCbCat(PlaceFileDir, sizeof(PlaceFileDir), NormalPlaceSubdir);
}
fCopyResult = CopyTheFile(FullFileName,FilePart,PlaceFileDir,PlaceFileNewName);
if (!fCopyResult) {
break;
}
if ( !fDontLog ) {
int len = 0;
LPSTR LogFileName = NULL;
HANDLE hMutex;
time_t Time;
FILE *fSlmIni;
UCHAR szProject[MAX_PATH];
UCHAR szSlmServer[MAX_PATH];
UCHAR szEnlistment[MAX_PATH];
UCHAR szSlmDir[MAX_PATH];
UCHAR *szTime="";
UCHAR szFullDestName[MAX_PATH+1];
LPSTR szDestFile;
// Get some other interesting info.
fSlmIni = fopen("slm.ini", "r");
if (fSlmIni) {
fgets(szProject, sizeof(szProject), fSlmIni);
fgets(szSlmServer, sizeof(szSlmServer), fSlmIni);
fgets(szEnlistment, sizeof(szEnlistment), fSlmIni);
fgets(szSlmDir, sizeof(szSlmDir), fSlmIni);
// Get rid of the trailing newlines
szProject[strlen(szProject)-1] = '\0';
szSlmServer[strlen(szSlmServer)-1] = '\0';
szSlmDir[strlen(szSlmDir)-1] = '\0';
fclose(fSlmIni);
} else {
szSlmServer[0] = '\0';
szProject[0] = '\0';
szSlmDir[0] = '\0';
}
Time = time(NULL);
szTime = ctime(&Time);
// Remove the built-in CR / NewLine
szTime[ strlen(szTime) - 1 ] = '\0';
StringCbPrintfA(szExtraInfo, sizeof(szExtraInfo),
"%s\t%s\t%s\t%s",
szSlmServer,
szProject,
szSlmDir,
szTime);
// Generate full path to destination
szFullDestName[0] = '\0';
GetFullPathName( gDestinationFile, MAX_PATH + 1, szFullDestName, &szDestFile );
if ((LogFileName = getenv("BINPLACE_LOG")) != NULL) {
if (!MakeSureDirectoryPathExists(LogFileName)) {
fprintf(stderr,"BINPLACE : error BNP0000: Unable to make directory to \"%s\"\n", LogFileName);
}
hMutex = CreateMutex(NULL, FALSE, "WRITE_BINPLACE_LOG");
if (hMutex != NULL) {
if ( WaitForSingleObject(hMutex, INFINITE) != WAIT_FAILED ) {
LogFile = fopen(LogFileName, "a");
if ( !LogFile ) {
fprintf(stderr,"BINPLACE : error BNP0110: fopen of log file %s failed %d\n", LogFileName,GetLastError());
} else {
setvbuf(LogFile, NULL, _IONBF, 0);
if ( fLogPdbPaths ) {
len = fprintf(LogFile,"%s\t%s\t%s\t%s\t%s\n",gFullFileName,szExtraInfo,szFullDestName,gPublicPdbFullPath,gPrivatePdbFullPath);
} else {
len = fprintf(LogFile,"%s\t%s\t%s\n",gFullFileName,szExtraInfo,szFullDestName);
}
if ( len < 0 ) {
fprintf(stderr,"BINPLACE : error BNP0000: write to log file %s failed %d\n", LogFileName, GetLastError());
}
fclose(LogFile);
}
ReleaseMutex(hMutex);
CloseHandle(hMutex);
} else {
fprintf(stderr,"BINPLACE : error BNP0970: failed to acquire mutex (error code 0x%x)\n", GetLastError());
}
} // hMutex != NULL
}
}
}
return(fCopyResult);
}
}
}
if (fMakeErrorOnDumpCopy) {
fprintf(stderr, "BINPLACE : error BNP0000: File '%s' is not listed in '%s'. Copying to dump.\n", FullFileName, PlaceFileName);
return CopyTheFile(
FullFileName,
FilePart,
PutInDebug ? "Symbols" : (PutInLcDir ? BinplaceLcDir : (DumpOverride ? DumpOverride : DEFAULT_DUMP)),
NULL
);
} else {
return TRUE;
}
}
BOOL
CopyTheFile(
LPSTR SourceFileName,
LPSTR SourceFilePart,
LPSTR DestinationSubdir,
LPSTR DestinationFilePart
)
{
CHAR DestinationFile[MAX_PATH+1];
CHAR TmpDestinationFile[MAX_PATH+1];
CHAR TmpDestinationDir[MAX_PATH+1];
CHAR DestinationLcFile[MAX_PATH+1];
char Drive[_MAX_DRIVE];
char Dir[_MAX_DIR];
char Ext[_MAX_EXT];
char Name[_MAX_FNAME];
char TmpName[_MAX_FNAME];
char TmpPath[_MAX_PATH+1];
char FileSystemType[8];
char DriveRoot[4];
CHAR *TmpSymbolFilePath;
DWORD dwFileSystemFlags;
DWORD dwMaxCompLength;
CHAR ErrMsg[MAX_SYM_ERR]; // Symbol checking error message
BOOL fBinplaceLc;
ULONG SymbolFlag;
BOOL fRetail;
if ( !PlaceRootName ) {
fprintf(stderr,"BINPLACE : warning BNP0000: PlaceRoot is not specified\n");
return FALSE;
}
if (fCheckDelayload && !_stricmp(SourceFilePart, gDelayLoadModule))
{
StringCbCopy(TmpDestinationFile, sizeof(TmpDestinationFile), PlaceRootName);
StringCbCat( TmpDestinationFile, sizeof(TmpDestinationFile), "\\");
StringCbCat( TmpDestinationFile, sizeof(TmpDestinationFile), DEFAULT_DELAYLOADDIR);
StringCbCat( TmpDestinationFile, sizeof(TmpDestinationFile), "\\");
StringCbCat( TmpDestinationFile, sizeof(TmpDestinationFile), SourceFilePart);
StringCbCat( TmpDestinationFile, sizeof(TmpDestinationFile), ".ini");
if (!MakeSureDirectoryPathExists(TmpDestinationFile))
{
fprintf(stderr, "BINPLACE : error BNP0000: Unable to create directory path '%s' (%u)\n", TmpDestinationFile, GetLastError());
}
else
{
WritePrivateProfileString("Default", "DelayLoadHandler", gDelayLoadHandler, TmpDestinationFile);
StringCbCopy(TmpDestinationDir, sizeof(TmpDestinationDir), ".\\"); //default to "retail"
if ((*DestinationSubdir != '.') && (*(DestinationSubdir+1) != '\0'))
{
StringCbCopy(TmpDestinationDir,sizeof(TmpDestinationDir), DestinationSubdir);
StringCbCat( TmpDestinationDir,sizeof(TmpDestinationDir), "\\");
}
WritePrivateProfileString("Default", "DestinationDir", TmpDestinationDir, TmpDestinationFile);
}
}
//
// We also neuter SourceIsNewer on FAT partitions since they have a 2 second
// file time granularity
//
_splitpath(SourceFileName, DriveRoot, Dir, NULL, NULL);
StringCbCat(DriveRoot, sizeof(DriveRoot), "\\");
GetVolumeInformation(DriveRoot, NULL, 0, NULL, &dwMaxCompLength, &dwFileSystemFlags, FileSystemType, 7);
if (lstrcmpi(FileSystemType, "FAT") == 0 || lstrcmpi(FileSystemType, "FAT32") == 0)
fPatheticOS = TRUE;
StringCbCopy(DestinationFile, sizeof(DestinationFile), PlaceRootName);
StringCbCat( DestinationFile, sizeof(DestinationFile), "\\");
StringCbCat( DestinationFile, sizeof(DestinationFile), DestinationSubdir);
StringCbCat( DestinationFile, sizeof(DestinationFile), "\\");
StringCbCopy(TmpDestinationDir, sizeof(TmpDestinationDir), DestinationFile);
if (!MakeSureDirectoryPathExists(DestinationFile)) {
fprintf(stderr, "BINPLACE : error BNP0000: Unable to create directory path '%s' (%u)\n",
DestinationFile, GetLastError()
);
}
if (DestinationFilePart) {
StringCbCat(DestinationFile, sizeof(DestinationFile), DestinationFilePart);
} else {
StringCbCat(DestinationFile, sizeof(DestinationFile), SourceFilePart);
}
if ((fVerbose || fTestMode)) {
fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n",SourceFileName,DestinationFile);
}
// SymbolFlag = IGNORE_IF_SPLIT;
fRetail = (*DestinationSubdir == '.') && (*(DestinationSubdir+1) == '\0');
if ( fForcePlace||SourceIsNewer(SourceFileName,DestinationFile,fPatheticOS) ) {
fprintf(stdout, "binplace %s\n", SourceFileName);
if (!VerifyFinalImage(SourceFileName, fRetail, fVerifyLc, LcFullFileName, pVerifyLocConstraintA, &fBinplaceLc) )
return FALSE;
// Verify Symbols
if ( fSymChecking && !fSignCode) {
_splitpath(SourceFileName,Drive, Dir, Name, Ext );
StringCbCopy(TmpName, sizeof(TmpName), Name);
StringCbCat( TmpName, sizeof(TmpName), Ext);
StringCbCopy(TmpPath, sizeof(TmpPath), Drive);
StringCbCat( TmpPath, sizeof(TmpPath), Dir);
if (!CheckSymbols( SourceFileName,
TmpPath,
ExcludeFileName,
fDbgControl,
ErrMsg,
sizeof(ErrMsg)
) ) {
fprintf(stderr,"BINPLACE : error BNP0000: %s",ErrMsg);
return FALSE;
}
}
}
// Store the destination globally so we can access it for output to the log file
StringCbCopy( gDestinationFile, sizeof(gDestinationFile), DestinationFile );
if (!fTestMode) {
//
// In Setup mode, copy the file only if it's newer than
// the one that's already there.
//
if ( fForcePlace||SourceIsNewer(SourceFileName,DestinationFile,fPatheticOS) ) {
if (fVerbose) {
fprintf(stdout,"BINPLACE : warning BNP0000: copy %s to %s\n",SourceFileName,DestinationFile);
}
} else {
return(TRUE);
}
SetFileAttributes(DestinationFile,FILE_ATTRIBUTE_NORMAL);
if (!fIgnoreHardLinks && fHardLinks) {
if ((*pCreateHardLinkA)(SourceFileName, DestinationFile, NULL)) {
if (!fKeepAttributes)
SetFileAttributes(DestinationFile,FILE_ATTRIBUTE_NORMAL);
return(TRUE);
}
}
if ( !CopyFile(SourceFileName,DestinationFile, FALSE)) {
fprintf(stderr,"BINPLACE : warning BNP0000: CopyFile(%s,%s) failed %d\n",SourceFileName,DestinationFile,GetLastError());
return FALSE;
}
if (!fKeepAttributes)
SetFileAttributes(DestinationFile,FILE_ATTRIBUTE_NORMAL);
if (!fNoClassInSymbolsDir) {
StringCbCopy(TmpDestinationDir, sizeof(TmpDestinationDir), SymbolFilePath);
if ((DestinationSubdir[0] == '.') && (DestinationSubdir[1] == '\0')) {
StringCbCat(TmpDestinationDir, sizeof(TmpDestinationDir),"\\retail");
} else {
char * pSubdir;
char * pTmp;
StringCbCat(TmpDestinationDir, sizeof(TmpDestinationDir), "\\");
pSubdir = DestinationSubdir;
if (pSubdir[0] == '.' && pSubdir[1] == '\\')
{
pSubdir += 2;
}
//
// Put the root dir only on the path
// Optionally change asms to retail.
//
pTmp = strchr(pSubdir, '\\');
if (pTmp) {
const static char asms[] = "asms\\";
if (fChangeAsmsToRetailForSymbols
&& _strnicmp(pSubdir, asms, sizeof(asms) - 1) ==0) {
//
StringCbCopy(TmpDestinationFile, sizeof(TmpDestinationFile), "retail");
StringCbCat( TmpDestinationDir, sizeof(TmpDestinationDir), TmpDestinationFile);
} else {
StringCbCopy(TmpDestinationFile, sizeof(TmpDestinationFile), pSubdir);
TmpDestinationFile[pTmp - pSubdir] = '\0';
StringCbCat(TmpDestinationDir, sizeof(TmpDestinationDir), TmpDestinationFile);
}
} else {
StringCbCat(TmpDestinationDir, sizeof(TmpDestinationDir), pSubdir);
}
}
TmpSymbolFilePath = TmpDestinationDir;
} else {
TmpSymbolFilePath = SymbolFilePath;
}
if (fSplitSymbols && !fBypassSplitSymX) {
// temp var for getting PDB path from SplitSymbolsX()
CHAR TempFullPublicPdbPath[MAX_PATH]="";
LPSTR* tmp = NULL;
_splitpath(SourceFileName, Drive, Dir, NULL, Ext);
_makepath(DebugFilePath, Drive, Dir, NULL, NULL);
SplitFlags |= SPLITSYM_SYMBOLPATH_IS_SRC;
if ( SplitSymbolsX( DestinationFile, TmpSymbolFilePath, (PCHAR) DebugFilePath, sizeof(DebugFilePath),
SplitFlags, szRSDSDllToLoad, TempFullPublicPdbPath, sizeof(TempFullPublicPdbPath) )) {
if (fVerbose)
fprintf( stdout, "BINPLACE : warning BNP0000: Symbols stripped from %s into %s\n", DestinationFile, DebugFilePath);
if (fLogPdbPaths) {
if ( GetFullPathName(TempFullPublicPdbPath, MAX_PATH+1, gPublicPdbFullPath, tmp) > (MAX_PATH+1) ) {
gPublicPdbFullPath[0] = '\0';
}
}
} else {
if (fVerbose)
fprintf( stdout, "BINPLACE : warning BNP0000: No symbols to strip from %s\n", DestinationFile);
if ( ! ConcatPaths(DebugFilePath, sizeof(DebugFilePath), PlaceRootName, TmpSymbolFilePath, &Ext[1]) ) {
fprintf(stderr, "BINPLACE : error BNP1532: Unable to create public symbol file path.\n");
return(FALSE);
} else {
if (fVerbose) {
fprintf( stdout, "BINPLACE : warning BNP1536: Public symbols being copied to %s.\n", DebugFilePath);
}
}
BinplaceCopyPdb(DebugFilePath, SourceFileName, TRUE, SplitFlags & SPLITSYM_REMOVE_PRIVATE);
}
if ((SplitFlags & SPLITSYM_REMOVE_PRIVATE) && (PrivateSymbolFilePath != NULL)) {
CHAR Dir1[_MAX_PATH];
CHAR Dir2[_MAX_PATH];
_splitpath(DebugFilePath, Drive, Dir, NULL, NULL);
_makepath(Dir1, Drive, Dir, NULL, NULL);
StringCbCopy(Dir2, sizeof(Dir2), PrivateSymbolFilePath);
StringCbCat( Dir2, sizeof(Dir2), Dir1+strlen(SymbolFilePath));
MakeSureDirectoryPathExists(Dir2);
BinplaceCopyPdb(Dir2, SourceFileName, TRUE, FALSE);
}
} else {
BinplaceCopyPdb(DestinationFile, SourceFileName, FALSE, fSplitSymbols ? (SplitFlags & SPLITSYM_REMOVE_PRIVATE) : FALSE);
}
//
// trace formatting
//
if (fWppFmt) {
CHAR PdbName[MAX_PATH+1];
DWORD PdbSig;
if ( BinplaceGetSourcePdbName(SourceFileName, sizeof(PdbName), PdbName, &PdbSig) ) {
if (strcmp(PdbName,LastPdbName) != 0) { // Have we just processed this PDB?
if (fVerbose) {
fprintf( stdout, "BINPLACE : warning BNP0000: Trace Formats being built from %s\n", PdbName );
}
if (TraceFormatFilePath[0] == '\0') {
if (PrivateSymbolFilePath != NULL) {
StringCbPrintfA(TraceFormatFilePath,sizeof(TraceFormatFilePath),"%s\\%s",PrivateSymbolFilePath,TraceDir);
} else {
strncpy(TraceFormatFilePath, TraceDir, MAX_PATH) ;
}
if (fVerbose) {
fprintf( stdout, "BINPLACE : warning BNP0000: Trace Formats file path set to %s\n", TraceFormatFilePath );
}
}
BinplaceWppFmt(PdbName, TraceFormatFilePath, szRSDSDllToLoad, fVerbose);
// because files are frequently copied to multiple places, the PDB is also placed
// several times, there is no point in us processing it more than once.
strncpy(LastPdbName,PdbName,MAX_PATH);
} else {
if (fVerbose) {
fprintf( stdout, "BINPLACE : warning BNP0000: Trace Formats skipping %s (same as last)\n", PdbName );
}
}
}
}
StripCVSymbolPath(DestinationFile);
if (fPlaceWin95SymFile) {
char DestSymPath[_MAX_PATH];
char DestSymDir[_MAX_PATH];
char SrcSymPath[_MAX_PATH];
_splitpath(CurrentImageName, Drive, Dir, Name, Ext);
_makepath(SrcSymPath, Drive, Dir, Name, ".sym");
if (!_access(SrcSymPath, 0)) {
if (fSplitSymbols) {
StringCbCopy(DestSymPath, sizeof(DestSymPath), TmpSymbolFilePath);
StringCbCat( DestSymPath, sizeof(DestSymPath), "\\");
StringCbCat( DestSymPath, sizeof(DestSymPath), Ext[0] == '.' ? &Ext[1] : Ext);
StringCbCat( DestSymPath, sizeof(DestSymPath), "\\");
StringCbCat( DestSymPath, sizeof(DestSymPath), Name);
StringCbCat( DestSymPath, sizeof(DestSymPath), ".sym");
} else {
_splitpath(DestinationFile, Drive, Dir, NULL, NULL);
_makepath(DestSymPath, Drive, Dir, Name, ".sym");
}
SetFileAttributes(DestSymPath, FILE_ATTRIBUTE_NORMAL);
if ( fForcePlace||SourceIsNewer(SrcSymPath, SourceFileName,fPatheticOS) ) {
// Only binplace the .sym file if it was built AFTER the image itself.
// Make sure to create the destination path in case it is not there already.
StringCbCopy(DestSymDir, sizeof(DestSymDir), TmpSymbolFilePath);
StringCbCat( DestSymDir, sizeof(DestSymDir), "\\");
StringCbCat( DestSymDir, sizeof(DestSymDir), Ext[0] == '.' ? &Ext[1] : Ext);
StringCbCat( DestSymDir, sizeof(DestSymDir), "\\");
MakeSureDirectoryPathExists(DestSymDir);
if (!CopyFile(SrcSymPath, DestSymPath, FALSE)) {
fprintf(stderr,"BINPLACE : warning BNP0000: CopyFile(%s,%s) failed %d\n", SrcSymPath, DestSymPath ,GetLastError());
}
}
if (!fKeepAttributes)
SetFileAttributes(DestinationFile,FILE_ATTRIBUTE_NORMAL);
} else {
if (fVerbose) {
fprintf( stdout, "BINPLACE : warning BNP0000: Unable to locate \"%s\" for \"%s\"\n", SrcSymPath, CurrentImageName );
}
}
}
if (fDigitalSign) {
SignWithIDWKey( DestinationFile, fVerbose );
}
if (fBinplaceLc) {
StringCbCopy(DestinationLcFile, sizeof(DestinationLcFile), PlaceRootName);
StringCbCat( DestinationLcFile, sizeof(DestinationLcFile), "\\");
StringCbCat( DestinationLcFile, sizeof(DestinationLcFile), BinplaceLcDir);
StringCbCat( DestinationLcFile, sizeof(DestinationLcFile), "\\");
StringCbCat( DestinationLcFile, sizeof(DestinationLcFile), DestinationSubdir);
StringCbCat( DestinationLcFile, sizeof(DestinationLcFile), "\\");
if (!MakeSureDirectoryPathExists(DestinationLcFile)) {
fprintf(stderr, "BINPLACE : error BNP0000: Unable to create directory path '%s' (%u)\n",
DestinationLcFile, GetLastError()
);
}
StringCbCat(DestinationLcFile, sizeof(DestinationLcFile), LcFilePart);
if (!CopyFile(LcFullFileName, DestinationLcFile, FALSE)) {
fprintf(stderr,"BINPLACE : warning BNP0000: CopyFile(%s,%s) failed %d\n",
LcFullFileName,DestinationLcFile,GetLastError());
}
}
}
return TRUE;
}
BOOL
BinplaceCopyPdb (
LPSTR DestinationFile,
LPSTR SourceFileName,
BOOL CopyFromSourceOnly,
BOOL StripPrivate
)
{
LOADED_IMAGE LoadedImage;
DWORD DirCnt;
IMAGE_DEBUG_DIRECTORY UNALIGNED *DebugDirs, *CvDebugDir;
if (MapAndLoad(
CopyFromSourceOnly ? SourceFileName : DestinationFile,
NULL,
&LoadedImage,
FALSE,
CopyFromSourceOnly ? TRUE : FALSE) == FALSE) {
return (FALSE);
}
DebugDirs = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData(
LoadedImage.MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_DEBUG,
&DirCnt
);
if (!DebugDirectoryIsUseful(DebugDirs, DirCnt)) {
UnMapAndLoad(&LoadedImage);
return(FALSE);
}
DirCnt /= sizeof(IMAGE_DEBUG_DIRECTORY);
CvDebugDir = NULL;
while (DirCnt) {
DirCnt--;
if (DebugDirs[DirCnt].Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
CvDebugDir = &DebugDirs[DirCnt];
break;
}
}
if (!CvDebugDir) {
// Didn't find any CV debug dir. Bail.
UnMapAndLoad(&LoadedImage);
return(FALSE);
}
if (CvDebugDir->PointerToRawData != 0) {
PCVDD pDebugDir;
ULONG mysize;
pDebugDir = (PCVDD) (CvDebugDir->PointerToRawData + (PCHAR)LoadedImage.MappedAddress);
if (pDebugDir->dwSig == '01BN' ) {
mysize=sizeof(NB10IH);
} else {
mysize=sizeof(RSDSIH);
}
if (pDebugDir->dwSig == '01BN' || pDebugDir->dwSig == 'SDSR' ) {
// Got a PDB. The name immediately follows the signature.
LPSTR szMyDllToLoad;
CHAR PdbName[sizeof(((PRSDSI)(0))->szPdb)];
CHAR NewPdbName[sizeof(((PRSDSI)(0))->szPdb)];
CHAR Drive[_MAX_DRIVE];
CHAR Dir[_MAX_DIR];
CHAR Filename[_MAX_FNAME];
CHAR FileExt[_MAX_EXT];
if (pDebugDir->dwSig == '01BN') {
szMyDllToLoad=NULL;
} else {
szMyDllToLoad=szRSDSDllToLoad;
}
ZeroMemory(PdbName, sizeof(PdbName));
memcpy(PdbName, ((PCHAR)pDebugDir) + mysize, __min(CvDebugDir->SizeOfData - mysize, sizeof(PdbName)));
_splitpath(PdbName, NULL, NULL, Filename, FileExt);
// Calculate the destination name
_splitpath(DestinationFile, Drive, Dir, NULL, NULL);
_makepath(NewPdbName, Drive, Dir, Filename, FileExt);
// Then the source name. First we try in the same dir as the image itself
_splitpath(SourceFileName, Drive, Dir, NULL, NULL);
_makepath(PdbName, Drive, Dir, Filename, FileExt);
if ((fVerbose || fTestMode)) {
fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n", PdbName, NewPdbName);
}
if (!MakeSureDirectoryPathExists(NewPdbName)) {
fprintf(stderr, "BINPLACE : error BNP0000: Unable to create directory path '%s' (%u)\n",
NewPdbName, GetLastError());
}
SetFileAttributes(NewPdbName,FILE_ATTRIBUTE_NORMAL);
if (fLogPdbPaths) {
LPTSTR *tmp=NULL;
// when stripping privates, we get the public pdb path, otherwise we get the private pdb path
if ( StripPrivate ) {
// use GetFullPathName to normalize path
if ( GetFullPathName(NewPdbName, MAX_PATH+1, gPublicPdbFullPath, tmp) > (MAX_PATH+1) ) {
gPublicPdbFullPath[0] = '\0';
fprintf(stderr,"BINPLACE : warning BNP1697: Unable to log PDB public path\n");
}
} else {
// use GetFullPathName to normalize path
if ( GetFullPathName(NewPdbName, MAX_PATH+1, gPrivatePdbFullPath, tmp) > (MAX_PATH+1) ) {
gPrivatePdbFullPath[0] = '\0';
fprintf(stderr,"BINPLACE : warning BNP1691: Unable to log PDB private path\n");
}
}
}
if ( !CopyPdbX(PdbName, NewPdbName, StripPrivate, szMyDllToLoad)) {
if ((fVerbose || fTestMode)) {
fprintf(stderr,"BINPLACE : warning BNP0000: Unable to copy (%s,%s) %d\n", PdbName, NewPdbName, GetLastError());
}
// The file is not in the same dir as the image - try the path listed in the image
ZeroMemory(PdbName, sizeof(PdbName));
memcpy(PdbName, ((PCHAR)pDebugDir) + mysize, __min(CvDebugDir->SizeOfData - mysize, sizeof(PdbName)));
if ((fVerbose || fTestMode)) {
fprintf(stdout,"BINPLACE : warning BNP0000: place %s in %s\n", PdbName, NewPdbName);
}
if ( !CopyPdbX(PdbName, NewPdbName, StripPrivate, szMyDllToLoad)) {
if (fLogPdbPaths) {
if ( StripPrivate ) {
gPublicPdbFullPath[0] = '\0';
fprintf(stderr,"BINPLACE : warning BNP1697: Unable to log PDB public path (%s)\n", NewPdbName);
} else {
gPrivatePdbFullPath[0] = '\0';
fprintf(stderr,"BINPLACE : warning BNP1697: Unable to log PDB private path (%s)\n", NewPdbName);
}
}
// fprintf(stderr,"BINPLACE : warning BNP0000: CopyPdb(%s,%s) failed %d\n", PdbName, NewPdbName, GetLastError());
}
}
if (!fKeepAttributes)
SetFileAttributes(NewPdbName, FILE_ATTRIBUTE_NORMAL);
if (fSrcControl && !StripPrivate) {
CHAR CvdumpName[sizeof(((PRSDSI)(0))->szPdb)]; // [_MAX_PATH + _MAX_FNAME];
UINT i;
LONG pos;
CHAR buf[_MAX_PATH*3];
// Find the start of "symbols.pri" in NewPdbName
pos=-1;
i=0;
while ( (i < strlen(NewPdbName) - strlen("symbols.pri")) && pos== -1) {
if (_strnicmp( NewPdbName+i, "symbols.pri", strlen("symbols.pri") ) == 0 ) {
pos=i;
} else {
i++;
}
}
if ( pos >= 0 ) {
StringCbCopy(CvdumpName, sizeof(CvdumpName), NewPdbName);
CvdumpName[i]='\0';
StringCbCat(CvdumpName, sizeof(CvdumpName), "cvdump.pri" );
StringCbCat(CvdumpName, sizeof(CvdumpName), NewPdbName + pos + strlen("symbols.pri") );
StringCbCat(CvdumpName, sizeof(CvdumpName), ".dmp");
// Get the Directory name and create it
if ( MakeSureDirectoryPathExists(CvdumpName) ) {
StringCbPrintfA(buf, sizeof(buf), "cvdump -sf %s > %s", NewPdbName, CvdumpName);
// Spawn off cvdump.exe - this is a security risk since we don't specifically specify the path
// to cvdump.exe. However, we can't guarentee that it exists nor that
// if we find it dynamically that the correct one will be used so I'm not
// certain that we can do this any differently.
system(buf);
} else {
fprintf( stdout, "BINPLACE : error BNP0000: Cannot create directory for the file %s\n", CvdumpName);
}
}
}
}
UnMapAndLoad(&LoadedImage);
return(TRUE);
}
UnMapAndLoad(&LoadedImage);
return(FALSE);
}
//
// Finds the name of the source PDB using the CV data from the source binary. Returns the name and the
// PDB Sig.
//
BOOL BinplaceGetSourcePdbName(LPTSTR SourceFileName, DWORD BufferSize, CHAR* SourcePdbName, DWORD* PdbSig) {
BOOL Return = FALSE;
LOADED_IMAGE LoadedImage;
DWORD DirCnt;
IMAGE_DEBUG_DIRECTORY UNALIGNED *DebugDirs,
*CvDebugDir;
if (MapAndLoad(SourceFileName,
NULL,
&LoadedImage,
FALSE,
TRUE) == FALSE) {
return (FALSE);
}
DebugDirs = (PIMAGE_DEBUG_DIRECTORY) ImageDirectoryEntryToData(LoadedImage.MappedAddress,
FALSE,
IMAGE_DIRECTORY_ENTRY_DEBUG,
&DirCnt);
if (!DebugDirectoryIsUseful(DebugDirs, DirCnt)) {
UnMapAndLoad(&LoadedImage);
return(FALSE);
}
DirCnt /= sizeof(IMAGE_DEBUG_DIRECTORY);
CvDebugDir = NULL;
while (DirCnt) {
DirCnt--;
if (DebugDirs[DirCnt].Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
CvDebugDir = &DebugDirs[DirCnt];
break;
}
}
if (!CvDebugDir) {
// Didn't find any CV debug dir. Bail.
UnMapAndLoad(&LoadedImage);
return(FALSE);
}
if (CvDebugDir->PointerToRawData != 0) {
PCVDD pDebugDir;
ULONG mysize;
pDebugDir = (PCVDD) (CvDebugDir->PointerToRawData + (PCHAR)LoadedImage.MappedAddress);
*PdbSig = pDebugDir->dwSig;
if (pDebugDir->dwSig == '01BN' ) {
mysize=sizeof(NB10IH);
} else {
mysize=sizeof(RSDSIH);
}
if (pDebugDir->dwSig == '01BN' || pDebugDir->dwSig == 'SDSR' ) {
// Got a PDB. The name immediately follows the signature.
LPSTR szMyDllToLoad;
CHAR PdbName[sizeof(((PRSDSI)(0))->szPdb)];
CHAR NewPdbName[sizeof(((PRSDSI)(0))->szPdb)];
CHAR Drive[_MAX_DRIVE];
CHAR Dir[_MAX_DIR];
CHAR Filename[_MAX_FNAME];
CHAR FileExt[_MAX_EXT];
ZeroMemory(PdbName, sizeof(PdbName));
StringCbCopy(PdbName, sizeof(PdbName), ((PCHAR)pDebugDir) + mysize);
_splitpath(PdbName, NULL, NULL, Filename, FileExt);
// Then the source name. First we try in the same dir as the image itself
_splitpath(SourceFileName, Drive, Dir, NULL, NULL);
_makepath(SourcePdbName, Drive, Dir, Filename, FileExt);
//
// Handle the case where the PDB doesn't exist in the given location
// by checking for it in the same directory as the binary!
//
// make sure the file exists and is readable
if ( _access(SourcePdbName, 4) != 0 ) {
// The file is not in the same dir as the image - try the path listed in the image
memcpy(SourcePdbName, ((PCHAR)pDebugDir) + mysize, __min(CvDebugDir->SizeOfData - mysize, BufferSize));
// make sure the file exists and is readable
if ( _access(SourcePdbName, 4) == 0 ) {
Return = TRUE;
}
} else {
Return = TRUE;
}
}
UnMapAndLoad(&LoadedImage);
return(TRUE);
}
UnMapAndLoad(&LoadedImage);
return(FALSE);
}
// shared globals for InitMessageBufferWithCwd(), GetAndLogNextArg() and PrintMessageLogBuffer()
static CHAR * MessageLogBuffer= NULL;
static BOOL MessageLogError = FALSE;
// puts CWD into MessageLogBuffer
BOOL InitMessageBufferWithCwd(void) {
BOOL fRetVal = FALSE;
if ( GetCurrentDirectory(_msize(MessageLogBuffer)/sizeof(TCHAR), MessageLogBuffer) == 0 ) {
// use GetLastError() to find the specifics- all I care about here is
// whether we succeeded or not.
fRetVal = FALSE;
} else {
if (StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), " ") != S_OK) {
fRetVal = FALSE;
} else {
fRetVal = TRUE;
}
}
return(fRetVal);
}
// Calls GetNextArg and logs the result
DWORD GetAndLogNextArg(OUT TCHAR* Buffer, IN DWORD BufferSize, OPTIONAL OUT DWORD* RequiredSize) {
DWORD TempValue = GetNextArg(Buffer, BufferSize, RequiredSize);
CHAR* TempBuffer;
if (MessageLogBuffer == NULL) {
MessageLogBuffer = (CHAR*)malloc(sizeof(CHAR)*1024); // initial size
// make sure we have memory
if ( MessageLogBuffer == NULL ) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1771: Unable log command line.");
// stick CWD into buffer
} else if ( ! InitMessageBufferWithCwd() ) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1771: Unable log command line.");
// add this arg to the buffer
} else if ( StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), Buffer) != S_OK||
StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), " ") != S_OK) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1771: Unable log command line.");
}
} else {
if (_msize(MessageLogBuffer) < strlen(MessageLogBuffer) + strlen(Buffer) + 2) {
TempBuffer = (CHAR*)realloc(MessageLogBuffer, _msize(MessageLogBuffer) + 1024);
if (TempBuffer == NULL) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1779: Unable log command line.");
} else {
MessageLogBuffer = TempBuffer;
if (StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), Buffer) != S_OK) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1783: Unable log command line.");
}
if (StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), " ") != S_OK) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1783: Unable log command line.");
}
}
} else {
if (StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), Buffer) != S_OK) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1783: Unable log command line.");
}
if (StringCbCat(MessageLogBuffer, _msize(MessageLogBuffer), " ") != S_OK) {
MessageLogError = TRUE;
fprintf(stderr,"BINPLACE : warning BNP1783: Unable log command line.");
}
}
}
return(TempValue);
}
// writes LogBuffer to supplied handle
BOOL PrintMessageLogBuffer(FILE* fLogHandle) {
BOOL bRetVal = TRUE;
if (fLogHandle != NULL) {
if (MessageLogError) {
// ';' denotes the beginning of a comment in the binplace message log
// write what we can of the command line and note that it might not be valid
// also, write the line as a comment to avoid accicental execution of it.
fprintf(fLogHandle, "; ERROR: Possible bad command line follows\n");
fprintf(fLogHandle, "; %s\n", MessageLogBuffer);
} else {
fprintf(fLogHandle, "%s\n", MessageLogBuffer);
}
}
return(bRetVal);
}
BOOL FreeMessageLogBuffer(void) {
if (MessageLogBuffer != NULL) {
free(MessageLogBuffer);
MessageLogBuffer = NULL;
}
return(TRUE);
}
///////////////////////////////////////////////////////////////////////////////
//
// Local replacement for GetFullPathName that correctly handles lpFileName when
// it begins with '\'
//
DWORD PrivateGetFullPathName(LPCTSTR lpFilename, DWORD nBufferLength, LPTSTR lpBuffer, LPTSTR *lpFilePart) {
DWORD Return = 0;
CHAR* ch;
//
// GetFullPath flounders when referring to the root of the drive, so use
// a private version that handles it
//
if ( lpFilename[0] == '\\' ) {
// handle network paths
if ( lpFilename[1] == '\\' ) {
if ( StringCchCopy(lpBuffer, nBufferLength, lpFilename)!=S_OK ) {
Return = 0;
} else {
// fill in the return data
ch = strrchr(lpBuffer, '\\');
ch++;
lpFilePart = (LPTSTR*)ch;
Return = strlen(lpBuffer);
}
} else {
Return = GetCurrentDirectory(nBufferLength, lpBuffer);
// truncate everything after drive name
if ( (Return!=0) && (Return <= MAX_PATH+1)) {
ch = strchr(lpBuffer, '\\');
if (ch!=NULL) {
*ch = '\0';
}
// push in the filename
if ( StringCchCat(lpBuffer, nBufferLength, lpFilename)!=S_OK ) {
Return = 0;
} else {
// fill in the return data
ch = strrchr(lpBuffer, '\\');
ch++;
lpFilePart = (LPTSTR*)ch;
Return = strlen(lpBuffer);
}
} else {
// return the needed size
}
}
} else {
//
// Not refering to drive root, just call the API
//
Return = GetFullPathName(lpFilename, nBufferLength, lpBuffer, lpFilePart);
}
return(Return);
}
//////////////////////////////////////////////////////////////////////////////////////////////
// concat 3 paths together handling the case where the second may be relative to the first
// or may be absolute
BOOL ConcatPaths( LPTSTR pszDest, size_t cbDest, LPCTSTR Root, LPCTSTR Symbols, LPCTSTR Ext) {
CHAR* TempPath = malloc(sizeof(TCHAR) * cbDest);
LPTSTR Scratch;
if (TempPath == NULL) {
return(FALSE);
}
if (Symbols[1] == ':') { // symbols contains a drive spec
if ( StringCbCopy(TempPath, cbDest, Symbols) != S_OK ) {
free(TempPath);
return(FALSE);
}
} else if (Symbols[0] == '\\') { // symbols contains a root path or UNC path
if ( Symbols[1] == '\\' ) { // UNC path
if ( StringCbCopy(TempPath, cbDest, Symbols) != S_OK ) {
free(TempPath);
return(FALSE);
}
} else { // path from drive root
CHAR drive[_MAX_DRIVE];
CHAR dir[ _MAX_DIR];
CHAR file[ _MAX_FNAME];
CHAR ext[ _MAX_EXT];
_splitpath(Root, drive, dir, file, ext);
if ( StringCbCopy(TempPath, cbDest, drive) != S_OK ) {
free(TempPath);
return(FALSE);
}
if ( StringCbCat(TempPath, cbDest, Symbols) != S_OK ) {
free(TempPath);
return(FALSE);
}
}
} else {
if ( StringCbCopy(TempPath, cbDest, Root) != S_OK ) {
free(TempPath);
return(FALSE);
}
if ( TempPath[strlen(TempPath)] != '\\' ) {
if ( StringCbCat(TempPath, cbDest, "\\") != S_OK ) {
free(TempPath);
return(FALSE);
}
}
if ( StringCbCat(TempPath, cbDest, Symbols) != S_OK ) {
free(TempPath);
return(FALSE);
}
}
if ( TempPath[strlen(TempPath)] != '\\' && Ext[0] != '\\' ) {
if ( StringCbCat(TempPath, cbDest, "\\") != S_OK ) {
free(TempPath);
return(FALSE);
}
}
if ( StringCbCat(TempPath, cbDest, Ext) != S_OK ) {
free(TempPath);
return(FALSE);
}
// final string needs to end in '\\'
if ( StringCbCat(TempPath, cbDest, "\\") != S_OK ) {
free(TempPath);
return(FALSE);
}
// return size doesn't include final \0, so don't use '<='
if ( PrivateGetFullPathName(TempPath, cbDest, pszDest, &Scratch) < cbDest ) {
free(TempPath);
return(TRUE);
} else {
free(TempPath);
return(FALSE);
}
}