Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2237 lines
72 KiB

  1. # ---------------------------------------------------------------------------
  2. # Script: muimake.pm
  3. #
  4. # (c) 2000 Microsoft Corporation. All rights reserved.
  5. #
  6. # Purpose: This script creates the mui satallite dlls
  7. #
  8. # Version: 1.00 (09/2/2000) : (dmiura) Inital port from win2k
  9. #---------------------------------------------------------------------
  10. # Set Package
  11. package muimake;
  12. # Set the script name
  13. $ENV{script_name} = 'muimake.pm';
  14. # Set version
  15. $VERSION = '1.00';
  16. # Set required perl version
  17. require 5.003;
  18. # Use section
  19. use lib $ENV{ "RazzleToolPath" };
  20. use lib $ENV{ "RazzleToolPath" } . "\\PostBuildScripts";
  21. use GetParams;
  22. use LocalEnvEx;
  23. use Logmsg;
  24. use strict;
  25. no strict 'vars';
  26. use HashText;
  27. use ParseTable;
  28. use File::Copy;
  29. use File::Find;
  30. use Cwd;
  31. use DirHandle;
  32. # Require section
  33. require Exporter;
  34. # Global variable section
  35. sub Main {
  36. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  37. # Begin Main code section
  38. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  39. # Return when you want to exit on error
  40. # <Implement your code here>
  41. # Make sure that text written to STDOUT and STDERR is displayed in correct order
  42. # $| = 1;
  43. # Check environment variables
  44. if (!&CheckEnv()) {
  45. wrnmsg ("The environment is not correct for MUI build.");
  46. return 1;
  47. }
  48. # Define some constants
  49. if (!&DefineConstants()) {
  50. errmsg ("The constants could not be defined.");
  51. return 0;
  52. }
  53. # Get language's LCID and ISO code
  54. if (!&GetCodes()) {
  55. errmsg ("The language's LCID and ISO code could note be extracted from the CODEFILE.");
  56. return 0;
  57. }
  58. # Make sure directories exist
  59. if (!&CheckDirs()) {
  60. errmsg ("The required directorys do not exist.");
  61. return 0;
  62. }
  63. # Update mui.inf with the current build number
  64. if (!&UpdateMuiinf()) {
  65. errmsg ("mui.inf could not be updated with the correct build number.");
  66. }
  67. # Extract files listed in extracts.txt
  68. if (!&ExtractCabFiles()) {
  69. errmsg ("The files listed in extracts.txt could not be extracted.");
  70. }
  71. # Get (filtered) contents of source directory
  72. if (!&MakeSourceFileList()) {
  73. errmsg ("Could not get the filtered contents of the source directory.");
  74. }
  75. # Generate resource dlls from the files in the source file list
  76. if (!&GenResDlls()) {
  77. errmsg ("");
  78. }
  79. # Rename the files listed in renfile.txt
  80. if (!&RenameRenfiles()) {
  81. errmsg ("");
  82. }
  83. # Copy over the files listed in copyfile.txt
  84. if (!&CopyCopyfiles()) {
  85. errmsg ("");
  86. }
  87. # Copy over the files from \mui\drop
  88. if (!&CopyDroppedfiles()) {
  89. errmsg ("");
  90. }
  91. # Delete the files listed in delfile.txt
  92. if (!&DeleteDelfiles()) {
  93. errmsg ("");
  94. }
  95. # Copy over components' files to a separate directory
  96. if (!&CopyComponentfiles()) {
  97. errmsg ("");
  98. }
  99. # Compress the resource dlls (& CHM/CHQ/CNT files)
  100. if (!&CompressResDlls()) {
  101. errmsg ("");
  102. }
  103. # Fusion team has changed its MUI manifest implementation
  104. # Copy fusion files
  105. # if (!&CopyFusionFiles ("$_NTPOSTBLD\\asms", "$TARGETDIR\\asms") ||
  106. # !&CopyFusionFiles ("$_NTPOSTBLD\\asms", "$COMPDIR\\asms")) {
  107. # errmsg("");
  108. # }
  109. # Copy MUI tools to release share
  110. if (!&CopyMUIRootFiles()) {
  111. errmsg("");
  112. }
  113. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  114. # End Main code section
  115. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  116. }
  117. # <Implement your subs here>
  118. sub muimake {
  119. &Main();
  120. logmsg("This is a muimake test message");
  121. return 0;
  122. }
  123. #-----------------------------------------------------------------------------
  124. # CheckEnv - validates necessary environment variables
  125. #-----------------------------------------------------------------------------
  126. sub CheckEnv {
  127. logmsg ("Validating the environment.");
  128. $RAZZLETOOLPATH=$ENV{RazzleToolPath};
  129. $_NTTREE=$ENV{_NTTREE};
  130. $_NTPOSTBLD=$ENV{_NTPOSTBLD};
  131. # if ($LANG=~/psu/i || $LANG=~/gb/i || $LANG=~/ca/i)
  132. # {
  133. # $_NTPOSTBLD="$ENV{_NTPostBld_Bak}\\psu";
  134. # }
  135. # logmsg ("Reset _NTPostBld for PSU to $_NTPOSTBLD");
  136. if ($LANG=~/psu_(.*)/i)
  137. {
  138. $Special_Lang=$1;
  139. }
  140. elsif ($LANG=~/psu/i || $LANG=~/mir/i )
  141. {
  142. if (defined( $ENV{"LANG_MUI"} ) )
  143. {
  144. $Special_Lang=$ENV{"LANG_MUI"};
  145. }
  146. elsif ($LANG=~/psu/i)
  147. {
  148. $Special_Lang="ro";
  149. }
  150. else
  151. {
  152. $Special_Lang="ara";
  153. }
  154. }
  155. else
  156. {
  157. $Special_Lang=$LANG;
  158. }
  159. logmsg ("------- special lang is $Special_Lang");
  160. $PROCESSOR=$ENV{PROCESSOR};
  161. if ($ENV{_BuildArch}=~/x86/i) {
  162. $_BuildArch="i386";
  163. } else {
  164. $_BuildArch=$ENV{_BuildArch};
  165. }
  166. $LOGS=$ENV{temp};
  167. if ($ENV{_BuildType} =~ /^chk$/i) {
  168. wrnmsg ("This does not run on chk machines");
  169. return 0;
  170. }
  171. if(defined($SAFEMODE=$ENV{SAFEMODE})) {
  172. logmsg ("SAFEMODE is ON");
  173. }
  174. logmsg ("Success: Validating the environment.");
  175. return 1;
  176. } # CheckEnv
  177. #-----------------------------------------------------------------------------
  178. # DefineConstants - defines global constants
  179. #-----------------------------------------------------------------------------
  180. sub DefineConstants {
  181. my ($layout);
  182. logmsg ("Definition of global constants.");
  183. # Directories
  184. $LOCBINDIR = "$_NTPOSTBLD";
  185. $USBINDIR = "$_NTTREE";
  186. $MUIDIR = "$_NTPOSTBLD\\mui";
  187. $MUI_RELEASE_DIR = "$MUIDIR\\release\\$_BuildArch";
  188. $CONTROLDIR = "$MUIDIR\\control";
  189. $TMPDIR = "$MUIDIR\\$Special_Lang\\tmp";
  190. $RESDIR = "$MUIDIR\\$Special_Lang\\res";
  191. $TARGETDIR = "$MUIDIR\\$Special_Lang\\$_BuildArch.uncomp";
  192. #$COMPDIR = "$MUIDIR\\$Special_Lang\\$_BuildArch";
  193. $IE5DIR = "$MUIDIR\\drop\\ie5";
  194. # Filenames
  195. $CODEFILE = "$RAZZLETOOLPATH\\codes.txt";
  196. $INFFILE = "$MUIDIR\\mui.inf";
  197. $COPYFILE = "$CONTROLDIR\\copyfile.txt";
  198. $DELFILE = "$CONTROLDIR\\delfile.txt";
  199. $EXTFILE= "$CONTROLDIR\\extracts.txt";
  200. $RENFILE = "$CONTROLDIR\\renfile.txt";
  201. $COMPEXCLUDEFILE = "$CONTROLDIR\\compexclude.txt";
  202. $layout = GetCDLayOut();
  203. $COMPDIR = "$MUI_RELEASE_DIR\\$layout\\$Special_Lang\.mui\\$_BuildArch";
  204. # Other Constants
  205. if($_BuildArch =~ /i386/i) {
  206. $MACHINE = "IX86";
  207. }
  208. elsif ($_BuildArch =~ /ia64/i) {
  209. $MACHINE = "IA64";
  210. }
  211. if ($LANG =~ /^(ARA|HEB)$/i) {
  212. $RESOURCE_TYPES = "2 3 4 5 6 9 10 11 14 16 HTML MOFDATA 23 240 1024 2110";
  213. }
  214. else {
  215. $RESOURCE_TYPES = "4 5 6 9 10 11 16 HTML MOFDATA 23 240 1024 2110";
  216. }
  217. logmsg ("Success: Definition of global constants.");
  218. $BuildChecksum=1;
  219. return 1;
  220. } # DefineConstants
  221. #-----------------------------------------------------------------------------
  222. # GetCodes - gets the language's LCID and ISO language code from CODEFILE
  223. #-----------------------------------------------------------------------------
  224. sub GetCodes {
  225. logmsg ("Get the language's LCID and ISO language code form CODEFILE.");
  226. my(@data);
  227. # Don't allow nec_98 or CHT to be processed!
  228. if($Special_Lang =~ /^(NEC_98|CHT)$/i) {
  229. logmsg ("No MUI available for $Special_Lang");
  230. exit 0;
  231. }
  232. # Search CODEFILE for $Special_Lang, $LCID, $LANG_ISO, etc.
  233. if(!open(CODEFILE, "$CODEFILE")) {
  234. errmsg ("Can't open lcid file $CODEFILE for reading.");
  235. return 0;
  236. }
  237. CODES_LOOP: while (<CODEFILE>) {
  238. if (/^$Special_Lang\s+/i) {
  239. @data = split(/\s+/,$_);
  240. last CODES_LOOP;
  241. }
  242. }
  243. close(CODEFILE);
  244. if(!@data) {
  245. logmsg ("$Special_Lang is an unknown language");
  246. &Usage;
  247. return 0;
  248. }
  249. $LCID = $data[2];
  250. $LCID_SHORT = $LCID;
  251. $LCID_SHORT =~ s/^0x//;
  252. $LANG_ISO = $data[8];
  253. $GUID = $data[11];
  254. $LANG_NAME = $data[$#data]; # The comments are the last column
  255. logmsg ("Success: Get the language's LCID and ISO language code form CODEFILE.");
  256. return 1;
  257. } # GetCodes
  258. #-----------------------------------------------------------------------------
  259. # CheckDirs - makes sure that the necessary directories exist
  260. #-----------------------------------------------------------------------------
  261. sub CheckDirs {
  262. logmsg ("Make sure the necessary directories exist.");
  263. my($status);
  264. # Make sure the source directories exist
  265. foreach ($LOCBINDIR,$MUIDIR,$CONTROLDIR) {
  266. if(! -e $_) {
  267. logmsg ("$0: ERROR: $_ does not exist");
  268. return 0;
  269. }
  270. }
  271. # Make sure destination directories exist
  272. foreach ($IE5DIR,$TMPDIR,$RESDIR,$TARGETDIR,$COMPDIR) {
  273. if(! -e $_) {
  274. $status = system("md $_");
  275. if($status) {
  276. logmsg ("$0: ERROR: cannot create $_");
  277. return 0;
  278. }
  279. }
  280. }
  281. logmsg ("Success: Make sure the necessary directories exist.");
  282. return 1;
  283. } # CheckDirs
  284. #-----------------------------------------------------------------------------
  285. # UpdateMuiinf - updates mui.inf with current build number
  286. #-----------------------------------------------------------------------------
  287. sub UpdateMuiinf {
  288. logmsg ("Update mui.inf with the current build number.");
  289. my(@inf_contents, $build_section, $build_line_found, $bldno_already_there,
  290. @new_contents);
  291. # Get current build number
  292. $LOGS="$_NTPOSTBLD\\build_logs";
  293. my $filename="$LOGS\\buildname.txt";
  294. open (BUILDNAME, "< $filename") or die "Can't open $filename for reading: $!\n";
  295. while (<BUILDNAME>) {
  296. $BLDNO = $_;
  297. $BLDNO =~ s/\.[\w\W]*//i;
  298. }
  299. close BUILDNAME;
  300. if ($BLDNO =~ /(^\d+)-*\d*$/) {
  301. $BLDNO = $1;
  302. }
  303. else
  304. {
  305. errmsg ("$BLDNO");
  306. return 0;
  307. }
  308. chomp($BLDNO);
  309. # Read $INFFILE
  310. if(!open(INFFILE, $INFFILE)) {
  311. errmsg ("Cannot open $INFFILE for reading.");
  312. return 0;
  313. }
  314. @inf_contents = <INFFILE>;
  315. close(INFFILE);
  316. # Modify contents in memory
  317. $build_section = 0;
  318. $build_line_found = 0;
  319. $bldno_already_there = 0;
  320. foreach (@inf_contents) {
  321. # If we find [Buildnumber] we're in the build_section.
  322. if(/^\[Buildnumber\]$/ && !$build_section) {
  323. $build_section = 1;
  324. }
  325. # If we find <something>=1 within the build section, replace
  326. # with $BLDNO and mark the end of the build section.
  327. elsif($build_section && /^(.*)=1$/) {
  328. if(/^$BLDNO=1$/) {
  329. $bldno_already_there = 1;
  330. }
  331. else {
  332. s/^.*=1$/$BLDNO=1/;
  333. }
  334. $build_line_found = 1;
  335. $build_section = 0;
  336. }
  337. push(@new_contents, $_);
  338. }
  339. # If no build line was found, the format is wrong - error msg and exit
  340. if(!$build_line_found) {
  341. errmsg ("$INFFILE doesnt have the expected format.");
  342. logmsg ("Looking for:");
  343. logmsg ("[Buildnumber]");
  344. logmsg ("<something>=1");
  345. return 0;
  346. }
  347. # If $INFFILE already contains the current build number, leave it alone.
  348. if($bldno_already_there) {
  349. logmsg ("$INFFILE already contains the current build number - no update performed.");
  350. }
  351. # Overwrite $INFFILE
  352. else {
  353. if(!open(INFFILE, ">$INFFILE")) {
  354. errmsg ("Cannot open $INFFILE for writing.");
  355. return 0;
  356. }
  357. print INFFILE @new_contents;
  358. close(INFFILE);
  359. # Confirm the update
  360. logmsg ("$INFFILE successfully updated with Build Number = $BLDNO");
  361. }
  362. logmsg ("Success: Update mui.inf with the current build number.");
  363. return 1;
  364. } # UpdateMuiinf
  365. #-----------------------------------------------------------------------------
  366. # Ie5Mui - creates a language-specific version of ie5ui.inf
  367. #-----------------------------------------------------------------------------
  368. sub Ie5Mui {
  369. logmsg ("Create a language-specific version of ie5ui.inf");
  370. my(@new_inf, $input_file, $output_file);
  371. $input_file = "$IE5FILE";
  372. $output_file = "$IE5DIR\\ie5ui.inf";
  373. # Check existence of input file
  374. if(!-e $input_file) {
  375. errmsg ("Can't find $input_file.");
  376. logmsg ("$output_file not created.");
  377. return 0;
  378. }
  379. # If the output file already exists and is newer than
  380. # the input file, return. (Unless the FORCE option has been set)
  381. if(-e $output_file) {
  382. if($VERBOSE) {
  383. logmsg ("$output_file already exists.");
  384. }
  385. if(&ModAge($output_file) <= &ModAge($input_file)) {
  386. if($VERBOSE) {
  387. logmsg ("$output_file is newer than $input_file");
  388. }
  389. if(!$FORCE) {
  390. if($VERBOSE) {
  391. logmsg ("$output_file will not be overwritten.");
  392. }
  393. logmsg ("Success: Create a language-specific version of ie5ui.inf");
  394. return 1;
  395. }
  396. else {
  397. if($VERBOSE) {
  398. logmsg ("FORCE option is ON - overwriting anyway.");
  399. }
  400. }
  401. }
  402. }
  403. if(!open(INPUTFILE, "$input_file")) {
  404. errmsg ("Cannot open $input_file for reading.");
  405. logmsg ("$output_file not created.");
  406. return 0;
  407. }
  408. while (<INPUTFILE>) {
  409. # Replace the human readable language names
  410. s/#LANGUAGE#/$LANG_NAME/g;
  411. # Replace the GUIDs
  412. s/#GUID#/$GUID/g;
  413. # Replace the iso language IDs
  414. s/#ISO#/$LANG_ISO/g;
  415. # Replace the LCIDS
  416. s/#LCID#/$LCID_SHORT/g;
  417. # Remove the SourceDiskName
  418. s/"Internet Explorer UI Satellite Kit"//g;
  419. push(@new_inf, $_);
  420. }
  421. close INPUTFILE;
  422. # Special case for Japanese
  423. if($LANG_ISO eq "JA") {
  424. push(@new_inf, "\n\[Run.MSGotUpd\]\n");
  425. push(@new_inf, "%49501%\\MUI\\0411\\msgotupd.exe \/q\n");
  426. }
  427. # Display and log any errors
  428. # (if @new_inf has 2 lines or less, it's probably an error)
  429. if(scalar(@new_inf) <= 2) {
  430. errmsg ("Error from $CONTROLDIR\\ie5mui.pl");
  431. foreach (@new_inf) {
  432. logmsg ($_);
  433. }
  434. logmsg ("$output_file not created");
  435. return 0;
  436. }
  437. # Write the output of ie5mui.pl to ie5ui.inf
  438. if(!open(OUTFILE,">$output_file")) {
  439. errmsg ("Can't open $output_file for writing.");
  440. logmsg ("$output_file not created.");
  441. return 0;
  442. }
  443. print OUTFILE @new_inf;
  444. close(OUTFILE);
  445. logmsg ("$output_file successfully created.");
  446. logmsg ("Success: Create a language-specific version of ie5ui.inf");
  447. return 1;
  448. } # Ie5Mui
  449. #-----------------------------------------------------------------------------
  450. # ExtractCabFiles - extracts files listed in extracts.txt from their cabfiles.
  451. #-----------------------------------------------------------------------------
  452. sub ExtractCabFiles {
  453. logmsg ("Extract files listed in extracts.txt from their cabfiles.");
  454. my($files_extracted, $file_errors, $total_extracts);
  455. # Initial messages
  456. logmsg ("--------------------------------------------------------");
  457. logmsg ("MUI Cab File Extraction");
  458. logmsg ("--------------------------------------------------------");
  459. # Extract files from their cabfiles
  460. ($files_extracted, $file_errors, $total_extracts) = &ExtractFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $EXTFILE, 0);
  461. # Final messages
  462. if ($file_errors=~/0/i) {
  463. logmsg ("RESULTS: Process Succeeded");
  464. } else {
  465. logmsg ("RESULTS: Process Failed!");
  466. }
  467. logmsg ("Total number of files listed in:....................($total_extracts)");
  468. logmsg (" $EXTFILE");
  469. logmsg ("Number of files extracted to:.......................($files_extracted)");
  470. logmsg (" $TARGETDIR");
  471. logmsg ("Number of errors:...................................($file_errors)");
  472. return 1;
  473. } # ExtractFiles
  474. #-----------------------------------------------------------------------------
  475. # MakeSourceFileList - gets list of appropriate files to process
  476. #-----------------------------------------------------------------------------
  477. sub MakeSourceFileList {
  478. logmsg ("Get list of appropriate files to process.");
  479. my(@files,@files2,@Fusion_filelist,$filename);
  480. # Initial messages
  481. logmsg ("--------------------------------------------------------");
  482. logmsg ("MUI Resource-only dll Generation");
  483. logmsg ("--------------------------------------------------------");
  484. # Get contents of source directory
  485. if(!opendir(LOCBINDIR, $LOCBINDIR)) {
  486. errmsg ("Can't open $LOCBINDIR");
  487. return 0;
  488. }
  489. @files = grep !/\.(gpd|icm|ppd|bmp|txt|cab|cat|hlp|chm|chq|cnt|mfl)$/i, readdir LOCBINDIR;
  490. close(LOCBINDIR);
  491. if(!opendir(TMPDIR, $TMPDIR)) {
  492. errmsg ("Can't open $TMPDIR");
  493. return 0;
  494. }
  495. @files2 = grep !/\.(gpd|icm|ppd|bmp|txt|cab|cat|hlp|chm|chq|cnt|mfl)$/i, readdir TMPDIR;
  496. close(TMPDIR);
  497. # Filter out non-binaries, store in global @FILE_LIST
  498. # (muibld.exe gives errors on text files, and produces annoying
  499. # pop-up dialogs for directories)
  500. @FILE_LIST = ();
  501. foreach (@files) {
  502. if(-B "$LOCBINDIR\\$_") {
  503. push(@FILE_LIST, "$LOCBINDIR\\$_");
  504. }
  505. }
  506. foreach (@files2) {
  507. if(-B "$TMPDIR\\$_") {
  508. push(@FILE_LIST, "$TMPDIR\\$_");
  509. }
  510. }
  511. # Append fusion files
  512. # @Fusion_filelist = `dir /s /b $_NTPOSTBLD\\asms\\*.dll $_NTPOSTBLD\\asms\\*.exe`;
  513. # foreach $filename (@Fusion_filelist)
  514. # {
  515. # chomp ($filename);
  516. # push(@FILE_LIST, $filename);
  517. # }
  518. logmsg ("Success: Get list of appropriate files to process.");
  519. return 1;
  520. } # MakeSourceFileList
  521. #-----------------------------------------------------------------------------
  522. # GenResDlls - loops over the file list, performs muibld, and logs output
  523. #-----------------------------------------------------------------------------
  524. sub GenResDlls {
  525. logmsg ("Loop over the file list, perform muibld, and log output");
  526. my($error, $resdlls_created, @resdlls, $total_resdlls);
  527. # Process each (binary) file in the source directory
  528. $resdlls_created = 0;
  529. foreach $_ (@FILE_LIST) {
  530. $error = &MuiBld($_);
  531. if(!$error) {
  532. $resdlls_created++;
  533. }
  534. }
  535. # Get total number of resource-only dlls in destination directory
  536. if(!opendir(TARGETDIR, $TARGETDIR)) {
  537. wrnmsg ("WARNING: Can't open $TARGETDIR");
  538. }
  539. @resdlls = grep /\.mui$/, readdir TARGETDIR;
  540. close(TARGETDIR);
  541. $total_resdlls = scalar(@resdlls);
  542. # Final messages
  543. logmsg ("RESULTS: Process Succeeded");
  544. logmsg ("Number of resource-only dlls created in:...........($resdlls_created)");
  545. logmsg (" $TARGETDIR");
  546. logmsg ("Total number of resource-only dlls in:.............($total_resdlls)");
  547. logmsg (" $TARGETDIR");
  548. return 1;
  549. }
  550. sub FindOriginalFile {
  551. my ($filename);
  552. my ($original_file);
  553. ($filename) = @_;
  554. #
  555. # If the US file exists and checksum feature is enabled, add the -c to muibld to embed the checksum.
  556. # The original file is the US English version of the file that $source file is localized against.
  557. #
  558. $original_file = "$USBINDIR\\$filename";
  559. if (-e $original_file) {
  560. return $original_file;
  561. } else {
  562. #
  563. # Check if the original file exists in %_NTTREE%\<LANG>\
  564. #
  565. $original_file = "$USBINDIR\\$LANG\\$filename";
  566. if (-e $original_file) {
  567. return $original_file;
  568. } else {
  569. #
  570. # Check if the original file exists in %_NTTREE%\lang\<LANG>\
  571. #
  572. $original_file = $USBINDIR . "\\lang\\$LANG\\$filename";
  573. if (-e $original_file) {
  574. return $original_file;
  575. }
  576. }
  577. }
  578. return "";
  579. }
  580. sub ExecuteProgram {
  581. $Last_Command = shift;
  582. @Last_Output = `$Last_Command`;
  583. chomp $_ foreach ( @Last_Output );
  584. return $Last_Output[0];
  585. }
  586. #-----------------------------------------------------------------------------
  587. # MuiBld - creates a resource dll for the input file, using muibld.exe
  588. # and link (but not if the corresponding resource dll already exists and is
  589. # newer than the input file).
  590. #-----------------------------------------------------------------------------
  591. sub MuiBld {
  592. # logmsg ("MUI build creates the resource dll's");
  593. my ($filename, $source, $resource, $resdll, $status, @stat, $resdll_time,
  594. $source_time, $muibld_command, $link_command, @trash);
  595. my ($original_file, $file_ver_string, $machine_flag);
  596. $source = shift;
  597. # Make sure target folder exist before calling MUIBLD and LINK
  598. if ($source =~ /\Q$LOCBINDIR\E\\(.*)/) {
  599. $filename = $1;
  600. $resource = "$RESDIR\\$1.res";
  601. $resdll = "$TARGETDIR\\$1.mui";
  602. if($resource =~ /(^\S+)\\([^\\]+)$/) {
  603. mkdir($1, 0777);
  604. }
  605. if($resdll =~ /(^\S+)\\([^\\]+)$/) {
  606. mkdir($1, 0777);
  607. }
  608. }
  609. else {
  610. errmsg ("$source: invalid file");
  611. return 0;
  612. }
  613. # If the source doesn't exist, return.
  614. if(! -e $source) {
  615. logmsg ("warning: $source not found");
  616. return 1;
  617. }
  618. # If the corresponding resource dll already exists and is newer than
  619. # the input file, return. (Unless the FORCE option has been set)
  620. if( -e $resdll && !$FORCE) {
  621. if(&ModAge($resdll) <= &ModAge($source)) {
  622. if($VERBOSE) {
  623. logmsg ("$source: $resdll already exists and is newer; conversion not performed.");
  624. }
  625. return 0;
  626. }
  627. }
  628. # Construct muibld command
  629. $muibld_command = "muibld.exe -l $LCID -i $RESOURCE_TYPES $source $resource 2>&1";
  630. if ($BuildChecksum) {
  631. $original_file = &FindOriginalFile($filename);
  632. if ($original_file =~ /\w+/) {
  633. $muibld_command = "muibld.exe -c $original_file -l $LCID -i $RESOURCE_TYPES $source $resource 2>&1";
  634. logmsg($muibld_command);
  635. } else {
  636. logmsg($muibld_command);
  637. wrnmsg ("$source: muibld.exe: The US version of this file ($original_file) is not found. Resource checksum is not included.");
  638. }
  639. } else {
  640. logmsg($muibld_command);
  641. }
  642. # If SAFEMODE is on, just print muibld command
  643. if($SAFEMODE) {
  644. print "$muibld_command\n";
  645. $status = 0;
  646. }
  647. # Execute muibld.exe for the appropriate language, localized binary, and
  648. # resource file.
  649. else {
  650. # Execute command
  651. @trash = `$muibld_command`;
  652. $status = $?/256;
  653. # Display warnings from muibld.exe
  654. if($VERBOSE) {
  655. SWITCH: {
  656. if($status >= 100) {
  657. wrnmsg ("$source: muibld.exe: SYSTEM ERROR $status");
  658. last SWITCH;
  659. }
  660. if($status >= 7) {
  661. wrnmsg ("$source: muibld.exe: TOO FEW ARGUMENTS");
  662. last SWITCH;
  663. }
  664. if($status == 6) {
  665. wrnmsg ("$source: muibld.exe: NO LANGUAGE_SPECIFIED");
  666. last SWITCH;
  667. }
  668. if($status == 5) {
  669. wrnmsg ("$source: muibld.exe: NO TARGET");
  670. last SWITCH;
  671. }
  672. if($status == 4) {
  673. wrnmsg ("$source: muibld.exe: NO SOURCE");
  674. last SWITCH;
  675. }
  676. if($status == 3) {
  677. wrnmsg ("$source: muibld.exe: LANGUAGE NOT IN SOURCE");
  678. last SWITCH;
  679. }
  680. if($status == 2) {
  681. wrnmsg ("$source: muibld.exe: NO RESOURCES");
  682. last SWITCH;
  683. }
  684. if($status == 1) {
  685. wrnmsg ("$source: muibld.exe: ONLY VERSION STAMP");
  686. last SWITCH;
  687. }
  688. }
  689. }
  690. }
  691. # Construct link command
  692. $machine_flag = $MACHINE;
  693. if ($MACHINE =~ /IA64/i && $original_file =~ /\w+/i) {
  694. $file_ver_string = &ExecuteProgram("filever $original_file");
  695. if ($file_ver_string =~ /i64/i) {
  696. $machine_flag = "IA64";
  697. }
  698. else {
  699. $machine_flag = "IX86";
  700. }
  701. }
  702. $link_command = "link /noentry /dll /nologo /nodefaultlib /machine:$machine_flag /out:$resdll $resource";
  703. # If SAFEMODE is on, just print link command
  704. if($SAFEMODE) {
  705. print "$link_command\n";
  706. }
  707. # If muibld.exe command failed, then the $status is non-zero.
  708. # Return $status to parent routine.
  709. if($status) {
  710. return $status;
  711. }
  712. # If the muibld.exe command was successful, execute link.exe for
  713. # the appropriate resource file and resource-only-dll.
  714. elsif( !$status ) {
  715. $? = 0; # Reset system error variable
  716. logmsg($link_command);
  717. # Execute command
  718. $message = `$link_command`;
  719. # Display error messages from link.exe
  720. if($message =~ /^LINK : (.*:.*)$/) {
  721. if($VERBOSE) {
  722. wrnmsg ("$source: link.exe: $1");
  723. }
  724. wrnmsg ("$source: link.exe: $1");
  725. return 0;
  726. }
  727. elsif($?) {
  728. $status = $?/256;
  729. if($status) {
  730. if($VERBOSE) {
  731. wrnmsg ("$source: link.exe: SYSTEM_ERROR $status");
  732. }
  733. wrnmsg ("$source: link.exe: SYSTEM_ERROR $status");
  734. return 0;
  735. }
  736. }
  737. elsif(! -e $resdll) {
  738. if($VERBOSE) {
  739. wrnmsg ("$source: link.exe: $resdll was not created");
  740. }
  741. wrnmsg ("$source: link.exe: $resdll was not created");
  742. return 0;
  743. }
  744. else {
  745. logmsg ("$source: created $resdll");
  746. return 0;
  747. }
  748. }
  749. return 1;
  750. } # MuiBld
  751. #-----------------------------------------------------------------------------
  752. # DeleteDelfiles - deletes files listed in delfile.txt
  753. #-----------------------------------------------------------------------------
  754. sub DeleteDelfiles {
  755. my($files_deleted, $file_errors, $total_delfiles);
  756. # Initial messages
  757. logmsg ("--------------------------------------------------------");
  758. logmsg ("BEGIN delfile.txt file deletes");
  759. logmsg ("--------------------------------------------------------");
  760. # Delete each of the files listed in delfile.txt
  761. ($files_deleted, $file_errors, $total_delfiles) = &DeleteFiles("$_NTPOSTBLD\\mui\\$Special_Lang", $DELFILE, 0);
  762. # Final messages
  763. if ($file_errors=~/0/i) {
  764. logmsg ("RESULTS: Process Succeeded");
  765. } else {
  766. logmsg ("RESULTS: Process Failed!");
  767. }
  768. logmsg ("Total number of files listed in:....................($total_delfiles)");
  769. logmsg (" $DELFILE");
  770. logmsg ("Number of delfile.txt files deleted from:...........($files_deleted)");
  771. logmsg (" $TARGETDIR");
  772. logmsg ("Number of errors:...................................($file_errors)");
  773. return 1;
  774. } # DeleteDelfiles
  775. #-----------------------------------------------------------------------------
  776. # RenameRenfiles - renames files listed in renfile.txt
  777. #-----------------------------------------------------------------------------
  778. sub RenameRenfiles {
  779. my($files_renamed, $file_errors, $total_renfiles);
  780. # Initial messages
  781. logmsg ("--------------------------------------------------------");
  782. logmsg ("BEGIN renfile.txt file rename");
  783. logmsg ("--------------------------------------------------------");
  784. # Rename files listed in renfile.txt
  785. ($files_renamed, $file_errors, $total_renfiles) = &RenameFiles("$_NTPOSTBLD\\mui\\$Special_Lang", "$_NTPOSTBLD\\mui\\$Special_Lang", $RENFILE, 0);
  786. # Final messages
  787. if ($file_errors=~/0/i) {
  788. logmsg ("RESULTS: Process Succeeded");
  789. } else {
  790. logmsg ("RESULTS: Process Failed!");
  791. }
  792. logmsg ("Total number of files listed in:.....................($total_renfiles)");
  793. # logmsg (" $RENFILE");
  794. logmsg ("Number of renfile.txt files renamed:.................($files_renamed)");
  795. logmsg ("Number of errors:....................................($file_errors)");
  796. return 1;
  797. } # RenameRenfiles
  798. #-----------------------------------------------------------------------------
  799. # CompressResDlls - compresses the resource dlls (& hlp|chm files)
  800. #-----------------------------------------------------------------------------
  801. sub CompressResDlls {
  802. my(@messages, $status, $exclude, $tmp_compressdir);
  803. # Initial messages
  804. logmsg ("--------------------------------------------------------");
  805. logmsg ("BEGIN compression");
  806. logmsg ("--------------------------------------------------------");
  807. #Create a hash-hash from the control file table
  808. ParseTable::parse_table_file($COMPEXCLUDEFILE, \%CompExFiles);
  809. # Compress the resource dlls, using compress.exe
  810. @filelist = `dir /a-d/s/b $TARGETDIR\\*.*`;
  811. foreach $file (@filelist) {
  812. chomp $file;
  813. $exclude = "no";
  814. $filename = $file;
  815. $filename =~/(\w*\.\w+)$/;
  816. $filename = $1;
  817. chomp $filename;
  818. if ($file !~ /\w*/) {
  819. next;
  820. }
  821. #Loop through all control file entries
  822. foreach $CompExFile (keys %CompExFiles) {
  823. if ($CompExFiles{$CompExFile}{FileType} =~ /^folder/i && $file =~ /\\$CompExFile\\/i) {
  824. if ($file =~ /\Q$TARGETDIR\E(\S*)\\[^\\]*/) {
  825. $tmp_compressdir = "$COMPDIR$1";
  826. mkdir($tmp_compressdir, 0777);
  827. logmsg ("No compression for:$filename");
  828. logmsg ("Copying $file -> $tmp_compressdir\\$filename");
  829. unless (copy($file, $tmp_compressdir)) {
  830. logmsg("$!");
  831. }
  832. }
  833. $exclude = "yes";
  834. last;
  835. } elsif ($filename eq $CompExFile) {
  836. logmsg ("No compression for:$filename");
  837. logmsg ("Copying $file -> $COMPDIR\\$filename");
  838. unless (copy($file, $COMPDIR)) {
  839. logmsg("$!");
  840. }
  841. $exclude = "yes";
  842. last;
  843. }
  844. }
  845. # If not excluded from compression
  846. if ($exclude eq "no") {
  847. $tmp_compressdir = $COMPDIR;
  848. foreach $ComponentFolder (@ComponentFolders) {
  849. # Skip blank
  850. if ($ComponentFolder eq "") {
  851. next;
  852. }
  853. # If component folder is in the file path
  854. if ($file =~ /\\\Q$ComponentFolder\E\\/i) {
  855. # Filter out component directory
  856. if ($file =~ /\Q$TARGETDIR\E(\S*)\\[^\\]*/) {
  857. # Append component dir to the compress dir
  858. $tmp_compressdir = "$COMPDIR$1";
  859. mkdir($tmp_compressdir, 0777);
  860. # Don't compress component's inf files
  861. if ($file =~ /.*\.inf/i && $file !~ /.*\.mui/i) {
  862. logmsg ("No compression for:$file");
  863. logmsg ("Copying $file -> $tmp_compressdir\\$file");
  864. copy($file, $tmp_compressdir);
  865. $exclude = "yes";
  866. }
  867. last;
  868. }
  869. }
  870. }
  871. # Starts compression
  872. if ($exclude eq "no") {
  873. $result = `compress.exe -d -zx21 -s -r $file $tmp_compressdir`;
  874. if($?) {
  875. $status = $?/256;
  876. errmsg ("error in compress.exe: $status");
  877. }
  878. # Print the output of compress.exe
  879. chomp $result;
  880. logmsg ($result);
  881. }
  882. # Print the output of compress.exe
  883. chomp $result;
  884. logmsg ($result);
  885. }
  886. }
  887. logmsg ("Success: Compress the files");
  888. return 1;
  889. } # CompressResDlls
  890. #-----------------------------------------------------------------------------
  891. # CopyCopyfiles - copies files listed in copyfile.txt
  892. #-----------------------------------------------------------------------------
  893. sub CopyCopyfiles {
  894. my($files_copied, $file_errors, $total_copyfiles);
  895. # Initial messages
  896. logmsg ("--------------------------------------------------------");
  897. logmsg ("BEGIN copyfile.txt file copy");
  898. logmsg ("--------------------------------------------------------");
  899. # Copy files listed in copyfile.txt to $COMPDIR
  900. # ($files_copied, $file_errors, $total_copyfiles) = &CopyFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $COPYFILE, 0);
  901. # workaround bug of Xcopy.exe
  902. $src_temp ="$_NTPOSTBLD\.mui.tmp";
  903. $dest_final="$_NTPOSTBLD\\mui\\$Special_Lang";
  904. if ( -e $src_temp) {
  905. system "rmdir /S /Q $src_temp";
  906. }
  907. mkdir($src_temp, 0777);
  908. if (-e $src_temp) {
  909. ($files_copied, $file_errors, $total_copyfiles) = &CopyFiles("$_NTPOSTBLD", "$src_temp", $COPYFILE, 0);
  910. unless (system "xcopy /evcirfy $src_temp $dest_final") {
  911. }
  912. system "rmdir /S /Q $src_temp";
  913. }
  914. else {
  915. logmsg ("Error: Create temp. folder for work around failed: $src_temp");
  916. ($files_copied, $file_errors, $total_copyfiles) = &CopyFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $COPYFILE, 0);
  917. }
  918. # Final messages
  919. if ($file_errors=~/0/i) {
  920. logmsg ("RESULTS: Process Succeeded");
  921. } else {
  922. logmsg ("RESULTS: Process Failed!");
  923. }
  924. logmsg ("Total number of files listed in:....................($total_copyfiles)");
  925. logmsg (" $COPYFILE");
  926. logmsg ("Number of copyfile.txt files copied to:.............($files_copied)");
  927. logmsg (" $COMPDIR");
  928. logmsg ("Number of errors:...................................($file_errors)");
  929. return 1;
  930. } # CopyCopyfiles
  931. #-----------------------------------------------------------------------------
  932. # CopyDroppedfiles - copies dropped files from \mui\drop
  933. #-----------------------------------------------------------------------------
  934. sub CopyDroppedfiles {
  935. my($files_copied, $file_errors, $total_copyfiles);
  936. # Initial messages
  937. logmsg ("--------------------------------------------------------");
  938. logmsg ("BEGIN \mui\drop file copy");
  939. logmsg ("--------------------------------------------------------");
  940. # Copy files from \mui\drop $COMPDIR
  941. ($files_copied, $file_errors, $total_copyfiles) = &CopyDropFiles("$_NTPOSTBLD\\mui\\drop", "$TARGETDIR", 0);
  942. # Final messages
  943. if ($file_errors=~/0/i) {
  944. logmsg ("RESULTS: Process Succeeded");
  945. } else {
  946. logmsg ("RESULTS: Process Failed!");
  947. }
  948. logmsg ("Total number of files listed in \mui\drop:............($total_copyfiles)");
  949. logmsg ("Number of \mui\drop files copied to:..................($files_copied)");
  950. logmsg (" $COMPDIR");
  951. logmsg ("Number of errors:...................................($file_errors)");
  952. return 1;
  953. } # CopyCopyfiles
  954. #-----------------------------------------------------------------------------
  955. # CopyIE5files - copies ie5 files over to a separate directory
  956. #-----------------------------------------------------------------------------
  957. sub CopyIE5files {
  958. my($ie5_files_copied, $ie5_file_errors, $total_ie5files, $web_files_copied,
  959. $web_file_errors, $total_webfiles, $total_files_in_dir, @files);
  960. # Initial messages
  961. logmsg ("--------------------------------------------------------");
  962. logmsg ("BEGIN ie5 file copy");
  963. logmsg ("--------------------------------------------------------");
  964. logmsg ("Copy files listed in the [Satellite.files.install] section of ie5ui.inf");
  965. $listfile = "$IE5DIR\\ie5ui.inf";
  966. if (-e $listfile) {
  967. $section = "Satellite.files.install";
  968. @filelist = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $listfile $section`;
  969. ($ie5_files_copied, $ie5_file_errors, $total_ie5files) = &CopyFileList ("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang\\$_BuildArch\\ie5", @filelist);
  970. # BUGBUG - For RTM, ARA/HEB get different *HTT for MUI than for loc build
  971. if($Special_Lang =~ /^(ara|heb)$/i) {
  972. $HTTDIR = "$_NTBINDIR\\loc\\mui\\$Special_Lang\\web";
  973. @messages=`xcopy /vy $HTTDIR\\* $IE5DIR\\ 2>&1`;
  974. logmsg (@messages);
  975. }
  976. }
  977. # Final messages
  978. logmsg ("RESULTS: Process Succeeded");
  979. logmsg ("Total number of ie5 files listed in:..................($total_ie5files)");
  980. logmsg (" $IE5FILE");
  981. logmsg ("Number of ie5 files copied to:........................($ie5_files_copied)");
  982. logmsg (" $IE5DIR");
  983. logmsg ("Number of ie5 file errors:............................($ie5_file_errors)");
  984. logmsg ("Total number of web files listed in:..................($total_webfiles)");
  985. logmsg (" $IE5FILE");
  986. logmsg ("Number of web files copied to:........................($web_files_copied)");
  987. logmsg (" $IE5DIR");
  988. logmsg ("Number of web file errors:............................($web_file_errors)");
  989. logmsg (" $IE5DIR");
  990. return 1;
  991. } # CopyIE5files
  992. #-----------------------------------------------------------------------------
  993. # CopyComponentfiles - copies compoents' files over to a separate directory
  994. #-----------------------------------------------------------------------------
  995. sub CopyComponentfiles {
  996. my($files_copied, $file_errors, $total_files, $total_components);
  997. # Initial messages
  998. logmsg ("--------------------------------------------------------");
  999. logmsg ("BEGIN component file copy");
  1000. logmsg ("--------------------------------------------------------");
  1001. logmsg ("Copy files listed in the installation section of component INF file.");
  1002. if ($_BuildArch =~ /ia64/i) {
  1003. if (-e "$_NTPOSTBLD\\build_logs\\cplocation.txt") {
  1004. system "del /f $_NTPOSTBLD\\build_logs\\cplocation.txt";
  1005. }
  1006. system "$RAZZLETOOLPATH\\PostBuildScripts\\cplocation.cmd /l:$Special_Lang";
  1007. }
  1008. if (-e $INFFILE)
  1009. {
  1010. # Get component list from MUI.INF
  1011. @filelist = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE "Components"`;
  1012. $total_components = 0;
  1013. foreach $Component (@filelist)
  1014. {
  1015. # Format: CompnentName=ComponentDirectory,ComponentINF_FileName,InstallationSection,UninstallationSection
  1016. # $1 ComponentName
  1017. # $2 ComponentDirectory
  1018. # $3 ComponentINF_FileName
  1019. # $4 InstallationSection
  1020. if ($Component !~ /\w/)
  1021. {
  1022. next;
  1023. }
  1024. if ($Component =~ /^\s*;/i)
  1025. {
  1026. next;
  1027. }
  1028. logmsg ("Process component : $Component");
  1029. if ($Component =~ /([^\=]*)=([^\,]*),([^\,]*),([^\,]*),(.*)/)
  1030. {
  1031. # All external components inf files have to be binplaced to mui\drop\[component dir]
  1032. $ComponentName = $1;
  1033. $ComponentDir = $2;
  1034. $ComponentInf = "$MUIDIR\\drop\\$2\\$3";
  1035. $ComponentInstallSection = $4;
  1036. $ComponentFolders[$total_components] = $2;
  1037. $total_components++;
  1038. if (-e $ComponentInf)
  1039. {
  1040. # Get INF file default file install section
  1041. @ComponentFileInstall = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $ComponentInf $ComponentInstallSection`;
  1042. logmsg ("Installing $ComponentInf $ComponentInstallSection");
  1043. foreach $ComponentInstall (@ComponentFileInstall)
  1044. {
  1045. logmsg ($ComponentInstall);
  1046. #Parse CopyFiles list
  1047. if ($ComponentInstall =~ /.*CopyFiles.*=(.*)/i)
  1048. {
  1049. $ComponentFileCopySections = $1;
  1050. #Loop through all sections
  1051. while ($ComponentFileCopySections ne "")
  1052. {
  1053. if ($ComponentFileCopySections =~ /([^\,]*),(.*)/i)
  1054. {
  1055. $ComponentFileCopySections = $2;
  1056. $CopyFileSectionName = $1;
  1057. }
  1058. else
  1059. {
  1060. $CopyFileSectionName = $ComponentFileCopySections;
  1061. $ComponentFileCopySections = "";
  1062. }
  1063. # Get copy file list
  1064. @ComponentFileList = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $ComponentInf $CopyFileSectionName`;
  1065. ($files_copied, $file_errors, $total_files) = &CopyFileList ("$_NTPOSTBLD", "$TARGETDIR\\$ComponentDir", @ComponentFileList);
  1066. # BUGBUG - For RTM, ARA/HEB get different *HTT for MUI than for loc build
  1067. if(($ComponentName =~ /ie5/i) && ($Special_Lang =~ /^(ara|heb)$/i && $1))
  1068. {
  1069. $HTTDIR = "$_NTBINDIR\\loc\\mui\\$Special_Lang\\web";
  1070. $IE5DIR = "$MUIDIR\\drop\\ie5";
  1071. @messages=`xcopy /vy $HTTDIR\\* $IE5DIR\\ 2>&1`;
  1072. logmsg (@messages);
  1073. }
  1074. # Final messages
  1075. logmsg ("RESULTS: Process Succeeded");
  1076. logmsg ("Total number of $ComponentName-$CopyFileSectionName files listed in:..................($total_files)");
  1077. logmsg ("Number of $ComponentName-$CopyFileSectionName files copied to:........................($files_copied)");
  1078. logmsg ("Number of $ComponentName-$CopyFileSectionName file errors:............................($file_errors)");
  1079. }
  1080. }
  1081. }
  1082. }
  1083. }
  1084. else
  1085. {
  1086. logmsg ("Warning: Invalid INF file, please check $Component");
  1087. }
  1088. }
  1089. }
  1090. # Always success
  1091. return 1;
  1092. } # CopyComponentfiles
  1093. # Function to copy dropped external partners files
  1094. sub CopyDropFiles {
  1095. my ($SrcDir, $DestDir, $Incremental);
  1096. my (%CopyFiles, @CopyLangs, $files_copied, $file_errors, $total_files_copied);
  1097. #Pickup parameters
  1098. ($SrcDir, $DestDir, $Incremental) = @_;
  1099. #Set defaults
  1100. $files_copied = 0;
  1101. $file_errors = 0;
  1102. $total_files_copied = 0;
  1103. #Create the destination dir if it does not exist
  1104. unless (-e $DestDir) {
  1105. logmsg("Make dir:$DestDir");
  1106. &MakeDir($DestDir);
  1107. }
  1108. #Copy the files recursivly
  1109. system "xcopy /verifk $SrcDir $DestDir";
  1110. #Copy fusion manifest files
  1111. if (-e "$DestDir\\asms") {
  1112. #Remove previous copied files
  1113. system "rd /s /q $DestDir\\asms";
  1114. if (-e "$SrcDir\\asms\\$Special_Lang") {
  1115. logmsg("Copy fusion manifest files");
  1116. system "xcopy /verifk $SrcDir\\asms\\$Special_Lang $DestDir\\asms";
  1117. system "xcopy /verifk $SrcDir\\asms\\$Special_Lang $COMPDIR\\asms";
  1118. }
  1119. else {
  1120. logmsg("Warning: fusion $SrcDir\\asms\\$Special_Lang not found");
  1121. }
  1122. }
  1123. return ($files_copied, $file_errors, $total_files_copied);
  1124. }
  1125. sub CopyFusionFiles
  1126. {
  1127. my ($SrcDir, $DestDir);
  1128. my ($filename, @Manifest_filelist);
  1129. #Pickup parameters
  1130. ($SrcDir, $DestDir) = @_;
  1131. logmsg("Copying fusion manifest files");
  1132. #Search all manifest file.
  1133. @Manifest_filelist = `dir /s /b $SrcDir\\*.man`;
  1134. #For each manifest file, verify if the corresponding dll is already
  1135. #in the destination folder. If not, skip the manifest file copy.
  1136. foreach $filename (@Manifest_filelist)
  1137. {
  1138. chomp $filename;
  1139. if ($filename =~ /\Q$SrcDir\E(.*).man/i)
  1140. {
  1141. if (-e "$DestDir$1.dll" |
  1142. -e "$DestDir$1.exe" |
  1143. -e "$DestDir$1.dl_" |
  1144. -e "$DestDir$1.ex_")
  1145. {
  1146. system "xcopy /v /k $filename $DestDir$1.*";
  1147. }
  1148. }
  1149. }
  1150. return 1;
  1151. }
  1152. #Function to copy files using a specified control file
  1153. sub CopyFiles {
  1154. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  1155. my (%CopyFiles, @CopyLangs, $files_copied, $file_errors, $total_files_copied, $excludefile);
  1156. #Pickup parameters
  1157. ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental) = @_;
  1158. # Set defaults
  1159. $files_copied = 0;
  1160. $file_errors = 0;
  1161. $total_files_copied = 0;
  1162. #Use exclude file for recursive copies
  1163. $excludefile="$ENV{RazzleToolPath}\\PostBuildScripts\\muiexclude.txt";
  1164. #Create a hash-hash from the control file table
  1165. ParseTable::parse_table_file($ControlFile, \%CopyFiles);
  1166. #Loop through all control file entries
  1167. foreach $SrcFile (keys %CopyFiles) {
  1168. # Create file record hash
  1169. $CopyFileRecord{SourceFile} = $SrcFile;
  1170. $CopyFileRecord{SourceDir} = $CopyFiles{$SrcFile}{SourceDir};
  1171. $CopyFileRecord{DestFile} = $CopyFiles{$SrcFile}{DestFile};
  1172. $CopyFileRecord{DestDir} = $CopyFiles{$SrcFile}{DestDir};
  1173. $CopyFileRecord{Recursive} = $CopyFiles{$SrcFile}{Recursive};
  1174. $CopyFileRecord{Languages} = $CopyFiles{$SrcFile}{Languages};
  1175. #Preprocess file record hash
  1176. unless ($CopyFileRecord = &PreProcessRecord(\%CopyFileRecord) ) {
  1177. next;
  1178. }
  1179. #Process "-" entry in text file list
  1180. if ($CopyFileRecord->{SourceDir}=~/^-$/i) {
  1181. $SrcCopyFileDir="$SrcRootDir";
  1182. } else {
  1183. $SrcCopyFileDir="$SrcRootDir\\$CopyFileRecord->{SourceDir}";
  1184. }
  1185. if ($CopyFileRecord->{DestDir}=~/^-$/i) {
  1186. $DestCopyFileDir="$DestRootDir";
  1187. } else {
  1188. $DestCopyFileDir="$DestRootDir\\$CopyFileRecord->{DestDir}";
  1189. }
  1190. #Create the destination dir if it does not exist
  1191. unless (-e $DestCopyFileDir) {
  1192. &MakeDir($DestCopyFileDir);
  1193. }
  1194. $SrcCopyFile = "$SrcCopyFileDir\\$CopyFileRecord->{SourceFile}";
  1195. if ($CopyFileRecord->{DestFile}=~/^-$/i) {
  1196. $DestCopyFile = "$DestCopyFileDir";
  1197. } else {
  1198. $DestCopyFile = "$DestCopyFileDir\\$CopyFileRecord->{DestFile}";
  1199. }
  1200. if ($CopyFileRecord{Recursive}=~/(y|yes|true)/i) {
  1201. #Copy the files recursivly
  1202. if (-e $SrcCopyFileDir) {
  1203. unless (system "xcopy /evcirfy $SrcCopyFile $DestCopyFile /EXCLUDE:$excludefile") {
  1204. }
  1205. }
  1206. } else {
  1207. #Copy the file
  1208. for $SrcSingleCopyFile (glob "$SrcCopyFile") {
  1209. # Support multiple target files - file names separated by ','
  1210. @DestFiles = split /,/, $CopyFileRecord->{DestFile};
  1211. foreach $file (@DestFiles) {
  1212. if ($CopyFileRecord->{DestFile}=~/^-$/i) {
  1213. $DestCopyFile = "$DestCopyFileDir";
  1214. } else {
  1215. $DestCopyFile = "$DestCopyFileDir\\$file";
  1216. }
  1217. logmsg ("Copying $SrcSingleCopyFile -> $DestCopyFile");
  1218. $total_files_copied++;
  1219. if (copy("$SrcSingleCopyFile", "$DestCopyFile") ) {
  1220. $files_copied++;
  1221. } else {
  1222. logmsg("$!");
  1223. $file_errors++;
  1224. }
  1225. }
  1226. }
  1227. }
  1228. }
  1229. return ($files_copied, $file_errors, $total_files_copied);
  1230. }
  1231. #Function to validate a comma seperated lang list given a control lang
  1232. sub IsValidFileForLang {
  1233. #Declare local variables
  1234. my ($ValidFileLangs, $lang) = @_;
  1235. #Copy only for the specified languages in the control file
  1236. @ValidLangs = split /,/i, $ValidFileLangs;
  1237. unless (grep /(all|$lang)/i, @ValidLangs) {
  1238. return;
  1239. }
  1240. return 1;
  1241. }
  1242. #Function to preprocess a hashref file record list
  1243. sub PreProcessRecord {
  1244. #Declare local variables
  1245. my ($FileRecord) = @_;
  1246. #Verify arguments;
  1247. unless (@_ == 1 && ref($FileRecord) eq 'HASH') {
  1248. print "usage: HASHREF";
  1249. return;
  1250. }
  1251. #Validate language for file record
  1252. unless (&IsValidFileForLang($FileRecord->{Languages}, $Special_Lang) ) {
  1253. return;
  1254. }
  1255. #Sub in environment vars
  1256. foreach $field (keys %$FileRecord) {
  1257. while ( $FileRecord->{$field}=~/(%\w+%)/i ) {
  1258. $EnvVar=$1;
  1259. $CmdVar=$1;
  1260. $EnvVar=~s/%//ig;
  1261. $CmdValue=$ENV{$EnvVar};
  1262. #Environment value substutions
  1263. $CmdValue=~s/x86/i386/i;
  1264. #Substutute the environment values into the file record
  1265. $FileRecord->{$field}=~s/$CmdVar/$CmdValue/i;
  1266. }
  1267. }
  1268. return ($FileRecord);
  1269. }
  1270. #Function to copy files using a specified array of files
  1271. sub CopyFileList {
  1272. my ($SrcRootDir, $DestRootDir, $RootMUIFile, @FileList, $Incremental);
  1273. my ($files_copied, $file_errors, $total_files_copied, $RootMUIFile);
  1274. #Pickup parameters
  1275. ($SrcRootDir, $DestRootDir, @FileList, $Incremental) = @_;
  1276. # Set defaults
  1277. $files_copied = 0;
  1278. $file_errors = 0;
  1279. $total_files_copied = 0;
  1280. #Loop through all control file entries
  1281. foreach $SrcFile (@FileList) {
  1282. chomp $SrcFile;
  1283. #Don't process blank line
  1284. if ($SrcFile !~ /\w/) {
  1285. next;
  1286. }
  1287. $total_files_copied++;
  1288. #Create the destination dir if it does not exist
  1289. unless (-e $DestRootDir) {
  1290. &MakeDir($DestRootDir);
  1291. }
  1292. # Source file could be in the format of "[original file], [compressed file]"
  1293. if ($SrcFile =~ /(.*),\s*(.*)\s*/) {
  1294. $SrcFile = $2;
  1295. }
  1296. #Make sure source file doesn't contain MUI extension
  1297. if ($SrcFile =~ /(.*)\.mu_/i ||$SrcFile =~ /(.*)\.mui/i ) {
  1298. $SrcFile = $1;
  1299. }
  1300. $SrcCopyFile = "$SrcRootDir\\$SrcFile";
  1301. #Append .MUI to the file name
  1302. $DestCopyFile = "$DestRootDir\\$SrcFile.mui";
  1303. if (!(-e $SrcCopyFile)) {
  1304. $SrcCopyFile = "$SrcRootDir\\dump\\$SrcFile";
  1305. }
  1306. if (!(-e $SrcCopyFile)) {
  1307. $SrcCopyFile = "$SrcRootDir\\mui\\drop\\$SrcFile";
  1308. }
  1309. # For ia64, we need to try some extral step to get external files
  1310. # from wow64 or i386 release server
  1311. if (!(-e $SrcCopyFile) && ($_BuildArch =~ /ia64/i)) {
  1312. if (!(-e $SrcCopyFile)) {
  1313. $SrcCopyFile = "$SrcRootDir\\wowbins_uncomp\\$SrcFile";
  1314. }
  1315. if (!(-e $SrcCopyFile)) {
  1316. $SrcCopyFile = "$SrcRootDir\\wowbins\\$SrcFile";
  1317. }
  1318. if (-e "$_NTPOSTBLD\\build_logs\\cplocation.txt" && !(-e $SrcCopyFile)) {
  1319. if (open (X86_BIN, "$_NTPOSTBLD\\build_logs\\cplocation.txt")) {
  1320. $SrcRootDir = <X86_BIN>;
  1321. chomp ($SrcRootDir);
  1322. $SrcCopyFile = "$SrcRootDir\\$SrcFile";
  1323. if (!(-e $SrcCopyFile)) {
  1324. $SrcCopyFile = "$SrcRootDir\\dump\\$SrcFile";
  1325. }
  1326. if (!(-e $SrcCopyFile)) {
  1327. $SrcCopyFile = "$SrcRootDir\\mui\\drop\\$SrcFile";
  1328. }
  1329. logmsg("Copy $SrcCopyFile from i386 release");
  1330. close (X86_BIN);
  1331. }
  1332. }
  1333. }
  1334. $RootMUIFile = "$DestRootDir\\..\\$SrcFile.mui";
  1335. if (-e $RootMUIFile) {
  1336. logmsg ("Copying $RootMUIFile -> $DestCopyFile");
  1337. if (copy("$RootMUIFile", "$DestCopyFile") ) {
  1338. if (unlink $RootMUIFile)
  1339. {
  1340. logmsg ("Deleting $RootMUIFile");
  1341. }
  1342. $files_copied++;
  1343. } else {
  1344. logmsg("$!");
  1345. $file_errors++;
  1346. }
  1347. }
  1348. elsif (-e $SrcCopyFile) {
  1349. logmsg ("Copying $SrcCopyFile -> $DestCopyFile");
  1350. if (copy("$SrcCopyFile", "$DestCopyFile") ) {
  1351. $files_copied++;
  1352. } else {
  1353. logmsg("$!");
  1354. $file_errors++;
  1355. }
  1356. }
  1357. elsif (!($SrcCopyFile =~ /\.inf/i))
  1358. {
  1359. logmsg("warning: $SrcCopyFile not found");
  1360. }
  1361. }
  1362. return ($files_copied, $file_errors, $total_files_copied);
  1363. }
  1364. #Function to rename files using a specifiec control file
  1365. sub RenameFiles {
  1366. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  1367. my (%RenFiles, @RenLangs, $files_renamed, $file_errors, $total_files_renamed);
  1368. #Pickup parameters
  1369. ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental) = @_;
  1370. # Set defaults
  1371. $files_renamed = 0;
  1372. $file_errors = 0;
  1373. $total_files_renamed = 0;
  1374. #Create a hash-hash from the control file table
  1375. ParseTable::parse_table_file($ControlFile, \%RenFiles);
  1376. #Loop through all control file entries
  1377. foreach $SrcFile (keys %RenFiles) {
  1378. # Create file record hash
  1379. $RenFileRecord{SourceFile} = $SrcFile;
  1380. $RenFileRecord{SourceDir} = $RenFiles{$SrcFile}{SourceDir};
  1381. $RenFileRecord{DestFile} = $RenFiles{$SrcFile}{DestFile};
  1382. $RenFileRecord{DestDir} = $RenFiles{$SrcFile}{DestDir};
  1383. $RenFileRecord{Languages} = $RenFiles{$SrcFile}{Languages};
  1384. #Preprocess file record hash
  1385. unless ($RenFileRecord = &PreProcessRecord(\%RenFileRecord) ) {
  1386. next;
  1387. }
  1388. #Process "-" entry in text file list
  1389. if ($RenFileRecord->{SourceDir}=~/^-$/i) {
  1390. $SrcRenFileDir="$SrcRootDir";
  1391. } else {
  1392. $SrcRenFileDir="$SrcRootDir\\$RenFileRecord->{SourceDir}";
  1393. }
  1394. if ($RenFileRecord->{DestDir}=~/^-$/i) {
  1395. $DestRenFileDir="$DestRootDir";
  1396. } else {
  1397. $DestRenFileDir="$DestRootDir\\$RenFileRecord->{DestDir}";
  1398. }
  1399. #Create the destination dir if it does not exist
  1400. unless (-e $DestRenFileDir) {
  1401. &MakeDir($DestRenFileDir);
  1402. }
  1403. $SrcRenFile = "$SrcRenFileDir\\$SrcFile";
  1404. if ($RenFileRecord->{DestFile}=~/^-$/i) {
  1405. $DestRenFile = "$DestRenFileDir";
  1406. } else {
  1407. $DestRenFile = "$DestRenFileDir\\$RenFileRecord->{DestFile}";
  1408. }
  1409. #Rename the file
  1410. for $SrcSingleRenFile (glob "$SrcRenFile") {
  1411. logmsg ("Rename $SrcSingleRenFile -> $DestRenFile");
  1412. $total_files_renamed++;
  1413. if (rename("$SrcSingleRenFile", "$DestRenFile") ) {
  1414. $files_renamed++;
  1415. } else {
  1416. logmsg("$!");
  1417. $file_errors++;
  1418. }
  1419. }
  1420. }
  1421. return ($files_renamed, $file_errors, $total_files_renamed);
  1422. }
  1423. #Function to move files using a specifiec control file
  1424. sub MoveFiles {
  1425. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  1426. my (%MoveFiles, @MoveLangs, $files_moved, $file_errors, $total_files_moved);
  1427. #Pickup parameters
  1428. ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental) = @_;
  1429. # Set defaults
  1430. $files_moved = 0;
  1431. $file_errors = 0;
  1432. $total_files_moved = 0;
  1433. #Create a hash-hash from the control file table
  1434. ParseTable::parse_table_file($ControlFile, \%MoveFiles);
  1435. #Loop through all control file entries
  1436. foreach $SrcFile (keys %MoveFiles) {
  1437. # Create file record hash
  1438. $MoveFileRecord{SourceFile} = $SrcFile;
  1439. $MoveFileRecord{SourceDir} = $MoveFiles{$SrcFile}{SourceDir};
  1440. $MoveFileRecord{DestFile} = $MoveFiles{$SrcFile}{DestFile};
  1441. $MoveFileRecord{DestDir} = $MoveFiles{$SrcFile}{DestDir};
  1442. $MoveFileRecord{Languages} = $MoveFiles{$SrcFile}{Languages};
  1443. #Preprocess file record hash
  1444. unless ($MoveFileRecord = &PreProcessRecord(\%MoveFileRecord) ) {
  1445. next;
  1446. }
  1447. #Process "-" entry in text file list
  1448. if ($MoveFileRecord->{SourceDir}=~/^-$/i) {
  1449. $SrcMoveFileDir="$SrcRootDir";
  1450. } else {
  1451. $SrcMoveFileDir="$SrcRootDir\\$MoveFileRecord->{SourceDir}";
  1452. }
  1453. if ($MoveFileRecord->{DestDir}=~/^-$/i) {
  1454. $DestMoveFileDir="$DestRootDir";
  1455. } else {
  1456. $DestMoveFileDir="$DestRootDir\\$MoveFileRecord->{DestDir}";
  1457. }
  1458. #Create the destination dir if it does not exist
  1459. unless (-e $DestMoveFileDir) {
  1460. &MakeDir($DestMoveFileDir);
  1461. }
  1462. $SrcMoveFile = "$SrcMoveFileDir\\$MoveFileRecord->{SourceFile}";
  1463. if ($MoveFileRecord->{DestFile}=~/^-$/i) {
  1464. $DestMoveFile = "$DestMoveFileDir";
  1465. } else {
  1466. $DestMoveFile = "$DestMoveFileDir\\$MoveFileRecord->{DestFile}";
  1467. }
  1468. #Move the file
  1469. for $SrcSingleMoveFile (glob "$SrcMoveFile") {
  1470. logmsg ("Copying $SrcSingleMoveFile -> $DestMoveFile");
  1471. $total_files_moved++;
  1472. if (move("$SrcSingleMoveFile", "$DestMoveFile") ) {
  1473. $files_moved++;
  1474. } else {
  1475. logmsg("$!");
  1476. $file_errors++;
  1477. }
  1478. }
  1479. }
  1480. return ($files_moved, $file_errors, $total_files_moved);
  1481. }
  1482. #Function to delete files using a specifiec control file
  1483. sub DeleteFiles {
  1484. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  1485. my (%DelFiles, @ValidLangs, $files_deleted, $file_errors, $total_files_deleted);
  1486. #Pickup parameters
  1487. ($SrcRootDir, $ControlFile, $Incremental) = @_;
  1488. # Set defaults
  1489. $files_deleted = 0;
  1490. $file_errors = 0;
  1491. $total_files_deleted = 0;
  1492. #Create a hash-hash from the control file table
  1493. ParseTable::parse_table_file($ControlFile, \%DelFiles);
  1494. #Loop through all control file entries
  1495. foreach $SrcFile (keys %DelFiles) {
  1496. # Create file record hash
  1497. $DelFileRecord{SourceFile} = $SrcFile;
  1498. $DelFileRecord{SourceDir} = $DelFiles{$SrcFile}{SourceDir};
  1499. $DelFileRecord{Languages} = $DelFiles{$SrcFile}{Languages};
  1500. #Preprocess file record hash
  1501. unless ($DelFileRecord = &PreProcessRecord(\%DelFileRecord) ) {
  1502. next;
  1503. }
  1504. #Process "-" entry in text file list
  1505. if ($DelFileRecord->{SourceDir}=~/^-$/i) {
  1506. $SrcDelFileDir="$SrcRootDir";
  1507. } else {
  1508. $SrcDelFileDir="$SrcRootDir\\$DelFileRecord->{SourceDir}";
  1509. }
  1510. $SrcDelFile = "$SrcDelFileDir\\$DelFileRecord->{SourceFile}";
  1511. #Delete the file
  1512. for $SrcSingleDelFile (glob "$SrcDelFile") {
  1513. logmsg ("Deleting $SrcSingleDelFile");
  1514. $total_files_deleted++;
  1515. if (-e $SrcSingleDelFile) {
  1516. if (unlink $SrcSingleDelFile) {
  1517. $files_deleted++;
  1518. } else {
  1519. logmsg("$!");
  1520. $file_errors++;
  1521. }
  1522. }
  1523. }
  1524. }
  1525. return ($files_deleted, $file_errors, $total_files_deleted);
  1526. }
  1527. #Function to extract files from a cab file using a specifiec control file
  1528. sub ExtractFiles {
  1529. my ($CabRootDir, $ExtractRootDir, $ControlFile, $Incremental);
  1530. my (%ExtractFiles, @ExtractLangs, $files_extracted, $file_errors, $total_files_extracted);
  1531. #Pickup parameters
  1532. ($CabRootDir, $ExtractRootDir, $ControlFile, $Incremental) = @_;
  1533. # Set defaults
  1534. $files_extracted = 0;
  1535. $file_errors = 0;
  1536. $total_files_extracted = 0;
  1537. #Create a hash-hash from the control file table
  1538. ParseTable::parse_table_file($ControlFile, \%ExtractFiles);
  1539. #Loop through all control file entries
  1540. foreach $ExtractFile (keys %ExtractFiles) {
  1541. # Create file record hash
  1542. $ExtractFileRecord{ExtractFile} = $ExtractFile;
  1543. $ExtractFileRecord{ExtractDir} = $ExtractFiles{$ExtractFile}{ExtractDir};
  1544. $ExtractFileRecord{CabFile} = $ExtractFiles{$ExtractFile}{CabFile};
  1545. $ExtractFileRecord{CabDir} = $ExtractFiles{$ExtractFile}{CabDir};
  1546. $ExtractFileRecord{Languages} = $ExtractFiles{$ExtractFile}{Languages};
  1547. #Preprocess file record hash
  1548. unless ($ExtractFileRecord = &PreProcessRecord(\%ExtractFileRecord) ) {
  1549. next;
  1550. }
  1551. #Process "-" entry in text file list
  1552. if ($ExtractFileRecord->{CabDir}=~/^-$/i) {
  1553. $CabFileDir="$CabRootDir";
  1554. } else {
  1555. $CabFileDir="$CabRootDir\\$ExtractFileRecord->{CabDir}";
  1556. }
  1557. if ($ExtractFileRecord->{ExtractDir}=~/^-$/i) {
  1558. $ExtractFileDir="$ExtractRootDir";
  1559. } else {
  1560. $ExtractFileDir="$ExtractRootDir\\$ExtractFileRecord->{ExtractDir}";
  1561. }
  1562. #Create the destination dir if it does not exist
  1563. unless (-e $ExtractFileDir) {
  1564. &MakeDir($ExtractFileDir);
  1565. }
  1566. $CabFile = "$CabFileDir\\$ExtractFileRecord->{CabFile}";
  1567. if ($ExtractFileRecord->{ExtractFile}=~/^-$/i) {
  1568. $ExtractFile = "$ExtractFileDir";
  1569. } else {
  1570. $ExtractFile = "$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}";
  1571. }
  1572. #Extract the file
  1573. logmsg ("extract.exe /y /l $ExtractFileDir $CabFile $ExtractFileRecord->{ExtractFile}");
  1574. $total_files_extracted++;
  1575. if (-e $CabFile) {
  1576. if (!system ("extract.exe /y /l $ExtractFileDir $CabFile $ExtractFileRecord->{ExtractFile}") ) {
  1577. $files_extracted++;
  1578. rename("$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}", "$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}\.mui");
  1579. $files_extracted++;
  1580. }
  1581. } else {
  1582. logmsg ("Cabinet file:$CabFile not found!");
  1583. }
  1584. }
  1585. return ($files_extracted, $file_errors, $total_files_extracted);
  1586. }
  1587. #Function to copy a directory given a filter
  1588. sub CopyDir {
  1589. my ($SrcDir, $DestDir, $FileFilter, $Incremental);
  1590. my (@CopyFiles, $files_copied, $file_errors, $total_files_copied);
  1591. ($SrcDir, $DestDir, $FileFilter, $Incremental) = @_;
  1592. #If a file filter is not defined set a file filter of *.
  1593. if (!defined $FileFilter) {$FileFilter ="*"};
  1594. #Create the destination dir if it does not exist
  1595. unless (-e $DestDir) {
  1596. &MakeDir($DestDir);
  1597. }
  1598. my $LocalDirHandle = DirHandle->new($SrcDir);
  1599. @CopyFiles = sort grep {-f} map {"$SrcDir\\$_"} grep {!/^\./} grep {/\.$FileFilter$/i} $LocalDirHandle->read();
  1600. foreach $SrcCopyFile (@CopyFiles) {
  1601. #Copy the file
  1602. logmsg ("Copying $SrcCopyFile -> $DestDir");
  1603. if (copy("$SrcCopyFile", "$DestDir") ) {
  1604. $files_copied++;
  1605. } else {
  1606. logmsg("$!");
  1607. $file_errors++;
  1608. }
  1609. }
  1610. return;
  1611. }
  1612. # Function to create a directory
  1613. sub MakeDir {
  1614. my ($fulldir) = @_;
  1615. my ($drive, $path) = $fulldir =~ /((?:[a-z]:)|(?:\\\\[\w-]+\\[^\\]+))?(.*)/i;
  1616. logmsg ("Making dir:$fulldir");
  1617. my $thisdir = '';
  1618. for my $part ($path =~ /(\\[^\\]+)/g) {
  1619. $thisdir .= "$part";
  1620. mkdir( "$drive$thisdir", 0777 );
  1621. }
  1622. if ( ! -d $fulldir ) {
  1623. errmsg ("Could not mkdir:$fulldir $!");
  1624. return 0;
  1625. }
  1626. return;
  1627. }
  1628. #-----------------------------------------------------------------------------
  1629. # ModAge - returns (fractional) number of days since file was last modified
  1630. # NOTE: this script is necessary only because x86 and alpha give different
  1631. # answers to perl's file age functions:
  1632. # Alpha:
  1633. # -C = days since creation
  1634. # -M = days since last modification
  1635. # -A = days since last access
  1636. # X86:
  1637. # -C = days since last modification
  1638. # -M = days since last access
  1639. # -A = ???
  1640. #-----------------------------------------------------------------------------
  1641. sub ModAge {
  1642. my($file, $mod_age);
  1643. # Get input arguments
  1644. ($file) = @_;
  1645. # i386 uses -C when alpha uses -M
  1646. if($PROCESSOR =~ /^[iI]386$/) {
  1647. $mod_age = -C $file;
  1648. }
  1649. elsif($PROCESSOR =~ /^(ALPHA|Alpha|alpha)$/) {
  1650. $mod_age = -M $file;
  1651. }
  1652. return $mod_age;
  1653. } # ModAge
  1654. sub ValidateParams {
  1655. #<Add your code for validating the parameters here>
  1656. }
  1657. # <Add your usage here>
  1658. sub Usage {
  1659. print <<USAGE;
  1660. $0 - creates resource dlls for all files in relbins\<lang>
  1661. and populates the %_nt_bindir%\\mui tree
  1662. Creates language-specific resource only DLLs from localized
  1663. 32-bit images. These DLLs are used for the Multilingual User
  1664. Interface (MUI), aka pluggable UI product for NT5.
  1665. By default, does not create a resource-only-dll if there already
  1666. is one of the same name and it is newer than the localized binary.
  1667. Also Creates a language-specific version of ie5ui.inf,
  1668. and updates mui.inf to contain the current build number.
  1669. perl $0 [-f] [-v] <lang>
  1670. -f: Force option - overrides the incremental behavior of this script.
  1671. Overwrites output files (such as resource-only dlls) even if
  1672. they already exist and are newer than their input files (such as
  1673. the localized binaries).
  1674. -v: Verbose option - gives extra messages describing what is happening
  1675. to each file. By default, the only messages displayed are successes
  1676. and errors which abort the process.
  1677. lang: valid 2-letter (Dublin) or 3-letter (Redmond) code for a
  1678. language (There is no default value for lang)
  1679. OUTPUT
  1680. The language-specific resource-only DLLs are placed in:
  1681. %_NTBINDIR%\\mui\\<lang>\\%_BuildArch%
  1682. The language-specific resource files are placed in:
  1683. %_NTBINDIR%\\mui\\<lang>\\res
  1684. A logfile is created, named:
  1685. %_NTBINDIR%\\logs\\muigen.<lang>.log
  1686. Safemode: if you want the command echoed to stdout and not run,
  1687. set safemode=1
  1688. (This also turns off the logfile)
  1689. EXAMPLE
  1690. perl $0 ger
  1691. USAGE
  1692. }
  1693. sub GetParams {
  1694. # Step 1: Call pm getparams with specified arguments
  1695. &GetParams::getparams(@_);
  1696. # Step 2: Set the language into the enviroment
  1697. $ENV{lang}=$lang;
  1698. # Step 3: Call the usage if specified by /?
  1699. if ($HELP) {
  1700. &Usage();
  1701. exit 1;
  1702. }
  1703. }
  1704. # Cmd entry point for script.
  1705. if (eval("\$0 =~ /" . __PACKAGE__ . "\\.pm\$/i")) {
  1706. # Step 1: Parse the command line
  1707. # <run perl.exe GetParams.pm /? to get the complete usage for GetParams.pm>
  1708. &GetParams ('-o', 'fvl:', '-p', 'FORCE VERBOSE lang', @ARGV);
  1709. # Include local environment extensions
  1710. &LocalEnvEx::localenvex('initialize');
  1711. # Set lang from the environment
  1712. $LANG=$ENV{lang};
  1713. # Validate the option given as parameter.
  1714. &ValidateParams;
  1715. # Step 4: Call the main function
  1716. &muimake::Main();
  1717. # End local environment extensions.
  1718. &LocalEnvEx::localenvex('end');
  1719. }
  1720. # Copy MUI root files
  1721. sub CopyMUIRootFiles {
  1722. my ($layout);
  1723. my ($us_muisetup);
  1724. $layout = GetCDLayOut();
  1725. logmsg("Copy MUI root files");
  1726. system "xcopy /vy $MUIDIR\\*.* $MUI_RELEASE_DIR\\$layout\\*.*";
  1727. # muisetup.exe exists under US binary and it is a signed binary
  1728. # so we'll grab US version to prevent file protection issues
  1729. $us_muisetup = &FindOriginalFile("muisetup.exe");
  1730. if (-e $us_muisetup) {
  1731. system "xcopy /vy $us_muisetup $MUI_RELEASE_DIR\\$layout\\*.*";
  1732. system "xcopy /vy $us_muisetup $MUIDIR\\*.*";
  1733. logmsg ("Copy signed MUISETUP.EXE");
  1734. }
  1735. else
  1736. {
  1737. logmsg ("WARNING: signed MUISETUP.EXE not found");
  1738. }
  1739. return 1;
  1740. }
  1741. # Get CD layout from MUI.INF
  1742. sub GetCDLayOut {
  1743. my(@cd_layout, @lang_map, $muilang, $lang_id);
  1744. # Map lang
  1745. @lang_map = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE Languages`;
  1746. foreach $muilang (@lang_map)
  1747. {
  1748. if ($muilang =~ /(.*)=$LANG\.mui/i)
  1749. {
  1750. # Get layout
  1751. $langid = $1;
  1752. # Try ia64 section first if we're building ia64 MUI
  1753. if ($_BuildArch =~ /ia64/i)
  1754. {
  1755. @cd_layout = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE CD_LAYOUT_IA64`;
  1756. foreach $layout (@cd_layout)
  1757. {
  1758. chomp($layout);
  1759. if ($layout =~ /$langid=(\d+)/i)
  1760. {
  1761. return uc("cd$1");
  1762. }
  1763. }
  1764. }
  1765. @cd_layout = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE CD_LAYOUT`;
  1766. foreach $layout (@cd_layout)
  1767. {
  1768. chomp($layout);
  1769. if ($layout =~ /$langid=(\d+)/i)
  1770. {
  1771. return uc("cd$1");
  1772. }
  1773. }
  1774. last;
  1775. }
  1776. }
  1777. return lc("psu");
  1778. }
  1779. # -------------------------------------------------------------------------------------------
  1780. # Script: template_script.pm
  1781. # Purpose: Template perl perl script for the NT postbuild environment
  1782. # SD Location: %sdxroot%\tools\postbuildscripts
  1783. #
  1784. # (1) Code section description:
  1785. # CmdMain - Developer code section. This is where your work gets done.
  1786. # <Implement your subs here> - Developer subs code section. This is where you write subs.
  1787. #
  1788. # (2) Reserved Variables -
  1789. # $ENV{HELP} - Flag that specifies usage.
  1790. # $ENV{lang} - The specified language. Defaults to USA.
  1791. # $ENV{logfile} - The path and filename of the logs file.
  1792. # $ENV{logfile_bak} - The path and filename of the logfile.
  1793. # $ENV{errfile} - The path and filename of the error file.
  1794. # $ENV{tmpfile} - The path and filename of the temp file.
  1795. # $ENV{errors} - The scripts errorlevel.
  1796. # $ENV{script_name} - The script name.
  1797. # $ENV{_NTPostBld} - Abstracts the language from the files path that
  1798. # postbuild operates on.
  1799. # $ENV{_NTPostBld_Bak} - Reserved support var.
  1800. # $ENV{_temp_bak} - Reserved support var.
  1801. #
  1802. # (3) Reserved Subs -
  1803. # Usage - Use this sub to discribe the scripts usage.
  1804. # ValidateParams - Use this sub to verify the parameters passed to the script.
  1805. #
  1806. # (4) Call other executables or command scripts by using:
  1807. # system "foo.exe";
  1808. # Note that the executable/script you're calling with system must return a
  1809. # non-zero value on errors to make the error checking mechanism work.
  1810. #
  1811. # Example
  1812. # if (system("perl.exe foo.pl -l $lang")){
  1813. # errmsg("perl.exe foo.pl -l $lang failed.");
  1814. # # If you need to terminate function's execution on this error
  1815. # goto End;
  1816. # }
  1817. #
  1818. # (5) Log non-error information by using:
  1819. # logmsg "<log message>";
  1820. # and log error information by using:
  1821. # errmsg "<error message>";
  1822. #
  1823. # (6) Have your changes reviewed by a member of the US build team (ntbusa) and
  1824. # by a member of the international build team (ntbintl).
  1825. #
  1826. # -------------------------------------------------------------------------------------------
  1827. =head1 NAME
  1828. B<mypackage> - What this package for
  1829. =head1 SYNOPSIS
  1830. <An code example how to use>
  1831. =head1 DESCRIPTION
  1832. <Use above example to describe this package>
  1833. =head1 INSTANCES
  1834. =head2 <myinstances>
  1835. <Description of myinstances>
  1836. =head1 METHODS
  1837. =head2 <mymathods>
  1838. <Description of mymathods>
  1839. =head1 SEE ALSO
  1840. <Some related package or None>
  1841. =head1 AUTHOR
  1842. <Your Name <your e-mail address>>
  1843. =cut
  1844. 1;