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.
 
 
 
 
 
 

1469 lines
45 KiB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tchar.h>
#include <assert.h>
#include "dbghelp.h"
#include "strsafe.h"
#define X86INF 200
#define ALPHAINF 201
// Prototypes
typedef struct _COMMAND_ARGS {
DWORD dwCabSize; // Default size of cab
LPTSTR szInputFileName; // Name of the list of files to put into cabs
LPTSTR szOutDir; // Directory to place the makefile and DDF's
LPTSTR szDDFHeader; // Header for the DDF
LPTSTR szSymDir; // Root of symbols directory
LPTSTR szCabDir; // Directory to write cabs to
LPTSTR szInfDir; // Directory to write infs to
LPTSTR szSymCabName; // Symbol cab name
BOOL MergeIntoOne; // Will cabs all be merged into one cab?
} COM_ARGS, *PCOM_ARGS;
typedef struct _SYM_FILE {
TCHAR szCabName [_MAX_FNAME + 1]; // Final destination cab for this file
TCHAR szTmpCabName [_MAX_FNAME + 1]; // Original cab this file is in before it
// is combined into a bigger cab
TCHAR szExeName [_MAX_PATH + 1];
TCHAR szSymName [_MAX_PATH + 1];
TCHAR szSymReName [_MAX_PATH + 1];
TCHAR szSymSrcPath [_MAX_PATH + 1];
TCHAR szInstallPath [_MAX_PATH + 1];
TCHAR szInstallPathX [_MAX_PATH + 1]; // This is the install path with
// the /'s changed to .'s
BOOL Duplicate; // Duplicate File, ignore it
BOOL ReName; // Two different files have the same
// name. Example, exe\dcpromo.dbg,
// dll\dcpromo.dbg
DWORD dwCabNumber; // Number of the cab in symbols.inf
} SYM_FILE, *PSYM_FILE;
typedef struct _SYM_LIST {
DWORD dwSize; // Number of Entries
PSYM_FILE* pSymList; // list of symbol files
} SYM_LIST, *PSYM_LIST;
BOOL PrintFullSymbolPath(
IN FILE* OutputFile,
IN OPTIONAL LPTSTR SymbolRoot,
IN LPTSTR SymbolPath
);
PCOM_ARGS GetCommandLineArgs(
int argc,
char **argv
);
PSYM_LIST
GetList(
LPTSTR szFileName
);
VOID
Usage (
VOID
);
int __cdecl
SymComp(
const void *e1,
const void *e2
);
int __cdecl
SymSortBySymbolName(
const void *e1,
const void *e2
);
int __cdecl
SymSortByInstallPath(
const void *e1,
const void *e2
);
int __cdecl
SymSortByCabNumber(
const void *e1,
const void *e2
);
BOOL
ComputeCabNames(
PSYM_LIST pList,
DWORD dwCabSize,
LPTSTR szSymCabName
);
BOOL
CreateMakefile(
PSYM_LIST pList,
LPTSTR szOutDir,
LPTSTR szSymDir,
LPTSTR szCabDir
);
BOOL
CreateDDFs(
PSYM_LIST pList,
LPTSTR szOutDir, // Directory to write the DDFs to
LPTSTR szSymDir, // Root of the symbols tree
LPTSTR szCabDir // Directory where cabs are written to
);
BOOL
CreateCDF(
PSYM_LIST pList,
LPTSTR szOutDir, // Directory to write the CDF to
LPTSTR szSymDir, // Root of the symbols tree
LPTSTR szSymCabName,
LPTSTR szInfDir // Destination for the CAT file
);
BOOL
CreateCabList(
PSYM_LIST pList,
LPTSTR szOutDir
);
BOOL
FindDuplicatesAndFilesToReName(
PSYM_LIST pList
);
BOOL
RenameAllTheFiles(
PSYM_LIST pList
);
BOOL
ComputeFinalCabNames(
PSYM_LIST pList,
LPTSTR szSymCabName,
BOOL MergeIntoOne
);
BOOL
CreateInf(
PSYM_LIST pList,
LPTSTR szInfDir,
LPTSTR szSymCabName
);
BOOL FreePList(PSYM_LIST pList);
int
_cdecl
main( int argc, char **argv)
{
PCOM_ARGS pArgs;
PSYM_LIST pList;
DWORD i;
pArgs = GetCommandLineArgs(argc, argv);
pList = GetList(pArgs->szInputFileName);
if (pList)
{
if ( pList->dwSize < 1 ) {
FreePList(pList);
exit(1);
}
// First, sort the list by Symbol name
qsort( (void*)pList->pSymList, (size_t)pList->dwSize,
(size_t)sizeof(PSYM_FILE), SymSortBySymbolName );
FindDuplicatesAndFilesToReName(pList);
RenameAllTheFiles(pList);
// Compute Temporary cab names ...
// Make a bunch of small cabs and then combine them to
// make symbol cabbing more efficient.
// all functions must return TRUE
if ( ComputeCabNames(pList, pArgs->dwCabSize, pArgs->szSymCabName) &&
CreateMakefile( pList, pArgs->szOutDir, pArgs->szSymDir, pArgs->szCabDir) &&
CreateCabList( pList, pArgs->szOutDir ) &&
CreateDDFs( pList, pArgs->szOutDir, pArgs->szSymDir, pArgs->szCabDir) &&
CreateCDF( pList, pArgs->szOutDir, pArgs->szSymDir, pArgs->szSymCabName,
pArgs->szInfDir ) &&
ComputeFinalCabNames(pList, pArgs->szSymCabName, pArgs->MergeIntoOne) &&
// Creates symbols.inf that is used to install the symbols
CreateInf(pList, pArgs->szInfDir, pArgs->szSymCabName) ) {
return(0);
} else {
return(1);
}
}
return 0;
}
VOID
Usage (
VOID
)
{
printf("\n");
printf("Usage: symmake [/m] /c CabName /d DDFHeader /i InfFile /o OutDir \n");
printf(" /s CabSize /t SymbolPath\n");
printf(" /c cabname Name to give the cabs\n");
printf(" /d DDFHeader File with common DDF header formatting\n");
printf(" /i InfFile File with list of symbol files to copy\n");
printf(" /m Merge Merge the cabs into one cab\n");
printf(" /o OutDir Directory to place DDF files and makefile\n");
printf(" /s CabSize Number of files per cab\n");
printf(" /t SymPath Root of the symbol tree (i.e., d:\\binaries)\n");
printf(" SymPath is ignored if the symbol path in InfFile\n");
printf(" is already fully qualified.\n");
printf(" /x CabDest Full destination path for the cabs\n");
printf(" /y InfDest Full destination for the infs\n");
printf("\n");
exit(1);
}
PCOM_ARGS
GetCommandLineArgs(
int argc,
char **argv
)
{
PCOM_ARGS pArgs;
int i,cur,length;
TCHAR c;
BOOL NeedSecond = FALSE;
if (argc == 1) Usage();
pArgs = (PCOM_ARGS)malloc(sizeof(COM_ARGS));
if ( pArgs == NULL ) {
printf("Not enough memory to allocate pArgs\n");
exit(1);
}
memset( pArgs, 0, sizeof(COM_ARGS) );
pArgs->MergeIntoOne = FALSE;
pArgs->szSymDir = NULL; // expect this to be NULL or a valid string
for (i=1; i<argc; i++) {
if (!NeedSecond) {
if ( (argv[i][0] == '/') || (argv[i][0] == '-') ) {
length = _tcslen(argv[i]) -1;
for (cur=1; cur <= length; cur++) {
c = argv[i][cur];
switch (c) {
case 'c': NeedSecond = TRUE;
break;
case 'd': NeedSecond = TRUE;
break;
case 'i': NeedSecond = TRUE;
break;
case 'm': NeedSecond = FALSE;
pArgs->MergeIntoOne = TRUE;
break;
case 'o': NeedSecond = TRUE;
break;
case 's': NeedSecond = TRUE;
break;
case 't': NeedSecond = TRUE;
break;
case 'x': NeedSecond = TRUE;
break;
case 'y': NeedSecond = TRUE;
break;
default: Usage();
}
}
}
}
else {
NeedSecond = FALSE;
switch (c) {
case 'c': pArgs->szSymCabName = argv[i];
break;
case 'd': pArgs->szDDFHeader = argv[i];
break;
case 'i': pArgs->szInputFileName = argv[i];
break;
case 'o': pArgs->szOutDir = argv[i];
break;
case 's': pArgs->dwCabSize = atoi(argv[i]);
break;
case 't': pArgs->szSymDir = argv[i];
break;
case 'x': pArgs->szCabDir = argv[i];
break;
case 'y': pArgs->szInfDir = argv[i];
break;
default: Usage();
}
}
}
return (pArgs);
}
PSYM_LIST
GetList(
LPTSTR szFileName
)
{
PSYM_LIST pList;
FILE *fFile;
DWORD i;
TCHAR szEntry[_MAX_PATH * 4];
TCHAR *token, *c, *x;
LPTSTR seps=_T(",");
PTCHAR pCh;
pList = (PSYM_LIST)malloc(sizeof(SYM_LIST));
if (pList == NULL )
{
return NULL;
}
if ( (fFile = _tfopen(szFileName,_T("r") )) == NULL )
{
printf( "Cannot open the symbol inf input file %s\n",szFileName );
free(pList);
return NULL;
}
// Figure out the number of entries and allocate the list accordingly
pList->dwSize = 0;
while ( _fgetts(szEntry,_MAX_FNAME,fFile) )
{
(pList->dwSize)++;
}
// Go back to the beginning of the file and read the entries in
if ( fseek(fFile,0,0) != 0 )
{
free(pList);
pList = NULL;
}
else
{
pList->pSymList = NULL;
pList->pSymList = (PSYM_FILE*)malloc( sizeof(PSYM_FILE) *
(pList->dwSize));
if (pList->pSymList == NULL)
{
free(pList);
pList = NULL;
}
else
{
for (i=0; i<pList->dwSize; i++)
{
// Allocate the List element
pList->pSymList[i] = (PSYM_FILE)malloc( sizeof(SYM_FILE) );
if (pList->pSymList[i] == NULL)
{
pList->dwSize=i;
FreePList(pList);
pList = NULL;
break;
}
memset(pList->pSymList[i],0,sizeof(SYM_FILE) );
// Get the next list element from input file
memset(szEntry,0,_MAX_PATH*4);
if ( _fgetts(szEntry,_MAX_PATH*4,fFile) == NULL )
{
FreePList(pList);
pList = NULL;
break;
}
_tcslwr(szEntry);
// Replace the \n with \0
c = NULL;
c = _tcschr(szEntry, '\n');
if ( c != NULL )
{
*c = _T('\0');
}
// Fill in the four entry values
token = _tcstok( szEntry, seps);
if (token)
{
StringCbCopy(pList->pSymList[i]->szExeName, sizeof(pList->pSymList[i]->szExeName), token);
}
token = _tcstok( NULL, seps);
if (token)
{
StringCbCopy(pList->pSymList[i]->szSymName, sizeof(pList->pSymList[i]->szSymName), token);
}
token = _tcstok( NULL, seps);
if (token)
{
StringCbCopy(pList->pSymList[i]->szSymSrcPath, sizeof(pList->pSymList[i]->szSymSrcPath), token);
}
token = _tcstok( NULL, seps);
if (token)
{
StringCbCopy(pList->pSymList[i]->szInstallPath, sizeof(pList->pSymList[i]->szInstallPath), token);
// Create an install path that has any /'s changed to .'s
StringCbCopy(pList->pSymList[i]->szInstallPathX, sizeof(pList->pSymList[i]->szInstallPathX), token);
while ( (pCh = _tcschr(pList->pSymList[i]->szInstallPathX,'\\')) != NULL) {
*pCh = '.';
}
}
// Initialize other fields to NULL
StringCbCopy(pList->pSymList[i]->szSymReName, sizeof(pList->pSymList[i]->szSymReName), _T("") );
}
}
}
fclose(fFile);
return (pList);
}
int __cdecl
SymComp(
const void *e1,
const void *e2
)
{
PSYM_FILE p1;
PSYM_FILE p2;
int rc;
p1 = *((PSYM_FILE*)e1);
p2 = *((PSYM_FILE*)e2);
rc = _tcsicmp(p1->szCabName,p2->szCabName);
if ( rc == 0 ) {
rc = _tcsicmp(p1->szExeName, p2->szExeName);
if (rc == 0) {
rc = _tcsicmp(p1->szSymName, p2->szSymName);
}
}
return ( rc );
}
int __cdecl
SymSortBySymbolName(
const void *e1,
const void *e2
)
{
PSYM_FILE p1;
PSYM_FILE p2;
int rc;
p1 = *((PSYM_FILE*)e1);
p2 = *((PSYM_FILE*)e2);
rc = _tcsicmp(p1->szSymName, p2->szSymName);
if (rc == 0) {
rc = _tcsicmp(p1->szSymSrcPath, p2->szSymSrcPath);
}
return ( rc );
}
int __cdecl
SymSortByInstallPath(
const void *e1,
const void *e2
)
{
PSYM_FILE p1;
PSYM_FILE p2;
int rc;
p1 = *((PSYM_FILE*)e1);
p2 = *((PSYM_FILE*)e2);
rc = _tcsicmp(p1->szInstallPath, p2->szInstallPath);
if (rc == 0) {
rc = _tcsicmp(p1->szSymName, p2->szSymName);
}
return ( rc );
}
int __cdecl
SymSortByCabNumber(
const void *e1,
const void *e2
)
{
PSYM_FILE p1;
PSYM_FILE p2;
int rc;
p1 = *((PSYM_FILE*)e1);
p2 = *((PSYM_FILE*)e2);
if ( p1->dwCabNumber < p2->dwCabNumber) return(-1);
if ( p1->dwCabNumber > p2->dwCabNumber) return(1);
rc = _tcsicmp(p1->szSymName, p2->szSymName);
return ( rc );
}
BOOL
ComputeCabNames(
PSYM_LIST pList,
DWORD dwCabSize,
LPTSTR szSymCabName
)
{
// This divides the files into cabs of dwCabSize files.
// It appends a number to the end of each cab so they all
// have different names
// szTmpCabName is the name of the cab that each file is in
// originally. These may get combined into bigger cabs later.
// If they do, then the final cab name is in szCabName.
TCHAR szCurCabName[_MAX_PATH];
TCHAR szCurAppend[10];
DWORD i,dwCurCount,dwCurAppend;
if (dwCabSize <= 0 ) return 1;
if (szSymCabName == NULL) return FALSE;
// Get the Cab name of the first one
StringCbCopy(szCurCabName, sizeof(szCurCabName), szSymCabName );
StringCbCat( szCurCabName, sizeof(szCurCabName), _T("1") );
StringCbCopy(pList->pSymList[0]->szTmpCabName, sizeof(pList->pSymList[0]->szTmpCabName), szCurCabName);
dwCurCount = 1; // Number of files in this cab so far
dwCurAppend = 1; // Current number to append to the cab name
for ( i=1; i<pList->dwSize; i++ ) {
// Always put symbols for the same exe in the same cab
if ( (_tcsicmp( pList->pSymList[i-1]->szExeName,
pList->pSymList[i]->szExeName ) != 0) &&
(dwCurCount >= dwCabSize) ) {
dwCurAppend++;
dwCurCount = 0;
_itot(dwCurAppend, szCurAppend, 10);
StringCbCopy(szCurCabName, sizeof(szCurCabName), szSymCabName );
StringCbCat (szCurCabName, sizeof(szCurCabName), szCurAppend );
}
// Add the file to the current cab
StringCbCopy(pList->pSymList[i]->szTmpCabName, sizeof(pList->pSymList[i]->szTmpCabName), szCurCabName);
dwCurCount++;
}
return TRUE;
}
BOOL
ComputeFinalCabNames(
PSYM_LIST pList,
LPTSTR szSymCabName,
BOOL MergeIntoOne
)
{
DWORD i;
DWORD dwCabNumber, dwSkip;
// For right now, the final cab name is the same as the
// temporary cab name.
for ( i=0; i<pList->dwSize; i++ ) {
// Get the final cab name and number
if (MergeIntoOne) {
StringCbCopy(pList->pSymList[i]->szCabName, sizeof(pList->pSymList[i]->szCabName), szSymCabName);
pList->pSymList[i]->dwCabNumber = 1;
} else {
StringCbCopy(pList->pSymList[i]->szCabName,
sizeof(pList->pSymList[i]->szCabName),
pList->pSymList[i]->szTmpCabName);
// Also, get the number of the cab
dwSkip = _tcslen( szSymCabName );
dwCabNumber = atoi(pList->pSymList[i]->szTmpCabName + dwSkip);
pList->pSymList[i]->dwCabNumber = dwCabNumber;
}
}
return TRUE;
}
BOOL
CreateMakefile(
PSYM_LIST pList,
LPTSTR szOutDir,
LPTSTR szSymDir,
LPTSTR szCabDir
)
{
FILE *fFile;
TCHAR buf[_MAX_PATH * 2];
TCHAR buf2[_MAX_PATH];
BOOL newcab,rc;
DWORD i;
PCHAR ch;
if (szOutDir == NULL) return FALSE;
rc = TRUE;
StringCbCopy(buf, sizeof(buf), szOutDir);
MakeSureDirectoryPathExists(szOutDir);
StringCbCat(buf, sizeof(buf), "\\");
StringCbCat(buf, sizeof(buf), "makefile");
if ( (fFile = _tfopen(buf, _T("w") )) == NULL ) {
printf( "Cannot open the makefile %s for writing.\n",buf);
return (FALSE);
}
if (pList->dwSize <= 0 ) {
rc = FALSE;
goto cleanup;
}
// Print the lists for the individual cabs
newcab = TRUE;
for (i=0; i<pList->dwSize; i++) {
// Test for printing a new cab to the makefile
if ( newcab) {
StringCbPrintf(buf, sizeof(buf), "%s\\%s.cab:",
szCabDir,
pList->pSymList[i]->szTmpCabName);
_fputts(buf, fFile);
}
// Print the file, print the continuation mark first
if ( !(pList->pSymList[i]->Duplicate) ) {
_fputts("\t\\\n\t", fFile);
PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
}
// Decide if this is the end of this cab
if ( (i != pList->dwSize-1) &&
(_tcsicmp(pList->pSymList[i]->szTmpCabName,
pList->pSymList[i+1]->szTmpCabName) == 0) ) {
newcab = FALSE;
}
else {
newcab = TRUE;
StringCbPrintf(buf, sizeof(buf), "\n\t!echo $?>>%s.txt\n\n",
pList->pSymList[i]->szTmpCabName);
_fputts(buf, fFile);
}
}
cleanup:
fflush(fFile);
fclose(fFile);
return rc;
}
BOOL
CreateDDFs(
PSYM_LIST pList,
LPTSTR szOutDir, // Directory to write the DDFs to
LPTSTR szSymDir,
LPTSTR szCabDir
)
{
BOOL newddf;
FILE *fFile;
TCHAR szCabName[_MAX_PATH*2];
TCHAR buf[_MAX_PATH*2];
DWORD i;
if (szOutDir == NULL) return FALSE;
newddf = TRUE;
for (i=0; i<pList->dwSize; i++) {
if (newddf) {
newddf = FALSE;
StringCbCopy(szCabName, sizeof(szCabName), szOutDir);
StringCbCat(szCabName, sizeof(szCabName), _T("\\") );
StringCbCat(szCabName, sizeof(szCabName), pList->pSymList[i]->szTmpCabName);
StringCbCat(szCabName, sizeof(szCabName), _T(".ddf") );
if ( (fFile = _tfopen(szCabName, _T("w") )) == NULL ) {
printf( "Cannot open the ddf file %s for writing.\n",szCabName);
return FALSE;
}
//
// Write the header
//
// .option explicit will complain if you make a spelling error
// in any of the other .set commands
_fputts(".option explicit\n", fFile);
// Tell what directory to write the cabs to:
StringCbPrintf(buf, sizeof(buf), ".Set DiskDirectoryTemplate=%s\n", szCabDir);
_fputts(buf, fFile);
_fputts(".Set RptFileName=nul\n", fFile);
_fputts(".Set InfFileName=nul\n", fFile);
StringCbPrintf(buf, sizeof(buf), ".Set CabinetNameTemplate=%s.cab\n",
pList->pSymList[i]->szTmpCabName);
_fputts(buf, fFile);
_fputts(".Set CompressionType=MSZIP\n", fFile);
_fputts(".Set MaxDiskSize=CDROM\n", fFile);
_fputts(".Set ReservePerCabinetSize=0\n", fFile);
_fputts(".Set Compress=on\n", fFile);
_fputts(".Set CompressionMemory=21\n", fFile);
_fputts(".Set Cabinet=ON\n", fFile);
_fputts(".Set MaxCabinetSize=999999999\n", fFile);
_fputts(".Set FolderSizeThreshold=1000000\n", fFile);
}
// Write the file to the DDF
if ( !pList->pSymList[i]->Duplicate) {
fputs("\"",fFile); // begin quote
PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
fputs("\"",fFile); // end quote
// optional rename and \n
if ( pList->pSymList[i]->ReName) {
StringCbPrintf( buf, sizeof(buf), " \"%s\"\n",
pList->pSymList[i]->szSymReName);
} else {
StringCbPrintf(buf, sizeof(buf), "\n");
}
_fputts(buf, fFile);
}
// Check if this is the end of this DDF
if ( i == pList->dwSize-1) {
fflush(fFile);
fclose(fFile);
break;
}
// See if the next file in the list starts a new DDF
if ( _tcsicmp(pList->pSymList[i]->szTmpCabName,
pList->pSymList[i+1]->szTmpCabName) != 0 ) {
fflush(fFile);
fclose(fFile);
newddf = TRUE;
}
}
return TRUE;
}
BOOL
CreateCDF(
PSYM_LIST pList,
LPTSTR szOutDir, // Directory to write the CDF to
LPTSTR szSymDir, // Root of the symbols tree
LPTSTR szSymCabName,
LPTSTR szInfDir
)
{
FILE *fFile;
FILE *fFile2;
TCHAR buf[_MAX_PATH*2];
DWORD i;
TCHAR szCDFName[_MAX_PATH];
TCHAR szCDFMakefile[_MAX_PATH];
if (szOutDir == NULL) return FALSE;
if (szSymCabName == NULL) return FALSE;
StringCbCopy(szCDFName, sizeof(szCDFName), szOutDir);
StringCbCat( szCDFName, sizeof(szCDFName), _T("\\") );
StringCbCat( szCDFName, sizeof(szCDFName), szSymCabName);
// Create a makefile for this, so we can do incremental
// adds to the CAT file.
StringCbCopy(szCDFMakefile, sizeof(szCDFMakefile), szCDFName);
StringCbCat( szCDFMakefile, sizeof(szCDFMakefile), _T(".CDF.makefile") );
StringCbCat( szCDFName, sizeof(szCDFName), _T(".CDF.noheader") );
if ( (fFile = _tfopen(szCDFName, _T("w") )) == NULL ) {
printf( "Cannot open the CDF file %s for writing.\n",szCDFName);
return FALSE;
}
if ( (fFile2 = _tfopen(szCDFMakefile, _T("w") )) == NULL ) {
printf( "Cannot open the CDF file %s for writing.\n",szCDFMakefile);
return FALSE;
}
// Write the first line of the makefile for the Catalog
StringCbPrintf( buf, sizeof(buf), "%s\\%s.CAT:", szInfDir, szSymCabName );
_fputts( buf, fFile2);
for (i=0; i<pList->dwSize; i++) {
// Write the file to the DDF
if ( !pList->pSymList[i]->Duplicate) {
_fputts("<HASH>", fFile );
PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
_fputts( "=", fFile);
PrintFullSymbolPath(fFile, szSymDir, pList->pSymList[i]->szSymSrcPath);
_fputts("\n", fFile);
_fputts( " \\\n ", fFile2 );
PrintFullSymbolPath(fFile2, szSymDir, pList->pSymList[i]->szSymSrcPath);
}
}
// Write the last line of the makefile
StringCbPrintf(buf, sizeof(buf), "\n\t!echo $? >> %s\\%s.update\n",
szOutDir,
szSymCabName );
_fputts( buf, fFile2 );
fflush(fFile);
fclose(fFile);
fflush(fFile2);
fclose(fFile2);
return TRUE;
}
BOOL
CreateCabList(
PSYM_LIST pList,
LPTSTR szOutDir
)
{
FILE *fFile;
TCHAR buf[_MAX_PATH*2];
DWORD i;
BOOL rc;
rc = TRUE;
if (szOutDir == NULL) return FALSE;
StringCbCopy(buf, sizeof(buf), szOutDir);
MakeSureDirectoryPathExists(szOutDir);
StringCbCat( buf, sizeof(buf), "\\");
StringCbCat( buf, sizeof(buf), "symcabs.txt");
if ( (fFile = _tfopen(buf, _T("w") )) == NULL ) {
printf( "Cannot open %s for writing.\n",buf);
return(FALSE);
}
if (pList->dwSize <= 0 ) {
rc = FALSE;
goto cleanup;
}
// First, print a list of all the targets
StringCbPrintf(buf, sizeof(buf), "%s.cab\n",
pList->pSymList[0]->szTmpCabName);
_fputts(buf, fFile);
for (i=1; i<pList->dwSize; i++) {
if ( _tcsicmp(pList->pSymList[i]->szTmpCabName,
pList->pSymList[i-1]->szTmpCabName) != 0 ) {
StringCbPrintf(buf,sizeof(buf), "%s.cab\n",
pList->pSymList[i]->szTmpCabName);
_fputts(buf, fFile);
}
}
cleanup:
fflush(fFile);
fclose(fFile);
return (rc);
}
BOOL
RenameAllTheFiles(
PSYM_LIST pList
)
{
DWORD i;
PTCHAR pCh;
// Rename all the files so that there is consistency in
// file naming. This will help the transition to building
// slip-streamed service packs.
for (i=0; i<pList->dwSize; i++) {
pList->pSymList[i]->ReName = TRUE;
StringCbCopy(pList->pSymList[i]->szSymReName,
sizeof(pList->pSymList[i]->szSymReName),
pList->pSymList[i]->szSymName);
StringCbCat(pList->pSymList[i]->szSymReName,
sizeof(pList->pSymList[i]->szSymReName),
_T("."));
StringCbCat(pList->pSymList[i]->szSymReName,
sizeof(pList->pSymList[i]->szSymReName),
pList->pSymList[i]->szInstallPathX);
}
return (TRUE);
}
BOOL
FindDuplicatesAndFilesToReName(
PSYM_LIST pList
)
{
DWORD i;
PTCHAR pCh;
// Its a duplicate if the symbol file has the same name and its
// exe has the same extension (i.e., it has the same cab name
pList->pSymList[0]->Duplicate = FALSE;
pList->pSymList[0]->ReName = FALSE;
for (i=1; i<pList->dwSize; i++) {
// See if file name is duplicate
if ( _tcsicmp(pList->pSymList[i]->szSymName,
pList->pSymList[i-1]->szSymName) == 0) {
// These two symbol files have the same name. See if
// they get installed to the same directory.
if (_tcsicmp(pList->pSymList[i]->szInstallPath,
pList->pSymList[i-1]->szInstallPath) == 0) {
// We will ignore this file later
pList->pSymList[i]->Duplicate = TRUE;
} else {
// There are two versions of this file, but they
// are each different and get installed to different
// directories. One of them will need to be renamed
// since the names inside cabs and infs need to be
// unique.
pList->pSymList[i]->ReName = TRUE;
StringCbCopy(pList->pSymList[i]->szSymReName,
sizeof(pList->pSymList[i]->szSymReName),
pList->pSymList[i]->szSymName);
StringCbCat( pList->pSymList[i]->szSymReName,
sizeof(pList->pSymList[i]->szSymReName),
_T("."));
StringCbCat( pList->pSymList[i]->szSymReName,
sizeof(pList->pSymList[i]->szSymReName),
pList->pSymList[i]->szInstallPathX);
}
}
else {
pList->pSymList[i]->Duplicate = FALSE;
pList->pSymList[i]->ReName = FALSE;
}
}
return (TRUE);
}
//
// defines and structure for CreateInf
//
#define _MAX_STRING 40 // max length for strings
#define INSTALL_SECTION_COUNT 6 // number of install sections
typedef struct _INSTALL_SECTION_INFO {
CHAR SectionName[ _MAX_STRING+1]; // required
CHAR CustomDestination[_MAX_STRING+1]; // required
CHAR BeginPrompt[ _MAX_STRING+1]; // optional
CHAR EndPrompt[ _MAX_STRING+1]; // optional
} INSTALL_SECTION_INFO;
BOOL
CreateInf(
PSYM_LIST pList,
LPTSTR szInfDir,
LPTSTR szSymCabName
)
{
FILE *fFile;
TCHAR buf[_MAX_PATH*2];
TCHAR szCurInstallPathX[_MAX_PATH+1];
DWORD i, dwCurDisk;
INSTALL_SECTION_INFO InstallSections[INSTALL_SECTION_COUNT];
INT iLoop;
if (szInfDir == NULL) return FALSE;
if (szSymCabName == NULL) return FALSE;
// make all strings empty by default
ZeroMemory(InstallSections, sizeof(InstallSections));
// setup the variable data for each section
StringCbCopy(InstallSections[0].SectionName, sizeof(InstallSections[0].SectionName), "DefaultInstall");
StringCbCopy(InstallSections[0].CustomDestination, sizeof(InstallSections[0].CustomDestination), "CustDest");
StringCbCopy(InstallSections[0].BeginPrompt, sizeof(InstallSections[0].BeginPrompt), "BeginPromptSection");
StringCbCopy(InstallSections[0].EndPrompt, sizeof(InstallSections[0].EndPrompt), "EndPromptSection");
StringCbCopy(InstallSections[1].SectionName, sizeof(InstallSections[1].SectionName), "DefaultInstall.Quiet");
StringCbCopy(InstallSections[1].CustomDestination, sizeof(InstallSections[1].CustomDestination), "CustDest.2");
StringCbCopy(InstallSections[2].SectionName, sizeof(InstallSections[2].SectionName), "DefaultInstall.Chained.1");
StringCbCopy(InstallSections[2].CustomDestination, sizeof(InstallSections[2].CustomDestination), "CustDest");
StringCbCopy(InstallSections[2].BeginPrompt, sizeof(InstallSections[2].BeginPrompt), "BeginPromptSection");
StringCbCopy(InstallSections[3].SectionName, sizeof(InstallSections[3].SectionName), "DefaultInstall.Chained.1.Quiet");
StringCbCopy(InstallSections[3].CustomDestination, sizeof(InstallSections[3].CustomDestination), "CustDest.2");
StringCbCopy(InstallSections[4].SectionName, sizeof(InstallSections[4].SectionName), "DefaultInstall.Chained.2");
StringCbCopy(InstallSections[4].CustomDestination, sizeof(InstallSections[4].CustomDestination), "CustDest.2");
StringCbCopy(InstallSections[4].EndPrompt, sizeof(InstallSections[4].EndPrompt), "EndPromptSection");
StringCbCopy(InstallSections[5].SectionName, sizeof(InstallSections[5].SectionName), "DefaultInstall.Chained.2.Quiet");
StringCbCopy(InstallSections[5].CustomDestination, sizeof(InstallSections[5].CustomDestination), "CustDest.2");
StringCbCopy(buf, sizeof(buf), szInfDir);
MakeSureDirectoryPathExists(szInfDir);
// Get the name of the inf ... name it the same as the cabs
// with an .inf extension
StringCbCat(buf, sizeof(buf), _T("\\"));
StringCbCat(buf, sizeof(buf), szSymCabName);
StringCbCat(buf, sizeof(buf), _T(".inf") );
if ( (fFile = _tfopen(buf, _T("w") )) == NULL ) {
printf( "Cannot open %s for writing.\n",buf);
return FALSE;
}
// Write the header for the inf
_fputts("[Version]\n", fFile);
_fputts("AdvancedInf= 2.5\n", fFile);
_fputts("Signature= \"$CHICAGO$\"\n", fFile);
StringCbPrintf(buf, sizeof(buf), "CatalogFile= %s.CAT\n", szSymCabName);
_fputts(buf, fFile);
_fputts("\n", fFile);
//
// Do the default installs
// This inf has options for how it will be called. It has
// provision for a chained incremental install.
//
// DefaultInstall -- standalone install.
// DefaultInstall.Quiet -- standalone with no UI intervention
// DefaultInstall.Chained.1 -- first part of a chained install
// DefaultInstall.Chained.1.Quiet -- first part of a chained install with no UI intervention
// DefaultInstall.Chained.2 -- second part of a chained install
// DefaultInstall.Chained.2.Quiet -- second part of a chained install with no UI intervention
//
//
// Do the install sections
//
for (iLoop = 0; iLoop < INSTALL_SECTION_COUNT; iLoop++) {
fprintf(fFile, "[%s]\n" , InstallSections[iLoop].SectionName);
fprintf(fFile, "CustomDestination=%s\n", InstallSections[iLoop].CustomDestination);
// BeginPrompt is optional
if (strlen(InstallSections[iLoop].BeginPrompt) > 0) {
fprintf(fFile, "BeginPrompt=%s\n", InstallSections[iLoop].BeginPrompt);
}
// EndPrompt is optional
if (strlen(InstallSections[iLoop].EndPrompt) > 0) {
fprintf(fFile, "EndPrompt=%s\n", InstallSections[iLoop].EndPrompt);
}
// from here to end of loop, output is identical for all sections
_fputts("AddReg= RegVersion\n", fFile);
_fputts("RequireEngine= Setupapi;\n", fFile);
//
// Print the Copyfiles line
//
_fputts("CopyFiles= ", fFile);
// First, sort the list by Install Path
qsort( (void*)pList->pSymList, (size_t)pList->dwSize,
(size_t)sizeof(PSYM_FILE), SymSortByInstallPath);
// Print the files sections that need to be installed
StringCbPrintf( buf, sizeof(buf), "Files.%s",
pList->pSymList[0]->szInstallPathX);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->Duplicate) continue;
// See if we have a new files section
if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
szCurInstallPathX) != 0 ) {
// Print the files sections
StringCbPrintf(buf, sizeof(buf), ", Files.%s",
pList->pSymList[i]->szInstallPathX);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
}
}
_fputts("\n\n", fFile);
} // end of install sections loop
// Print the Default Uninstall line
//
_fputts("[DefaultUninstall]\n", fFile);
_fputts("CustomDestination= CustDest\n", fFile);
_fputts("BeginPrompt= DelBeginPromptSection\n", fFile);
_fputts("DelFiles= ", fFile);
// Print the files sections that need to be installed
StringCbPrintf(buf, sizeof(buf), "Files.%s", pList->pSymList[0]->szInstallPathX);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->Duplicate) continue;
// See if we have a new files section
if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
szCurInstallPathX) != 0 ) {
// Print the files sections
StringCbPrintf(buf, sizeof(buf), ", Files.%s",
pList->pSymList[i]->szInstallPathX);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
}
}
_fputts("\n", fFile);
_fputts("DelDirs= DelDirsSection\n", fFile);
_fputts("DelReg= RegVersion\n", fFile);
_fputts("EndPrompt= DelEndPromptSection\n", fFile);
_fputts("RequireEngine= Setupapi;\n\n", fFile);
//
// Print the [BeginPromptSection]
//
_fputts("[BeginPromptSection]\n", fFile);
_fputts("Title= \"Microsoft Windows Symbols\"\n", fFile);
_fputts("\n", fFile);
//
// Print the [DelBeginPromptSection]
//
_fputts("[DelBeginPromptSection]\n", fFile);
_fputts("Title= \"Microsoft Windows Symbol Uninstall\"\n", fFile);
_fputts("ButtonType= YESNO\n", fFile);
_fputts("Prompt= \"Do you want to remove Microsoft Windows Symbols?\"\n", fFile);
_fputts("\n", fFile);
//
// Print the [EndPromptSection]
//
_fputts("[EndPromptSection]\n", fFile);
_fputts("Title= \"Microsoft Windows Symbols\"\n", fFile);
_fputts("Prompt= \"Installation is complete\"\n", fFile);
_fputts("\n", fFile);
//
// Print the [DelEndPromptSection]
//
_fputts("[DelEndPromptSection]\n", fFile);
_fputts("Prompt= \"Uninstall is complete\"\n", fFile);
_fputts("\n", fFile);
//
// Print the [RegVersion] Section
//
_fputts("[RegVersion]\n", fFile);
_fputts("\"HKLM\",\"SOFTWARE\\Microsoft\\Symbols\\Directories\",\"Symbol Dir\",0,\"%49100%\"\n", fFile);
_fputts("\"HKCU\",\"SOFTWARE\\Microsoft\\Symbols\\Directories\",\"Symbol Dir\",0,\"%49100%\"\n", fFile);
_fputts("\"HKCU\",\"SOFTWARE\\Microsoft\\Symbols\\SymbolInstall\",\"Symbol Install\",,\"1\"\n", fFile);
_fputts(";\"HKLM\",\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Symbols\",\"DisplayName\",,\"Microsoft Windows Symbols\"\n", fFile);
_fputts(";\"HKLM\",\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Symbols\",\"UninstallString\",,\"RunDll32.exe advpack.dll,LaunchINFSection symusa.inf,DefaultUninstall\"\n", fFile);
_fputts(";\"HKLM\",\"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Symbols\",\"RequiresIESysFile\",,\"4.71\"\n", fFile);
_fputts("\n", fFile);
//
// Print the Custom Destination Section
//
_fputts("[SymCust]\n", fFile);
_fputts("\"HKCU\", \"Software\\Microsoft\\Symbols\\Directories\",\"Symbol Dir\",\"Symbols install directory\",\"%25%\\Symbols\"\n", fFile);
_fputts("\n", fFile);
//
// Print the CustDest section
//
_fputts("[CustDest]\n", fFile);
_fputts("49100=SymCust,1\n", fFile);
_fputts("\n", fFile);
//
// Print the CustDest section
// Don't prompt the user for where to install, just read
// it out of the registry
//
_fputts("[CustDest.2]\n", fFile);
_fputts("49100=SymCust,5\n", fFile);
_fputts("\n", fFile);
//
// Print the DestinationDirs section
//
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), "");
_fputts("[DestinationDirs]\n", fFile);
_fputts(";49100 is %systemroot%\\symbols\n", fFile);
_fputts("\n", fFile);
_fputts("Files.inf\t\t\t= 17\n", fFile);
_fputts("Files.system32\t\t\t= 11\n", fFile);
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->Duplicate) continue;
// See if we have a new files section
if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
szCurInstallPathX) != 0 ) {
// Print the files sections
StringCbPrintf(buf, sizeof(buf), "Files.%s\t\t\t= 49100,\"%s\"\n",
pList->pSymList[i]->szInstallPathX,
pList->pSymList[i]->szInstallPath
);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
}
}
_fputts("\n", fFile);
//
// Print the DelDirsSection
//
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
_fputts("[DelDirsSection]\n", fFile);
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->Duplicate) continue;
// See if we have a new files section
if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
szCurInstallPathX) != 0 ) {
// Print the files sections
_fputts("%49100%\\", fFile);
_fputts(pList->pSymList[i]->szInstallPath, fFile);
_fputts("\n", fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
}
}
_fputts("%49100%\n\n", fFile);
//
// Print the files section
//
_fputts("[Files.inf]\n", fFile);
StringCbPrintf(buf, sizeof(buf), "%s.inf,,,4\n\n", szSymCabName);
_fputts(buf, fFile);
_fputts("[Files.system32.x86]\n", fFile);
_fputts("advpack.dll,,,96\n\n", fFile);
_fputts("[Files.system32.alpha]\n", fFile);
_fputts("advpack.dll, advpacka.dll,,96\n\n", fFile);
StringCbPrintf(buf, sizeof(buf), "[Files.%s]\n", pList->pSymList[0]->szInstallPathX);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[0]->szInstallPathX);
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->Duplicate) continue;
// See if we have a new files section
if ( _tcsicmp( pList->pSymList[i]->szInstallPathX,
szCurInstallPathX) != 0 ) {
// Print the files sections
StringCbPrintf(buf, sizeof(buf), "\n[Files.%s]\n",
pList->pSymList[i]->szInstallPathX);
_fputts(buf, fFile);
StringCbCopy(szCurInstallPathX, sizeof(szCurInstallPathX), pList->pSymList[i]->szInstallPathX);
}
// Print the file name inside the cab
StringCbPrintf(buf, sizeof(buf), "%s,%s,,4\n", pList->pSymList[i]->szSymName,
pList->pSymList[i]->szSymReName);
_fputts(buf, fFile);
}
// Print the SourceDisksNames section
// First sort the list by the final cab name
qsort( (void*)pList->pSymList, (size_t)pList->dwSize,
(size_t)sizeof(PSYM_FILE), SymSortByCabNumber);
_fputts("\n[SourceDisksNames]\n", fFile);
dwCurDisk = -1;
// Print the SourceDisks section
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->dwCabNumber != dwCurDisk ) {
// New cab name
dwCurDisk = pList->pSymList[i]->dwCabNumber;
StringCbPrintf(buf, sizeof(buf), "%1d=\"%s.cab\",%s.cab,0\n",
dwCurDisk,
pList->pSymList[i]->szCabName,
pList->pSymList[i]->szCabName);
_fputts(buf, fFile);
}
}
// Print the SourceDisksFiles section
_fputts("\n[SourceDisksFiles]\n", fFile);
for (i=0; i<pList->dwSize; i++) {
if ( pList->pSymList[i]->ReName ) {
StringCbPrintf(buf, sizeof(buf), "%s=%1d\n",
pList->pSymList[i]->szSymReName,
pList->pSymList[i]->dwCabNumber );
} else {
StringCbPrintf(buf, sizeof(buf), "%s=%1d\n",
pList->pSymList[i]->szSymName,
pList->pSymList[i]->dwCabNumber );
}
_fputts(buf, fFile);
}
fflush(fFile);
fclose(fFile);
return TRUE;
}
BOOL FreePList(
PSYM_LIST pList
)
{
DWORD i;
if ( pList==NULL ) return TRUE;
if ( pList->pSymList == NULL ) {
free(pList);
return (TRUE);
}
for (i=0; i<pList->dwSize; i++) {
free(pList->pSymList[i]);
}
free(pList->pSymList);
free(pList);
return (TRUE);
}
/* ------------------------------------------------------------------------------------------------
Prints the fully qualified path to a symbol using the following logic:
- if SymbolRoot is NULL, assume SymbolPath is a fully qualified path and print it
- if SymbolPath begins with "%c:\" or "\\", assume SymbolPath is fully qualified and print it
- assume the concatenation "SymbolRoot\\SymbolPath" is the fully qualified path and print it
------------------------------------------------------------------------------------------------ */
BOOL PrintFullSymbolPath(IN FILE* OutputFile, IN OPTIONAL LPTSTR SymbolRoot, IN LPTSTR SymbolPath) {
if ( (OutputFile == NULL) || (SymbolPath == NULL) ) {
return(FALSE);
}
if (SymbolRoot == NULL) {
fprintf(OutputFile, "%s", SymbolPath);
} else if (isalpha(SymbolPath[0]) && SymbolPath[1] == ':' && SymbolPath[2] == '\\') {
fprintf(OutputFile, "%s", SymbolPath);
} else if (SymbolPath[0] == '\\' && SymbolPath[1] == '\\') {
fprintf(OutputFile, "%s", SymbolPath);
} else {
fprintf(OutputFile, "%s\\%s", SymbolRoot, SymbolPath);
}
return(TRUE);
}