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.

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