Source code of Windows XP (NT5)
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.

500 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. oemmint.h
  5. Abstract:
  6. Simple tool to create a Mini NT image
  7. from a regular NT image
  8. Author:
  9. Vijay Jayaseelan (vijayj) Aug-08-2000
  10. Revision History:
  11. None.
  12. --*/
  13. #include <setupapi.hpp>
  14. #include <queue.hpp>
  15. #include <algorithm>
  16. #include <list>
  17. #include <tchar.h>
  18. #include <strsafe.h>
  19. #define ARRAY_SIZE(_X) (sizeof(_X)/sizeof((_X)[0]))
  20. //
  21. // Different types of SxS assembly layouts on the distribution
  22. // media.
  23. //
  24. #define SXS_LAYOUT_TYPE_DIRECTORY 1
  25. #define SXS_LAYOUT_TYPE_CAB 2
  26. #define SXS_CAB_LAYOUT_BUILD_NUMBER 3606
  27. //
  28. // Invalid argument exception
  29. //
  30. struct InvalidArguments {};
  31. //
  32. // function prototypes
  33. //
  34. template <class T>
  35. bool
  36. CreateDirectories(
  37. const std::basic_string<T> &DirName,
  38. LPSECURITY_ATTRIBUTES SecurityAttrs
  39. );
  40. template <class T>
  41. bool
  42. IsFilePresent(
  43. const std::basic_string<T> &FileName
  44. );
  45. //
  46. // Argument cracker
  47. //
  48. template <class T>
  49. struct Arguments {
  50. std::basic_string<T> CurrentDirectory;
  51. std::basic_string<T> LayoutName;
  52. std::basic_string<T> DriverIndexName;
  53. std::basic_string<T> SourceDirectoryRoot;
  54. std::basic_string<T> SourceDirectory;
  55. std::basic_string<T> DestinationDirectory;
  56. std::basic_string<T> ExtraFileName;
  57. std::basic_string<T> OptionalSrcDirectory;
  58. std::basic_string<T> PlatformSuffix;
  59. std::basic_string<T> DosNetFileName;
  60. std::basic_string<T> ConfigInfFileName;
  61. std::basic_string<T> IntlInfFileName;
  62. std::basic_string<T> FontInfFileName;
  63. bool Verbose;
  64. bool WowFilesPresent;
  65. bool SkipWowFiles;
  66. bool SkipFileCopy;
  67. bool CheckVersion;
  68. bool IA64Image;
  69. int WinSxSLayout;
  70. DWORD MajorVersionNumber;
  71. DWORD MinorVersionNumber;
  72. DWORD MajorBuildNumber;
  73. Arguments(int Argc, T *Argv[]);
  74. friend std::ostream& operator<<(std::ostream &os,
  75. const Arguments &rhs) {
  76. os << rhs.SourceDirectory << ", "
  77. << rhs.DestinationDirectory << ", "
  78. << rhs.LayoutName << ", "
  79. << rhs.ExtraFileName << ", "
  80. << rhs.OptionalSrcDirectory << ", "
  81. << rhs.DriverIndexName << std::endl;
  82. return os;
  83. }
  84. protected:
  85. VOID IdentifySxSLayout( VOID );
  86. };
  87. //
  88. // Argument Types
  89. //
  90. typedef Arguments<char> AnsiArgs;
  91. typedef Arguments<wchar_t> UnicodeArgs;
  92. //
  93. // Driver Index File abstraction.
  94. //
  95. // This class helps in resolving a binary name to appropriate driver
  96. // cab file (like SP1.CAB or DRIVER.CAB).
  97. //
  98. template <class T>
  99. class DriverIndexInfFile : public InfFile<T> {
  100. public:
  101. //
  102. // constructor
  103. //
  104. DriverIndexInfFile(const std::basic_string<T> &FileName) : InfFile<T>(FileName){
  105. std::map<std::basic_string<T>, Section<T> *>::iterator Iter = Sections.find(CabsSectionName);
  106. if (Iter == Sections.end()) {
  107. throw new InvalidInfFile<T>(FileName);
  108. }
  109. CabsSection = (*Iter).second;
  110. Iter = Sections.find(VersionSectionName);
  111. if (Iter == Sections.end()) {
  112. throw new InvalidInfFile<T>(FileName);
  113. }
  114. Section<T> *VersionSection = (*Iter).second;
  115. SectionValues<T> &Values = VersionSection->GetValue(CabsSearchOrderKeyName);
  116. for (int Index=0; Index < Values.Count(); Index++) {
  117. if (sizeof(T) == sizeof(CHAR)) {
  118. SearchList.push_back((T *)_strlwr((PSTR)Values.GetValue(Index).c_str()));
  119. } else {
  120. SearchList.push_back((T *)_wcslwr((PWSTR)Values.GetValue(Index).c_str()));
  121. }
  122. }
  123. }
  124. //
  125. // Checks where the given is contained any of the driver cab files
  126. //
  127. bool IsFilePresent(const std::basic_string<T> &FileName){
  128. return (GetCabFileName(FileName).length() > 0);
  129. }
  130. //
  131. // Returns the driver cab file name which contains the given filename.
  132. //
  133. const std::basic_string<T>& GetCabFileName(const std::basic_string<T> &FileName) {
  134. const static basic_string<T> NullCabFileName;
  135. std::list<basic_string<T> >::iterator Iter;
  136. for(Iter = SearchList.begin(); Iter != SearchList.end(); Iter++) {
  137. std::map< std::basic_string<T>, Section<T> *>::iterator SectionIter = Sections.find(*Iter);
  138. if (SectionIter != Sections.end()) {
  139. Section<T> *CurrentSection = (*SectionIter).second;
  140. if (CurrentSection->IsKeyPresent(FileName)) {
  141. break;
  142. }
  143. }
  144. }
  145. if (Iter != SearchList.end()) {
  146. return CabsSection->GetValue(*Iter).GetValue(0);
  147. }
  148. return NullCabFileName;
  149. }
  150. protected:
  151. //
  152. // constant strings
  153. //
  154. const static std::basic_string<T> VersionSectionName;
  155. const static std::basic_string<T> CabsSectionName;
  156. const static std::basic_string<T> CabsSearchOrderKeyName;
  157. //
  158. // data members
  159. //
  160. std::list<std::basic_string<T> > SearchList; // the cab file list search order
  161. Section<T> *CabsSection; // the [cabs] section of drvindex.inf
  162. };
  163. //
  164. // File list creator functor object
  165. //
  166. template <class T>
  167. struct FileListCreatorContext {
  168. Arguments<T> &Args;
  169. Section<T> *CurrentSection;
  170. Section<T> *DirsSection;
  171. bool SkipInfFiles;
  172. ULONG FileCount;
  173. bool ProcessingExtraFiles;
  174. InfFile<T> &IntlInfFile;
  175. InfFile<T> &FontInfFile;
  176. InfFile<T> &ConfigInfFile;
  177. ULONG DummyDirectoryId;
  178. std::basic_string<T> WindowsDirectory;
  179. std::basic_string<T> WinSxsCabinetFileName;
  180. DriverIndexInfFile<T> &DriverIdxFile;
  181. std::basic_string<T> CurrentCabFileIdx; // the cab being currently iterated on
  182. std::basic_string<T> CurrentFileName; // the current file while iterating cab
  183. std::map<std::basic_string<T>, std::basic_string<T> > FileList;
  184. std::map<std::basic_string<T>, std::basic_string<T> > ExtraFileList;
  185. std::map<std::basic_string<T>, std::basic_string<T> > DestDirs;
  186. std::map<std::basic_string<T>, std::basic_string<T> > WinSxSFileList;
  187. std::map<std::basic_string<T>, std::basic_string<T> > NlsFileMap;
  188. std::map<std::basic_string<T>, std::basic_string<T> > NlsDirMap;
  189. //
  190. // Map of map i.e. map of cab filename to map of list of source to destination names
  191. // which need to be extracted for cab file
  192. //
  193. std::map<std::basic_string<T>, std::map<std::basic_string<T>, std::basic_string<T> > * > CabFileListMap;
  194. FileListCreatorContext(
  195. Arguments<T> &PrgArgs,
  196. Section<T> *Curr,
  197. Section<T> *Dirs,
  198. InfFile<T> &ConfigInf,
  199. InfFile<T> &IntlInf,
  200. InfFile<T> &FontInf,
  201. DriverIndexInfFile<T> &DrvIdxFile
  202. );
  203. DWORD ProcessNlsFiles(VOID);
  204. ~FileListCreatorContext() {
  205. std::map<std::basic_string<T>,
  206. std::map<std::basic_string<T>, std::basic_string<T> > * >::iterator Iter;
  207. for (Iter=CabFileListMap.begin(); Iter != CabFileListMap.end(); Iter++) {
  208. delete (*Iter).second;
  209. }
  210. }
  211. ULONG GetSourceCount() const {
  212. ULONG Count = (FileList.size() + ExtraFileList.size() +
  213. WinSxSFileList.size() + NlsFileMap.size());
  214. std::map<std::basic_string<T>,
  215. std::map<std::basic_string<T>, std::basic_string<T> > * >::iterator Iter;
  216. for (Iter=CabFileListMap.begin(); Iter != CabFileListMap.end(); Iter++) {
  217. Count += (*Iter).second->size();
  218. }
  219. return Count;
  220. }
  221. bool IsDriverCabFile(const std::basic_string<T> &FileName) {
  222. return DriverIdxFile.IsFilePresent(FileName);
  223. }
  224. //
  225. // Given the file name returns the cab file name (if any) which contains
  226. // the file. In case of error "" (empty string) is returned.
  227. //
  228. const std::basic_string<T>& GetDriverCabFileName(const std::basic_string<T> &FileName) {
  229. const std::basic_string<T> &CabFileName = DriverIdxFile.GetCabFileName(FileName);
  230. // std::cout << "GetDriverCabFileName(" << FileName << ") = " << CabFileName << std::endl;
  231. return CabFileName;
  232. }
  233. //
  234. // Adds to the per cab file map the given source and destination file name that
  235. // need to be extracted
  236. //
  237. void AddFileToCabFileList(const std::basic_string<T> &CabFileName,
  238. const std::basic_string<T> &SourceFile,
  239. const std::basic_string<T> &DestinationFile) {
  240. //cout << "AddFileToCabFileList(" << CabFileName << ", " << SourceFile << ", " << DestinationFile << ")" << endl;
  241. std::map<std::basic_string<T>,
  242. std::map<std::basic_string<T>, std::basic_string<T> >* >::iterator Iter;
  243. Iter = CabFileListMap.find(CabFileName);
  244. std::map<std::basic_string<T>, std::basic_string<T> > *FileMap = NULL;
  245. if (Iter != CabFileListMap.end()) {
  246. FileMap = (*Iter).second;
  247. } else {
  248. //
  249. // New cab file list
  250. //
  251. CabFileListMap[CabFileName] = FileMap = new std::map<std::basic_string<T>, std::basic_string<T> >();
  252. }
  253. (*FileMap)[SourceFile] = DestinationFile;
  254. }
  255. std::basic_string<T> GetNextDummyDirectoryId() {
  256. T Buffer[MAX_PATH];
  257. if (sizeof(T) == sizeof(CHAR)) {
  258. (void)StringCchPrintfA((PSTR)Buffer, ARRAY_SIZE(Buffer), "%d", DummyDirectoryId);
  259. } else {
  260. (void)StringCchPrintfW((PWSTR)Buffer, ARRAY_SIZE(Buffer), L"%d", DummyDirectoryId);
  261. }
  262. DummyDirectoryId++;
  263. return std::basic_string<T>((const T*)Buffer);
  264. }
  265. void AddDirectoryToNlsDirMap(const std::basic_string<T> &FileName) {
  266. T Separator;
  267. if (sizeof(T) == sizeof(CHAR)) {
  268. Separator = (T)'\\';
  269. } else {
  270. Separator = (T)L'\\';
  271. }
  272. std::basic_string<T> DirectoryKey = FileName.substr(0, FileName.rfind(Separator));
  273. if (DirectoryKey.length() && (NlsDirMap.find(DirectoryKey) == NlsDirMap.end())) {
  274. NlsDirMap[DirectoryKey] = GetNextDummyDirectoryId();
  275. }
  276. }
  277. void ProcessNlsDirMapEntries(void) {
  278. std::map<std::basic_string<T>, std::basic_string<T> >::iterator Iter;
  279. for (Iter = NlsDirMap.begin(); Iter != NlsDirMap.end(); Iter++) {
  280. DestDirs[(*Iter).second] = (*Iter).first;
  281. }
  282. }
  283. void RemoveDuplicateNlsEntries(void) {
  284. std::map<std::basic_string<T>, std::basic_string<T> >::iterator NlsIter, PrevIter;
  285. for (NlsIter = NlsFileMap.begin(); NlsIter != NlsFileMap.end(); ) {
  286. PrevIter = NlsFileMap.end();
  287. if (FileList.find((*NlsIter).first) != FileList.end()) {
  288. PrevIter = NlsIter;
  289. }
  290. NlsIter++;
  291. if (PrevIter != NlsFileMap.end()) {
  292. // std::cout << "Erasing : " << (*PrevIter).first << std::endl;
  293. NlsFileMap.erase(PrevIter);
  294. }
  295. }
  296. }
  297. void MoveDriverCabNlsFiles(void);
  298. //
  299. // static data members
  300. //
  301. static
  302. UINT
  303. NlsFileQueueScanWorker(
  304. PVOID Context,
  305. UINT Notification,
  306. UINT_PTR Param1,
  307. UINT_PTR Param2
  308. );
  309. };
  310. //
  311. // function prototypes
  312. //
  313. template <class T>
  314. void
  315. FileListCreator(
  316. SectionValues<T> &Values,
  317. PVOID Context
  318. );
  319. template <class T>
  320. bool
  321. IsWow64File(
  322. SectionValues<T> &Values,
  323. FileListCreatorContext<T> &Context
  324. );
  325. template <class T>
  326. bool
  327. IsFileSkipped(
  328. SectionValues<T> &Values,
  329. FileListCreatorContext<T> &Context
  330. );
  331. template <class T>
  332. ULONG
  333. CopyFileList(
  334. FileListCreatorContext<T> &Context
  335. );
  336. template <class T>
  337. ULONG
  338. ProcessExtraFiles(
  339. FileListCreatorContext<T> &Context
  340. );
  341. template <class T>
  342. ULONG
  343. ProcessWinSxSFiles(
  344. IN FileListCreatorContext<T> &Context
  345. );
  346. template <class T>
  347. ULONG
  348. PreCreateDirs(
  349. FileListCreatorContext<T> &Context
  350. );
  351. template <class T>
  352. bool
  353. ProcessInfChanges(
  354. Arguments<T> &Args,
  355. const std::basic_string<T> &InfName
  356. );
  357. template <class T>
  358. bool
  359. CheckMediaVersion(
  360. Arguments<T> &Args
  361. );
  362. //
  363. // utility function to tokenize a given line based on the delimiters
  364. // specified
  365. //
  366. template< class T >
  367. unsigned Tokenize(const T &szInput, const T & szDelimiters, std::vector<T>& tokens) {
  368. unsigned DelimiterCount = 0;
  369. tokens.clear();
  370. if(!szInput.empty()){
  371. if(!szDelimiters.empty()){
  372. T::const_iterator inputIter = szInput.begin();
  373. T::const_iterator copyIter = szInput.begin();
  374. while(inputIter != szInput.end()){
  375. if(szDelimiters.find(*inputIter) != string::npos){
  376. if (copyIter < inputIter) {
  377. tokens.push_back(szInput.substr(copyIter - szInput.begin(),
  378. inputIter - copyIter));
  379. }
  380. DelimiterCount++;
  381. inputIter++;
  382. copyIter = inputIter;
  383. continue;
  384. }
  385. inputIter++;
  386. }
  387. if(copyIter != inputIter){
  388. tokens.push_back(szInput.substr(copyIter - szInput.begin(),
  389. inputIter - szInput.begin()));
  390. }
  391. } else {
  392. tokens.push_back(szInput);
  393. }
  394. }
  395. return DelimiterCount;
  396. }