/*++ 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 #include #include #include #include #include #define ARRAY_SIZE(_X) (sizeof(_X)/sizeof((_X)[0])) // // 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 bool CreateDirectories( const std::basic_string &DirName, LPSECURITY_ATTRIBUTES SecurityAttrs ); template bool IsFilePresent( const std::basic_string &FileName ); // // Argument cracker // template struct Arguments { std::basic_string CurrentDirectory; std::basic_string LayoutName; std::basic_string DriverIndexName; std::basic_string SourceDirectoryRoot; std::basic_string SourceDirectory; std::basic_string DestinationDirectory; std::basic_string ExtraFileName; std::basic_string OptionalSrcDirectory; std::basic_string PlatformSuffix; std::basic_string DosNetFileName; std::basic_string ConfigInfFileName; std::basic_string IntlInfFileName; std::basic_string 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 AnsiArgs; typedef Arguments 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 DriverIndexInfFile : public InfFile { public: // // constructor // DriverIndexInfFile(const std::basic_string &FileName) : InfFile(FileName){ std::map, Section *>::iterator Iter = Sections.find(CabsSectionName); if (Iter == Sections.end()) { throw new InvalidInfFile(FileName); } CabsSection = (*Iter).second; Iter = Sections.find(VersionSectionName); if (Iter == Sections.end()) { throw new InvalidInfFile(FileName); } Section *VersionSection = (*Iter).second; SectionValues &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 &FileName){ return (GetCabFileName(FileName).length() > 0); } // // Returns the driver cab file name which contains the given filename. // const std::basic_string& GetCabFileName(const std::basic_string &FileName) { const static basic_string NullCabFileName; std::list >::iterator Iter; for(Iter = SearchList.begin(); Iter != SearchList.end(); Iter++) { std::map< std::basic_string, Section *>::iterator SectionIter = Sections.find(*Iter); if (SectionIter != Sections.end()) { Section *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 VersionSectionName; const static std::basic_string CabsSectionName; const static std::basic_string CabsSearchOrderKeyName; // // data members // std::list > SearchList; // the cab file list search order Section *CabsSection; // the [cabs] section of drvindex.inf }; // // File list creator functor object // template struct FileListCreatorContext { Arguments &Args; Section *CurrentSection; Section *DirsSection; bool SkipInfFiles; ULONG FileCount; bool ProcessingExtraFiles; InfFile &IntlInfFile; InfFile &FontInfFile; InfFile &ConfigInfFile; ULONG DummyDirectoryId; std::basic_string WindowsDirectory; std::basic_string WinSxsCabinetFileName; DriverIndexInfFile &DriverIdxFile; std::basic_string CurrentCabFileIdx; // the cab being currently iterated on std::basic_string CurrentFileName; // the current file while iterating cab std::map, std::basic_string > FileList; std::map, std::basic_string > ExtraFileList; std::map, std::basic_string > DestDirs; std::map, std::basic_string > WinSxSFileList; std::map, std::basic_string > NlsFileMap; std::map, std::basic_string > 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::map, std::basic_string > * > CabFileListMap; FileListCreatorContext( Arguments &PrgArgs, Section *Curr, Section *Dirs, InfFile &ConfigInf, InfFile &IntlInf, InfFile &FontInf, DriverIndexInfFile &DrvIdxFile ); DWORD ProcessNlsFiles(VOID); ~FileListCreatorContext() { std::map, std::map, std::basic_string > * >::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::map, std::basic_string > * >::iterator Iter; for (Iter=CabFileListMap.begin(); Iter != CabFileListMap.end(); Iter++) { Count += (*Iter).second->size(); } return Count; } bool IsDriverCabFile(const std::basic_string &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& GetDriverCabFileName(const std::basic_string &FileName) { const std::basic_string &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 &CabFileName, const std::basic_string &SourceFile, const std::basic_string &DestinationFile) { //cout << "AddFileToCabFileList(" << CabFileName << ", " << SourceFile << ", " << DestinationFile << ")" << endl; std::map, std::map, std::basic_string >* >::iterator Iter; Iter = CabFileListMap.find(CabFileName); std::map, std::basic_string > *FileMap = NULL; if (Iter != CabFileListMap.end()) { FileMap = (*Iter).second; } else { // // New cab file list // CabFileListMap[CabFileName] = FileMap = new std::map, std::basic_string >(); } (*FileMap)[SourceFile] = DestinationFile; } std::basic_string 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((const T*)Buffer); } void AddDirectoryToNlsDirMap(const std::basic_string &FileName) { T Separator; if (sizeof(T) == sizeof(CHAR)) { Separator = (T)'\\'; } else { Separator = (T)L'\\'; } std::basic_string 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 >::iterator Iter; for (Iter = NlsDirMap.begin(); Iter != NlsDirMap.end(); Iter++) { DestDirs[(*Iter).second] = (*Iter).first; } } void RemoveDuplicateNlsEntries(void) { std::map, std::basic_string >::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 void FileListCreator( SectionValues &Values, PVOID Context ); template bool IsWow64File( SectionValues &Values, FileListCreatorContext &Context ); template bool IsFileSkipped( SectionValues &Values, FileListCreatorContext &Context ); template ULONG CopyFileList( FileListCreatorContext &Context ); template ULONG ProcessExtraFiles( FileListCreatorContext &Context ); template ULONG ProcessWinSxSFiles( IN FileListCreatorContext &Context ); template ULONG PreCreateDirs( FileListCreatorContext &Context ); template bool ProcessInfChanges( Arguments &Args, const std::basic_string &InfName ); template bool CheckMediaVersion( Arguments &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& 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; }