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.

2028 lines
61 KiB

  1. @REM -----------------------------------------------------------------
  2. @REM
  3. @REM cddata.cmd - WadeLa, BPerkins
  4. @REM Reads inf files and generates file lists for postbuild
  5. @REM
  6. @REM Copyright (c) Microsoft Corporation. All rights reserved.
  7. @REM
  8. @REM -----------------------------------------------------------------
  9. @perl -x "%~f0" %*
  10. @goto :EOF
  11. #!perl
  12. #line 13
  13. use strict;
  14. use Carp;
  15. use File::Basename;
  16. use File::Copy;
  17. use IO::File;
  18. use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
  19. use lib $ENV{RAZZLETOOLPATH};
  20. use PbuildEnv;
  21. use ParseArgs;
  22. use Logmsg;
  23. use cksku;
  24. use A2U;
  25. use ReadSetupFiles;
  26. BEGIN {
  27. # A2u is setting itself as the script_name
  28. $ENV{SCRIPT_NAME} = 'cddata.cmd';
  29. }
  30. sub Usage { print<<USAGE; exit(1) }
  31. cddata [-f] [-c] [-d] [-x] [-g <search>] [-o <filename>] [-l <language>]
  32. -f Force list generation -- don't read old list
  33. -c Create CDFs
  34. -d Create CD lists (compression lists, link lists)
  35. -t Create exTension lists
  36. -x Don't truncate against bindiff file
  37. -g <search> Print to STDOUT or <Filename> the results
  38. of a search on the given input (see below)
  39. -o <filename> Send search output to the given filename
  40. -n Compare files found during the last full cddata creation
  41. with files expected from the dosnet.inf for each sku
  42. For the search command, valid expressions are:
  43. Field=xxx Return entries whose "Field" is exactly xxx
  44. Field?yyy Return entries whose "Field" contains yyy
  45. Field!zzz Return entries whose "Field" does not contain zzz
  46. Field1=xxx:Field2=yyy logically 'and's results
  47. Field names can be found in the keylist file
  48. USAGE
  49. # avoid search and replace for now, new template sets lang in the env.
  50. my $lang = $ENV{lang};
  51. # global switches/values set on the command line
  52. my ($ForceCreate, $CreateCDFs, $CreateLists, $CreateExtLists, $NoUseBindiff,
  53. $ArgSearchList, $OutputFile, $MakeDosnetChecks);
  54. parseargs('?' => \&Usage,
  55. 'f' => \$ForceCreate,
  56. 'c' => \$CreateCDFs,
  57. 'd' => \$CreateLists,
  58. 'x' => \$NoUseBindiff,
  59. 't' => \$CreateExtLists,
  60. 'g:'=> \$ArgSearchList,
  61. 'o:'=> \$OutputFile,
  62. 'n' => \$MakeDosnetChecks);
  63. # Global variables
  64. my( $TempDir );
  65. my( $Argument, $KeyFileName, $i );
  66. my( $nttree, $razpath );
  67. my( $Media, $DrmTxt, $Excludes, $Specsign, $Subdirs, $Layout, $LayoutTXT );
  68. my( $BigPrint, $BldArch, $AmX86 );
  69. my( @StructFields, %FieldLocations, @StructDefaults );
  70. my( %Hash, %RenameMap );
  71. my( $Key, @PrinterFiles, %Drmfiles );
  72. my( $Printer, $FieldName, @SearchPatterns, $SOperator, $SFieldName );
  73. my( $SFlagValue, $SearchHitCount, $FoundFlag, $SearchPattern );
  74. my( $BinDiffFile, $KeyFileName2, $IncFlag, $RootCdfDir);
  75. my( %CopyLocations );
  76. my( @AllSkus, @CDDataSKUs );
  77. my( @ConvertList );
  78. #
  79. # PROGRAM BEGINS
  80. #
  81. logmsg( "Beginning ..." );
  82. if ( !Main() ) {
  83. exit 1;
  84. }
  85. else {
  86. exit 0;
  87. }
  88. sub Main {
  89. $KeyFileName = "cddata.txt";
  90. # set up paths to important files
  91. $nttree = $ENV{ "_NTPostBld" };
  92. $razpath= $ENV{ "RazzleToolPath" };
  93. $TempDir = $ENV{ "TMP" };
  94. $Media = $nttree . "\\congeal\_scripts\\\_media.inx";
  95. $DrmTxt = $nttree . "\\congeal\_scripts\\drmlist.txt";
  96. $Excludes = $razpath . "\\PostBuildScripts\\exclude.lst";
  97. $Specsign = $razpath . "\\PostBuildScripts\\specsign.lst";
  98. $Subdirs = $razpath . "\\PostBuildScripts\\subdirs.lst";
  99. $Layout = $nttree . "\\congeal\_scripts\\layout.inx";
  100. $LayoutTXT = $nttree . "\\congeal\_scripts\\layout.txt";
  101. $BinDiffFile = $nttree . "\\build\_logs\\bindiff.txt";
  102. $RootCdfDir = "$TempDir\\CDFs";
  103. $BigPrint = $nttree . "\\ntprint.inf";
  104. # When adding additional skus remember to edit the functions
  105. # GetSkuIdLetter() and ReadSetupFiles::GetSetupDir()
  106. @AllSkus = qw(PRO PER SRV BLA SBS ADS DTC);
  107. # FUTURE: If we ever get rid of @AllSkus (good idea) should use cksku::GetSkus
  108. @CDDataSKUs = grep {cksku::CkSku($_, $lang, $ENV{_BuildArch})} @AllSkus;
  109. # All skus except PRO are based off another sku
  110. my %sku_hierarchy = ( PER => 'PRO',
  111. SRV => 'PRO',
  112. ADS => 'SRV',
  113. BLA => 'SRV',
  114. SBS => 'SRV',
  115. DTC => 'ADS' );
  116. # Remove the RootCdfDir
  117. # Why? Commenting this out for now -- if this goes away permanently remove
  118. # $RootCdfDir as this is the only place it is used (at least as of this comment)
  119. #system ( "if exist $RootCdfDir rd /s /q $RootCdfDir" );
  120. # Set IncFlag to false until we know otherwise
  121. undef $IncFlag;
  122. $BldArch = $ENV{ "\_BuildArch" };
  123. undef( $AmX86 );
  124. if ( ( $BldArch =~ /x86/i ) || ( $BldArch =~ /amd64/i ) || ( $BldArch =~ /ia64/i ) ) {
  125. $AmX86 = 1;
  126. }
  127. # enumerate fields
  128. # Signed -- am i catalog signed?
  129. # Prods -- what prods am i in? designated by letter ( pro=w, per=p, etc) - see GetSkuIdLetter()
  130. # Driver -- am i in driver.cab? i.e., did i come from an excdosnt?
  131. # Comp -- do i get compressed by default?
  132. # Print -- am i a printer?
  133. # Dosnet -- did i come from a dosnet?
  134. # Unicode -- do i get converted to unicode?
  135. # DrvIndex -- which drivercab am i in? designated by sku ID letter
  136. # DrmLevel -- am i drm encrypted?
  137. # Rename -- installed name (nul = no rename)
  138. # DoRename -- the file appears with its target name and needs renamed for the media
  139. #
  140. # Just to make things really confusing we decided to make d2
  141. # mean tablet files for x86 and wow files for 64-bit machines.
  142. # So we are going to stick with the trend and do things based
  143. # on architecture.
  144. # (x86) Tablet -- am i a Tablet PC File
  145. # (64) WOW -- am i a wow file
  146. #
  147. # also, see default settings for each of these fields just below.
  148. # CHANGEME
  149. @StructFields = ( "Signed", "Prods", "Driver", "Comp", "Print", "Dosnet",
  150. "Unicode", "DrvIndex", "DRMLevel", "Rename", "DoRename" );
  151. if ( 'x86' eq lc$BldArch ) {
  152. push @StructFields ,"TabletPC";
  153. }
  154. else {
  155. push @StructFields, "WOW";
  156. }
  157. %FieldLocations = ();
  158. for ( $i = 0; $i < @StructFields; $i++ ) {
  159. $FieldLocations{ $StructFields[ $i ] } = $i;
  160. }
  161. # create defaults
  162. @StructDefaults = ( "t", "nul", "f", "t", "f", "f", "f",
  163. "nul", "f", "nul", ,"f", "f"); # CHANGEME
  164. # see if we've already made our lists. if so, don't regen them.
  165. if ( ( ! ( defined( $ForceCreate ) ) ) &&
  166. ( -e "$TempDir\\$KeyFileName" ) ) {
  167. logmsg( "Reading previously created key list ..." );
  168. # read in the list instead of creating it
  169. if ( !ReadHashData( "$TempDir\\$KeyFileName" ) ) {
  170. return;
  171. }
  172. if ( -e $BinDiffFile &&
  173. 2 != HandleDiffFiles() ) {
  174. logmsg( "Writing keylist to $KeyFileName ..." );
  175. if ( !WriteHashData( "$TempDir\\$KeyFileName" ) ) {
  176. return;
  177. }
  178. }
  179. } else {
  180. # begin!
  181. undef( %Hash );
  182. undef( %CopyLocations );
  183. # Need to get these for all flavors as
  184. # this is a cumulative thing DTC = ADS + SRV + PRO
  185. # FUTURE: switch this to use @CDDataSKus and %sku_hierarchy
  186. foreach ( @AllSkus ) {
  187. AddDosnet( $_, $nttree );
  188. }
  189. foreach ( @CDDataSKUs ) {
  190. MarkExcDosnet( $_, $nttree );
  191. }
  192. # FUTURE: We could probably just pass @CDDataSKUs for these and be fine
  193. AddMedia( $Media, \@AllSkus );
  194. AddSpecsign( $Specsign, \@AllSkus );
  195. AddSubdirs( $Subdirs, \@AllSkus );
  196. # mark all driver files
  197. foreach ( @CDDataSKUs ) {
  198. AddDrvIndex( $_, $nttree );
  199. }
  200. # read in some info from layout (compressable, renamed)
  201. logmsg( "Marking all uncompressable and renamed entries ..." );
  202. # FUTURE: we should just read the layout entries from layout.inf.
  203. # This would get turned on now but I am not sure about
  204. # availability on intl builds (namely the unusual ones like CHH)
  205. # Plus it would be a bit slower.
  206. #foreach ( @CDDataSKUs ) {
  207. # AddLayout( $_, $nttree, \%sku_hierarchy );
  208. #}
  209. # FUTURE: This could likely be passed CDDataSKUs instead of ALLSkus
  210. # but then again we should just be using the code above...
  211. MarkLayoutAttributes( [$Layout, $LayoutTXT], \@AllSkus );
  212. SpecialExclusions();
  213. # at this point, we have all files from dosnet's excdosnt's and _media
  214. # now, if a key is in sedinf dir, add a listing for sedinf\key
  215. logmsg( "Adding keys for ". (join ", ", sort keys %sku_hierarchy). " ..." );
  216. # FUTURE: Using @AllSkus as we need to match what is in the hash and
  217. # we used it above -- can switch to @CDDataSKUs with above
  218. FindAllSkuSpecificFiles( \%Hash, $nttree, \%sku_hierarchy, \@AllSkus );
  219. # mark all printer keys
  220. logmsg( "Marking all printer entries ..." );
  221. # @PrinterFiles = `infflist.exe $BigPrint`;
  222. # the GetPrinterFiles subroutine will populate the @PrinterFiles array
  223. # in the same manner that calling infflist.exe would.
  224. GetPrinterFiles( $BigPrint );
  225. foreach $Printer ( @PrinterFiles ) {
  226. chomp( $Printer );
  227. if ( !$Printer ) { next; }
  228. ChangeSettings( $Printer, "Print=t" );
  229. }
  230. # Get the list of files to convert to unicode.
  231. @ConvertList = A2U::CdDataUpdate();
  232. foreach my $convertfile ( @ConvertList ) {
  233. ChangeSettings( $convertfile, "Unicode=t" );
  234. }
  235. #
  236. # Get the list of files with DRMLevel attributes
  237. #
  238. undef(%Drmfiles);
  239. GetDrmFiles( \%Drmfiles, $DrmTxt );
  240. foreach $Key ( sort keys %Drmfiles )
  241. {
  242. chomp $Key;
  243. if( !$Key ) { next; }
  244. ChangeSettings( $Key, "DRMLevel=$Drmfiles{$Key}" );
  245. }
  246. # WOW Files are not going to be found in the tree in the
  247. # following search and they will therefore be discarded
  248. # from the list, but we need to know which wow files
  249. # are compressed and which aren't so we will extract
  250. # that information here
  251. if ( 'x86' ne lc$BldArch ) {
  252. MakeWOWList($nttree) if $CreateLists;
  253. }
  254. # mark all unsigned keys and remove non-existent key/files:
  255. # unsigned files are printers, *.cat, and things in exclude.lst
  256. ExcludeSigning( $Excludes ); # must be done after subdirs.lst !!!
  257. logmsg( "Pruning entries and marking all unsignable entries ..." );
  258. foreach $Key ( keys( %Hash ) ) {
  259. my $fExists;
  260. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  261. $fExists = -e "$nttree\\". GetFlag( $Key, "Rename" );
  262. }
  263. else {
  264. $fExists = -e "$nttree\\$Key";
  265. }
  266. if ( !$fExists &&
  267. GetFlag( $Key, "Rename" ) ne "nul" &&
  268. -e "$nttree\\".GetFlag($Key, "Rename") ) {
  269. ChangeSettings( $Key, "DoRename=t" );
  270. }
  271. elsif ( !$fExists &&
  272. substr( $Key, -4, 4 ) ne ".cat" ) {
  273. delete( $Hash{ $Key } );
  274. }
  275. elsif ( GetFlag( $Key, "Print" ) eq "t" ||
  276. substr( $Key, -4, 4 ) eq ".cat" ) {
  277. ChangeSettings( $Key, "Signed=f" );
  278. }
  279. }
  280. # save off a copy of the full key file for bindiff.pl to cue off of
  281. if ( ( ! ( -e "$TempDir\\$KeyFileName.full" ) ) ||
  282. ( defined( $ForceCreate ) ) ) {
  283. logmsg( "Writing keylist to $KeyFileName.full ..." );
  284. if ( !WriteHashData( "$TempDir\\$KeyFileName.full" ) ) {
  285. return;
  286. }
  287. }
  288. if ( !copy("$TempDir\\$KeyFileName.full", "$nttree\\build_logs\\$KeyFileName.full") ) {
  289. errmsg ( "Error copying $TempDir\\$KeyFileName.full to $nttree\\build_logs\\$KeyFileName.full ($!)" );
  290. return;
  291. }
  292. if ( -e $BinDiffFile &&
  293. 2 != HandleDiffFiles() ) {
  294. logmsg( "Writing keylist to $KeyFileName ..." );
  295. if ( !WriteHashData( "$TempDir\\$KeyFileName" ) ) {
  296. return;
  297. }
  298. }
  299. else {
  300. logmsg( "Copying full list to $KeyFileName" );
  301. if ( !copy("$TempDir\\$KeyFileName.full", "$TempDir\\$KeyFileName" ) ) {
  302. errmsg ( "Error copying $TempDir\\$KeyFileName.full to $TempDir\\$KeyFileName ($!)" );
  303. return;
  304. }
  305. }
  306. # jeezuz! we're done! (Mike Carlson, v1)
  307. }
  308. if ( defined( $ArgSearchList ) ) {
  309. logmsg( "Search pattern is \'$ArgSearchList\' ..." );
  310. # user has asked to see a search on the hash
  311. if ( defined( $OutputFile ) ) {
  312. if ( open( OUTFILE, ">$OutputFile" ) ) {
  313. print( OUTFILE "; Results for search $ArgSearchList\n" );
  314. } else {
  315. errmsg( "Failed to open $OutputFile for writing ($!)." );
  316. undef( $OutputFile );
  317. }
  318. }
  319. @SearchPatterns = split( /\:/, $ArgSearchList );
  320. $SearchHitCount = 0;
  321. foreach $Key ( keys( %Hash ) ) {
  322. $FoundFlag = 1;
  323. foreach $SearchPattern ( @SearchPatterns ) {
  324. $SearchPattern =~ /^(\S*)([\=\?\!])(.*)$/;
  325. $SOperator = $2;
  326. $SFieldName = $1; $SFlagValue = $3;
  327. if ( $SOperator eq '=' &&
  328. GetFlag( $Key, $SFieldName ) ne $SFlagValue ) {
  329. undef $FoundFlag;
  330. } elsif ( $SOperator eq '?' &&
  331. GetFlag( $Key, $SFieldName ) !~ /$SFlagValue/ ) {
  332. undef $FoundFlag;
  333. } elsif ( $SOperator eq '!' &&
  334. GetFlag( $Key, $SFieldName ) =~ /\Q$SFlagValue\E/ ) {
  335. undef $FoundFlag;
  336. }
  337. }
  338. if ( $FoundFlag ) {
  339. $SearchHitCount++;
  340. if ( $OutputFile ) {
  341. print( OUTFILE "$Key = ". (join ":", map {(defined $Hash{$Key}->[$_])?$Hash{$Key}->[$_]:$StructDefaults[$_]} (0..$#StructFields)). "\n" );
  342. } else {
  343. print( "$Key = ". (join ":", map {(defined $Hash{$Key}->[$_])?$Hash{$Key}->[$_]:$StructDefaults[$_]} (0..$#StructFields)). "\n" );
  344. }
  345. }
  346. }
  347. if ( $OutputFile ) { close OUTFILE }
  348. logmsg( "Files found: $SearchHitCount" );
  349. }
  350. # now we can generate cdfs and any other lists we need
  351. MakeLists();
  352. # Generate extension lists for rebase/rebind
  353. MakeExtensionLists() if (!$IncFlag || $CreateExtLists);
  354. if ( $MakeDosnetChecks ) {
  355. logmsg( "Reading in full cddata for dosnet checks ..." );
  356. if ( !ReadHashData("$TempDir\\$KeyFileName.full") ) {
  357. return;
  358. }
  359. CheckDosnet( $nttree, $_, \%sku_hierarchy ) foreach (@CDDataSKUs);
  360. }
  361. logmsg( "Finished." );
  362. return 1;
  363. }
  364. # <Implement your subs here>
  365. sub ReadHashData
  366. {
  367. my $infile = shift;
  368. if ( !open INFILE, $infile ) {
  369. errmsg( "Failed to parse old keylist.txt ($!)." );
  370. return;
  371. }
  372. my @KeyListLines = <INFILE>;
  373. close INFILE;
  374. # Clear global hash
  375. undef( %Hash );
  376. my $KeyListLine;
  377. foreach $KeyListLine ( @KeyListLines ) {
  378. chomp $KeyListLine;
  379. if ( !$KeyListLine ||
  380. $KeyListLine =~ /^;/ ) { next; }
  381. # <filename> = a:bbbb:c:d:e:f
  382. $KeyListLine =~ /^(\S*)( = )(.*)$/;
  383. my ($KeyFileName2, $KeyValues) = ($1, $3);
  384. my @TheseSettings = split( /\:/, $KeyValues );
  385. my $CurSet = join ":", map { "$StructFields[$_]=$TheseSettings[$_]" } (0..$#StructFields);
  386. NewSettings( $KeyFileName2, $CurSet );
  387. }
  388. return 1;
  389. }
  390. sub WriteHashData
  391. {
  392. my $outfile = shift;
  393. if ( !open OUTFILE, ">$outfile" ) {
  394. errmsg( "Failed to open $outfile for writing ($!)." );
  395. return;
  396. }
  397. print( OUTFILE "; Fields are listed as follows:\n; " );
  398. #old output began with a space so just in case here is a backup method
  399. #print OUTFILE map { " $_" } @StructFields;
  400. print OUTFILE (join " ", @StructFields). "\n";
  401. foreach $Key ( keys( %Hash ) ) {
  402. print OUTFILE "$Key = ". (join ":", map {(defined $Hash{$Key}->[$_])?$Hash{$Key}->[$_]:$StructDefaults[$_]} (0..$#StructFields)). "\n";
  403. }
  404. close OUTFILE;
  405. return 1;
  406. }
  407. #
  408. # Function:
  409. # GetSkuIdLetter
  410. #
  411. # Arguments:
  412. #
  413. # Sku (scalar) - sku to return single-letter ID for
  414. #
  415. # Purpose:
  416. # Returns the letter used by cddata to identify the sku
  417. # per=p, pro=w, bla=b, sbs=l, srv=s, ads=e, dtc=d
  418. #
  419. # Returns:
  420. # String representing setup dir
  421. # UNDEF on failure
  422. sub GetSkuIdLetter
  423. {
  424. my $Sku = lc$_[0];
  425. my %id = ( per => 'p',
  426. pro => 'w',
  427. bla => 'b',
  428. sbs => 'l',
  429. srv => 's',
  430. ads => 'e',
  431. dtc => 'd' );
  432. if ( exists $id{$Sku} ) {
  433. return $id{$Sku};
  434. }
  435. else {
  436. # Unrecognized SKU
  437. return;
  438. }
  439. }
  440. sub FindAllSkuSpecificFiles
  441. {
  442. my $file_info = shift;
  443. my $root_path = shift;
  444. my $sku_hierarchy = shift;
  445. my $all_skus = shift;
  446. my %processed_skus;
  447. my $fFail;
  448. foreach ( keys %$sku_hierarchy )
  449. {
  450. if ( !FindSkuSpecificFiles( $_,
  451. $file_info,
  452. $root_path,
  453. $sku_hierarchy,
  454. $all_skus,
  455. \%processed_skus ) )
  456. {
  457. $fFail++;
  458. }
  459. }
  460. if ( $fFail )
  461. {
  462. return;
  463. }
  464. else
  465. {
  466. return 1;
  467. }
  468. }
  469. sub FindSkuSpecificFiles
  470. {
  471. my $sku = shift;
  472. # Not going to use this right now as ChangeSettings() and NewSettings()
  473. # both reference the global hash, and this would just be confusing aliasing
  474. my $file_info = shift;
  475. my $root_path = shift;
  476. my $sku_hierarchy = shift;
  477. my $all_skus = shift;
  478. my $processed_skus = shift;
  479. # reference sku in uppercase
  480. $sku = uc$sku;
  481. # If we are a base, don't do anything
  482. if ( !exists $sku_hierarchy->{$sku} )
  483. {
  484. return 1;
  485. }
  486. # if we have already been called we are done
  487. elsif ( exists $processed_skus->{$sku} )
  488. {
  489. return 1;
  490. }
  491. # Reverse the hierarchy list to find out who is dependent on us
  492. my %dependents = map{ lc$_ => 1 } GetDependentSkus( $sku, $sku_hierarchy );
  493. # Make sure any dependent skus have had a chance to be processed before us.
  494. # This is so that they pickup files closest to them before taking our closest ones
  495. foreach ( keys %dependents )
  496. {
  497. if ( !exists $processed_skus->{$_} )
  498. {
  499. if ( !FindSkuSpecificFiles( $_,
  500. $file_info,
  501. $root_path,
  502. $sku_hierarchy,
  503. $all_skus,
  504. $processed_skus ) )
  505. {
  506. return;
  507. }
  508. }
  509. }
  510. my $removeRelatedSkus = join ":", map {"Prods-". GetSkuIdLetter($_)} ($sku, keys %dependents);
  511. my $removeUnrelatedSkus = join ":", map {"Prods-". GetSkuIdLetter($_)} grep {lc$sku ne lc$_ && !exists $dependents{lc$_}} @$all_skus;
  512. # Need to know where to look for sku-specific files
  513. my $sku_dir = ReadSetupFiles::GetSetupDir( $sku );
  514. # ASSERT
  515. if ( '.' eq $sku_dir ) { croak "$sku is returning the base directory as its directory" }
  516. my $path = $root_path . ($root_path !~ /\\$/?'\\':''). $sku_dir;
  517. # Get a list of all files under sku path
  518. my @sku_files = map {chomp; s/^\Q$path\E\\//i; lc$_} `dir /s/b/a-d "$path\\"`;
  519. my $file;
  520. foreach $file ( @sku_files )
  521. {
  522. my $frename;
  523. if ( !exists $Hash{$file} ) {
  524. # If we match the name of a target-rename file, then
  525. # just switch our name to the one that appears in dosnet
  526. if ( !exists $RenameMap{$file} ) {
  527. next;
  528. }
  529. else {
  530. $file = $RenameMap{$file};
  531. $frename = 1;
  532. }
  533. }
  534. # inherit properties from original entry
  535. my $copy = $Hash{$file}; my @copy = @$copy;
  536. $Hash{ "$sku_dir\\$file" } = \@copy;
  537. # remove skus from our new entry that are unrelated to our sku
  538. ChangeSettings( "$sku_dir\\$file", $removeUnrelatedSkus. ($frename?":DoRename=t":"") );
  539. # If we are left with nothing, remove the new key
  540. if ( GetFlag( "$sku_dir\\$file", "Prods" ) eq "nul" ) {
  541. delete $Hash{ "$sku_dir\\$file" };
  542. }
  543. # remove our sku and all of our dependent skus from the original entry
  544. # as we are now all going to use this newly found file/key
  545. ChangeSettings( $file, $removeRelatedSkus );
  546. # If nobody is now using the original key, remove it
  547. if ( GetFlag( $file, "Prods" ) eq "nul" ) { delete( $Hash{ $file } ); }
  548. }
  549. # This sku was successfully processed
  550. $processed_skus->{$sku} = 1;
  551. return 1;
  552. }
  553. sub GetDependentSkus
  554. {
  555. my $sku = shift;
  556. my $sku_hierarchy = shift;
  557. my @dependents;
  558. foreach ( keys %$sku_hierarchy )
  559. {
  560. if ( uc$sku eq $sku_hierarchy->{$_} )
  561. {
  562. push @dependents, $_;
  563. push @dependents, GetDependentSkus($_, $sku_hierarchy);
  564. }
  565. }
  566. return @dependents;
  567. }
  568. sub GetSkuSearchPaths
  569. {
  570. my $sku = shift;
  571. my $root_path = shift;
  572. my $sku_hierarchy = shift;
  573. return map{"$root_path". ($root_path !~ /\\$/?"\\":""). $_} GetSkuOrderedLayers($sku, $sku_hierarchy);
  574. }
  575. sub GetSkuOrderedLayers
  576. {
  577. my $sku = shift;
  578. my $sku_hierarchy = shift;
  579. my @layers = ( ReadSetupFiles::GetSetupDir( $sku ) );
  580. if ( exists $sku_hierarchy->{uc$sku} )
  581. {
  582. push @layers, GetSkuOrderedLayers( $sku_hierarchy->{uc$sku}, $sku_hierarchy );
  583. }
  584. return @layers;
  585. }
  586. sub AddDosnet
  587. {
  588. my( $Sku, $RootPath ) = @_;
  589. my( $File, @Files, @SecondaryFiles );
  590. my( $StructSettings );
  591. logmsg( "Adding files in $Sku dosnet ..." );
  592. if ( !ReadSetupFiles::ReadDosnet( $RootPath,
  593. $Sku,
  594. $BldArch,
  595. \@Files,
  596. \@SecondaryFiles ) ) {
  597. errmsg( "Can't add $Sku dosnet files to hash." );
  598. return;
  599. }
  600. $StructSettings = "Dosnet=t:Prods+". GetSkuIdLetter($Sku);
  601. foreach $File ( @Files ) {
  602. $File = lc$File;
  603. if ( exists $Hash{ $File } ) {
  604. ChangeSettings( $File, $StructSettings );
  605. } else {
  606. NewSettings( $File, $StructSettings );
  607. }
  608. }
  609. # WOW vs TabletPC secondary files
  610. if ( 'x86' eq lc$BldArch ) {
  611. $StructSettings .= ":TabletPC=t";
  612. }
  613. else {
  614. $StructSettings .= ":WOW=t";
  615. }
  616. foreach $File ( @SecondaryFiles ) {
  617. $File = lc$File;
  618. if ( exists $Hash{ $File } ) {
  619. ChangeSettings( $File, $StructSettings );
  620. } else {
  621. NewSettings( $File, $StructSettings );
  622. }
  623. }
  624. return 1;
  625. }
  626. sub MarkExcDosnet
  627. {
  628. my( $Sku, $RootPath ) = @_;
  629. my( $File, @Files );
  630. my( $StructSettings );
  631. logmsg( "Adding files in $Sku excdosnt ..." );
  632. if ( !ReadSetupFiles::ReadExcDosnet( $RootPath,
  633. $Sku,
  634. \@Files ) ) {
  635. errmsg( "Can't add $Sku excdosnt files to hash." );
  636. return;
  637. }
  638. $StructSettings = "Driver=t:Dosnet=f:Comp=f:Prods+". GetSkuIdLetter($Sku);
  639. foreach $File ( @Files ) {
  640. $File = lc$File;
  641. if ( exists $Hash{ $File } ) {
  642. ChangeSettings( $File, $StructSettings );
  643. } else { # following old behavior -- there shouldn't be any files to add here
  644. NewSettings( $File, $StructSettings );
  645. }
  646. }
  647. }
  648. sub AddMedia
  649. {
  650. my( $MediaPath, $MarkSkus ) = @_;
  651. my( $File, %FileHash, @MediaLines );
  652. my( $StructSettings, $Uncomp );
  653. logmsg( "Adding files in $MediaPath ..." );
  654. unless ( open MEDIA, $MediaPath ) {
  655. errmsg( "Failed to open $MediaPath ($!)" );
  656. return;
  657. }
  658. @MediaLines = <MEDIA>;
  659. close MEDIA;
  660. # Can use the layout parser to read the media file
  661. if ( !ReadSetupFiles::ParseLayoutFile( \@MediaLines,
  662. $BldArch,
  663. \%FileHash ) ) {
  664. errmsg( "Can't add $MediaPath files to hash." )
  665. }
  666. $StructSettings = "Prods=" . (join '', map {GetSkuIdLetter($_)} @$MarkSkus);
  667. foreach $File ( keys %FileHash ) {
  668. $Uncomp = $FileHash{$File}{BootMediaOrd} =~ /^_/;
  669. $File = lc$File;
  670. if ( exists $Hash{ $File } ) {
  671. ChangeSettings( $File, $StructSettings. ($Uncomp?":Comp=f":"") );
  672. } else {
  673. NewSettings( $File, $StructSettings. ($Uncomp?":Comp=f":"") );
  674. }
  675. }
  676. return 1;
  677. }
  678. sub ChangeSettings
  679. {
  680. my( $File, $StructSettings ) = @_;
  681. my( @Requests, $Request );
  682. my( $FldLoc, $Operator, $SetVal );
  683. if ( !$File ) { return; }
  684. $File = lc$File;
  685. if ( ! exists $Hash{ $File } ) { return; }
  686. @Requests = split( /\:/, $StructSettings );
  687. foreach $Request ( @Requests ) {
  688. if ( $Request !~ /^(\w+)([\=\+\-]{1})(\S+|".*")$/ ) {
  689. wrnmsg( "Invalid settings specified for $File ($Request)" );
  690. next;
  691. }
  692. $FldLoc = $FieldLocations{ $1 };
  693. $Operator = $2; $SetVal = $3;
  694. # look for a "="
  695. if ( $Operator eq "\?" ) { next; }
  696. if ( $Operator eq "\=" ) {
  697. # set the field explicitly
  698. $Hash{$File}->[$FldLoc] = $SetVal;
  699. }
  700. # look for a "+"
  701. elsif ( $Operator eq "\+" ) {
  702. # add the field to the list if not there
  703. if ( !defined $Hash{$File}->[ $FldLoc ] ||
  704. $Hash{$File}->[ $FldLoc ] !~ /$SetVal/ ) {
  705. $Hash{$File}->[ $FldLoc ] .= $SetVal;
  706. }
  707. }
  708. # look for a "-"
  709. elsif ( ( $Operator eq "\-" ) && ( defined $Hash{$File}->[ $FldLoc ] ) ) {
  710. # sub the field from the list if there
  711. $Hash{$File}->[ $FldLoc ] =~ s/$SetVal//;
  712. if ( !$Hash{$File}->[ $FldLoc ] ) {
  713. undef $Hash{$File}->[ $FldLoc ];
  714. }
  715. }
  716. # If we have changed the value to match the default, undef it
  717. if ( defined $Hash{$File}->[$FldLoc] &&
  718. $Hash{$File}->[$FldLoc] eq $StructDefaults[$FldLoc] ) {
  719. undef $Hash{$File}->[$FldLoc];
  720. }
  721. }
  722. return 1;
  723. }
  724. sub NewSettings
  725. {
  726. my( $File, $StructSettings ) = @_;
  727. $File = lc$File;
  728. my @newEntry = map {undef} (1..@StructFields);
  729. $Hash{ $File } = \@newEntry;
  730. $StructSettings =~ s/\?/\=/g;
  731. return ChangeSettings( $File, $StructSettings );
  732. }
  733. sub AddSpecsign
  734. {
  735. my( $SpecFile, $AllSkus ) = @_;
  736. my( @SpecLines, $Line );
  737. logmsg( "Adding files in $SpecFile ..." );
  738. unless ( open( INFILE, $SpecFile ) ) {
  739. errmsg( "Failed to open $SpecFile ($!)." );
  740. return( undef );
  741. }
  742. my $StructSettings = "Signed=t";
  743. @SpecLines = <INFILE>;
  744. close( INFILE );
  745. foreach $Line ( @SpecLines ) {
  746. chomp( $Line );
  747. if ( !$Line ||
  748. substr( $Line, 0, 1 ) eq ";" ) { next; }
  749. # add file with defaults to hash
  750. $Line = lc$Line;
  751. if ( exists( $Hash{ $Line } ) ) {
  752. ChangeSettings( $Line, $StructSettings );
  753. } else {
  754. NewSettings( $Line, $StructSettings. ":Comp=f" );
  755. }
  756. }
  757. return 1;
  758. }
  759. sub AddSubdirs
  760. {
  761. my( $SubdirsFile, $AllSkus ) = @_;
  762. my( @DirsLines, $Line, $SubName );
  763. my( $DirName, $IsRecursive, @DirList, $TreeLen );
  764. logmsg( "Adding files in $SubdirsFile ..." );
  765. unless ( open( INFILE, $SubdirsFile ) ) {
  766. errmsg( "Failed to open $SubdirsFile ($!)." );
  767. return;
  768. }
  769. my $StructSettings = "Signed=t:Prods=". (join '', map{ GetSkuIdLetter($_) } @$AllSkus);
  770. @DirsLines = <INFILE>;
  771. close( INFILE );
  772. $TreeLen = length( $nttree ) + 1;
  773. foreach $Line ( @DirsLines ) {
  774. chomp( $Line );
  775. if ( !$Line || substr( $Line, 0, 1 ) eq ";" ) {
  776. next;
  777. }
  778. ( $DirName, $IsRecursive ) = split( /\s+/, $Line );
  779. if ( ! ( -d "$nttree\\$DirName" ) ) {
  780. wrnmsg( "Directory '$DirName' from subdirs.lst does not exist -- skipping" );
  781. next;
  782. }
  783. if ( defined( $IsRecursive ) ) {
  784. @DirList = `dir /a-d /b /s $nttree\\$DirName`;
  785. } else {
  786. @DirList = `dir /a-d /b $nttree\\$DirName`;
  787. }
  788. foreach $SubName ( @DirList ) {
  789. chomp( $SubName );
  790. if ( defined( $IsRecursive ) ) {
  791. $SubName = substr( $SubName, $TreeLen );
  792. } else {
  793. $SubName = "$DirName\\" . $SubName;
  794. }
  795. $SubName = lc$SubName;
  796. if ( !$SubName ) { next; }
  797. if ( exists( $Hash{ $SubName } ) ) {
  798. ChangeSettings( $SubName, $StructSettings. ($DirName eq "lang"?":Comp=t":"") );
  799. } else {
  800. NewSettings( $SubName, $StructSettings. ($DirName eq "lang"?":Comp=t":":Comp=f") );
  801. }
  802. }
  803. }
  804. return 1;
  805. }
  806. sub AddLayout
  807. {
  808. my( $Sku, $RootPath, $SkuHierarchy ) = @_;
  809. my( $File, %FileHash );
  810. my( $StructSettings );
  811. logmsg( "Adding files in $Sku layout ..." );
  812. if ( !ReadSetupFiles::ReadLayout( $RootPath,
  813. $Sku,
  814. $BldArch,
  815. \%FileHash ) ) {
  816. errmsg( "Can't add $Sku layout files to hash." );
  817. return;
  818. }
  819. my @searchKeys = GetSkuOrderedLayers( $Sku, $SkuHierarchy );
  820. foreach $File ( keys %FileHash ) {
  821. my $FileInfo = $FileHash{$File};
  822. my @Settings;
  823. # Mark uncompressed files
  824. if ( $FileInfo->{BootMediaOrd} =~ /^_/ ) {
  825. push @Settings, "Comp=f";
  826. }
  827. # Add rename information
  828. if ( $FileInfo->{TargetName} ) {
  829. push @Settings, "Rename=$FileInfo->{TargetName}";
  830. }
  831. if ( @Settings ) {
  832. foreach ( @searchKeys ) {
  833. # Update the key we will be using in construction of our SKU
  834. if ( ChangeSettings( ($_ ne "."?"$_\\":"").lc$File, join ":", @Settings ) ) {
  835. last;
  836. }
  837. }
  838. }
  839. }
  840. return 1;
  841. }
  842. sub MarkLayoutAttributes
  843. {
  844. my( $ConcatFiles, $AllSkus ) = @_;
  845. my( $File, %FileHash );
  846. my( $StructSettings );
  847. my @LayoutLines;
  848. foreach ( @$ConcatFiles ) {
  849. unless ( open( INFILE, $_ ) ) {
  850. errmsg( "Failed to open $_ ($!)." );
  851. return;
  852. }
  853. push @LayoutLines, <INFILE>;
  854. close INFILE;
  855. }
  856. if ( !ReadSetupFiles::ParseLayoutFile( \@LayoutLines,
  857. $BldArch,
  858. \%FileHash ) ) {
  859. errmsg( "Failed adding info from ". (join ", ", @$ConcatFiles) ." to hash." );
  860. return;
  861. }
  862. foreach $File ( keys %FileHash ) {
  863. my $FileInfo = $FileHash{$File};
  864. my $FileName = lc$File;
  865. my @Settings;
  866. $FileName =~ s/.*://; # remove possible @x:@x: tags
  867. # Mark uncompressed files
  868. if ( $FileInfo->{BootMediaOrd} =~ /^_/ ) {
  869. push @Settings, "Comp=f";
  870. }
  871. # Add rename information
  872. if ( $FileInfo->{TargetName} ) {
  873. my $rename_file = $FileInfo->{TargetName};
  874. push @Settings, "Rename=$rename_file";
  875. $rename_file =~ s/"//g;
  876. $RenameMap{lc$rename_file} = $FileName;
  877. }
  878. if ( @Settings ) {
  879. ChangeSettings( $FileName, join ":", @Settings );
  880. }
  881. }
  882. return 1;
  883. }
  884. sub ExcludeSigning
  885. {
  886. my( $ExcFile ) = @_;
  887. my( @ExcLines, $Line );
  888. unless ( open( INFILE, $ExcFile ) ) {
  889. errmsg( "Failed to open $ExcFile ($!)." );
  890. return;
  891. }
  892. @ExcLines = <INFILE>;
  893. close( INFILE );
  894. foreach $Line ( @ExcLines ) {
  895. chomp( $Line );
  896. if ( !$Line || substr( $Line, 0, 1 ) eq ";" ) {
  897. next;
  898. }
  899. ChangeSettings( $Line, "Signed=f" );
  900. }
  901. return 1;
  902. }
  903. sub GetFlag
  904. {
  905. my( $Key, $FieldFlag ) = @_;
  906. my( @FieldList );
  907. if ( !exists $Hash{$Key} ) { carp "Attempting to lookup info for invalid key $Key" }
  908. if ( !exists $FieldLocations{ $FieldFlag } ) { carp "Attempting to lookup invalid value '$FieldFlag'" }
  909. my $FldLoc = $FieldLocations{ $FieldFlag };
  910. return (defined $Hash{$Key}->[$FldLoc])?$Hash{$Key}->[$FldLoc]:$StructDefaults[$FldLoc];
  911. }
  912. sub MakeInfCdf
  913. {
  914. my( $Skus ) = @_;
  915. my( $Key, $Flags );
  916. my ( $CdfExt );
  917. my $DrmLevel = "ATTR1=0x10010001:DRMLevel:";
  918. if ( $IncFlag ) { $CdfExt = ".icr"; }
  919. else { $CdfExt = ".cdf"; }
  920. logmsg( "Generating nt5inf$CdfExt for ". (join ', ', @$Skus). " ..." );
  921. my %SkuInfo; # sku_id, file_handle, temp_dir
  922. for ( $i = 0; $i < @$Skus; $i++ ) {
  923. my $CdfDir;
  924. my $SkuName = lc$Skus->[$i];
  925. my $SkuSubDir = ReadSetupFiles::GetSetupDir( $SkuName );
  926. my $fh;
  927. $CdfDir = "$TempDir\\CDFs". ( $SkuSubDir ne '.'?"\\$SkuSubDir":"" );
  928. system( "if not exist $CdfDir md $CdfDir" );
  929. # Open the CDF files for writing
  930. $fh = new IO::File ">$CdfDir\\nt5inf$CdfExt";
  931. if ( !defined $fh ) {
  932. errmsg( "Unable to open $CdfDir\\nt5inf$CdfExt for writing ($!)." );
  933. foreach (keys %SkuInfo) {$SkuInfo{$_}->[1]->close() if defined $SkuInfo{$_}->[1]}
  934. return;
  935. }
  936. $SkuInfo{$SkuName} = [lc GetSkuIdLetter($SkuName), $fh, $CdfDir];
  937. }
  938. my $AllProductTags = join '', sort map {lc GetSkuIdLetter($_)} @AllSkus;
  939. if ( !$IncFlag ) {
  940. # put in CDF header crap
  941. my $header = join "\n", ( "[CatalogHeader]",
  942. "Name=nt5inf",
  943. "PublicVersion=0x0000001",
  944. "EncodingType=0x00010001",
  945. "CATATTR1=0x10010001:OSAttr:2:5.2",
  946. "",
  947. "[CatalogFiles]" );
  948. $_->print("$header\n") foreach map {$SkuInfo{$_}->[1]} (keys %SkuInfo);
  949. }
  950. foreach $Key ( keys( %Hash ) ) {
  951. $Flags = lc GetFlag( $Key, "Prods" );
  952. if ( $Flags eq 'nul' ) {next}
  953. # Sort sku ids so we can compare with an entry matching all skus
  954. $Flags = join '', sort split '', $Flags;
  955. if ( $Flags ne $AllProductTags &&
  956. GetFlag( $Key, "Signed" ) eq "t" ) {
  957. my $path;
  958. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  959. $path = "$nttree\\".GetFlag( $Key, "Rename" );
  960. }
  961. else {
  962. $path = "$nttree\\$Key";
  963. }
  964. my $Sku;
  965. foreach $Sku ( keys %SkuInfo ) {
  966. my $ProductTag = $SkuInfo{$Sku}->[0];
  967. if ( $Flags =~ /$ProductTag/ ) {
  968. if ( !$IncFlag ) {
  969. $SkuInfo{$Sku}->[1]->print( "<hash>$path=$path\n" );
  970. $SkuInfo{$Sku}->[1]->print( "<hash>$path$DrmLevel", GetFlag( $Key, "DRMLevel" ), "\n" ) if( GetFlag( $Key, "DRMLevel" ) ne "f" );
  971. }
  972. else {
  973. $SkuInfo{$Sku}->[1]->print( "$path\n" );
  974. }
  975. }
  976. }
  977. }
  978. }
  979. # special exemptions
  980. # mark the wks layout.inf as signed in the srv nt5inf.cdf
  981. if ( exists $SkuInfo{'srv'} ) {
  982. if ( !$IncFlag ) {
  983. $SkuInfo{'srv'}->[1]->print( "<hash>$nttree\\layout.inf=$nttree\\layout.inf\n" );
  984. }
  985. elsif ( exists $Hash{ "srvinf\\layout.inf" } ) {
  986. $SkuInfo{'srv'}->[1]->print( "$nttree\\layout.inf\n" );
  987. }
  988. }
  989. close $SkuInfo{$_}->[1] foreach ( keys %SkuInfo );
  990. # copy the CDF to the build_logs for intl
  991. my( $BaseCopyDir ) = "$nttree\\build_logs\\cdfs";
  992. mkdir( $BaseCopyDir, 0777 ) if ( ! -d $BaseCopyDir );
  993. foreach ( keys %SkuInfo ) {
  994. if ( !copy($SkuInfo{$_}->[2]."\\nt5inf$CdfExt", "$BaseCopyDir\\nt5".$SkuInfo{$_}->[0]."inf$CdfExt" ) ) {
  995. wrnmsg( "Failed to copy nt5inf.cdf for $_ into the build ($!) ..." );
  996. }
  997. }
  998. }
  999. sub MakeMainCdfs
  1000. {
  1001. my( $CdfName, $PrtName ) = @_;
  1002. my( $Key, $Flags, $DrmLevel );
  1003. my ( $CdfExt );
  1004. $DrmLevel = "ATTR1=0x10010001:DRMLevel:";
  1005. if ( $IncFlag ) { $CdfExt = ".icr"; }
  1006. else { $CdfExt = ".cdf"; }
  1007. logmsg( "Generating $CdfName$CdfExt and $PrtName$CdfExt ..." );
  1008. system( "if not exist $TempDir\\CDFs md $TempDir\\CDFs" );
  1009. unless ( open( CDF, ">$TempDir\\CDFs\\$CdfName$CdfExt" ) ) {
  1010. errmsg( "Unable to open $CdfName$CdfExt for writing ($!)." );
  1011. return;
  1012. }
  1013. unless ( open( PRINTER, ">$TempDir\\CDFs\\$PrtName$CdfExt" ) ) {
  1014. errmsg( "Unable to open $PrtName$CdfExt for writing ($!)." );
  1015. close( CDF );
  1016. return;
  1017. }
  1018. my $AllProductTags = join '', sort map {GetSkuIdLetter($_)} @AllSkus;
  1019. if ( !$IncFlag ) {
  1020. foreach( "\[CatalogHeader\]",
  1021. "Name=$CdfName",
  1022. "PublicVersion=0x0000001",
  1023. "EncodingType=0x00010001",
  1024. "CATATTR1=0x10010001:OSAttr:2:5.2",
  1025. "",
  1026. "\[CatalogFiles\]" ) {
  1027. print CDF "$_\n";
  1028. }
  1029. foreach( "\[CatalogHeader\]",
  1030. "Name=$PrtName",
  1031. "PublicVersion=0x0000001",
  1032. "EncodingType=0x00010001",
  1033. "CATATTR1=0x10010001:OSAttr:2:5.0,2:5.1,2:5.2",
  1034. "",
  1035. "\[CatalogFiles\]" ) {
  1036. print PRINTER "$_\n";
  1037. }
  1038. }
  1039. foreach $Key ( keys( %Hash ) ) {
  1040. $Flags = GetFlag( $Key, "Prods" );
  1041. # Sort sku ids so we can compare with an entry matching all skus
  1042. if ( "nul" ne $Flags ) { $Flags = join '', sort split '', $Flags }
  1043. if ( ($Flags eq $AllProductTags || $Flags eq "nul") &&
  1044. GetFlag( $Key, "Signed" ) eq "t" )
  1045. {
  1046. my $path;
  1047. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  1048. $path = "$nttree\\".GetFlag( $Key, "Rename" );
  1049. }
  1050. else {
  1051. $path = "$nttree\\$Key";
  1052. }
  1053. if ( !$IncFlag ) {
  1054. print CDF "<hash>$path=$path\n";
  1055. print (CDF "<hash>$path$DrmLevel", GetFlag( $Key, "DRMLevel" ), "\n" ) if( GetFlag( $Key, "DRMLevel" ) ne "f" );
  1056. }
  1057. else {
  1058. print CDF "$path\n";
  1059. }
  1060. }
  1061. if ( GetFlag( $Key, "Print" ) eq "t" ) {
  1062. my $path;
  1063. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  1064. $path = "$nttree\\".GetFlag( $Key, "Rename" );
  1065. }
  1066. else {
  1067. $path = "$nttree\\$Key";
  1068. }
  1069. if ( !$IncFlag ) {
  1070. print PRINTER "<hash>$path=$path\n";
  1071. }
  1072. else {
  1073. print PRINTER "$path\n";
  1074. }
  1075. }
  1076. }
  1077. close CDF;
  1078. close PRINTER;
  1079. # copy the cdfs for intl
  1080. my( $BaseCopyDir ) = "$nttree\\build_logs\\cdfs";
  1081. mkdir( $BaseCopyDir, 0777 ) if ( ! -d $BaseCopyDir );
  1082. if ( !copy("$TempDir\\CDFs\\$CdfName$CdfExt", $BaseCopyDir ) ) {
  1083. wrnmsg( "Failed to copy nt5.cdf into the build ($!) ..." );
  1084. }
  1085. if ( !copy("$TempDir\\CDFs\\$PrtName$CdfExt", $BaseCopyDir ) ) {
  1086. wrnmsg( "Failed to copy $PrtName.cdf into the build ($!) ..." );
  1087. }
  1088. }
  1089. sub MakeProdLists
  1090. {
  1091. my( $Skus ) = @_;
  1092. my( $Key, $CompName );
  1093. logmsg( "Generating product lists for ". (join ', ', @$Skus). " ..." );
  1094. # SkuInfo array members:
  1095. # 0 - sku id letter
  1096. # 1 - (handle) all files
  1097. # 2 - (handle) compressed files
  1098. # 3 - (handle) uncompressed files
  1099. # 4 - (handle) all files from subdirectories
  1100. # 5 - (handle) compressed files from subdirectories
  1101. # 6 - (handle) uncompressed files from subdirectories
  1102. my %SkuInfo;
  1103. for ( $i = 0; $i < @$Skus; $i++ ) {
  1104. my $SkuName = lc$Skus->[$i];
  1105. $SkuInfo{$SkuName} = [lc GetSkuIdLetter($SkuName)];
  1106. # Open the log files for writing
  1107. my $offHandle = 1;
  1108. foreach ( "", "comp", "uncomp", "sub", "subcomp", "subuncomp" ) {
  1109. $SkuInfo{$SkuName}->[$offHandle] = new IO::File ">$TempDir\\$SkuName$_.lst";
  1110. if ( !defined $SkuInfo{$SkuName}->[$offHandle] ) {
  1111. errmsg( "Unable to open $TempDir\\$SkuName$_.lst for writing ($!)." );
  1112. foreach my $Sku (keys %SkuInfo) {close $_ foreach grep{defined $_} map {$SkuInfo{$Sku}->[$_]} (1..6)}
  1113. return;
  1114. }
  1115. $offHandle++;
  1116. }
  1117. }
  1118. foreach $Key ( keys( %Hash ) ) {
  1119. if ( ( GetFlag( $Key, "Driver" ) eq "t" ) &&
  1120. ( GetFlag( $Key, "Dosnet" ) eq "f" ) ) { next; }
  1121. my $Flags = GetFlag( $Key, "Prods" );
  1122. my $TabletPC = ('x86' eq lc$BldArch)?GetFlag( $Key, "TabletPC" ):'f';
  1123. if ( $Flags ne "nul" ) {
  1124. # Get the arrays of the skus that care about this file
  1125. # (arrays because we don't care about the names anymore)
  1126. # If a file is a TabletPC file then exclude it from the pro lists
  1127. my @matchingSkus = map {$SkuInfo{$_}}
  1128. grep {$Flags =~ /$SkuInfo{$_}->[0]/ &&
  1129. !('pro' eq lc$_ && 't' eq $TabletPC)} (keys %SkuInfo);
  1130. if ( !@matchingSkus ) { next; }
  1131. my $file;
  1132. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  1133. $file = GetFlag( $Key, "Rename" );
  1134. }
  1135. else {
  1136. $file = $Key;
  1137. }
  1138. if ( $file =~ /\\(\S+)$/ ) { $_->[4]->print( "$1\n" ) foreach(@matchingSkus); }
  1139. else { $_->[1]->print( "$file\n" ) foreach(@matchingSkus); }
  1140. if ( GetFlag( $Key, "Comp" ) eq "t" ) {
  1141. $CompName = MakeCompName( $file );
  1142. if ( $CompName =~ /\\(\S+)$/ ) { $_->[5]->print( "$1\n" ) foreach(@matchingSkus); }
  1143. else { $_->[2]->print( "$CompName\n" ) foreach(@matchingSkus); }
  1144. } else {
  1145. if ( $file =~ /\\(\S+)$/ ) { $_->[6]->print( "$1\n" ) foreach(@matchingSkus); }
  1146. else { $_->[3]->print( "$file\n" ) foreach(@matchingSkus); }
  1147. }
  1148. }
  1149. }
  1150. # Close file handles
  1151. foreach my $Sku (keys %SkuInfo) {close $_ foreach grep{defined $_} map {$SkuInfo{$Sku}->[$_]} (1..6)}
  1152. return 1;
  1153. }
  1154. sub MakeTabletList
  1155. {
  1156. my($key,$CompName);
  1157. unless ( open( FILE, ">$TempDir\\TabletPc.lst" ) ){
  1158. errmsg( "Failed to open TabletPc.lst ($!)" );
  1159. }
  1160. unless ( open( FILECOMP, ">$TempDir\\TabletPcComp.lst" ) ){
  1161. errmsg( "Failed to open TabletPcComp.lst ($!)" );
  1162. }
  1163. unless ( open( FILEUNCOMP, ">$TempDir\\TabletPcUnComp.lst" ) ){
  1164. errmsg( "Failed to open TabletPcUnComp.lst ($!)" );
  1165. }
  1166. foreach $key ( keys( %Hash ) ) {
  1167. if ( GetFlag( $key, "TabletPC" ) eq "t" ){
  1168. my $file;
  1169. if ( GetFlag( $key, "DoRename" ) eq 't' ) {
  1170. $file = GetFlag( $key, "Rename" );
  1171. # don't know about renaming tablet files, so
  1172. # add a warning until someone who knows better
  1173. # can decide if this is acceptable
  1174. wrnmsg( "Tablet file $Key marked for rename to $file" );
  1175. }
  1176. else {
  1177. $file = $key;
  1178. }
  1179. print( FILE "$file \n");
  1180. if ( GetFlag( $key, "Comp" ) eq "t" ) {
  1181. $CompName = MakeCompName( $file );
  1182. print( FILECOMP "$CompName \n");
  1183. } else {
  1184. print( FILEUNCOMP "$file \n");
  1185. }
  1186. }
  1187. }
  1188. close (FILE);
  1189. close (FILECOMP);
  1190. close (FILEUNCOMP);
  1191. }
  1192. sub MakeWOWList
  1193. {
  1194. my $root_path = shift;
  1195. my($key,$CompName);
  1196. unless ( open( FILE, ">$root_path\\congeal_scripts\\WOWfiles.lst" ) ){
  1197. errmsg( "Failed to open WOWfiles.lst ($!)" );
  1198. }
  1199. unless ( open( FILECOMP, ">$root_path\\congeal_scripts\\WOWfilesComp.lst" ) ){
  1200. errmsg( "Failed to open WOWfilesComp.lst ($!)" );
  1201. }
  1202. unless ( open( FILEUNCOMP, ">$root_path\\congeal_scripts\\WOWfilesUnComp.lst" ) ){
  1203. errmsg( "Failed to open WOWfilesUnComp.lst ($!)" );
  1204. }
  1205. foreach $key ( keys( %Hash ) ) {
  1206. if ( GetFlag( $key, "WOW" ) eq "t" ){
  1207. my $file;
  1208. if ( GetFlag( $key, "DoRename" ) eq 't' ) {
  1209. $file = GetFlag( $key, "Rename" );
  1210. wrnmsg( "WOW file $key marked for rename to $file" );
  1211. }
  1212. else {
  1213. $file = $key;
  1214. }
  1215. print( FILE "$file \n");
  1216. if ( GetFlag( $key, "Comp" ) eq "t" ) {
  1217. $CompName = MakeCompName( $file );
  1218. print( FILECOMP "$CompName \n");
  1219. } else {
  1220. print( FILEUNCOMP "$file \n");
  1221. }
  1222. }
  1223. }
  1224. close (FILE);
  1225. close (FILECOMP);
  1226. close (FILEUNCOMP);
  1227. }
  1228. sub MakeRenameList
  1229. {
  1230. my ( $skus ) = @_;
  1231. my($key,$comp_name,$comp_rename);
  1232. # SkuInfo array members:
  1233. # 0 - sku id letter
  1234. # 1 - (handle) standard rename files
  1235. # 2 - (handle) rename file using compressed names when the entry is marked as compressed
  1236. my %sku_info;
  1237. for ( $i = 0; $i < @$skus; $i++ ) {
  1238. my $sku_name = lc$skus->[$i];
  1239. $sku_info{$sku_name} = [lc GetSkuIdLetter($sku_name)];
  1240. # Open the log files for writing
  1241. my $off_handle = 1;
  1242. foreach ( "", "_c" ) {
  1243. $sku_info{$sku_name}->[$off_handle] = new IO::File ">$TempDir\\$sku_name"."rename$_.lst";
  1244. if ( !defined $sku_info{$sku_name}->[$off_handle] ) {
  1245. errmsg( "Unable to open $TempDir\\$sku_name"."rename$_.lst for writing ($!)." );
  1246. foreach my $sku (keys %sku_info) {close $_ foreach grep{defined $_} map {$sku_info{$sku}->[$_]} (1..6)}
  1247. return;
  1248. }
  1249. $off_handle++;
  1250. }
  1251. }
  1252. foreach $key ( keys %Hash ) {
  1253. if ( GetFlag( $key, "DoRename" ) eq 't' ) {
  1254. my $rename;
  1255. my $file;
  1256. my $flags = GetFlag( $key, "Prods" );
  1257. my $target_name = GetFlag( $key, "Rename" );
  1258. $target_name =~ s/"//g;
  1259. if ( $flags eq 'nul' ) { next }
  1260. # Get the arrays of the skus that care about this file
  1261. # (arrays because we don't care about the names anymore)
  1262. # If a file is a TabletPC file then exclude it from the pro lists
  1263. my @matching_skus = map {$sku_info{$_}}
  1264. grep {$flags =~ /$sku_info{$_}->[0]/} (keys %sku_info);
  1265. if ( !@matching_skus ) { next; }
  1266. # Want any path to be on the target name and not the source name
  1267. # (want relative path to actual file and then the rename name)
  1268. if ( $key =~ /\\([^\\]+)$/ ) {
  1269. $file = $1;
  1270. $rename = "$`\\$target_name";
  1271. }
  1272. else {
  1273. $file = $key;
  1274. $rename = $target_name;
  1275. }
  1276. # Special warning case for file-names with spaces
  1277. if ( $rename =~ /\s/ ) {
  1278. wrnmsg( "$key has been renamed to '$rename' containing spaces -- unsupported" );
  1279. }
  1280. $_->[1]->print( "$rename:$file\n" ) foreach(@matching_skus);
  1281. if ( GetFlag( $key, "Comp" ) eq "t" ) {
  1282. $comp_name = MakeCompName( $file );
  1283. $comp_rename = MakeCompName( $rename );
  1284. $_->[2]->print( "$comp_rename:$comp_name\n" ) foreach(@matching_skus);
  1285. } else {
  1286. $_->[2]->print( "$rename:$file\n" ) foreach(@matching_skus);
  1287. }
  1288. }
  1289. }
  1290. # Close file handles
  1291. foreach my $sku (keys %sku_info) {close $_ foreach grep{defined $_} map {$sku_info{$sku}->[$_]} (1..6)}
  1292. return 1;
  1293. }
  1294. #
  1295. # MakeDriverCabLists
  1296. #
  1297. # Arguments: $SkuName, $SkuLetter
  1298. #
  1299. # Purpose: generate driver lists for drivercab based on the sku given
  1300. #
  1301. # Returns: nothing
  1302. #
  1303. sub MakeDriverCabLists
  1304. {
  1305. # get passed args
  1306. my( $Skus ) = @_;
  1307. my @lists = @$Skus;
  1308. # Clear any previous lists
  1309. my @prev_lists = grep {-e $_} map {"$TempDir\\$_"."drivers.txt"} (@lists, 'common');
  1310. foreach ( @prev_lists ) {
  1311. unlink $_ or errmsg ( "Unable to delete $_ ($!)" );
  1312. }
  1313. if ( !$IncFlag ) {
  1314. unshift @lists, "common";
  1315. }
  1316. logmsg( "Generating driver lists for ". (join ', ', @lists). " ..." );
  1317. # SkuInfo array members:
  1318. # 0 - sku id letter
  1319. # 1 - (handle) driver cab files
  1320. # 2 - name of list file
  1321. my %ListInfo;
  1322. for ( $i = 0; $i < @lists; $i++ ) {
  1323. my $ListName = lc$lists[$i];
  1324. my $ListLog = "$TempDir\\$ListName"."drivers.txt";
  1325. my $fh;
  1326. $fh = new IO::File ">$ListLog";
  1327. if ( !defined $fh ) {
  1328. errmsg ( "Unable to open $ListLog for writing ($!)." );
  1329. foreach (keys %ListInfo) {$ListInfo{$_}->[1]->close() if defined $ListInfo{$_}->[1]}
  1330. return;
  1331. }
  1332. $ListInfo{$ListName} = [($ListName ne 'common'?lc GetSkuIdLetter($ListName):join '', sort map{ lc GetSkuIdLetter($_) } @CDDataSKUs),
  1333. $fh,
  1334. $ListLog];
  1335. }
  1336. foreach $Key ( keys( %Hash ) ) {
  1337. my $skus = lc GetFlag( $Key, "DrvIndex" );
  1338. if ( $skus eq 'nul' ) { next; }
  1339. # Sort sku ids so we can compare with common (all skus)
  1340. $skus = join '', sort split '', $skus;
  1341. my %matches;
  1342. # If we are in full mode and this is a common driver
  1343. # that is the only list that we want to write it to
  1344. if ( exists $ListInfo{'common'} &&
  1345. $skus eq $ListInfo{'common'}->[0] ) {
  1346. $matches{'common'} = $ListInfo{'common'};
  1347. }
  1348. else {
  1349. %matches = map{$_ => $ListInfo{$_}} grep {$skus =~ /$ListInfo{$_}->[0]/} (keys %ListInfo);
  1350. if ( !%matches ) { next; }
  1351. }
  1352. my $file;
  1353. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  1354. $file = GetFlag( $Key, "Rename" );
  1355. wrnmsg( "Driver file $Key marked for rename to $file" );
  1356. }
  1357. else {
  1358. $file = $Key;
  1359. }
  1360. $_->print( "$file\n" ) foreach map{$matches{$_}->[1]} (keys %matches);
  1361. }
  1362. # close the file handles
  1363. foreach (keys %ListInfo) {$ListInfo{$_}->[1]->close() if defined $ListInfo{$_}->[1]}
  1364. # delete the list if it has zero length
  1365. foreach ( map {$ListInfo{$_}->[2]} keys %ListInfo ) {
  1366. if ( -z $_ &&
  1367. !unlink $_ ) {
  1368. errmsg( "Failed to delete zero length driver list $_ ($!)..." );
  1369. }
  1370. }
  1371. }
  1372. sub MakeCompLists
  1373. {
  1374. my( $Key, $CompFile, $Ext );
  1375. my $Binaries = $ENV{'_NTPOSTBLD'};
  1376. my $CompressedBinaries = "$Binaries\\comp";
  1377. logmsg( "Generating compression lists ..." );
  1378. unless ( ( open( ALL, ">$TempDir\\allcomp.lst" ) ) &&
  1379. ( open( PRE, ">$TempDir\\precomp.lst" ) ) &&
  1380. ( open( POST, ">$TempDir\\postcomp.lst" ) ) ) {
  1381. errmsg( "Failed to open main compression lists ($!)." );
  1382. close( ALL );
  1383. close( PRE );
  1384. close( POST );
  1385. return;
  1386. }
  1387. # NOTE: keep these lower-cased so we don't need to lower-case them when comparing
  1388. my %allowed_subdirs = map { $_ => 1 } grep { $_ ne '.' } map { lc ReadSetupFiles::GetSetupDir($_) } @AllSkus;
  1389. $allowed_subdirs{lang} = 1;
  1390. my %onlyall_extensions = ( cat => 1 );
  1391. my %postcompress_extensions = ( ax => 1,
  1392. cat => 1,
  1393. com => 1,
  1394. cpl => 1,
  1395. dll => 1,
  1396. drv => 1,
  1397. exe => 1,
  1398. ocx => 1,
  1399. scr => 1,
  1400. tsp => 1 );
  1401. foreach $Key ( keys( %Hash ) ) {
  1402. if ( GetFlag( $Key, "Comp" ) eq "t" ) {
  1403. if ( $Key =~ /^([^\\]+)\\/ &&
  1404. !exists $allowed_subdirs{lc$1} ) {
  1405. next;
  1406. }
  1407. my $file;
  1408. if ( GetFlag( $Key, "DoRename" ) eq 't' ) {
  1409. $file = GetFlag( $Key, "Rename" );
  1410. }
  1411. else {
  1412. $file = $Key;
  1413. }
  1414. $CompFile = MakeCompName( $file );
  1415. print( ALL "$Binaries\\$file $CompressedBinaries\\$CompFile\n" );
  1416. ($Ext) = $Key =~ /\.([^\.]+)$/; # use the source extension
  1417. if ( !exists $onlyall_extensions{lc$Ext} &&
  1418. !exists $postcompress_extensions{lc$Ext} ) {
  1419. print( PRE "$Binaries\\$file $CompressedBinaries\\$CompFile\n" );
  1420. }
  1421. if ( !exists $onlyall_extensions{lc$Ext} &&
  1422. exists $postcompress_extensions{lc$Ext} ) {
  1423. print( POST "$Binaries\\$file $CompressedBinaries\\$CompFile\n" );
  1424. }
  1425. }
  1426. }
  1427. close( ALL );
  1428. close( PRE );
  1429. close( POST );
  1430. logmsg( "Sorting generated lists ..." );
  1431. system( "sort $TempDir\\allcomp.lst /o $TempDir\\allcomp.lst" );
  1432. system( "sort $TempDir\\precomp.lst /o $TempDir\\precomp.lst" );
  1433. system( "sort $TempDir\\postcomp.lst /o $TempDir\\postcomp.lst" );
  1434. }
  1435. sub MakeExtensionLists
  1436. {
  1437. logmsg( "Creating extension lists ..." );
  1438. my %handles_to_extension_lists;
  1439. # Use our own subdirectory
  1440. mkdir "$ENV{_NTPostBld}\\congeal_scripts\\exts", 0777 if ( ! -d "$ENV{_NTPostBld}\\congeal_scripts\\exts" );
  1441. foreach my $key ( keys( %Hash ) ) {
  1442. my ($ext) = $key =~ /\.([^\.]+)$/;
  1443. $ext ||= 'noext';
  1444. if ( !exists $handles_to_extension_lists{$ext} ) {
  1445. $handles_to_extension_lists{$ext} = new IO::File ">$ENV{_NTPostBld}\\congeal_scripts\\exts\\$ext\_files.lst";
  1446. if ( !exists $handles_to_extension_lists{$ext} ) {
  1447. errmsg( "Error opening $ENV{_NTPostBld}\\congeal_scripts\\exts\\$ext\_files.lst for writing ($!)" );
  1448. return;
  1449. }
  1450. }
  1451. my $file;
  1452. if ( GetFlag( $key, "DoRename" ) eq 't' ) {
  1453. $file = GetFlag( $key, "Rename" );
  1454. }
  1455. else {
  1456. $file = $key;
  1457. }
  1458. $handles_to_extension_lists{$ext}->print("$file\n");
  1459. }
  1460. # close all open handles
  1461. foreach ( keys %handles_to_extension_lists ) {
  1462. $handles_to_extension_lists{$_}->close();
  1463. }
  1464. return 1;
  1465. }
  1466. sub MakeLists
  1467. {
  1468. if ( ( defined( $CreateCDFs ) ) || ( defined( $CreateLists ) ) ) {
  1469. logmsg( "Beginning CDF and list generation ..." );
  1470. }
  1471. if ( 'x86' eq lc$BldArch ) {
  1472. MakeTabletList();
  1473. }
  1474. if ( defined( $CreateCDFs ) ) {
  1475. # let's make some cdf's
  1476. MakeMainCdfs( "nt5", "ntprint" );
  1477. MakeInfCdf( \@CDDataSKUs );
  1478. }
  1479. if ( defined( $CreateLists ) ) {
  1480. # let's make some product lists
  1481. MakeProdLists( \@CDDataSKUs );
  1482. # let's make some drivercab lists
  1483. MakeDriverCabLists( \@CDDataSKUs );
  1484. # let's make some compression lists
  1485. MakeCompLists();
  1486. # need to know which files we are responsible for renaming
  1487. MakeRenameList( \@CDDataSKUs );
  1488. }
  1489. if ( ( defined( $CreateCDFs ) ) || ( defined( $CreateLists ) ) ) {
  1490. logmsg( "Finished creating CDFs and lists." );
  1491. }
  1492. }
  1493. sub MakeCompName
  1494. {
  1495. my $fullname = shift;
  1496. my ($filename, $path) = fileparse($fullname);
  1497. $filename =~ s!(\.([^\.]*))?$!
  1498. if (not $2) { "._" } elsif (length $2 < 3) { ".$2_" } else { '.' . substr($2,0,-1) . '_' } !ex;
  1499. return ($path eq '.\\'?'':$path).$filename;
  1500. }
  1501. sub SpecialExclusions
  1502. {
  1503. # force ntkrnlmp.exe to be uncompressed on ia64 builds
  1504. if ( $BldArch =~ /ia64/i ) {
  1505. ChangeSettings( "ntkrnlmp.exe", "Comp=f" );
  1506. }
  1507. ChangeSettings( "driver.cab", "Signed=f" );
  1508. }
  1509. sub HandleDiffFiles
  1510. {
  1511. # declare locals
  1512. my( @BinDiffs, $NumDiffsLimit, %DiffFiles, $Line );
  1513. # here we need to make a decision.
  1514. # we can either do an incremental build if the diff list is smaller than
  1515. # some number of files, or we can run a full postbuild.
  1516. # first, set the limit on the number of differing files before running
  1517. # a full postbuild.
  1518. $NumDiffsLimit = 100;
  1519. undef $IncFlag;
  1520. # if the user specifically asked for no bindiff truncation, just return
  1521. if ( defined( $NoUseBindiff ) ) {
  1522. logmsg( "Not truncating against bindiff files ..." );
  1523. return 2;
  1524. }
  1525. # open the diff file and read it in
  1526. unless ( open( INFILE, $BinDiffFile ) ) {
  1527. errmsg( "Failed to open new file list '$BinDiffFile' ($!)" );
  1528. errmsg( "will assume a full postbuild is needed." );
  1529. return;
  1530. }
  1531. @BinDiffs = <INFILE>;
  1532. close( INFILE );
  1533. # make sure we're under the limit
  1534. if ( @BinDiffs > $NumDiffsLimit ) {
  1535. logmsg( "Too many files have changed, ignoring bindiff file." );
  1536. return 2;
  1537. }
  1538. # if we're here, then we have a small enough number of different files
  1539. # that we'll run an incremental postbuild.
  1540. # set a flag to indicate we are in incremental mode
  1541. $IncFlag = 1;
  1542. # so what we want to do is remove all hashes that do NOT appear in
  1543. # the diff file.
  1544. foreach $Line ( @BinDiffs ) {
  1545. chomp( $Line );
  1546. $Line = lc$Line;
  1547. # add the files to the temp hash
  1548. # print( "DEBUG: diff file '$Line'\n" );
  1549. $DiffFiles{ $Line } = 1;
  1550. }
  1551. foreach $Key ( keys( %Hash ) ) {
  1552. $Line = "\L$nttree\\$Key";
  1553. # print( "DEBUG: key check '$Line'\n" );
  1554. unless ( $DiffFiles{ $Line } ) { delete( $Hash{ $Key } ); }
  1555. }
  1556. # and we're done!
  1557. # just return true.
  1558. return 1;
  1559. }
  1560. sub GetPrinterFiles
  1561. {
  1562. # get passed args
  1563. my( $PrintFileName ) = @_;
  1564. # declare locals
  1565. my( @PrintLines, $Line, $PrintMe, $PrinterName, $Junk );
  1566. unless ( open( INFILE, $PrintFileName ) ) {
  1567. errmsg( "Failed to open $PrintFileName to determine printers ($!)" );
  1568. undef( @PrinterFiles );
  1569. return;
  1570. }
  1571. @PrintLines = <INFILE>;
  1572. close( INFILE );
  1573. undef( $PrintMe );
  1574. foreach $Line ( @PrintLines ) {
  1575. # first, a simple unicode conversion
  1576. $Line =~ s/\000//g;
  1577. # now a chomp that handles \r also
  1578. $Line =~ s/[\r\n]//g;
  1579. if ( ( length( $Line ) == 0 ) || ( $Line =~ /^\;/ ) ) { next; }
  1580. if ( $Line =~ /^\[/ ) { undef( $PrintMe ); }
  1581. if ( $PrintMe ) {
  1582. ( $PrinterName, $Junk ) = split( /\s+/, $Line );
  1583. push( @PrinterFiles, $PrinterName );
  1584. }
  1585. if ( $Line =~ /\[SourceDisksFiles\]/ ) { $PrintMe = 1; }
  1586. }
  1587. }
  1588. sub AddDrvIndex
  1589. {
  1590. # get passed args
  1591. my( $Sku, $RootPath ) = @_;
  1592. my( @Files, $File, $StatusChange );
  1593. # declare status
  1594. logmsg( "Marking drivers in $Sku drvindex ..." );
  1595. if ( !ReadSetupFiles::ReadDrvIndex( $RootPath,
  1596. $Sku,
  1597. \@Files ) ) {
  1598. }
  1599. $StatusChange = "DrvIndex+". GetSkuIdLetter($Sku);
  1600. foreach $File ( @Files ) {
  1601. if ( $Hash{ "$File" } ) {
  1602. ChangeSettings( $File, $StatusChange );
  1603. } else {
  1604. NewSettings( $File, $StatusChange );
  1605. }
  1606. }
  1607. }
  1608. #--
  1609. # GetDrmFiles
  1610. #
  1611. # First parameter is reference to associate array
  1612. # Associated array will be filled with values from $DrmTxt file.
  1613. #--
  1614. sub GetDrmFiles
  1615. {
  1616. #--
  1617. # Passed parameters
  1618. #--
  1619. my( $ref, $txtfile ) = @_;
  1620. #--
  1621. # Local variables
  1622. #--
  1623. my( $line, @DrmFileLines, $filename, $drmvalue, $rem );
  1624. unless( -f $txtfile )
  1625. {
  1626. wrnmsg( "Failed to find $txtfile to determine drm files" );
  1627. undef( %$ref );
  1628. return;
  1629. }
  1630. unless( open( INFILE, $txtfile ) )
  1631. {
  1632. errmsg( "Failed to open $txtfile to determine drm files ($!)" );
  1633. undef( %$ref );
  1634. return;
  1635. }
  1636. @DrmFileLines = <INFILE>;
  1637. close( INFILE );
  1638. foreach $line ( @DrmFileLines )
  1639. {
  1640. chomp $line;
  1641. s/\s+//g;
  1642. if( ( $line =~ /^\s*$/ ) || ( $line =~ /^[\;\#]/ ) ) { next; }
  1643. ( $filename, $drmvalue, $rem ) = split( /\:/, $line );
  1644. $$ref{$filename} = $drmvalue;
  1645. }
  1646. }
  1647. sub CheckDosnet
  1648. {
  1649. my( $RootPath, $Sku, $SkuHierarchy ) = @_;
  1650. my( $File, $ListName );
  1651. my ( @DosnetFiles, @SecondaryDosnetFiles );
  1652. if ( !ReadSetupFiles::ReadDosnet( $RootPath,
  1653. $Sku,
  1654. $BldArch,
  1655. \@DosnetFiles,
  1656. \@SecondaryDosnetFiles ) ) {
  1657. errmsg( "Failed parsing dosnet.inf for $Sku" );
  1658. return;
  1659. }
  1660. if ( lc$Sku eq 'ads' ) {
  1661. $ListName = $TempDir . "\\entnetck.lst";
  1662. }
  1663. else {
  1664. $ListName = $TempDir . "\\$Sku". "netck.lst";
  1665. }
  1666. unless ( open( LIST, ">$ListName" ) ) {
  1667. errmsg( "Failed to open $ListName for writing ($!)." );
  1668. return( undef );
  1669. }
  1670. my @possibleLocations = GetSkuOrderedLayers($Sku, $SkuHierarchy);;
  1671. my $missingFiles = 0;
  1672. foreach $File ( @DosnetFiles ) {
  1673. my $fFound;
  1674. foreach ( @possibleLocations ) {
  1675. if ( exists $Hash{$_ ne '.'?"\L$_\\$File":lc$File} ) {
  1676. $fFound = 1;
  1677. last;
  1678. }
  1679. }
  1680. if ( !$fFound ) {
  1681. $missingFiles++;
  1682. print( LIST "$File\n" );
  1683. }
  1684. }
  1685. close LIST;
  1686. if ( $missingFiles ) {
  1687. logmsg( "$missingFiles missing files found for $Sku -- see $ListName" );
  1688. }
  1689. else {
  1690. logmsg( "No missing files for $Sku." );
  1691. }
  1692. }