windows-nt/Source/XPSP1/NT/sdktools/restools/mui/infparser/infparser.cpp
2020-09-26 16:20:57 +08:00

1623 lines
51 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2001, Microsoft Corporation All rights reserved.
//
// Module Name:
//
// infparser.cpp
//
// Abstract:
//
// This file contains the entry point of the infparser.exe utility.
//
// Revision History:
//
// 2001-06-20 lguindon Created.
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// Includes Files.
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "infparser.h"
///////////////////////////////////////////////////////////////////////////////
//
// Global variable.
//
///////////////////////////////////////////////////////////////////////////////
BOOL bSilence = TRUE;
DWORD dwComponentCounter = 0;
DWORD dwDirectoryCounter = 1;
WORD gBuildNumber = 0;
///////////////////////////////////////////////////////////////////////////////
//
// Prototypes.
//
///////////////////////////////////////////////////////////////////////////////
BOOL DirectoryExist(LPSTR dirPath);
BOOL ValidateLanguage(LPSTR dirPath, LPSTR langName, DWORD binType);
WORD ConvertLanguage(LPSTR dirPath, LPSTR langName);
int ListContents(LPSTR filename, LPSTR dirPath, LPSTR lang, DWORD flavor, DWORD binType);
int ListComponents(FileList *dirList, LPSTR dirPath, LPSTR lang, DWORD flavor, DWORD binType);
int ListMuiFiles(FileList *dirList, LPSTR dirPath, LPSTR lang, DWORD flavor, DWORD binType);
void PrintFileList(FileList* list, HANDLE hFile, BOOL compressed, BOOL bWinDir);
BOOL PrintLine(HANDLE hFile, LPCSTR lpLine);
HANDLE CreateOutputFile(LPSTR filename);
VOID removeSpace(LPSTR src, LPSTR dest);
DWORD TransNum(LPTSTR lpsz);
void Usage();
///////////////////////////////////////////////////////////////////////////////
//
// Main entry point.
//
///////////////////////////////////////////////////////////////////////////////
int __cdecl main(int argc, char* argv[])
{
LPSTR sLangName = NULL;
LPSTR sDirPath = NULL;
DWORD dwFlavor = FLV_UNDEFINED;
DWORD dwBinType = BIN_UNDEFINED;
DWORD dwArg = ARG_UNDEFINED;
WORD wLangID = 0;
HANDLE hFile;
int argIndex = 1;
LPSTR lpFileName = NULL;
//
// Check if we have the minimal number of arguments.
//
if (argc < 6)
{
Usage();
return (-1);
}
//
// Parse the command line.
//
while (argIndex < argc)
{
if (*argv[argIndex] == '/')
{
switch(*(argv[argIndex]+1))
{
case('b'):
case('B'):
{
//
// Binairy i386 or ia64
//
if ((*(argv[argIndex]+3) == '3') && (*(argv[argIndex]+4) == '2'))
{
dwBinType = BIN_32;
}
else if ((*(argv[argIndex]+3) == '6') && (*(argv[argIndex]+4) == '4'))
{
dwBinType = BIN_64;
}
else
{
return (argIndex);
}
dwArg |= ARG_BINARY;
break;
}
case('l'):
case('L'):
{
//
// Language
//
sLangName = (argv[argIndex]+3);
dwArg |= ARG_LANG;
break;
}
case('f'):
case('F'):
{
//
// Flavor requested
//
switch(*(argv[argIndex]+3))
{
case('c'):
case('C'):
{
dwFlavor = FLV_CORE;
break;
}
case('p'):
case('P'):
{
dwFlavor = FLV_PROFESSIONAL;
break;
}
case('s'):
case('S'):
{
dwFlavor = FLV_SERVER;
break;
}
case('a'):
case('A'):
{
dwFlavor = FLV_ADVSERVER;
break;
}
case('d'):
case('D'):
{
dwFlavor = FLV_DATACENTER;
break;
}
default:
{
return (argIndex);
}
}
dwArg |= ARG_FLAVOR;
break;
}
case('s'):
case('S'):
{
//
// Binairy location
//
sDirPath = (argv[argIndex]+3);
dwArg |= ARG_DIR;
break;
}
case('o'):
case('O'):
{
//
// Output filename
//
/*
if ((hFile = CreateOutputFile(argv[argIndex]+3)) == INVALID_HANDLE_VALUE)
{
return (argIndex);
}
*/
lpFileName = argv[argIndex]+3;
dwArg |= ARG_OUT;
break;
}
case('v'):
case('V'):
{
//
// Verbose mode
//
bSilence = FALSE;
dwArg |= ARG_SILENT;
break;
}
default:
{
Usage();
return (argIndex);
}
}
}
else
{
Usage();
return (-1);
}
//
// Next argument
//
argIndex++;
}
//
// Validate arguments passed. Should have all five basic argument in order
// to continue.
//
if ((dwArg == ARG_UNDEFINED) ||
!((dwArg & ARG_BINARY) &&
(dwArg & ARG_LANG) &&
(dwArg & ARG_DIR) &&
(dwArg & ARG_OUT) &&
(dwArg & ARG_FLAVOR)))
{
Usage();
return (-1);
}
//
// Validate Source directory
//
if (!DirectoryExist(sDirPath))
{
return (-2);
}
//
// Validate Language
//
if (!ValidateLanguage(sDirPath, sLangName, dwBinType))
{
return (-3);
}
//
// Get LANGID from the language
//
if ( (gBuildNumber = ConvertLanguage(sDirPath, sLangName)) == 0x0000)
{
return (-4);
}
//
// Generate the file list
//
if ((dwArg & ARG_OUT) && lpFileName)
{
return ListContents(lpFileName, sDirPath, sLangName, dwFlavor, dwBinType);
}
}
///////////////////////////////////////////////////////////////////////////////
//
// ListContents()
//
// Generate the file list contents.
//
///////////////////////////////////////////////////////////////////////////////
int ListContents(LPSTR filename, LPSTR dirPath, LPSTR lang, DWORD flavor, DWORD binType)
{
int iRet = 0;
Uuid* uuid;
CHAR schemaPath[MAX_PATH] = {0};
CHAR outputString[4096] = {0};
FileList fileList;
HANDLE outputFile = CreateOutputFile(filename);
if (outputFile == INVALID_HANDLE_VALUE)
{
iRet = -1;
goto ListContents_EXIT;
}
//
// Create a UUID for this module and the schema path
//
uuid = new Uuid();
sprintf(schemaPath, "%s\\control\\MmSchema.xml", dirPath);
//
// Print module header.
//
PrintLine(outputFile, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
sprintf(outputString, "<Module Name=\"MUI MSI File Content\" Id=\"%s\" Language=\"0\" Version=\"1.0\" xmlns=\"%s\">", uuid->getString(), schemaPath);
PrintLine(outputFile, outputString);
delete uuid;
uuid = new Uuid();
sprintf(outputString, " <Package Id=\"%s\"", uuid->getString());
PrintLine(outputFile, outputString);
delete uuid;
PrintLine(outputFile, " Description=\"Content module\"");
PrintLine(outputFile, " Platforms=\"Intel\"");
PrintLine(outputFile, " Languages=\"0\"");
PrintLine(outputFile, " InstallerVersion=\"100\"");
PrintLine(outputFile, " Manufacturer=\"Microsoft Corporation\"");
PrintLine(outputFile, " Keywords=\"MergeModule, MSI, Database\"");
PrintLine(outputFile, " Comments=\"This merge module contains all the MUI file content\"");
PrintLine(outputFile, " ShortNames=\"yes\" Compressed=\"yes\"");
PrintLine(outputFile, "/>");
//
// Generate components file list
//
if ( (iRet = ListComponents(&fileList, dirPath, lang, flavor, binType)) != 0)
{
goto ListContents_EXIT;
}
//
// Generate Mui file list
//
if ((iRet =ListMuiFiles(&fileList, dirPath, lang, flavor, binType)) != 0)
{
goto ListContents_EXIT;
}
//
// Print compressed directory structure.
//
PrintLine(outputFile, "<Directory Name=\"SOURCEDIR\">TARGETDIR");
if (fileList.isDirId(TRUE))
{
PrintLine(outputFile, " <Directory Name=\"Windows\">WindowsFolder");
PrintFileList(&fileList, outputFile, TRUE, TRUE);
PrintLine(outputFile, " </Directory>");
}
if (fileList.isDirId(FALSE))
{
PrintLine(outputFile, " <Directory Name=\"ProgramFilesFolder\">ProgramFilesFolder");
PrintFileList(&fileList, outputFile, TRUE, FALSE);
PrintLine(outputFile, " </Directory>");
}
PrintLine(outputFile, "</Directory>");
//
// Print module footer.
//
PrintLine(outputFile, "</Module>");
ListContents_EXIT:
if (outputFile)
CloseHandle(outputFile);
return (iRet);
}
///////////////////////////////////////////////////////////////////////////////
//
// ListComponents()
//
// Generate the file list of each components.
//
///////////////////////////////////////////////////////////////////////////////
int ListComponents(FileList *dirList, LPSTR dirPath, LPSTR lang, DWORD flavor, DWORD binType)
{
HINF hFile;
CHAR muiFilePath[MAX_PATH];
UINT lineCount, lineNum;
INFCONTEXT context;
ComponentList componentList;
Component* component;
//
// Used only in core flavor
//
if (flavor != FLV_CORE)
{
return (0);
}
//
// Create the path to open the mui.inf file
//
sprintf(muiFilePath, "%s\\mui.inf", dirPath);
//
// Open the MUI.INF file.
//
hFile = SetupOpenInfFile(muiFilePath, NULL, INF_STYLE_WIN4, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return (-1);
}
//
// Get the number of component.
//
lineCount = (UINT)SetupGetLineCount(hFile, TEXT("Components"));
if (lineCount > 0)
{
//
// Go through all component of the list.
//
CHAR componentName[MAX_PATH];
CHAR componentFolder[MAX_PATH];
CHAR componentInf[MAX_PATH];
CHAR componentInst[MAX_PATH];
for (lineNum = 0; lineNum < lineCount; lineNum++)
{
if (SetupGetLineByIndex(hFile, TEXT("Components"), lineNum, &context) &&
SetupGetStringField(&context, 0, componentName, MAX_PATH, NULL) &&
SetupGetStringField(&context, 1, componentFolder, MAX_PATH, NULL) &&
SetupGetStringField(&context, 2, componentInf, MAX_PATH, NULL) &&
SetupGetStringField(&context, 3, componentInst, MAX_PATH, NULL))
{
//
// Create the components
//
if( (component = new Component( componentName,
componentFolder,
componentInf,
componentInst)) != NULL)
{
componentList.add(component);
}
}
}
}
//
// Close inf handle
//
SetupCloseInfFile(hFile);
//
// Output component information
//
component = componentList.getFirst();
while (component != NULL)
{
CHAR componentInfPath[MAX_PATH];
CHAR componentPath[MAX_PATH];
int fieldCount, fieldCount2;
INFCONTEXT context2;
INFCONTEXT context3;
File* file;
//
// Compute the component inf path.
//
if (binType == BIN_32)
{
sprintf( componentInfPath,
"%s\\%s\\i386.uncomp\\%s\\%s",
dirPath,
lang,
component->getFolderName(),
component->getInfName());
sprintf( componentPath,
"%s\\%s\\i386.uncomp\\%s",
dirPath,
lang,
component->getFolderName());
}
else
{
sprintf( componentInfPath,
"%s\\%s\\ia64.uncomp\\%s\\%s",
dirPath,
lang,
component->getFolderName(),
component->getInfName());
sprintf( componentPath,
"%s\\%s\\ai64.uncomp\\%s",
dirPath,
lang,
component->getFolderName());
}
//
// Open the component inf file.
//
hFile = SetupOpenInfFile(componentInfPath, NULL, INF_STYLE_WIN4, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return (-1);
}
//
// Search for the CopyFiles section
//
if (SetupFindFirstLine( hFile,
component->getInfInstallSectionName(),
"CopyFiles",
&context ) &&
(fieldCount = SetupGetFieldCount(&context)))
{
CHAR instSectionName[MAX_PATH];
INT destDirId;
CHAR destDirSubFolder[MAX_PATH];
CHAR destFileName[MAX_PATH];
CHAR srcFileName[MAX_PATH];
for (int fieldIdx = 1; fieldIdx <= fieldCount; fieldIdx++)
{
//
// Get the install section Names and search for the
// corresponding DestinationDirs.
//
if (SetupGetStringField(&context, fieldIdx, instSectionName, MAX_PATH, NULL) &&
SetupFindFirstLine(hFile, "DestinationDirs", instSectionName, &context2))
{
//
// Get the destination directory information for this
// installation section
//
if (SetupGetIntField(&context2, 1, &destDirId))
{
//
// Possible that no sub directory
//
if(!SetupGetStringField(&context2, 2, destDirSubFolder, MAX_PATH, NULL))
{
destDirSubFolder[0] = '\0';
}
//
// Scan the section for file
//
if ((lineCount = (UINT)SetupGetLineCount(hFile, instSectionName)) > 0)
{
for (lineNum = 0; lineNum < lineCount; lineNum++)
{
if (SetupGetLineByIndex(hFile, instSectionName, lineNum, &context3) &&
(fieldCount2 = SetupGetFieldCount(&context3)))
{
if (fieldCount2 > 1)
{
if (SetupGetStringField(&context3, 1, destFileName, MAX_PATH, NULL) &&
SetupGetStringField(&context3, 2, srcFileName, MAX_PATH, NULL))
{
//
// Create the components
//
if ((file = new File(destDirSubFolder,
destFileName,
componentPath,
srcFileName,
destDirId)) != NULL)
{
dirList->add(file);
}
}
}
else
{
if( SetupGetStringField(&context3, 0, destFileName, MAX_PATH, NULL))
{
//
// Create the components
//
if( (file = new File(destDirSubFolder,
destFileName,
componentPath,
destFileName,
destDirId)) != NULL)
{
dirList->add(file);
}
}
}
}
}
}
}
}
}
}
//
// Next Component
//
component = component->getNext();
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//
// ListMuiFiles()
//
// Generate the file list for MUI.
//
///////////////////////////////////////////////////////////////////////////////
int ListMuiFiles(FileList *dirList, LPSTR dirPath, LPSTR lang, DWORD flavor, DWORD binType)
{
HINF hFile;
CHAR muiFilePath[MAX_PATH];
CHAR muiFileSearchPath[MAX_PATH];
int lineCount, lineNum, fieldCount;
INFCONTEXT context;
FileLayoutExceptionList exceptionList;
WIN32_FIND_DATA findData;
HANDLE fileHandle;
File* file;
//
// Create the path to open the mui.inf file
//
sprintf(muiFilePath, "%s\\mui.inf", dirPath);
//
// Open the MUI.INF file.
//
hFile = SetupOpenInfFile(muiFilePath, NULL, INF_STYLE_WIN4, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return (-1);
}
//
// Get the number of file exception.
//
lineCount = (UINT)SetupGetLineCount(hFile, TEXT("File_Layout"));
if (lineCount > 0)
{
//
// Go through all file exception of the list.
//
CHAR originFilename[MAX_PATH];
CHAR destFilename[MAX_PATH];
CHAR fileFlavor[30];
DWORD dwFlavor;
for (lineNum = 0; lineNum < lineCount; lineNum++)
{
if (SetupGetLineByIndex(hFile, TEXT("File_Layout"), lineNum, &context) &&
(fieldCount = SetupGetFieldCount(&context)))
{
if (SetupGetStringField(&context, 0, originFilename, MAX_PATH, NULL) &&
SetupGetStringField(&context, 1, destFilename, MAX_PATH, NULL))
{
FileLayout* fileException;
dwFlavor = 0;
for(int fieldId = 2; fieldId <= fieldCount; fieldId++)
{
if(SetupGetStringField(&context, fieldId, fileFlavor, MAX_PATH, NULL))
{
switch(*fileFlavor)
{
case('p'):
case('P'):
{
dwFlavor |= FLV_PROFESSIONAL;
break;
}
case('s'):
case('S'):
{
dwFlavor |= FLV_SERVER;
break;
}
case('d'):
case('D'):
{
dwFlavor |= FLV_DATACENTER;
break;
}
case('a'):
case('A'):
{
dwFlavor |= FLV_ENTERPRISE;
break;
}
}
}
}
//
// Add only information needed for this specific flavor.
//
fileException = new FileLayout(originFilename, destFilename, dwFlavor);
exceptionList.insert(fileException);
}
}
}
}
//
// Close inf handle
//
SetupCloseInfFile(hFile);
//
// Compute the binary source path.
//
if (binType == BIN_32)
{
sprintf( muiFileSearchPath, "%s\\%s\\i386.uncomp", dirPath, lang);
sprintf( muiFilePath, "%s\\%s\\i386.uncomp\\*.*", dirPath, lang);
}
else
{
sprintf( muiFileSearchPath, "%s\\%s\\ia64.uncomp", dirPath, lang);
sprintf( muiFilePath, "%s\\%s\\ia64.uncomp\\*.*", dirPath, lang);
}
//
// Scan uncomp source directory for file information
//
if ((fileHandle = FindFirstFile(muiFilePath, &findData)) != INVALID_HANDLE_VALUE)
{
//
// Look for files
//
do
{
LPSTR extensionPtr;
INT dirIdentifier = 0;
CHAR destDirectory[MAX_PATH] = {0};
CHAR destName[MAX_PATH] = {0};
FileLayout* fileException = NULL;
//
// Scan only files at this level.
//
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
continue;
}
//
// Search the extension to determine the destination location and possibly
// exclude file destined for Personal.
//
if ((extensionPtr = strrchr(findData.cFileName, '.')) != NULL)
{
if( (_tcsicmp(extensionPtr, TEXT(".chm")) == 0) ||
(_tcsicmp(extensionPtr, TEXT(".chq")) == 0) ||
(_tcsicmp(extensionPtr, TEXT(".cnt")) == 0) ||
(_tcsicmp(extensionPtr, TEXT(".hlp")) == 0))
{
dirIdentifier = 18;
sprintf(destDirectory, "MUI\\%04x", gBuildNumber);
}
else if (_tcsicmp(extensionPtr, TEXT(".mfl")) == 0)
{
dirIdentifier = 11;
sprintf(destDirectory, "wbem\\MUI\\%04x", gBuildNumber);
}
else if (_tcsicmp(findData.cFileName, TEXT("hhctrlui.dll")) == 0)
{
dirIdentifier = 11;
sprintf(destDirectory, "MUI\\%04x", gBuildNumber);
}
else
{
dirIdentifier = 10;
sprintf(destDirectory, "MUI\\FALLBACK\\%04x", gBuildNumber);
}
}
//
// Search for different destination name in the exception list.
//
if ((fileException = exceptionList.search(findData.cFileName)) != NULL )
{
//
// Verify it's the needed flavor
//
if (fileException->isFlavor(flavor))
{
sprintf(destName, "%s", fileException->getDestFileName());
}
else
{
//
// Skip the file. Not need in this flavor.
//
continue;
}
}
else
{
if (((extensionPtr = strrchr(findData.cFileName, '.')) != NULL) &&
((*(extensionPtr-1) == 'P') || (*(extensionPtr-1) == 'p')))
{
continue;
}
else if (flavor != FLV_CORE)
{
continue;
}
else
{
sprintf(destName, "%s", findData.cFileName);
}
}
//
// Create a file
//
if (file = new File(destDirectory,
destName,
muiFileSearchPath,
findData.cFileName,
dirIdentifier))
{
dirList->add(file);
}
}
while (FindNextFile(fileHandle, &findData));
FindClose(fileHandle);
}
//
// Add Specific MuiSetup files.
//
file = new File( TEXT("MUI"),
TEXT("Muisetup.exe"),
dirPath,
TEXT("Muisetup.exe"),
10);
dirList->add(file);
file = new File( TEXT("MUI"),
TEXT("Muisetup.hlp"),
dirPath,
TEXT("Muisetup.hlp"),
10);
dirList->add(file);
file = new File( TEXT("MUI"),
TEXT("Eula.txt"),
dirPath,
TEXT("Eula.txt"),
10);
dirList->add(file);
file = new File( TEXT("MUI"),
TEXT("Relnotes.txt"),
dirPath,
TEXT("Relnotes.txt"),
10);
dirList->add(file);
file = new File( TEXT("MUI"),
TEXT("Readme.txt"),
dirPath,
TEXT("Readme.txt"),
10);
dirList->add(file);
file = new File( TEXT("MUI"),
TEXT("Mui.inf"),
dirPath,
TEXT("Mui.inf"),
10);
dirList->add(file);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
//
// ValidateLanguage()
//
// Verify if the language given is valid and checks is the files are
// available.
//
///////////////////////////////////////////////////////////////////////////////
BOOL ValidateLanguage(LPSTR dirPath, LPSTR langName, DWORD binType)
{
CHAR langPath[MAX_PATH] = {0};
//
// Check if the binary type in order to determine the right path.
//
if (binType == BIN_32)
{
sprintf(langPath, "%s\\%s\\i386.uncomp", dirPath, langName);
}
else
{
sprintf(langPath, "%s\\%s\\ia64.uncomp", dirPath, langName);
}
return (DirectoryExist(langPath));
}
///////////////////////////////////////////////////////////////////////////////
//
// DirectoryExist()
//
// Verify if the given directory exists and contains files.
//
///////////////////////////////////////////////////////////////////////////////
BOOL DirectoryExist(LPSTR dirPath)
{
WIN32_FIND_DATA FindData;
HANDLE FindHandle;
//
// Sanity check.
//
if (dirPath == NULL)
{
return FALSE;
}
//
// See if the language group directory exists.
//
FindHandle = FindFirstFile(dirPath, &FindData);
if (FindHandle != INVALID_HANDLE_VALUE)
{
FindClose(FindHandle);
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//
// Return success.
//
return (TRUE);
}
}
//
// Return failure.
//
if (!bSilence)
{
printf("ERR[%s]: No files found in the directory.\n", dirPath);
}
return (FALSE);
}
///////////////////////////////////////////////////////////////////////////////
//
// ConvertLanguage()
//
// Look into mui.inf file for the corresponding language identifier.
//
///////////////////////////////////////////////////////////////////////////////
WORD ConvertLanguage(LPSTR dirPath, LPSTR langName)
{
HINF hFile;
CHAR muiFilePath[MAX_PATH];
CHAR muiLang[30];
UINT lineCount, lineNum;
INFCONTEXT context;
DWORD langId = 0x00000000;
//
// Create the path to open the mui.inf file
//
sprintf(muiFilePath, "%s\\mui.inf", dirPath);
sprintf(muiLang, "%s.MUI", langName);
//
// Open the MUI.INF file.
//
hFile = SetupOpenInfFile(muiFilePath, NULL, INF_STYLE_WIN4, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return (0x0000);
}
//
// Get the number of Language.
//
lineCount = (UINT)SetupGetLineCount(hFile, TEXT("Languages"));
if (lineCount > 0)
{
//
// Go through all language of the list to find a .
//
CHAR langID[MAX_PATH];
CHAR name[MAX_PATH];
for (lineNum = 0; lineNum < lineCount; lineNum++)
{
if (SetupGetLineByIndex(hFile, TEXT("Languages"), lineNum, &context) &&
SetupGetStringField(&context, 0, langID, MAX_PATH, NULL) &&
SetupGetStringField(&context, 1, name, MAX_PATH, NULL))
{
if ( _tcsicmp(name, muiLang) == 0)
{
langId = TransNum(langID);
SetupCloseInfFile(hFile);
return (WORD)(langId);
}
}
}
}
//
// Close inf handle
//
SetupCloseInfFile(hFile);
return (0x0000);
}
////////////////////////////////////////////////////////////////////////////
//
// PrintFileList
//
// Print a file list in XML format.
//
////////////////////////////////////////////////////////////////////////////
void PrintFileList(FileList* list, HANDLE hFile, BOOL compressed, BOOL bWinDir)
{
if (compressed)
{
File* item;
CHAR itemDescription[4096];
CHAR spaces[30];
int j;
item = list->getFirst();
while (item != NULL)
{
LPSTR refDirPtr = NULL;
LPSTR dirPtr = NULL;
CHAR dirName[MAX_PATH];
CHAR dirName2[MAX_PATH];
LPSTR dirPtr2 = NULL;
LPSTR dirLvlPtr = NULL;
INT dirLvlCnt = 0;
BOOL componentInit = FALSE;
BOOL directoryInit = FALSE;
Uuid* uuid;
File* toBeRemoved;
CHAR fileObjectName[MAX_PATH];
UINT matchCount;
//
// Check destination directory.
//
if (item->isWindowsDir() != bWinDir)
{
item = item->getNext();
continue;
}
//
// Check is the destination is base dir
//
if (*(item->getDirectoryDestination()) == '\0')
{
//
// Component
//
uuid = new Uuid();
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Component Id='%s'>Content%i", spaces, uuid->getString(), dwComponentCounter);
delete uuid;
PrintLine(hFile, itemDescription);
//
// File
//
for (j = -1; j < dirLvlCnt+2; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
removeSpace(item->getName(), fileObjectName);
sprintf( itemDescription,
"%s<File Name=\"%s\" LongName=\"%s\" Compressed='yes' src=\"%s\\%s\">%s.%i</File>",
spaces,
item->getName(),
item->getName(),
item->getSrcDir(),
item->getSrcName(),
fileObjectName,
dwComponentCounter);
PrintLine(hFile, itemDescription);
//
// </Component>
//
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s</Component>", spaces);
PrintLine(hFile, itemDescription);
dwComponentCounter++;
toBeRemoved = item;
item = item->getNext();
list->remove(toBeRemoved);
continue;
}
//
// Print directory
//
sprintf(dirName, "%s",item->getDirectoryDestination());
dirPtr = dirName;
refDirPtr = dirPtr;
while (dirPtr != NULL)
{
dirLvlPtr = strchr(dirPtr, '\\');
if (dirLvlPtr != NULL)
{
*dirLvlPtr = '\0';
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Directory Name=\"%s\">%s%i", spaces, dirPtr, dirPtr, dwDirectoryCounter);
dwDirectoryCounter++;
PrintLine(hFile, itemDescription);
dirPtr = dirLvlPtr + 1;
dirLvlCnt++;
//
// Print all file under this specific directory
//
sprintf( dirName2, "%s", item->getDirectoryDestination());
dirName2[dirLvlPtr-refDirPtr] = '\0';
File* sameLvlItem = NULL;
matchCount = 0;
while((sameLvlItem = list->search(item, dirName2)) != NULL)
{
/* //
// Directory
//
if (!directoryInit)
{
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Directory Name=\"%s\">%s%i", spaces, dirPtr, dirPtr, dwDirectoryCounter);
dwDirectoryCounter++;
PrintLine(hFile, itemDescription);
dirLvlCnt++;
directoryInit = TRUE;
}
*/
//
// Component
//
if (!componentInit)
{
uuid = new Uuid();
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Component Id='%s'>Content%i", spaces, uuid->getString(), dwComponentCounter);
delete uuid;
PrintLine(hFile, itemDescription);
dwComponentCounter++;
componentInit = TRUE;
}
//
// File
//
matchCount++;
for (j = -1; j < dirLvlCnt+2; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
removeSpace(sameLvlItem->getName(), fileObjectName);
sprintf( itemDescription,
"%s<File Name=\"%s\" LongName=\"%s\" Compressed='yes' src=\"%s\\%s\">%s.%i</File>",
spaces,
sameLvlItem->getName(),
sameLvlItem->getName(),
sameLvlItem->getSrcDir(),
sameLvlItem->getSrcName(),
fileObjectName,
dwComponentCounter);
PrintLine(hFile, itemDescription);
list->remove(sameLvlItem);
}
if (matchCount)
{
//
// File
//
for (j = -1; j < dirLvlCnt+2; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
removeSpace(item->getName(), fileObjectName);
sprintf( itemDescription,
"%s<File Name=\"%s\" LongName=\"%s\" Compressed='yes' src=\"%s\\%s\">%s.%i</File>",
spaces,
item->getName(),
item->getName(),
item->getSrcDir(),
item->getSrcName(),
fileObjectName,
dwComponentCounter);
PrintLine(hFile, itemDescription);
dirPtr = NULL;
}
//
// Close component
//
if (componentInit)
{
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s</Component>", spaces);
PrintLine(hFile, itemDescription);
componentInit = FALSE;
}
//
// Close directory
//
if (directoryInit)
{
dirLvlCnt--;
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s</Directory>", spaces);
PrintLine(hFile, itemDescription);
directoryInit = FALSE;
}
}
else
{
if (!directoryInit)
{
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Directory Name=\"%s\">%s%i", spaces, dirPtr, dirPtr, dwDirectoryCounter);
dwDirectoryCounter++;
PrintLine(hFile, itemDescription);
dirLvlCnt++;
directoryInit = TRUE;
}
//
// Component
//
if (!componentInit)
{
uuid = new Uuid();
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Component Id='%s'>Content%i", spaces, uuid->getString(), dwComponentCounter);
delete uuid;
PrintLine(hFile, itemDescription);
componentInit = TRUE;
}
//
// Print all file under this specific directory
//
File* sameLvlItem;
while((sameLvlItem = list->search(item, item->getDirectoryDestination())) != NULL)
{
//
// File
//
for (j = -1; j < dirLvlCnt+2; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
removeSpace(sameLvlItem->getName(), fileObjectName);
sprintf( itemDescription,
"%s<File Name=\"%s\" LongName=\"%s\" Compressed='yes' src=\"%s\\%s\">%s.%i</File>",
spaces,
sameLvlItem->getName(),
sameLvlItem->getName(),
sameLvlItem->getSrcDir(),
sameLvlItem->getSrcName(),
fileObjectName,
dwComponentCounter);
PrintLine(hFile, itemDescription);
list->remove(sameLvlItem);
}
//
// File
//
for (j = -1; j < dirLvlCnt+2; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
removeSpace(item->getName(), fileObjectName);
sprintf( itemDescription,
"%s<File Name=\"%s\" LongName=\"%s\" Compressed='yes' src=\"%s\\%s\">%s.%i</File>",
spaces,
item->getName(),
item->getName(),
item->getSrcDir(),
item->getSrcName(),
fileObjectName,
dwComponentCounter);
PrintLine(hFile, itemDescription);
dwComponentCounter++;
dirPtr = NULL;
//
// Close component
//
if (componentInit)
{
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s</Component>", spaces);
PrintLine(hFile, itemDescription);
componentInit = FALSE;
}
//
// Close directory
//
if (directoryInit)
{
dirLvlCnt--;
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s</Directory>", spaces);
PrintLine(hFile, itemDescription);
directoryInit = FALSE;
}
}
}
for (int i = dirLvlCnt; i > 0; i--)
{
spaces[i] = '\0';
sprintf( itemDescription, "%s</Directory>", spaces);
PrintLine(hFile, itemDescription);
}
if (list->getFileNumber() > 1)
{
if (item->getNext() != NULL)
{
item = item->getNext();
list->remove(item->getPrevious());
}
else
{
list->remove(item);
item = NULL;
}
}
else
{
list->remove(item);
item = NULL;
}
}
}
else
{
File* item;
CHAR itemDescription[4096];
CHAR spaces[30];
int j;
item = list->getFirst();
while (item != NULL)
{
LPSTR dirPtr = NULL;
LPSTR dirLvlPtr = NULL;
INT dirLvlCnt = 0;
//
// Print directory
//
dirPtr = item->getDirectoryDestination();
while (dirPtr != NULL)
{
dirLvlPtr = strchr(dirPtr, '\\');
if (dirLvlPtr != NULL)
{
*dirLvlPtr = '\0';
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Directory Name=\"%s\">%s%i", spaces, dirPtr, dirPtr, dwDirectoryCounter);
dwDirectoryCounter++;
PrintLine(hFile, itemDescription);
dirPtr = dirLvlPtr + 1;
dirLvlCnt++;
}
else
{
Uuid* uuid = new Uuid();
for (j = -1; j < dirLvlCnt; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Directory Name=\"%s\">%s%i", spaces, dirPtr, dirPtr, dwDirectoryCounter);
dwDirectoryCounter++;
PrintLine(hFile, itemDescription);
dirLvlCnt++;
//
// Component
//
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s<Component Id='%s'>Content%i", spaces, uuid->getString(), dwComponentCounter);
delete uuid;
PrintLine(hFile, itemDescription);
//
// File
//
for (j = -1; j < dirLvlCnt+2; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription,
"%s<File Name=\"%s\" LongName=\"%s\" Compressed='yes' src=\"%s\\%s\">%s.%i</File>",
spaces,
item->getName(),
item->getName(),
item->getSrcDir(),
item->getSrcName(),
item->getName(),
dwComponentCounter);
PrintLine(hFile, itemDescription);
dwComponentCounter++;
dirPtr = NULL;
}
}
for (j = -1; j < dirLvlCnt+1; j++) {spaces[j+1] = ' '; spaces[j+2] = '\0';}
sprintf( itemDescription, "%s</Component>", spaces);
PrintLine(hFile, itemDescription);
for (int i = dirLvlCnt; i > 0; i--)
{
spaces[i] = '\0';
sprintf( itemDescription, "%s</Directory>", spaces);
PrintLine(hFile, itemDescription);
}
item = item->getNext();
}
}
/****************** DEBUG ******************
File* item;
CHAR itemDescription[4096];
item = list->getFirst();
while (item != NULL)
{
//
// Item description
//
sprintf(itemDescription,
" Source: %s\\%s",
item->getSrcDir(),
item->getSrcName());
PrintLine(hFile, itemDescription);
sprintf(itemDescription,
" Destination: %s\\%s",
item->getDirectoryDestination(),
item->getName());
PrintLine(hFile, itemDescription);
PrintLine(hFile, "");
item = item->getNext();
}
****************** DEBUG ******************/
}
////////////////////////////////////////////////////////////////////////////
//
// PrintLine
//
// Add a line at the end of the file.
//
////////////////////////////////////////////////////////////////////////////
BOOL PrintLine(HANDLE hFile, LPCSTR lpLine)
{
DWORD dwBytesWritten;
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile( hFile,
lpLine,
_tcslen(lpLine) * sizeof(TCHAR),
&dwBytesWritten,
NULL );
SetFilePointer(hFile, 0, NULL, FILE_END);
WriteFile( hFile,
TEXT("\r\n"),
_tcslen(TEXT("\r\n")) * sizeof(TCHAR),
&dwBytesWritten,
NULL );
return (TRUE);
}
///////////////////////////////////////////////////////////////////////////////
//
// CreateOutputFile()
//
// Create the file that would received the package file contents.
//
///////////////////////////////////////////////////////////////////////////////
HANDLE CreateOutputFile(LPSTR filename)
{
SECURITY_ATTRIBUTES SecurityAttributes;
//
// Sanity check.
//
if (filename == NULL)
{
return INVALID_HANDLE_VALUE;
}
//
// Create a security descriptor the output file.
//
SecurityAttributes.nLength = sizeof(SecurityAttributes);
SecurityAttributes.lpSecurityDescriptor = NULL;
SecurityAttributes.bInheritHandle = FALSE;
//
// Create the file.
//
return CreateFile( filename,
GENERIC_WRITE,
0,
&SecurityAttributes,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL );
}
////////////////////////////////////////////////////////////////////////////
//
// removeSpace
//
// Remove all space from a string.
//
////////////////////////////////////////////////////////////////////////////
VOID removeSpace(LPSTR src, LPSTR dest)
{
LPSTR strSrcPtr = src;
LPSTR strDestPtr = dest;
while (*strSrcPtr != '\0')
{
if (*strSrcPtr != ' ')
{
*strDestPtr = *strSrcPtr;
strDestPtr++;
}
strSrcPtr++;
}
*strDestPtr = '\0';
}
////////////////////////////////////////////////////////////////////////////
//
// TransNum
//
// Converts a number string to a dword value (in hex).
//
////////////////////////////////////////////////////////////////////////////
DWORD TransNum(LPTSTR lpsz)
{
DWORD dw = 0L;
TCHAR c;
while (*lpsz)
{
c = *lpsz++;
if (c >= TEXT('A') && c <= TEXT('F'))
{
c -= TEXT('A') - 0xa;
}
else if (c >= TEXT('0') && c <= TEXT('9'))
{
c -= TEXT('0');
}
else if (c >= TEXT('a') && c <= TEXT('f'))
{
c -= TEXT('a') - 0xa;
}
else
{
break;
}
dw *= 0x10;
dw += c;
}
return (dw);
}
///////////////////////////////////////////////////////////////////////////////
//
// Usage
//
// Print the fonction usage.
//
///////////////////////////////////////////////////////////////////////////////
void Usage()
{
printf("Create filecontents_CORE.wxm, filecontents_PRO.wxm and filecontents_SRV.wxm\n");
printf("Usage: infparser /b:[32|64] /l:<lang> /f:[p|s|a|d] /s:<dir> /o:<file> /v\n");
printf(" where\n");
printf(" /b means the binary.\n");
printf(" 32: i386\n");
printf(" 64: ia64\n");
printf(" /l means the language flag.\n");
printf(" <lang>: is the target language\n");
printf(" /f means the flavor.\n");
printf(" p: Professional\n");
printf(" s: Server\n");
printf(" a: Advanced Server\n");
printf(" d: Data Center\n");
printf(" /s means the location of the binairy data.\n");
printf(" <dir>: Fully qualified path\n");
printf(" /o means the xml file contents of specific flavor.\n");
printf(" <file>: Fully qualified path\n");
printf(" /v means the verbose mode [optional].\n");
}