|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
oemmint.h
Abstract:
Simple tool to create a Mini NT image from a regular NT image
Author:
Vijay Jayaseelan (vijayj) Aug-08-2000
Revision History:
None. --*/
#include <setupapi.hpp>
#include <queue.hpp>
#include <algorithm>
#include <list>
#include <tchar.h>
#include <strsafe.h>
#define ARRAY_SIZE(_X) (sizeof(_X)/sizeof((_X)[0]))
#define NULLSTR L""
//
// Different types of SxS assembly layouts on the distribution
// media.
//
#define SXS_LAYOUT_TYPE_DIRECTORY 1
#define SXS_LAYOUT_TYPE_CAB 2
#define SXS_CAB_LAYOUT_BUILD_NUMBER 3606
//
// Invalid argument exception
//
struct InvalidArguments {};
//
// function prototypes
//
template <class T> bool CreateDirectories( const std::basic_string<T> &DirName, LPSECURITY_ATTRIBUTES SecurityAttrs );
template <class T> bool IsFilePresent( const std::basic_string<T> &FileName );
//
// Argument cracker
//
template <class T> struct Arguments { std::basic_string<T> CurrentDirectory; std::basic_string<T> LayoutName; std::basic_string<T> DriverIndexName; std::basic_string<T> SourceDirectoryRoot; std::basic_string<T> SourceDirectory; std::basic_string<T> DestinationDirectory; std::basic_string<T> ExtraFileName; std::basic_string<T> OptionalSrcDirectory; std::basic_string<T> PlatformSuffix; std::basic_string<T> DosNetFileName; std::basic_string<T> ConfigInfFileName; std::basic_string<T> IntlInfFileName; std::basic_string<T> FontInfFileName; bool Verbose; bool WowFilesPresent; bool SkipWowFiles; bool SkipFileCopy; bool CheckVersion; bool IA64Image; int WinSxSLayout; DWORD MajorVersionNumber; DWORD MinorVersionNumber; DWORD MajorBuildNumber; Arguments(int Argc, T *Argv[]);
friend std::ostream& operator<<(std::ostream &os, const Arguments &rhs) { os << rhs.SourceDirectory << ", " << rhs.DestinationDirectory << ", " << rhs.LayoutName << ", " << rhs.ExtraFileName << ", " << rhs.OptionalSrcDirectory << ", " << rhs.DriverIndexName << std::endl;
return os; } protected: VOID IdentifySxSLayout( VOID ); };
//
// Argument Types
//
typedef Arguments<char> AnsiArgs; typedef Arguments<wchar_t> UnicodeArgs;
//
// Driver Index File abstraction.
//
// This class helps in resolving a binary name to appropriate driver
// cab file (like SP1.CAB or DRIVER.CAB).
//
template <class T> class DriverIndexInfFile : public InfFile<T> { public: //
// constructor
//
DriverIndexInfFile(const std::basic_string<T> &FileName) : InfFile<T>(FileName){ std::map<std::basic_string<T>, Section<T> *>::iterator Iter = Sections.find(CabsSectionName);
if (Iter == Sections.end()) { throw new InvalidInfFile<T>(FileName); }
CabsSection = (*Iter).second; Iter = Sections.find(VersionSectionName); if (Iter == Sections.end()) { throw new InvalidInfFile<T>(FileName); }
Section<T> *VersionSection = (*Iter).second; SectionValues<T> &Values = VersionSection->GetValue(CabsSearchOrderKeyName);
for (int Index=0; Index < Values.Count(); Index++) { if (sizeof(T) == sizeof(CHAR)) { SearchList.push_back((T *)_strlwr((PSTR)Values.GetValue(Index).c_str())); } else { SearchList.push_back((T *)_wcslwr((PWSTR)Values.GetValue(Index).c_str())); } } }
//
// Checks where the given is contained any of the driver cab files
//
bool IsFilePresent(const std::basic_string<T> &FileName){ return (GetCabFileName(FileName).length() > 0); }
//
// Returns the driver cab file name which contains the given filename.
//
const std::basic_string<T>& GetCabFileName(const std::basic_string<T> &FileName) { const static basic_string<T> NullCabFileName; std::list<basic_string<T> >::iterator Iter;
for(Iter = SearchList.begin(); Iter != SearchList.end(); Iter++) { std::map< std::basic_string<T>, Section<T> *>::iterator SectionIter = Sections.find(*Iter); if (SectionIter != Sections.end()) { Section<T> *CurrentSection = (*SectionIter).second; if (CurrentSection->IsKeyPresent(FileName)) { break; } } }
if (Iter != SearchList.end()) { return CabsSection->GetValue(*Iter).GetValue(0); }
return NullCabFileName; }
protected: //
// constant strings
//
const static std::basic_string<T> VersionSectionName; const static std::basic_string<T> CabsSectionName; const static std::basic_string<T> CabsSearchOrderKeyName;
//
// data members
//
std::list<std::basic_string<T> > SearchList; // the cab file list search order
Section<T> *CabsSection; // the [cabs] section of drvindex.inf
};
//
// File list creator functor object
//
template <class T> struct FileListCreatorContext { Arguments<T> &Args; Section<T> *CurrentSection; Section<T> *DirsSection; bool SkipInfFiles; ULONG FileCount; bool ProcessingExtraFiles; InfFile<T> &IntlInfFile; InfFile<T> &FontInfFile; InfFile<T> &ConfigInfFile; ULONG DummyDirectoryId; std::basic_string<T> WindowsDirectory; std::basic_string<T> WinSxsCabinetFileName; DriverIndexInfFile<T> &DriverIdxFile; std::basic_string<T> CurrentCabFileIdx; // the cab being currently iterated on
std::basic_string<T> CurrentFileName; // the current file while iterating cab
std::map<std::basic_string<T>, std::basic_string<T> > FileList; std::map<std::basic_string<T>, std::basic_string<T> > ExtraFileList; std::map<std::basic_string<T>, std::basic_string<T> > DestDirs; std::map<std::basic_string<T>, std::basic_string<T> > WinSxSFileList; std::map<std::basic_string<T>, std::basic_string<T> > NlsFileMap; std::map<std::basic_string<T>, std::basic_string<T> > NlsDirMap;
//
// Map of map i.e. map of cab filename to map of list of source to destination names
// which need to be extracted for cab file
//
std::map<std::basic_string<T>, std::map<std::basic_string<T>, std::basic_string<T> > * > CabFileListMap;
FileListCreatorContext( Arguments<T> &PrgArgs, Section<T> *Curr, Section<T> *Dirs, InfFile<T> &ConfigInf, InfFile<T> &IntlInf, InfFile<T> &FontInf, DriverIndexInfFile<T> &DrvIdxFile );
DWORD ProcessNlsFiles(VOID);
~FileListCreatorContext() { std::map<std::basic_string<T>, std::map<std::basic_string<T>, std::basic_string<T> > * >::iterator Iter;
for (Iter=CabFileListMap.begin(); Iter != CabFileListMap.end(); Iter++) { delete (*Iter).second; } }
ULONG GetSourceCount() const { ULONG Count = (FileList.size() + ExtraFileList.size() + WinSxSFileList.size() + NlsFileMap.size());
std::map<std::basic_string<T>, std::map<std::basic_string<T>, std::basic_string<T> > * >::iterator Iter;
for (Iter=CabFileListMap.begin(); Iter != CabFileListMap.end(); Iter++) { Count += (*Iter).second->size(); }
return Count; }
bool IsDriverCabFile(const std::basic_string<T> &FileName) { return DriverIdxFile.IsFilePresent(FileName); }
//
// Given the file name returns the cab file name (if any) which contains
// the file. In case of error "" (empty string) is returned.
//
const std::basic_string<T>& GetDriverCabFileName(const std::basic_string<T> &FileName) { const std::basic_string<T> &CabFileName = DriverIdxFile.GetCabFileName(FileName);
// std::cout << "GetDriverCabFileName(" << FileName << ") = " << CabFileName << std::endl;
return CabFileName; }
//
// Adds to the per cab file map the given source and destination file name that
// need to be extracted
//
void AddFileToCabFileList(const std::basic_string<T> &CabFileName, const std::basic_string<T> &SourceFile, const std::basic_string<T> &DestinationFile) { //cout << "AddFileToCabFileList(" << CabFileName << ", " << SourceFile << ", " << DestinationFile << ")" << endl;
std::map<std::basic_string<T>, std::map<std::basic_string<T>, std::basic_string<T> >* >::iterator Iter;
Iter = CabFileListMap.find(CabFileName);
std::map<std::basic_string<T>, std::basic_string<T> > *FileMap = NULL;
if (Iter != CabFileListMap.end()) { FileMap = (*Iter).second; } else { //
// New cab file list
//
CabFileListMap[CabFileName] = FileMap = new std::map<std::basic_string<T>, std::basic_string<T> >(); }
(*FileMap)[SourceFile] = DestinationFile; }
std::basic_string<T> GetNextDummyDirectoryId() { T Buffer[MAX_PATH]; if (sizeof(T) == sizeof(CHAR)) { (void)StringCchPrintfA((PSTR)Buffer, ARRAY_SIZE(Buffer), "%d", DummyDirectoryId); } else { (void)StringCchPrintfW((PWSTR)Buffer, ARRAY_SIZE(Buffer), L"%d", DummyDirectoryId); }
DummyDirectoryId++;
return std::basic_string<T>((const T*)Buffer); }
void AddDirectoryToNlsDirMap(const std::basic_string<T> &FileName) { T Separator;
if (sizeof(T) == sizeof(CHAR)) { Separator = (T)'\\'; } else { Separator = (T)L'\\'; }
std::basic_string<T> DirectoryKey = FileName.substr(0, FileName.rfind(Separator));
if (DirectoryKey.length() && (NlsDirMap.find(DirectoryKey) == NlsDirMap.end())) { NlsDirMap[DirectoryKey] = GetNextDummyDirectoryId(); } }
void ProcessNlsDirMapEntries(void) { std::map<std::basic_string<T>, std::basic_string<T> >::iterator Iter;
for (Iter = NlsDirMap.begin(); Iter != NlsDirMap.end(); Iter++) { DestDirs[(*Iter).second] = (*Iter).first; } }
void RemoveDuplicateNlsEntries(void) { std::map<std::basic_string<T>, std::basic_string<T> >::iterator NlsIter, PrevIter; for (NlsIter = NlsFileMap.begin(); NlsIter != NlsFileMap.end(); ) { PrevIter = NlsFileMap.end(); if (FileList.find((*NlsIter).first) != FileList.end()) { PrevIter = NlsIter; }
NlsIter++;
if (PrevIter != NlsFileMap.end()) { // std::cout << "Erasing : " << (*PrevIter).first << std::endl;
NlsFileMap.erase(PrevIter); } } }
void MoveDriverCabNlsFiles(void);
//
// static data members
//
static UINT NlsFileQueueScanWorker( PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2 ); };
//
// function prototypes
//
template <class T> void FileListCreator( SectionValues<T> &Values, PVOID Context );
template <class T> bool IsWow64File( SectionValues<T> &Values, FileListCreatorContext<T> &Context );
template <class T> bool IsFileSkipped( SectionValues<T> &Values, FileListCreatorContext<T> &Context );
template <class T> ULONG CopyFileList( FileListCreatorContext<T> &Context );
template <class T> ULONG ProcessExtraFiles( FileListCreatorContext<T> &Context );
template <class T> ULONG ProcessWinSxSFiles( IN FileListCreatorContext<T> &Context );
template <class T> ULONG PreCreateDirs( FileListCreatorContext<T> &Context );
template <class T> bool ProcessInfChanges( Arguments<T> &Args, const std::basic_string<T> &InfName );
template <class T> bool CheckMediaVersion( Arguments<T> &Args );
//
// utility function to tokenize a given line based on the delimiters
// specified
//
template< class T > unsigned Tokenize(const T &szInput, const T & szDelimiters, std::vector<T>& tokens) { unsigned DelimiterCount = 0;
tokens.clear();
if(!szInput.empty()){ if(!szDelimiters.empty()){ T::const_iterator inputIter = szInput.begin(); T::const_iterator copyIter = szInput.begin();
while(inputIter != szInput.end()){ if(szDelimiters.find(*inputIter) != string::npos){ if (copyIter < inputIter) { tokens.push_back(szInput.substr(copyIter - szInput.begin(), inputIter - copyIter)); }
DelimiterCount++; inputIter++; copyIter = inputIter; continue; }
inputIter++; }
if(copyIter != inputIter){ tokens.push_back(szInput.substr(copyIter - szInput.begin(), inputIter - szInput.begin())); } } else { tokens.push_back(szInput); } }
return DelimiterCount; }
|