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.

1242 lines
33 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. inflib.c
  5. Abstract:
  6. Source for inflib.lib that implements functions designed to build a
  7. layout context given a layout INF file. This sets up an infrastructure
  8. to build tools that will need to reference a layout inf file.
  9. Author:
  10. Vijesh Shetty (vijeshs)
  11. Revision History:
  12. --*/
  13. #include <stdio.h>
  14. #include <windows.h>
  15. #include <conio.h>
  16. #include <process.h>
  17. #include <tchar.h>
  18. #include <objbase.h>
  19. #include <io.h>
  20. #include <setupapi.h>
  21. #include <sputils.h>
  22. #include <inflib.h>
  23. #include <string.h>
  24. //#define DEBUG 1
  25. #define LAYOUT_DIR_SECTION TEXT("WinntDirectories")
  26. #define MAX_TEMP 500
  27. //Structure to pass parameters to the enumeration callback
  28. typedef struct _CALLBACK_PACKAGE{
  29. PLAYOUT_CONTEXT Context;
  30. PLAYOUTENUMCALLBACK Callback;
  31. DWORD_PTR Param;
  32. }CALLBACK_PACKAGE, *PCALLBACK_PACKAGE;
  33. //Structure to pass parameters to the enumeration callback
  34. typedef struct _WINNT_DIRCODES{
  35. TCHAR Dir[MAX_PATH];
  36. }WINNT_DIRCODES, *PWINNT_DIRCODES;
  37. #if DBG
  38. VOID
  39. AssertFail(
  40. IN PSTR FileName,
  41. IN UINT LineNumber,
  42. IN PSTR Condition
  43. )
  44. {
  45. int i;
  46. CHAR Name[MAX_PATH];
  47. PCHAR p;
  48. CHAR Msg[4096];
  49. //
  50. // Use dll name as caption
  51. //
  52. GetModuleFileNameA(NULL,Name,MAX_PATH);
  53. if(p = strrchr(Name,'\\')) {
  54. p++;
  55. } else {
  56. p = Name;
  57. }
  58. wsprintfA(
  59. Msg,
  60. "Assertion failure at line %u in file %s: %s\n\nCall DebugBreak()?",
  61. LineNumber,
  62. FileName,
  63. Condition
  64. );
  65. OutputDebugStringA(Msg);
  66. i = MessageBoxA(
  67. NULL,
  68. Msg,
  69. p,
  70. MB_YESNO | MB_TASKMODAL | MB_ICONSTOP | MB_SETFOREGROUND
  71. );
  72. if(i == IDYES) {
  73. DebugBreak();
  74. }
  75. }
  76. #define MYASSERT(x) if(!(x)) { AssertFail(__FILE__,__LINE__,#x); }
  77. #else
  78. #define MYASSERT( exp )
  79. #endif // DBG
  80. BOOL
  81. InternalEnumRoutine(
  82. IN PVOID StringTable,
  83. IN LONG StringId,
  84. IN PCTSTR String,
  85. IN PFILE_LAYOUTINFORMATION LayoutInfo,
  86. IN UINT LayoutInfoSize,
  87. IN LPARAM Param
  88. );
  89. BOOL ValidateTextmodeDirCodesSection(
  90. PCTSTR LayoutFile,
  91. PCTSTR WinntdirSection
  92. )
  93. /*
  94. Routine to validate the [WinntDirectories] section for a setup layout INF. This checks for errors that maybe encountered
  95. when people add/remove stuff from this section.
  96. Arguments:
  97. LayoutInf - Name of setup layout INF that contains the specified section
  98. WinntdirSection - Section that contains dir codes
  99. Checks -
  100. 1) Looks for duplicate or reused dir codes
  101. Return value:
  102. TRUE - Validation succeeded
  103. FALSE- Validation failed
  104. */
  105. {
  106. //OPen up the layout file.
  107. HINF LayoutInf;
  108. PVOID StringTable=NULL;
  109. INFCONTEXT LineContext;
  110. WINNT_DIRCODES WinntDirs, Buffer;
  111. BOOL ret = TRUE;
  112. LONG StrID, Size;
  113. TCHAR DirCode[4];
  114. LayoutInf = SetupOpenInfFile( LayoutFile, NULL, INF_STYLE_WIN4 | INF_STYLE_CACHE_ENABLE, NULL);
  115. if( !LayoutInf || (LayoutInf == INVALID_HANDLE_VALUE)){
  116. _tprintf(TEXT("Error E0000 : Could not open %s\n"), LayoutFile);
  117. return FALSE;
  118. }
  119. //Grovel through the specified section and populate our WINNT_DIRCODES structure
  120. if( !SetupFindFirstLine(LayoutInf,WinntdirSection,NULL,&LineContext)){
  121. _tprintf(TEXT("%s : Error E0000 : Can't find section [%s]\n"), LayoutFile, WinntdirSection);
  122. return(FALSE);
  123. }
  124. // Create a stringtable for hashing of the SourceDisksNames section.
  125. if( (StringTable=pSetupStringTableInitializeEx( sizeof(WINNT_DIRCODES), 0 )) == NULL ){
  126. _tprintf(TEXT("%s : Error E0000 : Internal error processing [%s] section (1)\n"), LayoutFile, WinntdirSection);
  127. return(FALSE);
  128. }
  129. do{
  130. ZeroMemory( &WinntDirs, sizeof(WINNT_DIRCODES));
  131. if( SetupGetStringField( &LineContext, 0, NULL, 0, &Size) ){
  132. if( SetupGetStringField( &LineContext, 0, DirCode, Size, NULL )){
  133. //
  134. // Add the Filename to the StringTable. Look for its presence so that the Count is updated
  135. //
  136. if(!SetupGetStringField( &LineContext, 1, WinntDirs.Dir, MAX_PATH, NULL)){
  137. _tprintf(TEXT("%s : Error E0000 : Directory missing for Dir ID %s\n"), LayoutFile, DirCode);
  138. ret = FALSE;
  139. break;
  140. }
  141. if( pSetupStringTableLookUpStringEx( StringTable,
  142. DirCode,
  143. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  144. &Buffer,
  145. sizeof(WINNT_DIRCODES)) != -1 ){
  146. _tprintf(TEXT("%s : Error E0000 : Duplicate Dir ID found in [%s] section - Dir ID %s reused by %s, %s\n"), LayoutFile, WinntdirSection, DirCode, Buffer.Dir, WinntDirs.Dir);
  147. }
  148. else{
  149. StrID = pSetupStringTableAddString( StringTable,
  150. DirCode,
  151. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE);
  152. if( StrID == -1 ){
  153. _tprintf(TEXT("%s : Error E0000 : Internal error processing [%s] section (2)\n"), LayoutFile, WinntdirSection);
  154. ret = FALSE;
  155. break;
  156. }
  157. if(!pSetupStringTableSetExtraData( StringTable, StrID, (PVOID)&WinntDirs, sizeof(WINNT_DIRCODES))){
  158. _tprintf(TEXT("%s : Error E0000 : Internal error processing [%s] section (3)\n"), LayoutFile, WinntdirSection);
  159. ret = FALSE;
  160. break;
  161. }
  162. }
  163. }else
  164. _tprintf(TEXT("%s : Error E0000 : Internal error processing [%s] section (4)\n"), LayoutFile, WinntdirSection);
  165. }else
  166. _tprintf(TEXT("%s : Error E0000 : Internal error processing [%s] section (5)\n"), LayoutFile, WinntdirSection);
  167. }while(SetupFindNextLine(&LineContext, &LineContext));
  168. // If we are here and ret=TRUE that means we are done and have suceeded.
  169. if( StringTable )
  170. pSetupStringTableDestroy( StringTable );
  171. return ret;
  172. }
  173. DWORD
  174. BuildMediaTagsInformation(
  175. IN HINF LayoutInf,
  176. IN LPCTSTR SectionName,
  177. IN PLAYOUT_CONTEXT LayoutContext,
  178. IN UINT Platform_Index)
  179. /*
  180. Function to populate the stringtable given a handle to the inf and the name of the
  181. SourceDisksFiles Section.
  182. Arguments :
  183. LayoutInf - Handle to a layout file that has the SourceDisksNames Section
  184. SectionName - Name of the SourceDisksNames Section (this is so that we can specify decorated sections)
  185. LayoutContext - Layout Context that we want to build
  186. Platform_Index - Index in the MEDIA_INFO Array
  187. */
  188. {
  189. DWORD Err = 0;
  190. INFCONTEXT LineContext;
  191. MEDIA_INFO Media_Info;
  192. TCHAR TempStr[500];
  193. LONG StrID;
  194. //Grovel through the specified section and populate our MEDIA_TAGS structure
  195. if( !SetupFindFirstLine(LayoutInf,SectionName,NULL,&LineContext))
  196. return(ERROR_NOT_ENOUGH_MEMORY); //BUGBUG - Fix error code
  197. //StringTableSetConstants( 4096000, 4096000 );
  198. // Create a stringtable for hashing of the SourceDisksNames section.
  199. if( (LayoutContext->MediaInfo[Platform_Index]=pSetupStringTableInitializeEx( sizeof(MEDIA_INFO), 0 )) == NULL )
  200. return(ERROR_NOT_ENOUGH_MEMORY); //BUGBUG - Fix error code
  201. // Now populate it
  202. do{
  203. ZeroMemory( &Media_Info, sizeof(MEDIA_INFO));
  204. if( SetupGetStringField( &LineContext, 0, TempStr, MAX_TEMP, NULL )){
  205. StrID = pSetupStringTableAddString( LayoutContext->MediaInfo[Platform_Index],
  206. TempStr,
  207. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE);
  208. if( StrID == -1 ){
  209. Err = ERROR_NOT_ENOUGH_MEMORY;
  210. _tprintf(TEXT("\nERROR-Could not add string to table\n"));
  211. break;
  212. }
  213. }else
  214. return( ERROR_NOT_ENOUGH_MEMORY ); //BUGBUG - Fix error code
  215. //_tprintf( TEXT("\nTagID - %s\n"), TempStr );
  216. if( SetupGetStringField( &LineContext, 1, TempStr, MAX_TEMP, NULL) )
  217. lstrcpy(Media_Info.MediaName, TempStr);
  218. if( SetupGetStringField( &LineContext, 2, TempStr, MAX_TEMP, NULL) )
  219. lstrcpy(Media_Info.TagFilename, TempStr);
  220. if( SetupGetStringField( &LineContext, 4, TempStr, MAX_TEMP, NULL) )
  221. lstrcpy(Media_Info.RootDir, TempStr);
  222. /*
  223. _tprintf( TEXT("\nMediaName - %s\n"), Media_Info.MediaName );
  224. _tprintf( TEXT("TagFilename - %s\n"), Media_Info.TagFilename );
  225. _tprintf( TEXT("RootDir - %s\n"), Media_Info.RootDir );
  226. */
  227. //
  228. // Now add the information to the string table.
  229. //
  230. if(!pSetupStringTableSetExtraData( LayoutContext->MediaInfo[Platform_Index], StrID, (PVOID)&Media_Info, sizeof(MEDIA_INFO))){
  231. Err = ERROR_NOT_ENOUGH_MEMORY; //BUGBUG - Fix error code
  232. _tprintf(TEXT("\nERROR-Could not set extra data for Media Info\n"));
  233. break;
  234. }
  235. }while(SetupFindNextLine(&LineContext, &LineContext));
  236. return Err;
  237. }
  238. DWORD
  239. BuildStringTableForSection(
  240. IN HINF LayoutInf,
  241. IN LPCTSTR SectionName,
  242. IN PLAYOUT_CONTEXT LayoutContext,
  243. IN UINT Platform_Index)
  244. /*
  245. Function to populate the stringtable given a handle to the inf and the name of the
  246. SourceDisksFiles Section.
  247. Arguments :
  248. LayoutInf - Handle to a layout file that has the SourceDisksFiles Section
  249. SectionName - Name of the SourceDisksFilesSection (this is so that we can specify decorated sections)
  250. LayoutContext - Layout Context that we want to build
  251. */
  252. {
  253. DWORD Err = 0;
  254. INFCONTEXT LineContext, TempContext;
  255. DWORD Size;
  256. int Temp;
  257. LONG StrID;
  258. LPTSTR p;
  259. TCHAR TempString[MAX_PATH];
  260. FILE_LAYOUTINFORMATION FileInformation;
  261. TCHAR FileName[MAX_PATH];
  262. TCHAR Buffer[10];
  263. PVOID LookupBuffer=NULL;
  264. PFILE_LAYOUTINFORMATION Lookup;
  265. #ifdef DEBUG
  266. int count=0;
  267. #endif
  268. LookupBuffer = pSetupMalloc( LayoutContext->ExtraDataSize );
  269. if( !LookupBuffer ){
  270. Err = ERROR_NOT_ENOUGH_MEMORY;
  271. goto cleanup;
  272. }
  273. //Grovel through the specified section and populate our FILE_LAYOUTINFORMATION structure for each file
  274. if( !SetupFindFirstLine(LayoutInf,SectionName,NULL,&LineContext)){
  275. Err = ERROR_NOT_ENOUGH_MEMORY; //BUGBUG - Fix error code
  276. goto cleanup;
  277. }
  278. do{
  279. ZeroMemory( &FileInformation, sizeof(FILE_LAYOUTINFORMATION));
  280. FileInformation.Compression = TRUE;
  281. if( SetupGetStringField( &LineContext, 0, NULL, 0, &Size) ){
  282. if( SetupGetStringField( &LineContext, 0, FileName, Size, NULL )){
  283. //
  284. // Add the Filename to the StringTable. Look for its presence so that the Count is updated
  285. //
  286. if( pSetupStringTableLookUpStringEx( LayoutContext->Context,
  287. FileName,
  288. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  289. LookupBuffer,
  290. LayoutContext->ExtraDataSize) != -1 ){
  291. Lookup = (PFILE_LAYOUTINFORMATION)(LookupBuffer);
  292. // Check for same platform section
  293. if( (Lookup->SectionIndex == Platform_Index) || (Lookup->SectionIndex == LAYOUTPLATFORMINDEX_COMMON))
  294. FileInformation.Count = Lookup->Count + 1;
  295. }
  296. else
  297. FileInformation.Count = 1;
  298. StrID = pSetupStringTableAddString( LayoutContext->Context,
  299. FileName,
  300. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE);
  301. if( StrID == -1 ){
  302. Err = ERROR_NOT_ENOUGH_MEMORY;
  303. _tprintf(TEXT("\nERROR-Could not add string to table\n"));
  304. break;
  305. }
  306. //
  307. // Now add the other related info for the file as ExtraData
  308. //
  309. // Get the directory code
  310. if( SetupGetIntField( &LineContext, 8, &Temp )){
  311. FileInformation.Directory_Code = Temp;
  312. _itot( Temp,Buffer, 10);
  313. //Now retrieve the directory Information through a lookup of [WinntDirectories]
  314. if( Temp && SetupFindFirstLine( LayoutInf, LAYOUT_DIR_SECTION, Buffer, &TempContext) ){
  315. if( SetupGetStringField( &TempContext, 1, TempString, MAX_PATH, NULL )){
  316. lstrcpy( FileInformation.Directory, TempString );
  317. }
  318. }
  319. }
  320. //
  321. // Get the Upgrade and Clean Install Dispositions
  322. //
  323. FileInformation.UpgradeDisposition = 3; //Default is don't copy
  324. if( SetupGetStringField( &LineContext, 9, TempString, MAX_PATH, NULL )){
  325. if( (TempString[0] >= 48) && (TempString[0] <= 57)){
  326. Temp = _ttoi( TempString );
  327. FileInformation.UpgradeDisposition = Temp;
  328. }
  329. }
  330. if( (FileInformation.UpgradeDisposition < 0) || (FileInformation.UpgradeDisposition > 3))
  331. _ftprintf(stderr, TEXT("%s - Bad Upgrade disposition value - Inf maybe corrupt\n"),FileName);
  332. FileInformation.CleanInstallDisposition = 3; //Default is don't copy
  333. if( SetupGetStringField( &LineContext, 10, TempString, MAX_PATH, NULL )){
  334. if( (TempString[0] >= 48) && (TempString[0] <= 57)){
  335. Temp = _ttoi( TempString );
  336. FileInformation.CleanInstallDisposition = Temp;
  337. }
  338. }
  339. if( (FileInformation.CleanInstallDisposition < 0) || (FileInformation.CleanInstallDisposition > 3))
  340. _ftprintf(stderr, TEXT("%s - Bad Clean Install disposition value - Inf maybe corrupt\n"),FileName);
  341. if( SetupGetStringField( &LineContext, 11, TempString, MAX_PATH, NULL )){
  342. lstrcpy( FileInformation.TargetFileName, TempString );
  343. }
  344. if( SetupGetStringField( &LineContext, 7, TempString, MAX_PATH, NULL )){
  345. if( *TempString && !_tcschr(TempString, TEXT('_'))){
  346. _ftprintf(stderr, TEXT("\nERROR-Bad Media ID - No _ qualifier - %s\n"), FileName);
  347. FileInformation.BootMediaNumber = -1; //Indicates error
  348. }else{
  349. // Check for Compression
  350. if( TempString[0] == TEXT('_') )
  351. FileInformation.Compression = FALSE;
  352. // Look for Boot Media Numbers
  353. p = TempString;
  354. while( (p[0] == TEXT('_')) ){
  355. p++;
  356. }
  357. FileInformation.BootMediaNumber = _ttoi(p);
  358. }
  359. }
  360. //Add the Media tag information
  361. if( SetupGetStringField( &LineContext, 1, TempString, MAX_PATH, NULL ))
  362. lstrcpy(FileInformation.Media_tagID, TempString);
  363. FileInformation.SectionIndex = Platform_Index;
  364. //Get the file sizes if present
  365. if( SetupGetIntField( &LineContext, 3, &Temp )){
  366. FileInformation.Size = (ULONG)Temp;
  367. }
  368. //
  369. // Now add the information to the string table.
  370. //
  371. if(!pSetupStringTableSetExtraData( LayoutContext->Context, StrID, (PVOID)&FileInformation, sizeof(FILE_LAYOUTINFORMATION))){
  372. Err = ERROR_NOT_ENOUGH_MEMORY; //BUGBUG - Fix error code
  373. _tprintf(TEXT("\nERROR-Could not set extra data\n"));
  374. break;
  375. }
  376. /*
  377. _tprintf(TEXT("File - %s\n"),FileName);
  378. _tprintf(TEXT("Dir Code %d - Dir - %s\n"),FileInformation.Directory_Code, FileInformation.Directory);
  379. _tprintf(TEXT("Upgrade Disposition - %d\n"),FileInformation.UpgradeDisposition);
  380. _tprintf(TEXT("Textmode Disposition - %d\n"),FileInformation.CleanInstallDisposition);
  381. _tprintf(TEXT("Media ID - %s\n"),FileInformation.Media_tagID);
  382. if( *(FileInformation.TargetFileName))
  383. _tprintf(TEXT("Target Filename - %s\n"),FileInformation.TargetFileName);
  384. if( !FileInformation.Compression )
  385. _tprintf(TEXT("No Compression\n"));
  386. if( FileInformation.BootMediaNumber )
  387. _tprintf(TEXT("Boot Media - %d\n"),FileInformation.BootMediaNumber);
  388. */
  389. }
  390. }
  391. #ifdef DEBUG
  392. count++;
  393. if( (count % 100) == 0)
  394. _ftprintf(stderr,TEXT("\b\b\b\b\b%5d"),count);
  395. #endif
  396. }while(SetupFindNextLine(&LineContext, &LineContext));// while
  397. cleanup:
  398. if( LookupBuffer )
  399. pSetupFree(LookupBuffer);
  400. return Err;
  401. }
  402. PLAYOUT_CONTEXT
  403. BuildLayoutInfContext(
  404. IN PCTSTR LayoutInfName,
  405. IN DWORD PlatformMask,
  406. IN UINT MaxExtraSize
  407. )
  408. /*
  409. Function to generate a internal representation of files listed in a layout INF file.
  410. It returns an opaque context that can be used with other APIs to
  411. manipulate/query this representation. The internal representation builds a structure
  412. associated with each file that lists its attributes.
  413. Arguments :
  414. LayoutInfName - Full path to Layout file.
  415. PlatFormMask - Can be one of the following....
  416. LAYOUTPLATFORMS_ALL (default) - Grovels through all the platform-specific section
  417. LAYOUTPLATFORMS_X86 - Grovels through the SourcedisksFiles.x86 section
  418. LAYOUTPLATFORMS_AMD64 - Grovels through the SourcedisksFiles.amd64 section
  419. LAYOUTPLATFORMS_IA64 - Grovels through the SourcedisksFiles.ia64 section
  420. LAYOUTPLATFORMS_COMMON - Grovels through the SourcedisksFiles section
  421. MaxExtraSize - Largest possible extra-data size that we may want to associate with
  422. each file
  423. Return value :
  424. An opaque LAYOUT_CONTEXT used to access the data structure in other calls.
  425. Returns NULL if we had a failure.
  426. */
  427. {
  428. PLAYOUT_CONTEXT LayoutContext;
  429. PVOID StringTable;
  430. HINF LayoutInf;
  431. DWORD Err;
  432. // Initialize the string table and set the max extra data size
  433. if( (StringTable=pSetupStringTableInitializeEx( (MaxExtraSize+sizeof(FILE_LAYOUTINFORMATION)), 0 )) == NULL )
  434. return NULL;
  435. //OPen up the layout file.
  436. LayoutInf = SetupOpenInfFile( LayoutInfName, NULL, INF_STYLE_WIN4 | INF_STYLE_CACHE_ENABLE, NULL);
  437. if( !LayoutInf || (LayoutInf == INVALID_HANDLE_VALUE)){
  438. pSetupStringTableDestroy( StringTable );
  439. return NULL;
  440. }
  441. LayoutContext = pSetupMalloc( sizeof(LAYOUT_CONTEXT));
  442. if( !LayoutContext )
  443. goto done;
  444. ZeroMemory( LayoutContext, sizeof(LAYOUT_CONTEXT));
  445. LayoutContext->Context = StringTable;
  446. LayoutContext->ExtraDataSize = (MaxExtraSize+sizeof(FILE_LAYOUTINFORMATION));
  447. //
  448. //Now we need to grovel throught the [SourceDisksFiles] sections
  449. //
  450. //
  451. // Grovel through the decorated sections first as specfied by PlatformMask
  452. //
  453. if(!PlatformMask)
  454. PlatformMask = LAYOUTPLATFORMS_ALL;
  455. //
  456. //
  457. //
  458. #ifdef DEBUG
  459. _tprintf( TEXT("\nBuilding x86 section\n"));
  460. #endif
  461. if( PlatformMask & LAYOUTPLATFORMS_X86 ){
  462. //
  463. // Build up the [SourceDisksNames.x86] Information
  464. //
  465. Err = BuildMediaTagsInformation( LayoutInf, TEXT("SourceDisksNames.x86"), LayoutContext, LAYOUTPLATFORMINDEX_X86);
  466. // Process [SourceDisksFiles.x86]
  467. Err = BuildStringTableForSection( LayoutInf, TEXT("SourceDisksFiles.x86"), LayoutContext, LAYOUTPLATFORMINDEX_X86 );
  468. }
  469. #ifdef DEBUG
  470. _tprintf( TEXT("\nBuilding amd64 section\n"));
  471. #endif
  472. if( PlatformMask & LAYOUTPLATFORMS_AMD64 ){
  473. //
  474. // Build up the [SourceDisksNames.amd64] Information
  475. //
  476. Err = BuildMediaTagsInformation( LayoutInf, TEXT("SourceDisksNames.amd64"), LayoutContext, LAYOUTPLATFORMINDEX_AMD64);
  477. // Process [SourceDisksFiles.amd64]
  478. Err = BuildStringTableForSection( LayoutInf, TEXT("SourceDisksFiles.amd64"), LayoutContext, LAYOUTPLATFORMINDEX_AMD64 );
  479. }
  480. #ifdef DEBUG
  481. _tprintf( TEXT("\nBuilding ia64 section\n"));
  482. #endif
  483. if( PlatformMask & LAYOUTPLATFORMS_IA64 ){
  484. //
  485. // Build up the [SourceDisksNames.ia64] Information
  486. //
  487. Err = BuildMediaTagsInformation( LayoutInf, TEXT("SourceDisksNames.ia64"), LayoutContext, LAYOUTPLATFORMINDEX_IA64);
  488. // Process [SourceDisksFiles.ia64]
  489. Err = BuildStringTableForSection( LayoutInf, TEXT("SourceDisksFiles.ia64"), LayoutContext, LAYOUTPLATFORMINDEX_IA64 );
  490. }
  491. #ifdef DEBUG
  492. _tprintf( TEXT("\nBuilding common section\n"));
  493. #endif
  494. if( PlatformMask & LAYOUTPLATFORMS_COMMON ){
  495. //
  496. // Build up the [SourceDisksNames] Information. In this case we have
  497. // currently set it to the same as x86. Should fix this to do something better - BUGBUG
  498. //
  499. Err = BuildMediaTagsInformation( LayoutInf, TEXT("SourceDisksNames"), LayoutContext, LAYOUTPLATFORMINDEX_COMMON);
  500. // Process [SourceDisksFiles]
  501. Err = BuildStringTableForSection( LayoutInf, TEXT("SourceDisksFiles"), LayoutContext, LAYOUTPLATFORMINDEX_COMMON);
  502. }
  503. done:
  504. SetupCloseInfFile( LayoutInf);
  505. return(LayoutContext) ;
  506. }
  507. BOOL
  508. EnumerateLayoutInf(
  509. IN PLAYOUT_CONTEXT LayoutContext,
  510. IN PLAYOUTENUMCALLBACK LayoutEnumCallback,
  511. IN DWORD_PTR Param
  512. )
  513. /*
  514. This function calls the specified callback function for each
  515. element in the SourceDisksFilesSection associated with the
  516. Layout Inf Context specified.
  517. It is required that the user has a LayoutInfContext open from a call to
  518. BuildLayoutInfContext.
  519. Arguments:
  520. Context - A LAYOUT_CONTEXT returned by BuildLayoutInfContext
  521. LayoutEnumCallback - specifies a callback function called for each file in the SourceDisksFile section
  522. CallerContext - An opaque context pointer passed on to the callback function
  523. The callback is of the form:
  524. typedef BOOL
  525. (CALLBACK *PLAYOUTENUMCALLBACK) (
  526. IN PLAYOUT_CONTEXT Context,
  527. IN PCTSTR FileName,
  528. IN PFILE_LAYOUTINFORMATION LayoutInformation,
  529. IN PVOID ExtraData,
  530. IN UINT ExtraDataSize,
  531. IN OUT DWORD_PTR Param
  532. );
  533. where
  534. Context - Pointer to open LAYOUT_CONTEXT
  535. FileName - Specifies the individual filename
  536. LayoutInformation - Pointer to Layout Information for this file. User should not modify this directly.
  537. ExtraData - Pointer to the ExtraData that the caller may have stored. User should not modify this directly.
  538. ExtraDataSize - Size in bytes of the ExtraData
  539. Param - the opaque param passed into this function is passed
  540. into the callback function
  541. Return value:
  542. TRUE if all the elements were enumerated. If not it returns
  543. FALSE and GetLastError() returns ERROR_CANCELLED. If the callback
  544. returns FALSE then the enumeration stops but this API returns TRUE.
  545. */
  546. {
  547. PVOID Buffer;
  548. CALLBACK_PACKAGE Package;
  549. BOOL ret;
  550. if( !LayoutContext ||
  551. !LayoutContext->Context ||
  552. !LayoutContext->ExtraDataSize ||
  553. !LayoutEnumCallback){
  554. SetLastError( ERROR_INVALID_PARAMETER );
  555. return( FALSE );
  556. }
  557. Buffer = pSetupMalloc( LayoutContext->ExtraDataSize );
  558. if( !Buffer ){
  559. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  560. return(FALSE);
  561. }
  562. //We use Package to send across parameters to the Callback
  563. Package.Context = LayoutContext;
  564. Package.Callback = LayoutEnumCallback;
  565. Package.Param = Param;
  566. ret = pSetupStringTableEnum( LayoutContext->Context,
  567. Buffer,
  568. LayoutContext->ExtraDataSize,
  569. InternalEnumRoutine,
  570. (LPARAM) &Package);
  571. pSetupFree( Buffer );
  572. return( ret );
  573. }
  574. BOOL
  575. InternalEnumRoutine(
  576. IN PVOID StringTable,
  577. IN LONG StringId,
  578. IN PCTSTR String,
  579. IN PFILE_LAYOUTINFORMATION LayoutInfo,
  580. IN UINT LayoutInfoSize,
  581. IN LPARAM Param
  582. )
  583. /*
  584. This is the enum callback routine that we provide to setupapi. We
  585. in turn have to call the callers callback routine each time we are called.
  586. The callback routine of the caller is in Package.
  587. For now, we don't care about the StringID and don't tell the caller
  588. about it.
  589. */
  590. {
  591. PVOID ExtraData;
  592. UINT ExtraDataSize;
  593. PCALLBACK_PACKAGE Package = (PCALLBACK_PACKAGE)Param;
  594. BOOL ret;
  595. MYASSERT( Package->Callback );
  596. ExtraData = LayoutInfo+sizeof(FILE_LAYOUTINFORMATION);
  597. ExtraDataSize = LayoutInfoSize-(sizeof(FILE_LAYOUTINFORMATION));
  598. //BUGBUG : Should probably put this in a try/except block
  599. ret = Package->Callback( Package->Context,
  600. String,
  601. LayoutInfo,
  602. ExtraData,
  603. ExtraDataSize,
  604. Package->Param );
  605. //
  606. // If the user's callback returns false we stop enumeration. However the
  607. // toplevel EnumerateLayoutInf function still returns TRUE as it was not an
  608. // error in itself.
  609. //
  610. if( !ret ){
  611. SetLastError(ERROR_INVALID_PARAMETER);
  612. return( FALSE );
  613. }
  614. return( TRUE );
  615. }
  616. BOOL
  617. FindFileInLayoutInf(
  618. IN PLAYOUT_CONTEXT LayoutContext,
  619. IN PCTSTR Filename,
  620. OUT PFILE_LAYOUTINFORMATION LayoutInformation, OPTIONAL
  621. OUT PVOID ExtraData, OPTIONAL
  622. OUT PUINT ExtraDataSize, OPTIONAL
  623. OUT PMEDIA_INFO Media_Info OPTIONAL
  624. )
  625. /*
  626. This function finds the file information for a given filename inside a
  627. built layout context. It returns the layout information as well as the
  628. extra data (if any) associated with the file.
  629. Arguments:
  630. Context - Pointer to open LAYOUT_CONTEXT
  631. Filename - Specifies the filename to search for
  632. LayoutInformation - Pointer to caller supplied buffer that gets Layout Information for this file.
  633. ExtraData - Pointer to the a caller supplied buffer that gets ExtraData that the caller may have stored.
  634. ExtraDataSize - Size in bytes of the ExtraData returned.
  635. Media_Info - Pointer to MEDIA_INFO structure that will get filled
  636. with the file's corresponding Media information.
  637. Return value;
  638. TRUE if the file is found - False otherwise.
  639. */
  640. {
  641. PVOID Buffer;
  642. MEDIA_INFO TagInfo;
  643. PFILE_LAYOUTINFORMATION Temp;
  644. BOOL Err = TRUE;
  645. TCHAR filename[MAX_PATH];
  646. if( !LayoutContext ||
  647. !LayoutContext->Context ||
  648. !LayoutContext->ExtraDataSize ||
  649. !Filename){
  650. SetLastError( ERROR_INVALID_PARAMETER );
  651. return( FALSE );
  652. }
  653. lstrcpy( filename, Filename ); //To get around constness problem
  654. Buffer = pSetupMalloc( LayoutContext->ExtraDataSize );
  655. if( !Buffer ){
  656. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  657. return(FALSE);
  658. }
  659. if( pSetupStringTableLookUpStringEx( LayoutContext->Context,
  660. filename,
  661. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  662. Buffer,
  663. LayoutContext->ExtraDataSize) == -1 ){
  664. Err = FALSE;
  665. goto cleanup;
  666. }
  667. if( LayoutInformation )
  668. CopyMemory( LayoutInformation, Buffer, sizeof(FILE_LAYOUTINFORMATION));
  669. if( ExtraData ){
  670. CopyMemory( ExtraData,
  671. ((PFILE_LAYOUTINFORMATION)Buffer+sizeof(FILE_LAYOUTINFORMATION)),
  672. ((LayoutContext->ExtraDataSize)-(sizeof(FILE_LAYOUTINFORMATION))) );
  673. }
  674. if( ExtraDataSize )
  675. *ExtraDataSize = (LayoutContext->ExtraDataSize)-(sizeof(FILE_LAYOUTINFORMATION));
  676. //
  677. // Now get the Media Information for the file if needed
  678. //
  679. if( Media_Info ){
  680. Temp = (PFILE_LAYOUTINFORMATION)Buffer;
  681. if( pSetupStringTableLookUpStringEx( LayoutContext->MediaInfo[Temp->SectionIndex],
  682. Temp->Media_tagID,
  683. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE,
  684. Media_Info,
  685. sizeof(MEDIA_INFO)) == -1 ){
  686. _tprintf( TEXT("\nError - Could not get Media Info for tag %s\n"), Temp->Media_tagID);
  687. }
  688. }
  689. cleanup:
  690. if( Buffer )
  691. pSetupFree( Buffer );
  692. return Err;
  693. }
  694. BOOL
  695. CloseLayoutInfContext(
  696. IN PLAYOUT_CONTEXT LayoutContext)
  697. /*
  698. This function closes a Layout Inf Context and frees all memory
  699. associated with it.
  700. Arguments :
  701. LayoutContext - LayoutContext to close
  702. Return values :
  703. TRUE if it succeeds, else FALSE
  704. */
  705. {
  706. int i;
  707. if( !LayoutContext ){
  708. SetLastError( ERROR_INVALID_PARAMETER );
  709. return( FALSE );
  710. }else{
  711. if( LayoutContext->Context )
  712. pSetupStringTableDestroy( LayoutContext->Context );
  713. for( i=0; i<MAX_PLATFORMS; i++ ){
  714. if( LayoutContext->MediaInfo[i] )
  715. pSetupStringTableDestroy( LayoutContext->MediaInfo[i] );
  716. }
  717. pSetupFree( LayoutContext );
  718. }
  719. return TRUE;
  720. }
  721. VOID
  722. MyConcatenatePaths(
  723. IN OUT PTSTR Path1,
  724. IN LPCTSTR Path2,
  725. IN DWORD BufferSizeChars
  726. )
  727. /*++
  728. Routine Description:
  729. Concatenate two path strings together, supplying a path separator
  730. character (\) if necessary between the 2 parts.
  731. Arguments:
  732. Path1 - supplies prefix part of path. Path2 is concatenated to Path1.
  733. Path2 - supplies the suffix part of path. If Path1 does not end with a
  734. path separator and Path2 does not start with one, then a path sep
  735. is appended to Path1 before appending Path2.
  736. BufferSizeChars - supplies the size in chars (Unicode version) or
  737. bytes (Ansi version) of the buffer pointed to by Path1. The string
  738. will be truncated as necessary to not overflow that size.
  739. Return Value:
  740. None.
  741. --*/
  742. {
  743. BOOL NeedBackslash = TRUE;
  744. DWORD l;
  745. if(!Path1)
  746. return;
  747. l = lstrlen(Path1);
  748. if(BufferSizeChars >= sizeof(TCHAR)) {
  749. //
  750. // Leave room for terminating nul.
  751. //
  752. BufferSizeChars -= sizeof(TCHAR);
  753. }
  754. //
  755. // Determine whether we need to stick a backslash
  756. // between the components.
  757. //
  758. if(l && (Path1[l-1] == TEXT('\\'))) {
  759. NeedBackslash = FALSE;
  760. }
  761. if(Path2 && *Path2 == TEXT('\\')) {
  762. if(NeedBackslash) {
  763. NeedBackslash = FALSE;
  764. } else {
  765. //
  766. // Not only do we not need a backslash, but we
  767. // need to eliminate one before concatenating.
  768. //
  769. Path2++;
  770. }
  771. }
  772. //
  773. // Append backslash if necessary and if it fits.
  774. //
  775. if(NeedBackslash && (l < BufferSizeChars)) {
  776. lstrcat(Path1,TEXT("\\"));
  777. }
  778. //
  779. // Append second part of string to first part if it fits.
  780. //
  781. if(Path2 && ((l+lstrlen(Path2)) < BufferSizeChars)) {
  782. lstrcat(Path1,Path2);
  783. }
  784. return;
  785. }