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.

3548 lines
126 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 File::Basename;
  20. use IO::File;
  21. use lib $ENV{ "RazzleToolPath" };
  22. use lib $ENV{ "RazzleToolPath" } . "\\PostBuildScripts";
  23. use ParseArgs;
  24. use GetParams;
  25. use LocalEnvEx;
  26. use Logmsg;
  27. use strict;
  28. no strict 'vars';
  29. use HashText;
  30. use ParseTable;
  31. use File::Copy;
  32. use File::Find;
  33. use Cwd;
  34. use DirHandle;
  35. # Require section
  36. require Exporter;
  37. # Global variable section
  38. sub Main {
  39. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  40. # Begin Main code section
  41. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  42. # Return when you want to exit on error
  43. # <Implement your code here>
  44. # Make sure that text written to STDOUT and STDERR is displayed in correct order
  45. # $| = 1;
  46. # Check environment variables
  47. if (!&CheckEnv()) {
  48. wrnmsg ("The environment is not correct for MUI build.");
  49. return 1;
  50. }
  51. # Define some constants
  52. if (!&DefineConstants()) {
  53. errmsg ("The constants could not be defined.");
  54. return 0;
  55. }
  56. # Get language's LCID and ISO code
  57. if (!&GetCodes()) {
  58. errmsg ("The language's LCID and ISO code could note be extracted from the CODEFILE.");
  59. return 0;
  60. }
  61. # Make sure directories exist
  62. if (!&CheckDirs()) {
  63. errmsg ("The required directorys do not exist.");
  64. return 0;
  65. }
  66. # Update mui.inf with the current build number
  67. if (!&UpdateMuiinf()) {
  68. errmsg ("mui.inf could not be updated with the correct build number.");
  69. }
  70. #
  71. # Note: We also extract US binaries for the purpose of adding resource checksum
  72. # Extract files listed in extracts.txt
  73. if (!&ExtractCabFiles()) {
  74. errmsg ("The files listed in extracts.txt could not be extracted.");
  75. }
  76. #
  77. #Add *.MSI to extracted
  78. #Note: We also extract US binaries for the purpose of adding resource checksum
  79. #
  80. if (!&ExtractMSIFiles()) {
  81. errmsg("The files listed in extmsi.txt could not be extracted.");
  82. }
  83. # Get (filtered) contents of source directory
  84. if (!&MakeSourceFileList()) {
  85. errmsg ("Could not get the filtered contents of the source directory.");
  86. }
  87. # Generate resource dlls from the files in the source file list
  88. if (!&GenResDlls()) {
  89. errmsg ("");
  90. }
  91. # Rename the files listed in renfile.txt
  92. if (!&RenameRenfiles()) {
  93. errmsg ("");
  94. }
  95. #
  96. # Copy over the files listed in copyfile.txt
  97. # We also add resource checksum to the files
  98. #
  99. if (!&CopyCopyfiles()) {
  100. errmsg ("");
  101. }
  102. #
  103. # Copy over the files from \mui\drop
  104. #
  105. if (!&CopyDroppedfiles()) {
  106. errmsg ("");
  107. }
  108. #
  109. # Copy over the updated server files
  110. #
  111. if (!&CopyServerFiles()) {
  112. errmsg ("");
  113. }
  114. # Delete the files listed in delfile.txt
  115. if (!&DeleteDelfiles()) {
  116. errmsg ("");
  117. }
  118. #
  119. # BUG BUG: this is a temporary hack to get past the fact that uddi mui package has a file bullet.gif
  120. # that exists both under locbin and where uddi files are supposed to be picked up, we make a copy of this file
  121. # and rename it to bulletuddi.gif and will rename it back to bullet.gif during mui installation (uddimui.inf)
  122. #
  123. if (!&CopyRenameUDDIFile()) {
  124. errmsg ("");
  125. }
  126. #
  127. # Note: We also extract US binaries for the purpose of adding resource checksum
  128. # Copy over components' files to a separate directory
  129. #
  130. if (!&CopyComponentfiles()) {
  131. errmsg ("");
  132. }
  133. #
  134. # BUG BUG: delete the file we just renamed for uddi
  135. #
  136. if (!&DeleteRenameUDDIFile()) {
  137. errmsg ("");
  138. }
  139. # Compress the resource dlls (& CHM/CHQ/CNT files)
  140. if (!&CompressResDlls()) {
  141. errmsg ("");
  142. }
  143. # Fusion team has changed its MUI manifest implementation
  144. # Copy fusion files
  145. # if (!&CopyFusionFiles ("$_NTPOSTBLD\\asms", "$TARGETDIR\\asms") ||
  146. # !&CopyFusionFiles ("$_NTPOSTBLD\\asms", "$COMPDIR\\asms")) {
  147. # errmsg("");
  148. # }
  149. # Copy MUI tools to release share
  150. if (!&CopyMUIRootFiles()) {
  151. errmsg("");
  152. }
  153. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  154. # End Main code section
  155. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  156. }
  157. # <Implement your subs here>
  158. sub muimake {
  159. &Main();
  160. logmsg("This is a muimake test message");
  161. return 0;
  162. }
  163. sub CopyRenameUDDIFile {
  164. logmsg ("Renaming and copying $UDDIORIGFILE --> $UDDIRENAMEFILE.");
  165. $status = system("copy /Y $UDDIORIGFILE $UDDIRENAMEFILE");
  166. if($status) {
  167. logmsg ("WARNING: Copy/Rename $UDDIORIGFILE --> $UDDIRENAMEFILE failed!");
  168. }
  169. return 1;
  170. }
  171. sub DeleteRenameUDDIFile {
  172. logmsg ("Deleting $UDDIRENAMEFILE file.");
  173. $status = system("del /F /Q $UDDIRENAMEFILE");
  174. if($status) {
  175. logmsg ("WARNING: cannot find $UDDIRENAMEFILE to delete!");
  176. }
  177. return 1;
  178. }
  179. #-----------------------------------------------------------------------------
  180. # CheckEnv - validates necessary environment variables
  181. #-----------------------------------------------------------------------------
  182. sub CheckEnv {
  183. logmsg ("Validating the environment.");
  184. $RAZZLETOOLPATH=$ENV{RazzleToolPath};
  185. $_NTTREE=$ENV{_NTTREE};
  186. $_NTPOSTBLD=$ENV{_NTPOSTBLD};
  187. # if ($LANG=~/psu/i || $LANG=~/gb/i || $LANG=~/ca/i)
  188. # {
  189. # $_NTPOSTBLD="$ENV{_NTPostBld_Bak}\\psu";
  190. # }
  191. # logmsg ("Reset _NTPostBld for PSU to $_NTPOSTBLD");
  192. if ($LANG=~/psu_(.*)/i)
  193. {
  194. $Special_Lang=$1;
  195. }
  196. elsif ($LANG=~/psu/i || $LANG=~/mir/i || $LANG=~/FE/i)
  197. {
  198. if (defined( $ENV{"LANG_MUI"} ) )
  199. {
  200. $Special_Lang=$ENV{"LANG_MUI"};
  201. }
  202. elsif ($LANG=~/psu/i)
  203. {
  204. $Special_Lang="ro";
  205. }
  206. elsif ($LANG=~/FE/i)
  207. {
  208. $Special_Lang="jpn";
  209. }
  210. else
  211. {
  212. $Special_Lang="ara";
  213. }
  214. }
  215. else
  216. {
  217. $Special_Lang=$LANG;
  218. }
  219. logmsg ("------- special lang is $Special_Lang");
  220. $PROCESSOR=$ENV{PROCESSOR};
  221. if ($ENV{_BuildArch}=~/x86/i) {
  222. $_BuildArch="i386";
  223. } else {
  224. $_BuildArch=$ENV{_BuildArch};
  225. }
  226. $_BuildArch_Release=$ENV{_BuildArch};
  227. $LOGS=$ENV{temp};
  228. if ($ENV{_BuildType} =~ /^chk$/i) {
  229. wrnmsg ("This does not run on chk machines");
  230. return 0;
  231. }
  232. if(defined($SAFEMODE=$ENV{SAFEMODE})) {
  233. logmsg ("SAFEMODE is ON");
  234. }
  235. logmsg ("Success: Validating the environment.");
  236. return 1;
  237. } # CheckEnv
  238. #-----------------------------------------------------------------------------
  239. # DefineConstants - defines global constants
  240. #-----------------------------------------------------------------------------
  241. sub DefineConstants {
  242. my ($layout);
  243. logmsg ("Definition of global constants.");
  244. # Directories
  245. $LOCBINDIR = "$_NTPOSTBLD";
  246. $USBINDIR = "$_NTTREE";
  247. $MUIDIR = "$_NTPOSTBLD\\mui";
  248. $MUI_VALUEADD_DIR = "valueadd";
  249. $MUI_PRINTER_DRIVER_DIR = "printer";
  250. $MUI_NETFX_DIR = "netfx"; # .net framework folder name
  251. $MUI_RELEASE_DIR = "$MUIDIR\\release\\$_BuildArch_Release\\Temp"; # changing this to hide the classic muisetup packages
  252. $MUI_RELEASE_DIR2 = "$MUIDIR\\release\\$_BuildArch_Release";
  253. $CONTROLDIR = "$MUIDIR\\control";
  254. $TMPDIR = "$MUIDIR\\$Special_Lang\\tmp";
  255. $MSIDIR = "$MUIDIR\\msi";
  256. $RESDIR = "$MUIDIR\\$Special_Lang\\res";
  257. $TARGETDIR = "$MUIDIR\\$Special_Lang\\$_BuildArch.uncomp";
  258. #$COMPDIR = "$MUIDIR\\$Special_Lang\\$_BuildArch";
  259. $IE5DIR = "$MUIDIR\\drop\\ie5";
  260. # Filenames
  261. $CODEFILE = "$RAZZLETOOLPATH\\codes.txt";
  262. $INFFILE = "$MUIDIR\\mui.inf";
  263. $COPYFILE = "$CONTROLDIR\\copyfile.txt";
  264. $DELFILE = "$CONTROLDIR\\delfile.txt";
  265. $EXTFILE= "$CONTROLDIR\\extracts.txt";
  266. $EXTMSIFILE="$CONTROLDIR\\extmsi.txt";
  267. $RENFILE = "$CONTROLDIR\\renfile.txt";
  268. $COMPEXCLUDEFILE = "$CONTROLDIR\\compexclude.txt";
  269. $UDDIORIGFILE = "$LOCBINDIR\\uddi\\webroot\\help\\default\\images\\bullet.gif";
  270. $UDDIRENAMEFILE = "$LOCBINDIR\\uddi\\webroot\\help\\default\\images\\bulletuddi.gif";
  271. $layout = GetCDLayOut();
  272. $COMPDIR = "$MUI_RELEASE_DIR\\$layout\\$Special_Lang\.mui\\$_BuildArch";
  273. # Other Constants
  274. if($_BuildArch =~ /i386/i) {
  275. $MACHINE = "IX86";
  276. }
  277. elsif ($_BuildArch =~ /ia64/i) {
  278. $MACHINE = "IA64";
  279. }
  280. if ($LANG =~ /^(ARA|HEB)$/i) {
  281. $RESOURCE_TYPES = "2 3 4 5 6 9 10 11 14 16 HTML MOFDATA 23 240 1024 2110";
  282. }
  283. else {
  284. $RESOURCE_TYPES = "4 5 6 9 10 11 16 HTML MOFDATA 23 240 1024 2110";
  285. }
  286. logmsg ("Success: Definition of global constants.");
  287. $BuildChecksum=1;
  288. if ($BuildChecksum) {
  289. if (! -d $USBINDIR) {
  290. logmsg("Build Resource Checksum is enabled but $USBINDIR doesn't exist");
  291. $BuildChecksum=0;
  292. }
  293. }
  294. $UnlocalizedFilesDir="$_NTPOSTBLD\\mui\\$Special_Lang\\cabtemp";
  295. $WorkTempFolder ="$_NTPOSTBLD\\mui\\$Special_Lang\\RCCheckSumFiles";
  296. $MSITemp ="$_NTPOSTBLD\\mui\\$Special_Lang\\msitemp";
  297. #
  298. # Read renfile.txt into hash so that we may access in muibld() quickly
  299. #
  300. %Global_RenFiles={};
  301. ParseTable::parse_table_file($RENFILE, \%Global_RenFiles);
  302. return 1;
  303. } # DefineConstants
  304. #-----------------------------------------------------------------------------
  305. # GetCodes - gets the language's LCID and ISO language code from CODEFILE
  306. #-----------------------------------------------------------------------------
  307. sub GetCodes {
  308. logmsg ("Get the language's LCID and ISO language code form CODEFILE.");
  309. my(@data);
  310. # Don't allow nec_98 or CHT to be processed!
  311. if($Special_Lang =~ /^(NEC_98|CHT)$/i) {
  312. logmsg ("No MUI available for $Special_Lang");
  313. exit 0;
  314. }
  315. # Search CODEFILE for $Special_Lang, $LCID, $LANG_ISO, etc.
  316. if(!open(CODEFILE, "$CODEFILE")) {
  317. errmsg ("Can't open lcid file $CODEFILE for reading.");
  318. return 0;
  319. }
  320. CODES_LOOP: while (<CODEFILE>) {
  321. if (/^$Special_Lang\s+/i) {
  322. @data = split(/\s+/,$_);
  323. last CODES_LOOP;
  324. }
  325. }
  326. close(CODEFILE);
  327. if(!@data) {
  328. logmsg ("$Special_Lang is an unknown language");
  329. &Usage;
  330. return 0;
  331. }
  332. $LCID = $data[2];
  333. $LCID_SHORT = $LCID;
  334. $LCID_SHORT =~ s/^0x//;
  335. $LANG_ISO = $data[8];
  336. $GUID = $data[11];
  337. $LANG_NAME = $data[$#data]; # The comments are the last column
  338. logmsg ("Success: Get the language's LCID and ISO language code form CODEFILE.");
  339. return 1;
  340. } # GetCodes
  341. #-----------------------------------------------------------------------------
  342. # CheckDirs - makes sure that the necessary directories exist
  343. #-----------------------------------------------------------------------------
  344. sub CheckDirs {
  345. logmsg ("Make sure the necessary directories exist.");
  346. my($status);
  347. # Make sure the source directories exist
  348. foreach ($LOCBINDIR,$MUIDIR,$CONTROLDIR) {
  349. if(! -e $_) {
  350. logmsg ("$0: ERROR: $_ does not exist");
  351. return 0;
  352. }
  353. }
  354. # Make sure destination directories exist
  355. foreach ($IE5DIR,$TMPDIR,$RESDIR,$TARGETDIR,$COMPDIR) {
  356. if(! -e $_) {
  357. $status = system("md $_");
  358. if($status) {
  359. logmsg ("$0: ERROR: cannot create $_");
  360. return 0;
  361. }
  362. }
  363. }
  364. logmsg ("Success: Make sure the necessary directories exist.");
  365. return 1;
  366. } # CheckDirs
  367. #-----------------------------------------------------------------------------
  368. # UpdateMuiinf - updates mui.inf with current build number, and insert the filelayout from layout.inx
  369. #-----------------------------------------------------------------------------
  370. sub UpdateMuiinf {
  371. logmsg ("Update mui.inf with the current build number.");
  372. my(@inf_contents, $build_section, $build_line_found,
  373. @new_contents);
  374. my($filelayout_section, $bInFileLayoutSection, $tempFile, $genfilelayoutCmd, @newFileLayout);
  375. # Get current build number
  376. $LOGS="$_NTPOSTBLD\\build_logs";
  377. my $filename="$LOGS\\buildname.txt";
  378. open (BUILDNAME, "< $filename") or die "Can't open $filename for reading: $!\n";
  379. while (<BUILDNAME>) {
  380. $BLDNO = $_;
  381. $BLDNO =~ s/\.[\w\W]*//i;
  382. }
  383. close BUILDNAME;
  384. if ($BLDNO =~ /(^\d+)-*\d*$/) {
  385. $BLDNO = $1;
  386. }
  387. else
  388. {
  389. errmsg ("$BLDNO");
  390. return 0;
  391. }
  392. chomp($BLDNO);
  393. # Read $INFFILE
  394. if(!open(INFFILE, $INFFILE)) {
  395. errmsg ("Cannot open $INFFILE for reading.");
  396. return 0;
  397. }
  398. @inf_contents = <INFFILE>;
  399. close(INFFILE);
  400. # Modify contents in memory
  401. $build_section = 0;
  402. $build_line_found = 0;
  403. $filelayout_section = "[File_Layout]";
  404. $bInFileLayoutSection = 0;
  405. foreach (@inf_contents) {
  406. # update the flag if we have exited the filelayout inf section
  407. if ($bInFileLayoutSection)
  408. {
  409. # if we encounter a new section, we know that we have exited the filelayout section
  410. if (/^\[\w+\]$/)
  411. {
  412. $bInFileLayoutSection = 0;
  413. logmsg("Finished reading existing [File_Layout] section.");
  414. }
  415. }
  416. # If we find [Buildnumber] we're in the build_section.
  417. if(/^\[Buildnumber\]$/ && !$build_section) {
  418. $build_section = 1;
  419. }
  420. # If we find <something>=1 within the build section, replace
  421. # with $BLDNO and mark the end of the build section.
  422. elsif($build_section && /^(.*)=1$/) {
  423. s/^.*=1$/$BLDNO=1/;
  424. $build_line_found = 1;
  425. $build_section = 0;
  426. }
  427. # flag it if we are entering file layout section
  428. if (/^\[File_Layout\]$/)
  429. {
  430. logmsg("mui.inf contains a [File_Layout] section, deleting this section and generating a new one dynamically.");
  431. $bInFileLayoutSection = 1;
  432. }
  433. # we don't copy the current filelayout section contents, we will
  434. # generate it later dynamically
  435. if (!$bInFileLayoutSection)
  436. {
  437. push(@new_contents, $_);
  438. }
  439. }
  440. $tempFile = "$MSIDIR\\flayout.txt";
  441. $infDir = "$ENV{SDXROOT}\\MergedComponents\\SetupInfs";
  442. $layoutinxFile = "$infDir\\layout.inx";
  443. $layouttxtFile = "$infDir\\usa\\layout.txt";
  444. # call genfilelayout.pl to generate a new filelayoutsection
  445. if(-e "$ENV{RazzleToolPath}\\PostBuildScripts\\genfilelayout.pm") {
  446. logmsg ("perl $ENV{RazzleToolPath}\\PostBuildScripts\\GenFileLayout.pm $layoutinxFile $layouttxtFile $USBINDIR > $tempFile");
  447. $returnResult = system ("perl $ENV{RazzleToolPath}\\PostBuildScripts\\GenFileLayout.pm $layoutinxFile $layouttxtFile $USBINDIR > $tempFile");
  448. if ($returnResult)
  449. {
  450. logmsg("GenFileLayout.pm ERROR: unable to generate a new [File_Layout] section for mui.inf!");
  451. return 0;
  452. }
  453. }
  454. else
  455. {
  456. errmsg("Cannot find genfilelayout.pm script! cannot update mui.inf filelayout section!");
  457. return 0;
  458. }
  459. # copy the generated file_layout section into the new mui.inf content array
  460. if(!open(INFFILE, $tempFile)) {
  461. errmsg ("Cannot open $tempFile for reading.");
  462. return 0;
  463. }
  464. @newFileLayout = <INFFILE>;
  465. close(INFFILE);
  466. push(@new_contents, "\n");
  467. push(@new_contents, "$filelayout_section\n");
  468. foreach (@newFileLayout) {
  469. push(@new_contents, $_);
  470. }
  471. # If no build line was found, the format is wrong - error msg and exit
  472. if(!$build_line_found) {
  473. errmsg ("$INFFILE doesnt have the expected format.");
  474. logmsg ("Looking for:");
  475. logmsg ("[Buildnumber]");
  476. logmsg ("<something>=1");
  477. return 0;
  478. }
  479. # Overwrite $INFFILE (mui.inf) always - we need to do this to update the filelayout section
  480. if(!open(INFFILE, ">$INFFILE")) {
  481. errmsg ("Cannot open $INFFILE for writing.");
  482. return 0;
  483. }
  484. print INFFILE @new_contents;
  485. close(INFFILE);
  486. # Confirm the update
  487. logmsg ("$INFFILE successfully updated with Build Number = $BLDNO");
  488. logmsg ("$INFFILE successfully updated with the generated [File_Layout] section in $tempFile.");
  489. return 1;
  490. } # UpdateMuiinf
  491. #-----------------------------------------------------------------------------
  492. # Ie5Mui - creates a language-specific version of ie5ui.inf
  493. #-----------------------------------------------------------------------------
  494. sub Ie5Mui {
  495. logmsg ("Create a language-specific version of ie5ui.inf");
  496. my(@new_inf, $input_file, $output_file);
  497. $input_file = "$IE5FILE";
  498. $output_file = "$IE5DIR\\ie5ui.inf";
  499. # Check existence of input file
  500. if(!-e $input_file) {
  501. errmsg ("Can't find $input_file.");
  502. logmsg ("$output_file not created.");
  503. return 0;
  504. }
  505. # If the output file already exists and is newer than
  506. # the input file, return. (Unless the FORCE option has been set)
  507. if(-e $output_file) {
  508. if($VERBOSE) {
  509. logmsg ("$output_file already exists.");
  510. }
  511. if(&ModAge($output_file) <= &ModAge($input_file)) {
  512. if($VERBOSE) {
  513. logmsg ("$output_file is newer than $input_file");
  514. }
  515. if(!$FORCE) {
  516. if($VERBOSE) {
  517. logmsg ("$output_file will not be overwritten.");
  518. }
  519. logmsg ("Success: Create a language-specific version of ie5ui.inf");
  520. return 1;
  521. }
  522. else {
  523. if($VERBOSE) {
  524. logmsg ("FORCE option is ON - overwriting anyway.");
  525. }
  526. }
  527. }
  528. }
  529. if(!open(INPUTFILE, "$input_file")) {
  530. errmsg ("Cannot open $input_file for reading.");
  531. logmsg ("$output_file not created.");
  532. return 0;
  533. }
  534. while (<INPUTFILE>) {
  535. # Replace the human readable language names
  536. s/#LANGUAGE#/$LANG_NAME/g;
  537. # Replace the GUIDs
  538. s/#GUID#/$GUID/g;
  539. # Replace the iso language IDs
  540. s/#ISO#/$LANG_ISO/g;
  541. # Replace the LCIDS
  542. s/#LCID#/$LCID_SHORT/g;
  543. # Remove the SourceDiskName
  544. s/"Internet Explorer UI Satellite Kit"//g;
  545. push(@new_inf, $_);
  546. }
  547. close INPUTFILE;
  548. # Special case for Japanese
  549. if($LANG_ISO eq "JA") {
  550. push(@new_inf, "\n\[Run.MSGotUpd\]\n");
  551. push(@new_inf, "%49501%\\MUI\\0411\\msgotupd.exe \/q\n");
  552. }
  553. # Display and log any errors
  554. # (if @new_inf has 2 lines or less, it's probably an error)
  555. if(scalar(@new_inf) <= 2) {
  556. errmsg ("Error from $CONTROLDIR\\ie5mui.pl");
  557. foreach (@new_inf) {
  558. logmsg ($_);
  559. }
  560. logmsg ("$output_file not created");
  561. return 0;
  562. }
  563. # Write the output of ie5mui.pl to ie5ui.inf
  564. if(!open(OUTFILE,">$output_file")) {
  565. errmsg ("Can't open $output_file for writing.");
  566. logmsg ("$output_file not created.");
  567. return 0;
  568. }
  569. print OUTFILE @new_inf;
  570. close(OUTFILE);
  571. logmsg ("$output_file successfully created.");
  572. logmsg ("Success: Create a language-specific version of ie5ui.inf");
  573. return 1;
  574. } # Ie5Mui
  575. #-----------------------------------------------------------------------------
  576. # ExtractCabFiles - extracts files listed in extracts.txt from their cabfiles.
  577. #-----------------------------------------------------------------------------
  578. sub ExtractCabFiles {
  579. logmsg ("Extract files listed in extracts.txt from their cabfiles.");
  580. my($files_extracted, $file_errors, $total_extracts);
  581. # Initial messages
  582. logmsg ("--------------------------------------------------------");
  583. logmsg ("MUI Cab File Extraction");
  584. logmsg ("--------------------------------------------------------");
  585. # Extract files from their cabfiles
  586. ($files_extracted, $file_errors, $total_extracts) = &ExtractFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $EXTFILE, 0);
  587. # Final messages
  588. if ($file_errors=~/0/i) {
  589. logmsg ("RESULTS: Process Succeeded");
  590. } else {
  591. logmsg ("RESULTS: Process Failed!");
  592. }
  593. logmsg ("Total number of files listed in:....................($total_extracts)");
  594. logmsg (" $EXTFILE");
  595. logmsg ("Number of files extracted to:.......................($files_extracted)");
  596. logmsg (" $TARGETDIR");
  597. logmsg ("Number of errors:...................................($file_errors)");
  598. return 1;
  599. } # ExtractFiles
  600. #-----------------------------------------------------------------------------
  601. # ExtractMSIFiles - extracts msi files listed in extmsi.txt from their cabfiles.
  602. #-----------------------------------------------------------------------------
  603. sub ExtractMSIFiles {
  604. logmsg ("Extract files listed in extracts.txt from their cabfiles.");
  605. my($files_extracted, $file_errors, $total_extracts);
  606. # Initial messages
  607. logmsg ("--------------------------------------------------------");
  608. logmsg ("MUI .MSI File Extraction");
  609. logmsg ("--------------------------------------------------------");
  610. # Extract files from their msifiles
  611. ($files_extracted, $file_errors, $total_extracts) = &ExtractMSICabFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $EXTMSIFILE, 0);
  612. # Final messages
  613. if ($file_errors=~/0/i) {
  614. logmsg ("RESULTS: Process Succeeded");
  615. } else {
  616. logmsg ("RESULTS: Process Failed!");
  617. }
  618. logmsg ("Total number of files listed in:....................($total_extracts)");
  619. logmsg (" $EXTMSIFILE");
  620. logmsg ("Number of files extracted to:.......................($files_extracted)");
  621. logmsg (" $TARGETDIR");
  622. logmsg ("Number of errors:...................................($file_errors)");
  623. return 1;
  624. } # ExtractMSIFiles
  625. #-----------------------------------------------------------------------------
  626. # MakeSourceFileList - gets list of appropriate files to process
  627. #-----------------------------------------------------------------------------
  628. sub MakeSourceFileList {
  629. logmsg ("Get list of appropriate files to process.");
  630. my(@files,@files2,@Fusion_filelist,$filename);
  631. # Initial messages
  632. logmsg ("--------------------------------------------------------");
  633. logmsg ("MUI Resource-only dll Generation");
  634. logmsg ("--------------------------------------------------------");
  635. # Get contents of source directory
  636. if(!opendir(LOCBINDIR, $LOCBINDIR)) {
  637. errmsg ("Can't open $LOCBINDIR");
  638. return 0;
  639. }
  640. @files = grep !/\.(gpd|icm|ppd|bmp|txt|cab|cat|hlp|chm|chq|cnt|mfl)$/i, readdir LOCBINDIR;
  641. close(LOCBINDIR);
  642. if(!opendir(TMPDIR, $TMPDIR)) {
  643. errmsg ("Can't open $TMPDIR");
  644. return 0;
  645. }
  646. @files2 = grep !/\.(gpd|icm|ppd|bmp|txt|cab|cat|hlp|chm|chq|cnt|mfl)$/i, readdir TMPDIR;
  647. close(TMPDIR);
  648. # Filter out non-binaries, store in global @FILE_LIST
  649. # (muibld.exe gives errors on text files, and produces annoying
  650. # pop-up dialogs for directories)
  651. @FILE_LIST = ();
  652. foreach (@files) {
  653. if(-B "$LOCBINDIR\\$_") {
  654. push(@FILE_LIST, "$LOCBINDIR\\$_");
  655. }
  656. }
  657. foreach (@files2) {
  658. if(-B "$TMPDIR\\$_") {
  659. push(@FILE_LIST, "$TMPDIR\\$_");
  660. }
  661. }
  662. # Append fusion files
  663. # @Fusion_filelist = `dir /s /b $_NTPOSTBLD\\asms\\*.dll $_NTPOSTBLD\\asms\\*.exe`;
  664. # foreach $filename (@Fusion_filelist)
  665. # {
  666. # chomp ($filename);
  667. # push(@FILE_LIST, $filename);
  668. # }
  669. logmsg ("Success: Get list of appropriate files to process.");
  670. return 1;
  671. } # MakeSourceFileList
  672. #-----------------------------------------------------------------------------
  673. # GenResDlls - loops over the file list, performs muibld, and logs output
  674. #-----------------------------------------------------------------------------
  675. sub GenResDlls {
  676. logmsg ("Loop over the file list, perform muibld, and log output");
  677. my($error, $resdlls_created, @resdlls, $total_resdlls);
  678. # Process each (binary) file in the source directory
  679. $resdlls_created = 0;
  680. foreach $_ (@FILE_LIST) {
  681. $error = &MuiBld($_);
  682. if(!$error) {
  683. $resdlls_created++;
  684. }
  685. }
  686. # Get total number of resource-only dlls in destination directory
  687. if(!opendir(TARGETDIR, $TARGETDIR)) {
  688. wrnmsg ("WARNING: Can't open $TARGETDIR");
  689. }
  690. @resdlls = grep /\.mui$/, readdir TARGETDIR;
  691. close(TARGETDIR);
  692. $total_resdlls = scalar(@resdlls);
  693. # Final messages
  694. logmsg ("RESULTS: Process Succeeded");
  695. logmsg ("Number of resource-only dlls created in:...........($resdlls_created)");
  696. logmsg (" $TARGETDIR");
  697. logmsg ("Total number of resource-only dlls in:.............($total_resdlls)");
  698. logmsg (" $TARGETDIR");
  699. return 1;
  700. }
  701. sub FindOriginalFile {
  702. my ($filename);
  703. my ($original_file);
  704. ($filename) = @_;
  705. #
  706. # If the US file exists and checksum feature is enabled, add the -c to muibld to embed the checksum.
  707. # The original file is the US English version of the file that $source file is localized against.
  708. #
  709. $original_file = "$USBINDIR\\$filename";
  710. if (-e $original_file) {
  711. return $original_file;
  712. }
  713. #
  714. # We also extract nonlocalized files to $original_file_Unl (.cab , .msi)
  715. #
  716. else {
  717. #
  718. # Check if the original file exists in %_NTTREE%\<LANG>\
  719. #
  720. $original_file = "$USBINDIR\\$LANG\\$filename";
  721. if (-e $original_file) {
  722. return $original_file;
  723. } else {
  724. #
  725. # Check if the original file exists in %_NTTREE%\lang\<LANG>\
  726. #
  727. $original_file = $USBINDIR . "\\lang\\$LANG\\$filename";
  728. if (-e $original_file) {
  729. return $original_file;
  730. }
  731. }
  732. }
  733. return "";
  734. }
  735. sub ExecuteProgram {
  736. $Last_Command = shift;
  737. @Last_Output = `$Last_Command`;
  738. chomp $_ foreach ( @Last_Output );
  739. return $Last_Output[0];
  740. }
  741. #-----------------------------------------------------------------------------
  742. # MuiBld - creates a resource dll for the input file, using muibld.exe
  743. # and link (but not if the corresponding resource dll already exists and is
  744. # newer than the input file).
  745. #-----------------------------------------------------------------------------
  746. sub MuiBld {
  747. # logmsg ("MUI build creates the resource dll's");
  748. my ($filename, $source, $resource, $resdll, $status, @stat, $resdll_time,
  749. $source_time, $muibld_command, $link_command, @trash);
  750. my ($original_file, $file_ver_string, $machine_flag, $MyFilenName);
  751. $source = shift;
  752. # Make sure target folder exist before calling MUIBLD and LINK
  753. if ($source =~ /\Q$LOCBINDIR\E\\(.*)/) {
  754. $filename = $1;
  755. $resource = "$RESDIR\\$1.res";
  756. $resdll = "$TARGETDIR\\$1.mui";
  757. if($resource =~ /(^\S+)\\([^\\]+)$/) {
  758. mkdir($1, 0777);
  759. }
  760. if($resdll =~ /(^\S+)\\([^\\]+)$/) {
  761. mkdir($1, 0777);
  762. }
  763. }
  764. else {
  765. errmsg ("$source: invalid file");
  766. return 0;
  767. }
  768. # If the source doesn't exist, return.
  769. if(! -e $source) {
  770. logmsg ("warning: $source not found");
  771. return 1;
  772. }
  773. # If the corresponding resource dll already exists and is newer than
  774. # the input file, return. (Unless the FORCE option has been set)
  775. if( -e $resdll && !$FORCE) {
  776. if(&ModAge($resdll) <= &ModAge($source)) {
  777. if($VERBOSE) {
  778. logmsg ("$source: $resdll already exists and is newer; conversion not performed.");
  779. }
  780. return 0;
  781. }
  782. }
  783. # Construct muibld command
  784. $muibld_command = "muibld.exe -l $LCID -i $RESOURCE_TYPES $source $resource 2>&1";
  785. if ($BuildChecksum) {
  786. #
  787. # Important: Check if this file is listed in renfile.txt. If it's the case, we should use renamed file name as key
  788. # to find original file(unlocalized file)
  789. #
  790. $MyFilenName=$filename.".mui";
  791. if (&IsWin32File($filename) && defined ($Global_RenFiles{ $MyFilenName}) )
  792. {
  793. $MyFileName = $Global_RenFiles{$MyFilenName}{DestFile};
  794. if ($MyFileName =~ /(.*)\.mu_/i ||$MyFileName =~ /(.*)\.mui/i ) {
  795. $MyFileName = $1;
  796. }
  797. $original_file = &FindOriginalFile($MyFileName);
  798. }
  799. else {
  800. $original_file = &FindOriginalFile($filename);
  801. }
  802. if ($original_file =~ /\w+/) {
  803. $muibld_command = "muibld.exe -c $original_file -l $LCID -i $RESOURCE_TYPES $source $resource 2>&1";
  804. logmsg($muibld_command);
  805. } else {
  806. logmsg($muibld_command);
  807. wrnmsg ("$source: muibld.exe: The US version of this file ($original_file) is not found. Resource checksum is not included.");
  808. }
  809. } else {
  810. logmsg($muibld_command);
  811. }
  812. # If SAFEMODE is on, just print muibld command
  813. if($SAFEMODE) {
  814. print "$muibld_command\n";
  815. $status = 0;
  816. }
  817. # Execute muibld.exe for the appropriate language, localized binary, and
  818. # resource file.
  819. else {
  820. # Execute command
  821. @trash = `$muibld_command`;
  822. $status = $?/256;
  823. # Display warnings from muibld.exe
  824. if($VERBOSE) {
  825. SWITCH: {
  826. if($status >= 100) {
  827. wrnmsg ("$source: muibld.exe: SYSTEM ERROR $status");
  828. last SWITCH;
  829. }
  830. if($status >= 7) {
  831. wrnmsg ("$source: muibld.exe: TOO FEW ARGUMENTS");
  832. last SWITCH;
  833. }
  834. if($status == 6) {
  835. wrnmsg ("$source: muibld.exe: NO LANGUAGE_SPECIFIED");
  836. last SWITCH;
  837. }
  838. if($status == 5) {
  839. wrnmsg ("$source: muibld.exe: NO TARGET");
  840. last SWITCH;
  841. }
  842. if($status == 4) {
  843. wrnmsg ("$source: muibld.exe: NO SOURCE");
  844. last SWITCH;
  845. }
  846. if($status == 3) {
  847. wrnmsg ("$source: muibld.exe: LANGUAGE NOT IN SOURCE");
  848. last SWITCH;
  849. }
  850. if($status == 2) {
  851. wrnmsg ("$source: muibld.exe: NO RESOURCES");
  852. last SWITCH;
  853. }
  854. if($status == 1) {
  855. wrnmsg ("$source: muibld.exe: ONLY VERSION STAMP");
  856. last SWITCH;
  857. }
  858. }
  859. }
  860. }
  861. # Construct link command
  862. $machine_flag = $MACHINE;
  863. if ($MACHINE =~ /IA64/i && $original_file =~ /\w+/i) {
  864. $file_ver_string = &ExecuteProgram("filever $original_file");
  865. if ($file_ver_string =~ /i64/i) {
  866. $machine_flag = "IA64";
  867. }
  868. else {
  869. $machine_flag = "IX86";
  870. }
  871. }
  872. $link_command = "link /noentry /dll /nologo /nodefaultlib /machine:$machine_flag /out:$resdll $resource";
  873. # If SAFEMODE is on, just print link command
  874. if($SAFEMODE) {
  875. print "$link_command\n";
  876. }
  877. # If muibld.exe command failed, then the $status is non-zero.
  878. # Return $status to parent routine.
  879. if($status) {
  880. return $status;
  881. }
  882. # If the muibld.exe command was successful, execute link.exe for
  883. # the appropriate resource file and resource-only-dll.
  884. elsif( !$status ) {
  885. $? = 0; # Reset system error variable
  886. logmsg($link_command);
  887. # Execute command
  888. $message = `$link_command`;
  889. # Display error messages from link.exe
  890. if($message =~ /^LINK : (.*:.*)$/) {
  891. if($VERBOSE) {
  892. wrnmsg ("$source: link.exe: $1");
  893. }
  894. wrnmsg ("$source: link.exe: $1");
  895. return 0;
  896. }
  897. elsif($?) {
  898. $status = $?/256;
  899. if($status) {
  900. if($VERBOSE) {
  901. wrnmsg ("$source: link.exe: SYSTEM_ERROR $status");
  902. }
  903. wrnmsg ("$source: link.exe: SYSTEM_ERROR $status");
  904. return 0;
  905. }
  906. }
  907. elsif(! -e $resdll) {
  908. if($VERBOSE) {
  909. wrnmsg ("$source: link.exe: $resdll was not created");
  910. }
  911. wrnmsg ("$source: link.exe: $resdll was not created");
  912. return 0;
  913. }
  914. else {
  915. logmsg ("$source: created $resdll");
  916. return 0;
  917. }
  918. }
  919. return 1;
  920. } # MuiBld
  921. #-----------------------------------------------------------------------------
  922. # DeleteDelfiles - deletes files listed in delfile.txt
  923. #-----------------------------------------------------------------------------
  924. sub DeleteDelfiles {
  925. my($files_deleted, $file_errors, $total_delfiles);
  926. # Initial messages
  927. logmsg ("--------------------------------------------------------");
  928. logmsg ("BEGIN delfile.txt file deletes");
  929. logmsg ("--------------------------------------------------------");
  930. # Delete each of the files listed in delfile.txt
  931. ($files_deleted, $file_errors, $total_delfiles) = &DeleteFiles("$_NTPOSTBLD\\mui\\$Special_Lang", $DELFILE, 0);
  932. # Final messages
  933. if ($file_errors=~/0/i) {
  934. logmsg ("RESULTS: Process Succeeded");
  935. } else {
  936. logmsg ("RESULTS: Process Failed!");
  937. }
  938. logmsg ("Total number of files listed in:....................($total_delfiles)");
  939. logmsg (" $DELFILE");
  940. logmsg ("Number of delfile.txt files deleted from:...........($files_deleted)");
  941. logmsg (" $TARGETDIR");
  942. logmsg ("Number of errors:...................................($file_errors)");
  943. return 1;
  944. } # DeleteDelfiles
  945. #-----------------------------------------------------------------------------
  946. # RenameRenfiles - renames files listed in renfile.txt
  947. #-----------------------------------------------------------------------------
  948. sub RenameRenfiles {
  949. my($files_renamed, $file_errors, $total_renfiles);
  950. # Initial messages
  951. logmsg ("--------------------------------------------------------");
  952. logmsg ("BEGIN renfile.txt file rename");
  953. logmsg ("--------------------------------------------------------");
  954. # Rename files listed in renfile.txt
  955. ($files_renamed, $file_errors, $total_renfiles) = &RenameFiles("$_NTPOSTBLD\\mui\\$Special_Lang", "$_NTPOSTBLD\\mui\\$Special_Lang", $RENFILE, 0);
  956. # Final messages
  957. if ($file_errors=~/0/i) {
  958. logmsg ("RESULTS: Process Succeeded");
  959. } else {
  960. logmsg ("RESULTS: Process Failed!");
  961. }
  962. logmsg ("Total number of files listed in:.....................($total_renfiles)");
  963. # logmsg (" $RENFILE");
  964. logmsg ("Number of renfile.txt files renamed:.................($files_renamed)");
  965. logmsg ("Number of errors:....................................($file_errors)");
  966. return 1;
  967. } # RenameRenfiles
  968. #-----------------------------------------------------------------------------
  969. # CompressResDlls - compresses the resource dlls (& hlp|chm files)
  970. #-----------------------------------------------------------------------------
  971. sub CompressResDlls {
  972. my(@messages, $status, $exclude, $tmp_compressdir);
  973. # Initial messages
  974. logmsg ("--------------------------------------------------------");
  975. logmsg ("BEGIN compression");
  976. logmsg ("--------------------------------------------------------");
  977. #Create a hash-hash from the control file table
  978. ParseTable::parse_table_file($COMPEXCLUDEFILE, \%CompExFiles);
  979. # Compress the resource dlls, using compress.exe
  980. @filelist = `dir /a-d/s/b $TARGETDIR\\*.*`;
  981. foreach $file (@filelist) {
  982. chomp $file;
  983. $exclude = "no";
  984. $filename = $file;
  985. $filename =~/(\w*\.\w+)$/;
  986. $filename = $1;
  987. chomp $filename;
  988. if ($file !~ /\w*/) {
  989. next;
  990. }
  991. #Loop through all control file entries
  992. foreach $CompExFile (keys %CompExFiles) {
  993. if ($CompExFiles{$CompExFile}{FileType} =~ /^folder/i && $file =~ /\\$CompExFile\\/i) {
  994. if ($file =~ /\Q$TARGETDIR\E(\S*)\\[^\\]*/) {
  995. $tmp_compressdir = "$COMPDIR$1";
  996. mkdir($tmp_compressdir, 0777);
  997. logmsg ("No compression for:$filename");
  998. logmsg ("Copying $file -> $tmp_compressdir\\$filename");
  999. unless (copy($file, $tmp_compressdir)) {
  1000. logmsg("$!");
  1001. }
  1002. }
  1003. $exclude = "yes";
  1004. last;
  1005. } elsif ($filename eq $CompExFile) {
  1006. logmsg ("No compression for:$filename");
  1007. logmsg ("Copying $file -> $COMPDIR\\$filename");
  1008. unless (copy($file, $COMPDIR)) {
  1009. logmsg("$!");
  1010. }
  1011. $exclude = "yes";
  1012. last;
  1013. }
  1014. }
  1015. # If not excluded from compression
  1016. if ($exclude eq "no") {
  1017. $tmp_compressdir = $COMPDIR;
  1018. foreach $ComponentFolder (@ComponentFolders) {
  1019. # Skip blank
  1020. if ($ComponentFolder eq "") {
  1021. next;
  1022. }
  1023. # If component folder is in the file path
  1024. if ($file =~ /\\\Q$ComponentFolder\E\\/i) {
  1025. # Filter out component directory
  1026. if ($file =~ /\Q$TARGETDIR\E(\S*)\\[^\\]*/) {
  1027. # create the directory if needed by appending it part by part
  1028. # Append component dir to the compress dir
  1029. @dir_parts = split(/\\/, $1);
  1030. foreach $subdir (@dir_parts)
  1031. {
  1032. $tmp_compressdir = "$tmp_compressdir\\$subdir";
  1033. if (!-e $tmp_compressdir)
  1034. {
  1035. logmsg("CompressResDlls: Component Directory to create is $tmp_compressdir");
  1036. mkdir($tmp_compressdir, 0777);
  1037. }
  1038. }
  1039. # Don't compress component's inf files
  1040. if ($file =~ /.*\.inf/i && $file !~ /.*\.mui/i) {
  1041. logmsg ("No compression for:$file");
  1042. logmsg ("Copying $file -> $tmp_compressdir\\$file");
  1043. copy($file, $tmp_compressdir);
  1044. $exclude = "yes";
  1045. }
  1046. # if we encountered a '\' we keep searching for a component directory that matches the everything but the filename
  1047. if (scalar(@dir_parts) > 0)
  1048. {
  1049. last;
  1050. }
  1051. }
  1052. }
  1053. }
  1054. # Starts compression
  1055. if ($exclude eq "no") {
  1056. $result = `compress.exe -d -zx21 -s -r $file $tmp_compressdir`;
  1057. if($?) {
  1058. $status = $?/256;
  1059. errmsg ("error in compress.exe: $status");
  1060. }
  1061. # Print the output of compress.exe
  1062. chomp $result;
  1063. logmsg ($result);
  1064. }
  1065. # Print the output of compress.exe
  1066. chomp $result;
  1067. logmsg ($result);
  1068. }
  1069. }
  1070. logmsg ("Success: Compress the files");
  1071. return 1;
  1072. } # CompressResDlls
  1073. #-----------------------------------------------------------------------------
  1074. # CopyCopyfiles - copies files listed in copyfile.txt
  1075. #-----------------------------------------------------------------------------
  1076. sub CopyCopyfiles {
  1077. my($files_copied, $file_errors, $total_copyfiles);
  1078. # Initial messages
  1079. logmsg ("--------------------------------------------------------");
  1080. logmsg ("BEGIN copyfile.txt file copy");
  1081. logmsg ("--------------------------------------------------------");
  1082. # Copy files listed in copyfile.txt to $COMPDIR
  1083. # ($files_copied, $file_errors, $total_copyfiles) = &CopyFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $COPYFILE, 0);
  1084. # workaround bug of Xcopy.exe
  1085. $src_temp ="$_NTPOSTBLD\.mui.tmp";
  1086. $dest_final="$_NTPOSTBLD\\mui\\$Special_Lang";
  1087. if ( -e $src_temp) {
  1088. system "rmdir /S /Q $src_temp";
  1089. }
  1090. mkdir($src_temp, 0777);
  1091. if (-e $src_temp) {
  1092. ($files_copied, $file_errors, $total_copyfiles) = &CopyFiles("$_NTPOSTBLD", "$src_temp", $COPYFILE, 0);
  1093. unless (system "xcopy /evcirfy $src_temp $dest_final") {
  1094. }
  1095. system "rmdir /S /Q $src_temp";
  1096. }
  1097. else {
  1098. logmsg ("Error: Create temp. folder for work around failed: $src_temp");
  1099. ($files_copied, $file_errors, $total_copyfiles) = &CopyFiles("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang", $COPYFILE, 0);
  1100. }
  1101. # Final messages
  1102. if ($file_errors=~/0/i) {
  1103. logmsg ("RESULTS: Process Succeeded");
  1104. } else {
  1105. logmsg ("RESULTS: Process Failed!");
  1106. }
  1107. logmsg ("Total number of files listed in:....................($total_copyfiles)");
  1108. logmsg (" $COPYFILE");
  1109. logmsg ("Number of copyfile.txt files copied to:.............($files_copied)");
  1110. logmsg (" $COMPDIR");
  1111. logmsg ("Number of errors:...................................($file_errors)");
  1112. return 1;
  1113. } # CopyCopyfiles
  1114. #-----------------------------------------------------------------------------
  1115. # CopyDroppedfiles - copies dropped files from \mui\drop
  1116. #-----------------------------------------------------------------------------
  1117. sub CopyDroppedfiles {
  1118. my($files_copied, $file_errors, $total_copyfiles);
  1119. # Initial messages
  1120. logmsg ("--------------------------------------------------------");
  1121. logmsg ("BEGIN \mui\drop file copy");
  1122. logmsg ("--------------------------------------------------------");
  1123. # Copy files from \mui\drop $COMPDIR
  1124. ($files_copied, $file_errors, $total_copyfiles) = &CopyDropFiles("$_NTPOSTBLD\\mui\\drop", "$TARGETDIR", 0);
  1125. # Final messages
  1126. if ($file_errors=~/0/i) {
  1127. logmsg ("RESULTS: Process Succeeded");
  1128. } else {
  1129. logmsg ("RESULTS: Process Failed!");
  1130. }
  1131. logmsg ("Total number of files listed in \mui\drop:............($total_copyfiles)");
  1132. logmsg ("Number of \mui\drop files copied to:..................($files_copied)");
  1133. logmsg (" $COMPDIR");
  1134. logmsg ("Number of errors:...................................($file_errors)");
  1135. return 1;
  1136. } # CopyCopyfiles
  1137. #-----------------------------------------------------------------------------
  1138. # CopyServerFiles - copies dropped files from \mui\drop
  1139. #-----------------------------------------------------------------------------
  1140. sub CopyServerFiles {
  1141. my($srvinfpath, $destdir);
  1142. $srvinfpath = "$LOCBINDIR\\srvinf";
  1143. $destdir = "$TARGETDIR";
  1144. # Initial messages
  1145. logmsg ("------------------------------------------------------------------");
  1146. logmsg ("BEGIN Copying .hlp and .chm files from $srvinfpath to $destdir");
  1147. logmsg ("------------------------------------------------------------------");
  1148. #Copy the files recursivly
  1149. if (-e "$srvinfpath")
  1150. {
  1151. if (system("copy /Y $srvinfpath\\*.hlp $destdir"))
  1152. {
  1153. logmsg("WARNING: CopyServerFiles - copy hlp files failed.");
  1154. }
  1155. if (system("copy /Y $srvinfpath\\*.chm $destdir"))
  1156. {
  1157. logmsg("WARNING: CopyServerFiles - copy chm files failed.");
  1158. }
  1159. }
  1160. else
  1161. {
  1162. logmsg ("WARNING: CopyServerFiles - $srvinfpath does not exist!");
  1163. logmsg ("WARNING: CopyServerFiles - Updated server help files may be missing from the MUI build!");
  1164. }
  1165. return 1;
  1166. } # CopyServerFiles
  1167. #-----------------------------------------------------------------------------
  1168. # Build the hash for the string in [Strings] sections of a INF file
  1169. #-----------------------------------------------------------------------------
  1170. sub BuildUpStringSection
  1171. {
  1172. my ($INFPath, $pTheStringSection) = @_;
  1173. my (@Items, @StringItems, $Section, $Line, $Counter, $Start_idx,$End_idx);
  1174. $Section='Strings';
  1175. $Counter=0;
  1176. %$pTheStringSection={};
  1177. unless (open(INFILE,$INFPath))
  1178. {
  1179. return $Counter;
  1180. }
  1181. @Items=<INFILE>;
  1182. close(INFILE);
  1183. if ( !&GetTheSection($Section,\@Items,\@StringItems,\$Start_idx,\$End_idx))
  1184. {
  1185. return $Counter;
  1186. }
  1187. ;
  1188. foreach $Line (@StringItems)
  1189. {
  1190. chomp($Line);
  1191. if (length($Line) == 0)
  1192. {
  1193. next;
  1194. }
  1195. if ($Line !~ /\w/)
  1196. {
  1197. next;
  1198. }
  1199. if (substr($Line,0,1) eq ";")
  1200. {
  1201. next;
  1202. }
  1203. if ( $Line =~ /\s*(\S+)\s*=\s*(\S*)/ )
  1204. {
  1205. $$pTheStringSection {$1} = $2;
  1206. $Counter++;
  1207. }
  1208. }
  1209. return $Counter;
  1210. }
  1211. sub GetTheSection
  1212. {
  1213. my ($SectioName, $pItems, $pSectionContent, $Start_Idx, $End_Idx) = @_;
  1214. my ($Idx, $Limit, $InSection, $LeadingChar, $Line, $Pattern, $Result);
  1215. $Idx=0;
  1216. $InSection=0;
  1217. $Limit=scalar(@$pItems);
  1218. $Pattern='^\[' . $SectioName . '\]$';
  1219. $$Start_Idx = -1;
  1220. $$End_Idx = -1;
  1221. $Result=0;
  1222. for ($Idx=0; $Idx < $Limit; $Idx++)
  1223. {
  1224. #chomp($$pItems[$Idx]);
  1225. $Line=$$pItems[$Idx];
  1226. $LeadingChar=substr($Line,0,1);
  1227. if ($LeadingChar ne ";")
  1228. {
  1229. if ($LeadingChar eq "[")
  1230. {
  1231. if ( $Line =~ /$Pattern/i )
  1232. {
  1233. if ( ! $InSection)
  1234. {
  1235. $InSection = 1;
  1236. }
  1237. }
  1238. else
  1239. {
  1240. if ($InSection)
  1241. {
  1242. $$End_Idx=$Idx-1;
  1243. $InSection=0;
  1244. }
  1245. }
  1246. next;
  1247. }
  1248. if ($InSection)
  1249. {
  1250. if ($$Start_Idx == -1)
  1251. {
  1252. $$Start_Idx=$Idx;
  1253. }
  1254. push(@$pSectionContent,$Line);
  1255. }
  1256. }
  1257. }
  1258. if ($InSection && ($$End_Idx== -1 ))
  1259. {
  1260. $$End_Idx=$Idx-1;
  1261. }
  1262. if (($$Start_Idx != -1) && ($$End_Idx != -1))
  1263. {
  1264. $Result=1;
  1265. }
  1266. return $Result;
  1267. }
  1268. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  1269. #
  1270. # IsFusionResource --- Check if the binary contains fusion resource (#24)
  1271. #
  1272. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  1273. sub IsFusionResource
  1274. {
  1275. my ($FileName) = @_;
  1276. my (@Rsrc_Record,@Qualified,$Num, $Result, $Rsrc_Temp);
  1277. $Result = 0;
  1278. if (! -e $FileName)
  1279. {
  1280. return $Result;
  1281. }
  1282. $Rsrc_Temp = $FileName."rsrc.out";
  1283. #
  1284. # Call RSRC to check
  1285. #
  1286. system("rsrc.exe $FileName >$Rsrc_Temp 2>nul");
  1287. unless (open(RSRCFILE, $Rsrc_Temp))
  1288. {
  1289. errmsg("Can't open RSRC for $FileName");
  1290. return $Result;
  1291. }
  1292. @Rsrc_Record=<RSRCFILE>;
  1293. close (RSRCFILE);
  1294. #
  1295. # Scan the output of rsrc.exe.
  1296. #
  1297. @Qualified=grep /^\s{3}18/ , @Rsrc_Record;
  1298. $Num=scalar(@Qualified);
  1299. if ($Num > 0 )
  1300. {
  1301. $Result = 1;
  1302. }
  1303. if (-e $Rsrc_Temp)
  1304. {
  1305. system("del $Rsrc_Temp");
  1306. }
  1307. return $Result;
  1308. }
  1309. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  1310. #
  1311. # DoMUIizedForFiles --- Do MUI'ization for a localized file
  1312. #
  1313. # /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
  1314. sub DoMUIizedForFiles
  1315. {
  1316. my ($LocalizedFile,$original_file) = @_;
  1317. my ($Result, $Checksum, $muibld_command, $resource, $resdll, @trash, $status);
  1318. my ($machine_flag, $file_ver_string, $link_command, $message);
  1319. $Result = 0;
  1320. $Checksum=0;
  1321. if (! -e $LocalizedFile)
  1322. {
  1323. return $Result;
  1324. }
  1325. if ( ($BuildChecksum) && ($original_file =~ /\w+/) && (-e $original_file))
  1326. {
  1327. $Checksum=1;
  1328. }
  1329. $resource = "$LocalizedFile.res";
  1330. $resdll = "$LocalizedFile.muitmp";
  1331. if ($Checksum)
  1332. {
  1333. $muibld_command = "muibld.exe -c $original_file -l $LCID -i $RESOURCE_TYPES $LocalizedFile $resource 2>&1";
  1334. }
  1335. else
  1336. {
  1337. $muibld_command = "muibld.exe -l $LCID -i $RESOURCE_TYPES $LocalizedFile $resource 2>&1";
  1338. }
  1339. @trash = `$muibld_command`;
  1340. $status = $?/256;
  1341. # Display warnings from muibld.exe
  1342. if($VERBOSE)
  1343. {
  1344. SWITCH:
  1345. {
  1346. if($status >= 100)
  1347. {
  1348. wrnmsg ("$LocalizedFile: muibld.exe: SYSTEM ERROR $status");
  1349. last SWITCH;
  1350. }
  1351. if($status >= 7)
  1352. {
  1353. wrnmsg ("$LocalizedFile: muibld.exe: TOO FEW ARGUMENTS");
  1354. last SWITCH;
  1355. }
  1356. if($status == 6)
  1357. {
  1358. wrnmsg ("$LocalizedFile: muibld.exe: NO LANGUAGE_SPECIFIED");
  1359. last SWITCH;
  1360. }
  1361. if($status == 5)
  1362. {
  1363. wrnmsg ("$LocalizedFile: muibld.exe: NO TARGET");
  1364. last SWITCH;
  1365. }
  1366. if($status == 4)
  1367. {
  1368. wrnmsg ("$LocalizedFile: muibld.exe: NO SOURCE");
  1369. last SWITCH;
  1370. }
  1371. if($status == 3)
  1372. {
  1373. wrnmsg ("$LocalizedFile: muibld.exe: LANGUAGE NOT IN SOURCE");
  1374. last SWITCH;
  1375. }
  1376. if($status == 2)
  1377. {
  1378. wrnmsg ("$LocalizedFile: muibld.exe: NO RESOURCES");
  1379. last SWITCH;
  1380. }
  1381. if($status == 1)
  1382. {
  1383. wrnmsg ("$LocalizedFile: muibld.exe: ONLY VERSION STAMP");
  1384. last SWITCH;
  1385. }
  1386. }
  1387. }
  1388. if($status)
  1389. {
  1390. if (-e $resource)
  1391. {
  1392. system("del $resource");
  1393. }
  1394. return $Result;
  1395. }
  1396. $machine_flag = $MACHINE;
  1397. if ( ($MACHINE =~ /IA64/i) && ($original_file =~ /\w+/i) && (-e $original_file))
  1398. {
  1399. $file_ver_string = &ExecuteProgram("filever $original_file");
  1400. if ($file_ver_string =~ /i64/i)
  1401. {
  1402. $machine_flag = "IA64";
  1403. }
  1404. else {
  1405. $machine_flag = "IX86";
  1406. }
  1407. }
  1408. $link_command = "link /noentry /dll /nologo /nodefaultlib /machine:$machine_flag /out:$resdll $resource";
  1409. if($SAFEMODE)
  1410. {
  1411. print "$link_command\n";
  1412. }
  1413. $? = 0; # Reset system error variable
  1414. logmsg($link_command);
  1415. # Execute command
  1416. $message = `$link_command`;
  1417. $Result = 1;
  1418. # Display error messages from link.exe
  1419. if($message =~ /^LINK : (.*:.*)$/)
  1420. {
  1421. wrnmsg ("$LocalizedFile: link.exe: $1");
  1422. $Result = 0;
  1423. }
  1424. elsif($?)
  1425. {
  1426. $status = $?/256;
  1427. if($status)
  1428. {
  1429. wrnmsg ("$LocalizedFile: link.exe: SYSTEM_ERROR $status");
  1430. $Result = 0;
  1431. }
  1432. }
  1433. elsif(! -e $resdll)
  1434. {
  1435. wrnmsg ("$LocalizedFile: link.exe: $resdll was not created");
  1436. $Result = 0;
  1437. }
  1438. else
  1439. {
  1440. logmsg ("$LocalizedFile: created $resdll");
  1441. }
  1442. if (-e $resource)
  1443. {
  1444. system("del $resource");
  1445. }
  1446. if ($Result)
  1447. {
  1448. if (system("move/y $resdll $LocalizedFile") != 0)
  1449. {
  1450. wrnmsg ("$LocalizedFile: can't move $resdll to $LocalizedFile");
  1451. }
  1452. }
  1453. else
  1454. {
  1455. if (-e $resdll)
  1456. {
  1457. system("del $resdll");
  1458. }
  1459. }
  1460. return $Result;
  1461. }
  1462. #-----------------------------------------------------------------------------
  1463. # CopyIE5files - copies ie5 files over to a separate directory
  1464. #-----------------------------------------------------------------------------
  1465. sub CopyIE5files {
  1466. my($ie5_files_copied, $ie5_file_errors, $total_ie5files, $web_files_copied,
  1467. $web_file_errors, $total_webfiles, $total_files_in_dir, @files);
  1468. my(%TheStringSection);
  1469. # Initial messages
  1470. logmsg ("--------------------------------------------------------");
  1471. logmsg ("BEGIN ie5 file copy");
  1472. logmsg ("--------------------------------------------------------");
  1473. logmsg ("Copy files listed in the [Satellite.files.install] section of ie5ui.inf");
  1474. $listfile = "$IE5DIR\\ie5ui.inf";
  1475. if (-e $listfile) {
  1476. $section = "Satellite.files.install";
  1477. @filelist = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $listfile $section`;
  1478. &BuildUpStringSection($listfile,\%TheStringSection);
  1479. ($ie5_files_copied, $ie5_file_errors, $total_ie5files) = &CopyFileList ("$_NTPOSTBLD", "$_NTPOSTBLD\\mui\\$Special_Lang\\$_BuildArch\\ie5", \%TheStringSection,@filelist);
  1480. # BUGBUG - For RTM, ARA/HEB get different *HTT for MUI than for loc build
  1481. if($Special_Lang =~ /^(ara|heb)$/i) {
  1482. $HTTDIR = "$_NTBINDIR\\loc\\mui\\$Special_Lang\\web";
  1483. @messages=`xcopy /vy $HTTDIR\\* $IE5DIR\\ 2>&1`;
  1484. logmsg (@messages);
  1485. }
  1486. }
  1487. # Final messages
  1488. logmsg ("RESULTS: Process Succeeded");
  1489. logmsg ("Total number of ie5 files listed in:..................($total_ie5files)");
  1490. logmsg (" $IE5FILE");
  1491. logmsg ("Number of ie5 files copied to:........................($ie5_files_copied)");
  1492. logmsg (" $IE5DIR");
  1493. logmsg ("Number of ie5 file errors:............................($ie5_file_errors)");
  1494. logmsg ("Total number of web files listed in:..................($total_webfiles)");
  1495. logmsg (" $IE5FILE");
  1496. logmsg ("Number of web files copied to:........................($web_files_copied)");
  1497. logmsg (" $IE5DIR");
  1498. logmsg ("Number of web file errors:............................($web_file_errors)");
  1499. logmsg (" $IE5DIR");
  1500. return 1;
  1501. } # CopyIE5files
  1502. #-----------------------------------------------------------------------------
  1503. # CopyComponentfiles - copies compoents' files over to a separate directory
  1504. #
  1505. # note that this function is changed to now also handle SKU specific components
  1506. #-----------------------------------------------------------------------------
  1507. sub CopyComponentfiles {
  1508. my($files_copied, $file_errors, $total_files, $total_components, @sku_dirs);
  1509. my(%TheStringSection, @OutputMsgs, $INFName, $DupINF);
  1510. @sku_dirs = ("", "blainf", "dtcinf", "entinf", "sbsinf", "srvinf"); # we ignore personal builds "perinf" directory
  1511. # Initial messages
  1512. logmsg ("--------------------------------------------------------");
  1513. logmsg ("BEGIN component file copy");
  1514. logmsg ("--------------------------------------------------------");
  1515. logmsg ("Copy files listed in the installation section of component INF file.");
  1516. if ($_BuildArch =~ /ia64/i) {
  1517. if (-e "$_NTPOSTBLD\\build_logs\\cplocation.txt") {
  1518. system "del /f $_NTPOSTBLD\\build_logs\\cplocation.txt";
  1519. }
  1520. system "$RAZZLETOOLPATH\\PostBuildScripts\\cplocation.cmd /l:$LANG";
  1521. }
  1522. if (-e $INFFILE)
  1523. {
  1524. # Get component list from MUI.INF
  1525. @filelist = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE "Components"`;
  1526. $total_components = 0;
  1527. foreach $Component (@filelist)
  1528. {
  1529. # Format: CompnentName=ComponentDirectory,ComponentINF_FileName,InstallationSection,UninstallationSection
  1530. # $1 ComponentName
  1531. # $2 ComponentDirectory
  1532. # $3 ComponentINF_FileName
  1533. # $4 InstallationSection
  1534. if ($Component !~ /\w/)
  1535. {
  1536. next;
  1537. }
  1538. if ($Component =~ /^\s*;/i)
  1539. {
  1540. next;
  1541. }
  1542. if ($Component =~ /([^\=]*)=([^\,]*),([^\,]*),([^\,]*),(.*)/)
  1543. {
  1544. foreach $Sku (@sku_dirs)
  1545. {
  1546. logmsg ("Process component : $Component, SKU is $Sku");
  1547. # All external components inf files have to be binplaced to mui\drop\[component dir]
  1548. # note that there may now be SKU specific sub folders, we will look for them and check
  1549. $ComponentName = $1;
  1550. if ($Sku eq "")
  1551. {
  1552. $ComponentDir = $2;
  1553. $INFName=$3;
  1554. $ComponentInf = "$MUIDIR\\drop\\$2\\$3";
  1555. }
  1556. else
  1557. {
  1558. $ComponentInf = "$MUIDIR\\drop\\$2\\$Sku\\$3";
  1559. $ComponentDir = "$2\\$Sku";
  1560. $INFName=$3;
  1561. }
  1562. logmsg("ComponentDir is $ComponentDir, ComponentInf is $ComponentInf");
  1563. $ComponentInstallSection = $4;
  1564. if (-e $ComponentInf)
  1565. {
  1566. $total_components++;
  1567. $ComponentFolders[$total_components] = $ComponentDir;
  1568. #
  1569. # Comment out those file don't exist
  1570. #
  1571. $DupINF="$TARGETDIR\\$ComponentDir\\$INFName";
  1572. @OutputMsgs=`$RAZZLETOOLPATH\\PostBuildScripts\\comminf.cmd -o:yes -m:$ComponentInf -s:$ComponentInstallSection -d:$DupINF -p:$_NTPOSTBLD`;
  1573. logmsg(@OutputMsgs);
  1574. #
  1575. # Get INF file default file install section
  1576. @ComponentFileInstall = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $ComponentInf $ComponentInstallSection`;
  1577. &BuildUpStringSection($ComponentInf,\%TheStringSection);
  1578. logmsg ("Installing $ComponentInf $ComponentInstallSection");
  1579. foreach $ComponentInstall (@ComponentFileInstall)
  1580. {
  1581. logmsg ($ComponentInstall);
  1582. #Parse CopyFiles list
  1583. if ($ComponentInstall =~ /.*CopyFiles.*=(.*)/i)
  1584. {
  1585. $ComponentFileCopySections = $1;
  1586. #Loop through all sections
  1587. while ($ComponentFileCopySections ne "")
  1588. {
  1589. if ($ComponentFileCopySections =~ /([^\,]*),(.*)/i)
  1590. {
  1591. $ComponentFileCopySections = $2;
  1592. $CopyFileSectionName = $1;
  1593. }
  1594. else
  1595. {
  1596. $CopyFileSectionName = $ComponentFileCopySections;
  1597. $ComponentFileCopySections = "";
  1598. }
  1599. # Get copy file list
  1600. @ComponentFileList = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $ComponentInf $CopyFileSectionName`;
  1601. if($ComponentDir =~ /oemhelp/i)
  1602. {
  1603. ($files_copied, $file_errors, $total_files) = &CopyFileList ("$_NTPOSTBLD\\oem\\help", "$TARGETDIR\\$ComponentDir", \%TheStringSection,@ComponentFileList);
  1604. }
  1605. else
  1606. {
  1607. ($files_copied, $file_errors, $total_files) = &CopyFileList ("$_NTPOSTBLD", "$TARGETDIR\\$ComponentDir", \%TheStringSection,@ComponentFileList);
  1608. }
  1609. # BUGBUG - For RTM, ARA/HEB get different *HTT for MUI than for loc build
  1610. if(($ComponentName =~ /ie5/i) && ($Special_Lang =~ /^(ara|heb)$/i && $1))
  1611. {
  1612. $HTTDIR = "$_NTBINDIR\\loc\\mui\\$Special_Lang\\web";
  1613. $IE5DIR = "$MUIDIR\\drop\\ie5";
  1614. @messages=`xcopy /vy $HTTDIR\\* $IE5DIR\\ 2>&1`;
  1615. logmsg (@messages);
  1616. }
  1617. # Final messages
  1618. logmsg ("RESULTS: Process Succeeded");
  1619. logmsg ("Total number of $ComponentName-$CopyFileSectionName files listed in:..................($total_files)");
  1620. logmsg ("Number of $ComponentName-$CopyFileSectionName files copied to:........................($files_copied)");
  1621. logmsg ("Number of $ComponentName-$CopyFileSectionName file errors:............................($file_errors)");
  1622. }
  1623. }
  1624. }
  1625. }
  1626. }
  1627. }
  1628. else
  1629. {
  1630. logmsg ("Warning: Invalid INF file, please check $Component");
  1631. }
  1632. }
  1633. }
  1634. # Always success
  1635. return 1;
  1636. } # CopyComponentfiles
  1637. # Function to copy dropped external partners files
  1638. sub CopyDropFiles {
  1639. my ($SrcDir, $DestDir, $Incremental);
  1640. my (%CopyFiles, @CopyLangs, $files_copied, $file_errors, $total_files_copied);
  1641. #Pickup parameters
  1642. ($SrcDir, $DestDir, $Incremental) = @_;
  1643. #Set defaults
  1644. $files_copied = 0;
  1645. $file_errors = 0;
  1646. $total_files_copied = 0;
  1647. #Create the destination dir if it does not exist
  1648. unless (-e $DestDir) {
  1649. logmsg("Make dir:$DestDir");
  1650. &MakeDir($DestDir);
  1651. }
  1652. #Copy the files recursivly
  1653. system "xcopy /verifky $SrcDir $DestDir";
  1654. #Copy fusion manifest files
  1655. if (-e "$DestDir\\asms") {
  1656. #Remove previous copied files
  1657. system "rd /s /q $DestDir\\asms";
  1658. if (-e "$SrcDir\\asms\\$Special_Lang") {
  1659. logmsg("Copy fusion manifest files");
  1660. system "xcopy /verifky $SrcDir\\asms\\$Special_Lang $DestDir\\asms";
  1661. system "xcopy /verifky $SrcDir\\asms\\$Special_Lang $COMPDIR\\asms";
  1662. }
  1663. else {
  1664. logmsg("Warning: fusion $SrcDir\\asms\\$Special_Lang not found");
  1665. }
  1666. }
  1667. return ($files_copied, $file_errors, $total_files_copied);
  1668. }
  1669. sub CopyFusionFiles
  1670. {
  1671. my ($SrcDir, $DestDir);
  1672. my ($filename, @Manifest_filelist);
  1673. #Pickup parameters
  1674. ($SrcDir, $DestDir) = @_;
  1675. logmsg("Copying fusion manifest files");
  1676. #Search all manifest file.
  1677. @Manifest_filelist = `dir /s /b $SrcDir\\*.man`;
  1678. #For each manifest file, verify if the corresponding dll is already
  1679. #in the destination folder. If not, skip the manifest file copy.
  1680. foreach $filename (@Manifest_filelist)
  1681. {
  1682. chomp $filename;
  1683. if ($filename =~ /\Q$SrcDir\E(.*).man/i)
  1684. {
  1685. if (-e "$DestDir$1.dll" |
  1686. -e "$DestDir$1.exe" |
  1687. -e "$DestDir$1.dl_" |
  1688. -e "$DestDir$1.ex_")
  1689. {
  1690. system "xcopy /v /k $filename $DestDir$1.*";
  1691. }
  1692. }
  1693. }
  1694. return 1;
  1695. }
  1696. #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1697. #
  1698. # Generate Exclude file for xcopy
  1699. #
  1700. #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1701. sub GenerateExcludeList
  1702. {
  1703. my ($ExcludeList,$RootPath,$OutputFile) = @_;
  1704. my ($Result, @Data, $Line, $TempFile);
  1705. $Result = 0;
  1706. unless (open(INFILE,$ExcludeList))
  1707. {
  1708. errmsg("Can't open input for $ExcludeList");
  1709. return $Result;
  1710. }
  1711. $TempFile=$ENV{temp};
  1712. $TempFile="$TempFile\\muiexclude.txt";
  1713. unless (open(OUTFILE,">$TempFile"))
  1714. {
  1715. errmsg("Can't open output for $TempFile");
  1716. close(INFILE);
  1717. return $Result;
  1718. }
  1719. @Data=<INFILE>;
  1720. close(INFILE);
  1721. foreach $Line (@Data)
  1722. {
  1723. chomp($Line);
  1724. $NewLine="$RootPath\\$Line";
  1725. print(OUTFILE "$NewLine\n");
  1726. }
  1727. close(OUTFILE);
  1728. $$OutputFile = $TempFile;
  1729. $Result = 1;
  1730. return $Result;
  1731. }
  1732. #
  1733. #Function to copy files using a specified control file
  1734. # We also add Resource Checksum to the files being copied
  1735. #
  1736. sub CopyFiles {
  1737. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  1738. my (%CopyFiles, @CopyLangs, $files_copied, $file_errors, $total_files_copied, $excludefile);
  1739. my ($SrcCopyFile_US, $MyFileName, $MyPath, $FileCheckSumAdded, $UseModifiedFile,$CopyResult);
  1740. my ($NewExcludeFile);
  1741. #Pickup parameters
  1742. ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental) = @_;
  1743. # Set defaults
  1744. $files_copied = 0;
  1745. $file_errors = 0;
  1746. $total_files_copied = 0;
  1747. #Use exclude file for recursive copies
  1748. $excludefile="$ENV{RazzleToolPath}\\PostBuildScripts\\muiexclude.txt";
  1749. #Create a hash-hash from the control file table
  1750. ParseTable::parse_table_file($ControlFile, \%CopyFiles);
  1751. #Loop through all control file entries
  1752. foreach $SrcFile (keys %CopyFiles) {
  1753. # Create file record hash
  1754. $CopyFileRecord{SourceFile} = $SrcFile;
  1755. $CopyFileRecord{SourceDir} = $CopyFiles{$SrcFile}{SourceDir};
  1756. $CopyFileRecord{DestFile} = $CopyFiles{$SrcFile}{DestFile};
  1757. $CopyFileRecord{DestDir} = $CopyFiles{$SrcFile}{DestDir};
  1758. $CopyFileRecord{Recursive} = $CopyFiles{$SrcFile}{Recursive};
  1759. $CopyFileRecord{Languages} = $CopyFiles{$SrcFile}{Languages};
  1760. #Preprocess file record hash
  1761. unless ($CopyFileRecord = &PreProcessRecord(\%CopyFileRecord) ) {
  1762. next;
  1763. }
  1764. #Process "-" entry in text file list
  1765. if ($CopyFileRecord->{SourceDir}=~/^-$/i) {
  1766. $SrcCopyFileDir="$SrcRootDir";
  1767. } else {
  1768. $SrcCopyFileDir="$SrcRootDir\\$CopyFileRecord->{SourceDir}";
  1769. }
  1770. if ($CopyFileRecord->{DestDir}=~/^-$/i) {
  1771. $DestCopyFileDir="$DestRootDir";
  1772. } else {
  1773. $DestCopyFileDir="$DestRootDir\\$CopyFileRecord->{DestDir}";
  1774. }
  1775. #Create the destination dir if it does not exist
  1776. unless (-e $DestCopyFileDir) {
  1777. &MakeDir($DestCopyFileDir);
  1778. }
  1779. $SrcCopyFile = "$SrcCopyFileDir\\$CopyFileRecord->{SourceFile}";
  1780. if ($CopyFileRecord->{DestFile}=~/^-$/i) {
  1781. $DestCopyFile = "$DestCopyFileDir";
  1782. } else {
  1783. $DestCopyFile = "$DestCopyFileDir\\$CopyFileRecord->{DestFile}";
  1784. }
  1785. if ($CopyFileRecord{Recursive}=~/(y|yes|true)/i) {
  1786. #Copy the files recursivly
  1787. if ( GenerateExcludeList($excludefile,$SrcRootDir,\$NewExcludeFile) && (-e $SrcCopyFileDir))
  1788. {
  1789. if (system ("xcopy /evcirfy $SrcCopyFile $DestCopyFile /EXCLUDE:$NewExcludeFile") != 0)
  1790. {
  1791. errmsg("Fatal: Failed=>xcopy /evcirfy $SrcCopyFile $DestCopyFile /EXCLUDE:$$NewExcludeFile");
  1792. }
  1793. }
  1794. else
  1795. {
  1796. errmsg("Fatal: can't do copy for $SrcCopyFile $DestCopyFile /EXCLUDE:$NewExcludeFile");
  1797. }
  1798. } else {
  1799. #Copy the file
  1800. for $SrcSingleCopyFile (glob "$SrcCopyFile") {
  1801. # Support multiple target files - file names separated by ','
  1802. @DestFiles = split /,/, $CopyFileRecord->{DestFile};
  1803. foreach $file (@DestFiles) {
  1804. $UseModifiedFile=0;
  1805. #
  1806. # We'll add Resource Checksum
  1807. #
  1808. if ($CopyFileRecord->{DestFile}=~/^-$/i) {
  1809. $DestCopyFile = "$DestCopyFileDir";
  1810. ($MyFileName, $MyPath ) = fileparse($SrcSingleCopyFile);
  1811. } else {
  1812. $DestCopyFile = "$DestCopyFileDir\\$file";
  1813. $MyFileName=$file;
  1814. }
  1815. if ($BuildChecksum) {
  1816. if ($MyFileName =~ /(.*)\.mu_/i ||$MyFileName =~ /(.*)\.mui/i ) {
  1817. $MyFileName = $1;
  1818. }
  1819. $SrcCopyFile_US = &FindOriginalFile($MyFileName);
  1820. if ( (&IsWin32File($MyFileName)) && (length($SrcCopyFile_US) > 0) ) {
  1821. #
  1822. # Copy source file to a temporary location
  1823. #
  1824. unless ( -e $WorkTempFolder) {
  1825. &MakeDir($WorkTempFolder);
  1826. }
  1827. $FileCheckSumAdded=$WorkTempFolder."\\$MyFileName.mui";
  1828. logmsg("Copying $SrcSingleCopyFile -> $FileCheckSumAdded");
  1829. if (system("copy $SrcSingleCopyFile $FileCheckSumAdded") != 0) {
  1830. logmsg("Can't copy $SrcSingleCopyFile to $FileCheckSumAdded");
  1831. $file_errors++;
  1832. }
  1833. #
  1834. # Add resource checksum to the file
  1835. #
  1836. else {
  1837. if ( system("checksum.exe $FileCheckSumAdded") == 0) {
  1838. logmsg("muirct.exe -c $SrcCopyFile_US -z $FileCheckSumAdded");
  1839. system("muirct.exe -c $SrcCopyFile_US -z $FileCheckSumAdded");
  1840. }
  1841. else {
  1842. logmsg("Resource Checksum already in $FileCheckSumAdded");
  1843. }
  1844. if ( -e $FileCheckSumAdded) {
  1845. $UseModifiedFile=1;
  1846. }
  1847. else {
  1848. logmsg("Failed:muirct.exe -c $SrcCopyFile_US -z $FileCheckSumAdded");
  1849. }
  1850. }
  1851. } #if ( (&IsWin32File($MyFileName)) && (length($SrcCopyFile_US) > 0) )
  1852. } # if ($BuildChecksum)
  1853. if ($UseModifiedFile) {
  1854. logmsg ("Copying $FileCheckSumAdded -> $DestCopyFile");
  1855. }
  1856. else {
  1857. logmsg ("Copying $SrcSingleCopyFile -> $DestCopyFile");
  1858. }
  1859. $total_files_copied++;
  1860. if ($UseModifiedFile) {
  1861. $CopyResult=copy("$FileCheckSumAdded", "$DestCopyFile");
  1862. } else {
  1863. $CopyResult=copy("$SrcSingleCopyFile", "$DestCopyFile");
  1864. }
  1865. if ($CopyResult ) {
  1866. $files_copied++;
  1867. } else {
  1868. logmsg("$!");
  1869. $file_errors++;
  1870. }
  1871. }
  1872. }
  1873. }
  1874. }
  1875. return ($files_copied, $file_errors, $total_files_copied);
  1876. }
  1877. #Function to validate a comma seperated lang list given a control lang
  1878. sub IsValidFileForLang {
  1879. #Declare local variables
  1880. my ($ValidFileLangs, $lang) = @_;
  1881. #Copy only for the specified languages in the control file
  1882. @ValidLangs = split /,/i, $ValidFileLangs;
  1883. unless (grep /(all|$lang)/i, @ValidLangs) {
  1884. return;
  1885. }
  1886. return 1;
  1887. }
  1888. #Function to preprocess a hashref file record list
  1889. sub PreProcessRecord {
  1890. #Declare local variables
  1891. my ($FileRecord) = @_;
  1892. #Verify arguments;
  1893. unless (@_ == 1 && ref($FileRecord) eq 'HASH') {
  1894. print "usage: HASHREF";
  1895. return;
  1896. }
  1897. #Validate language for file record
  1898. unless (&IsValidFileForLang($FileRecord->{Languages}, $Special_Lang) ) {
  1899. return;
  1900. }
  1901. #Sub in environment vars
  1902. foreach $field (keys %$FileRecord) {
  1903. while ( $FileRecord->{$field}=~/(%\w+%)/i ) {
  1904. $EnvVar=$1;
  1905. $CmdVar=$1;
  1906. $EnvVar=~s/%//ig;
  1907. $CmdValue=$ENV{$EnvVar};
  1908. #Environment value substutions
  1909. $CmdValue=~s/x86/i386/i;
  1910. #Substutute the environment values into the file record
  1911. $FileRecord->{$field}=~s/$CmdVar/$CmdValue/i;
  1912. }
  1913. }
  1914. return ($FileRecord);
  1915. }
  1916. sub IsWin32File
  1917. {
  1918. my ($FileName) = @_;
  1919. my %FileTypeTbl = (
  1920. ".exe" => 1,
  1921. ".dll" => 1,
  1922. ".cpl" => 1,
  1923. ".ocx" => 1,
  1924. ".tsp" => 1,
  1925. ".scr" => 1
  1926. );
  1927. my ($Result, $TheFileExt);
  1928. $Result=0;
  1929. if (length($FileName) > 4) {
  1930. $TheFileExt=substr($FileName,-4,4);
  1931. $TheFileExt="\L$TheFileExt";
  1932. if (defined ($FileTypeTbl{$TheFileExt}) ) {
  1933. $Result=1;
  1934. }
  1935. }
  1936. return $Result;
  1937. }
  1938. #
  1939. #Function to copy files using a specified array of files
  1940. #
  1941. # We'll also add resource checksum to the files
  1942. #
  1943. sub CopyFileList {
  1944. my ($SrcRootDir, $DestRootDir, $RootMUIFile, $pTheStringSection, @FileList, $Incremental);
  1945. my ($files_copied, $file_errors, $total_files_copied, $RootMUIFile, $FileCheckSumAdded, $SrcCopyFile_US);
  1946. my ($IsWin32Res, $TheFileExt, $CopyResult);
  1947. my ($Replaced, $SrcFileNew, $Doit, $DoCnt, $TheLine);
  1948. #Pickup parameters
  1949. ($SrcRootDir, $DestRootDir, $pTheStringSection, @FileList, $Incremental) = @_;
  1950. # Set defaults
  1951. $files_copied = 0;
  1952. $file_errors = 0;
  1953. $total_files_copied = 0;
  1954. #Loop through all control file entries
  1955. foreach $SrcFile (@FileList) {
  1956. chomp $SrcFile;
  1957. #Don't process blank line
  1958. if ($SrcFile !~ /\w/) {
  1959. next;
  1960. }
  1961. if (substr($SrcFile,0,1) eq ";")
  1962. {
  1963. next;
  1964. }
  1965. $total_files_copied++;
  1966. #Create the destination dir if it does not exist
  1967. unless (-e $DestRootDir) {
  1968. &MakeDir($DestRootDir);
  1969. }
  1970. # Source file could be in the format of "[original file], [compressed file]"
  1971. if ($SrcFile =~ /(.*),\s*(.*)\s*/) {
  1972. $SrcFile = $2;
  1973. }
  1974. #Make sure source file doesn't contain MUI extension
  1975. if ($SrcFile =~ /(.*)\.mu_/i ||$SrcFile =~ /(.*)\.mui/i ) {
  1976. $SrcFile = $1;
  1977. }
  1978. $Doit=1;
  1979. $DoCnt=0;
  1980. $SrcFileNew=$SrcFile;
  1981. while( ($Doit) && ($SrcFileNew =~ /(.*)%(.*)%(.*)/))
  1982. {
  1983. if ( defined ($$pTheStringSection{$2}))
  1984. {
  1985. $Replaced=$$pTheStringSection{$2};
  1986. $SrcFileNew=$1.$Replaced.$3;
  1987. $DoCnt++;
  1988. }
  1989. else
  1990. {
  1991. logmsg("**** Can't map:$2*");
  1992. $SrcFileNew=$SrcFile;
  1993. $Doit=0;
  1994. }
  1995. }
  1996. if (($Doit) && ($DoCnt))
  1997. {
  1998. logmsg("$SrcFile is mapped to $SrcFileNew");
  1999. }
  2000. $SrcFile=$SrcFileNew;
  2001. #
  2002. # Some source file may have form like %Filename%%LCID% which Filename and LCID comes from string section
  2003. # of INF file. We have to replace these name on the fly
  2004. #
  2005. $SrcCopyFile = "$SrcRootDir\\$SrcFile";
  2006. $SrcCopyFile_US = "$USBINDIR\\$SrcFile";
  2007. #Append .MUI to the file name
  2008. $DestCopyFile = "$DestRootDir\\$SrcFile.mui";
  2009. if (!(-e $SrcCopyFile)) {
  2010. $SrcCopyFile = "$SrcRootDir\\dump\\$SrcFile";
  2011. $SrcCopyFile_US = "$USBINDIR\\dump\\$SrcFile";
  2012. }
  2013. if (!(-e $SrcCopyFile)) {
  2014. $SrcCopyFile = "$SrcRootDir\\netfx\\$SrcFile";
  2015. $SrcCopyFile_US = "$USBINDIR\\netfx\\$SrcFile";
  2016. }
  2017. if (!(-e $SrcCopyFile)) {
  2018. $SrcCopyFile = "$SrcRootDir\\mui\\drop\\$SrcFile";
  2019. $SrcCopyFile_US = "$USBINDIR\\mui\\drop\\$SrcFile";
  2020. }
  2021. if (!(-e $SrcCopyFile)) {
  2022. $SrcCopyFile = "$SrcRootDir\\uddi\\system32\\$SrcFile";
  2023. $SrcCopyFile_US = "$USBINDIR\\uddi\\system32\\$SrcFile";
  2024. }
  2025. if (!(-e $SrcCopyFile)) {
  2026. $SrcCopyFile = "$SrcRootDir\\uddi\\resources\\$SrcFile";
  2027. $SrcCopyFile_US = "$USBINDIR\\uddi\\resources\\$SrcFile";
  2028. }
  2029. if (!(-e $SrcCopyFile)) {
  2030. $SrcCopyFile = "$SrcRootDir\\uddi\\help\\$SrcFile";
  2031. $SrcCopyFile_US = "$USBINDIR\\uddi\\help\\$SrcFile";
  2032. }
  2033. if (!(-e $SrcCopyFile)) {
  2034. $SrcCopyFile = "$SrcRootDir\\uddi\\webroot\\help\\default\\$SrcFile";
  2035. $SrcCopyFile_US = "$USBINDIR\\uddi\\webroot\\help\\default\\$SrcFile";
  2036. }
  2037. if (!(-e $SrcCopyFile)) {
  2038. $SrcCopyFile = "$SrcRootDir\\uddi\\webroot\\help\\default\\images\\$SrcFile";
  2039. $SrcCopyFile_US = "$USBINDIR\\uddi\\webroot\\help\\default\\images\\$SrcFile";
  2040. }
  2041. # For ia64, we need to try some extral step to get external files
  2042. # from wow64 or i386 release server
  2043. if (!(-e $SrcCopyFile) && ($_BuildArch =~ /ia64/i)) {
  2044. if (!(-e $SrcCopyFile)) {
  2045. $SrcCopyFile = "$SrcRootDir\\wowbins_uncomp\\$SrcFile";
  2046. $SrcCopyFile_US = "$USBINDIR\\wowbins_uncomp\\$SrcFile";
  2047. }
  2048. if (!(-e $SrcCopyFile)) {
  2049. $SrcCopyFile = "$SrcRootDir\\wowbins\\$SrcFile";
  2050. $SrcCopyFile_US = "$USBINDIR\\wowbins\\$SrcFile";
  2051. }
  2052. if (-e "$_NTPOSTBLD\\build_logs\\cplocation.txt" && !(-e $SrcCopyFile)) {
  2053. if (open (X86_BIN, "$_NTPOSTBLD\\build_logs\\cplocation.txt")) {
  2054. $SrcRootDir = <X86_BIN>;
  2055. chomp ($SrcRootDir);
  2056. $SrcCopyFile = "$SrcRootDir\\$SrcFile";
  2057. $SrcCopyFile_US = "$USBINDIR\\$SrcFile";
  2058. if (!(-e $SrcCopyFile)) {
  2059. $SrcCopyFile = "$SrcRootDir\\dump\\$SrcFile";
  2060. $SrcCopyFile_US = "$USBINDIR\\dump\\$SrcFile";
  2061. }
  2062. if (!(-e $SrcCopyFile)) {
  2063. $SrcCopyFile = "$SrcRootDir\\mui\\drop\\$SrcFile";
  2064. $SrcCopyFile_US = "$USBINDIR\\mui\\drop\\$SrcFile";
  2065. }
  2066. logmsg("Copy $SrcCopyFile from i386 release");
  2067. close (X86_BIN);
  2068. }
  2069. }
  2070. }
  2071. $RootMUIFile = "$DestRootDir\\..\\$SrcFile.mui";
  2072. if (-e $RootMUIFile) {
  2073. logmsg ("Copying $RootMUIFile -> $DestCopyFile");
  2074. if (copy("$RootMUIFile", "$DestCopyFile") ) {
  2075. if (unlink $RootMUIFile)
  2076. {
  2077. logmsg ("Deleting $RootMUIFile");
  2078. }
  2079. $files_copied++;
  2080. } else {
  2081. logmsg("$!");
  2082. $file_errors++;
  2083. }
  2084. }
  2085. elsif (-e $SrcCopyFile) {
  2086. #
  2087. # We want to add resource checksum to the file before it's added
  2088. #
  2089. $IsWin32Res=&IsWin32File($SrcFile);
  2090. if (($BuildChecksum) && ($IsWin32Res) && (-e $SrcCopyFile_US) ) {
  2091. unless ( -e $WorkTempFolder) {
  2092. &MakeDir($WorkTempFolder);
  2093. }
  2094. #
  2095. # Copy source file to a temporary location
  2096. #
  2097. $FileCheckSumAdded=$WorkTempFolder."\\$SrcFile.mui";
  2098. logmsg("Copying $SrcCopyFile -> $FileCheckSumAdded");
  2099. if (system("copy $SrcCopyFile $FileCheckSumAdded") != 0) {
  2100. logmsg("Can't copy $SrcCopyFile to $FileCheckSumAdded");
  2101. $file_errors++;
  2102. }
  2103. #
  2104. # Add resource checksum to the file
  2105. #
  2106. else {
  2107. if (system("checksum.exe $FileCheckSumAdded") == 0) {
  2108. logmsg("muirct.exe -c $SrcCopyFile_US -z $FileCheckSumAdded");
  2109. system("muirct.exe -c $SrcCopyFile_US -z $FileCheckSumAdded");
  2110. }
  2111. else {
  2112. logmsg("Resource Checksum already in $FileCheckSumAdded");
  2113. }
  2114. if (-e $FileCheckSumAdded)
  2115. {
  2116. logmsg("Copying $FileCheckSumAdded -> $DestCopyFile");
  2117. $CopyResult=copy("$FileCheckSumAdded", "$DestCopyFile");
  2118. }
  2119. else {
  2120. logmsg("Failed:muirct.exe -c $SrcCopyFile_US -z $FileCheckSumAdded");
  2121. logmsg ("Copying $SrcCopyFile -> $DestCopyFile");
  2122. $CopyResult=copy("$SrcCopyFile", "$DestCopyFile");
  2123. }
  2124. if ($CopyResult) {
  2125. $files_copied++;
  2126. } else {
  2127. logmsg("$!");
  2128. $file_errors++;
  2129. }
  2130. }
  2131. }
  2132. else
  2133. {
  2134. logmsg ("Copying $SrcCopyFile -> $DestCopyFile");
  2135. if (copy("$SrcCopyFile", "$DestCopyFile") ) {
  2136. $files_copied++;
  2137. } else {
  2138. logmsg("$!");
  2139. $file_errors++;
  2140. }
  2141. }
  2142. }
  2143. elsif (!($SrcCopyFile =~ /\.inf/i))
  2144. {
  2145. logmsg("warning: $SrcCopyFile not found");
  2146. }
  2147. }
  2148. return ($files_copied, $file_errors, $total_files_copied);
  2149. }
  2150. #Function to rename files using a specifiec control file
  2151. sub RenameFiles {
  2152. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  2153. my (%RenFiles, @RenLangs, $files_renamed, $file_errors, $total_files_renamed);
  2154. #Pickup parameters
  2155. ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental) = @_;
  2156. # Set defaults
  2157. $files_renamed = 0;
  2158. $file_errors = 0;
  2159. $total_files_renamed = 0;
  2160. #Create a hash-hash from the control file table
  2161. ParseTable::parse_table_file($ControlFile, \%RenFiles);
  2162. #Loop through all control file entries
  2163. foreach $SrcFile (keys %RenFiles) {
  2164. # Create file record hash
  2165. $RenFileRecord{SourceFile} = $SrcFile;
  2166. $RenFileRecord{SourceDir} = $RenFiles{$SrcFile}{SourceDir};
  2167. $RenFileRecord{DestFile} = $RenFiles{$SrcFile}{DestFile};
  2168. $RenFileRecord{DestDir} = $RenFiles{$SrcFile}{DestDir};
  2169. $RenFileRecord{Languages} = $RenFiles{$SrcFile}{Languages};
  2170. #Preprocess file record hash
  2171. unless ($RenFileRecord = &PreProcessRecord(\%RenFileRecord) ) {
  2172. next;
  2173. }
  2174. #Process "-" entry in text file list
  2175. if ($RenFileRecord->{SourceDir}=~/^-$/i) {
  2176. $SrcRenFileDir="$SrcRootDir";
  2177. } else {
  2178. $SrcRenFileDir="$SrcRootDir\\$RenFileRecord->{SourceDir}";
  2179. }
  2180. if ($RenFileRecord->{DestDir}=~/^-$/i) {
  2181. $DestRenFileDir="$DestRootDir";
  2182. } else {
  2183. $DestRenFileDir="$DestRootDir\\$RenFileRecord->{DestDir}";
  2184. }
  2185. #Create the destination dir if it does not exist
  2186. unless (-e $DestRenFileDir) {
  2187. &MakeDir($DestRenFileDir);
  2188. }
  2189. $SrcRenFile = "$SrcRenFileDir\\$SrcFile";
  2190. if ($RenFileRecord->{DestFile}=~/^-$/i) {
  2191. $DestRenFile = "$DestRenFileDir";
  2192. } else {
  2193. $DestRenFile = "$DestRenFileDir\\$RenFileRecord->{DestFile}";
  2194. }
  2195. #Rename the file
  2196. for $SrcSingleRenFile (glob "$SrcRenFile") {
  2197. logmsg ("Rename $SrcSingleRenFile -> $DestRenFile");
  2198. $total_files_renamed++;
  2199. if (rename("$SrcSingleRenFile", "$DestRenFile") ) {
  2200. $files_renamed++;
  2201. } else {
  2202. logmsg("$!");
  2203. $file_errors++;
  2204. }
  2205. }
  2206. }
  2207. return ($files_renamed, $file_errors, $total_files_renamed);
  2208. }
  2209. #Function to move files using a specifiec control file
  2210. sub MoveFiles {
  2211. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  2212. my (%MoveFiles, @MoveLangs, $files_moved, $file_errors, $total_files_moved);
  2213. #Pickup parameters
  2214. ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental) = @_;
  2215. # Set defaults
  2216. $files_moved = 0;
  2217. $file_errors = 0;
  2218. $total_files_moved = 0;
  2219. #Create a hash-hash from the control file table
  2220. ParseTable::parse_table_file($ControlFile, \%MoveFiles);
  2221. #Loop through all control file entries
  2222. foreach $SrcFile (keys %MoveFiles) {
  2223. # Create file record hash
  2224. $MoveFileRecord{SourceFile} = $SrcFile;
  2225. $MoveFileRecord{SourceDir} = $MoveFiles{$SrcFile}{SourceDir};
  2226. $MoveFileRecord{DestFile} = $MoveFiles{$SrcFile}{DestFile};
  2227. $MoveFileRecord{DestDir} = $MoveFiles{$SrcFile}{DestDir};
  2228. $MoveFileRecord{Languages} = $MoveFiles{$SrcFile}{Languages};
  2229. #Preprocess file record hash
  2230. unless ($MoveFileRecord = &PreProcessRecord(\%MoveFileRecord) ) {
  2231. next;
  2232. }
  2233. #Process "-" entry in text file list
  2234. if ($MoveFileRecord->{SourceDir}=~/^-$/i) {
  2235. $SrcMoveFileDir="$SrcRootDir";
  2236. } else {
  2237. $SrcMoveFileDir="$SrcRootDir\\$MoveFileRecord->{SourceDir}";
  2238. }
  2239. if ($MoveFileRecord->{DestDir}=~/^-$/i) {
  2240. $DestMoveFileDir="$DestRootDir";
  2241. } else {
  2242. $DestMoveFileDir="$DestRootDir\\$MoveFileRecord->{DestDir}";
  2243. }
  2244. #Create the destination dir if it does not exist
  2245. unless (-e $DestMoveFileDir) {
  2246. &MakeDir($DestMoveFileDir);
  2247. }
  2248. $SrcMoveFile = "$SrcMoveFileDir\\$MoveFileRecord->{SourceFile}";
  2249. if ($MoveFileRecord->{DestFile}=~/^-$/i) {
  2250. $DestMoveFile = "$DestMoveFileDir";
  2251. } else {
  2252. $DestMoveFile = "$DestMoveFileDir\\$MoveFileRecord->{DestFile}";
  2253. }
  2254. #Move the file
  2255. for $SrcSingleMoveFile (glob "$SrcMoveFile") {
  2256. logmsg ("Copying $SrcSingleMoveFile -> $DestMoveFile");
  2257. $total_files_moved++;
  2258. if (move("$SrcSingleMoveFile", "$DestMoveFile") ) {
  2259. $files_moved++;
  2260. } else {
  2261. logmsg("$!");
  2262. $file_errors++;
  2263. }
  2264. }
  2265. }
  2266. return ($files_moved, $file_errors, $total_files_moved);
  2267. }
  2268. #Function to delete files using a specifiec control file
  2269. sub DeleteFiles {
  2270. my ($SrcRootDir, $DestRootDir, $ControlFile, $Incremental);
  2271. my (%DelFiles, @ValidLangs, $files_deleted, $file_errors, $total_files_deleted);
  2272. #Pickup parameters
  2273. ($SrcRootDir, $ControlFile, $Incremental) = @_;
  2274. # Set defaults
  2275. $files_deleted = 0;
  2276. $file_errors = 0;
  2277. $total_files_deleted = 0;
  2278. #Create a hash-hash from the control file table
  2279. ParseTable::parse_table_file($ControlFile, \%DelFiles);
  2280. #Loop through all control file entries
  2281. foreach $SrcFile (keys %DelFiles) {
  2282. # Create file record hash
  2283. $DelFileRecord{SourceFile} = $SrcFile;
  2284. $DelFileRecord{SourceDir} = $DelFiles{$SrcFile}{SourceDir};
  2285. $DelFileRecord{Languages} = $DelFiles{$SrcFile}{Languages};
  2286. #Preprocess file record hash
  2287. unless ($DelFileRecord = &PreProcessRecord(\%DelFileRecord) ) {
  2288. next;
  2289. }
  2290. #Process "-" entry in text file list
  2291. if ($DelFileRecord->{SourceDir}=~/^-$/i) {
  2292. $SrcDelFileDir="$SrcRootDir";
  2293. } else {
  2294. $SrcDelFileDir="$SrcRootDir\\$DelFileRecord->{SourceDir}";
  2295. }
  2296. $SrcDelFile = "$SrcDelFileDir\\$DelFileRecord->{SourceFile}";
  2297. #Delete the file
  2298. for $SrcSingleDelFile (glob "$SrcDelFile") {
  2299. logmsg ("Deleting $SrcSingleDelFile");
  2300. $total_files_deleted++;
  2301. if (-e $SrcSingleDelFile) {
  2302. if (unlink $SrcSingleDelFile) {
  2303. $files_deleted++;
  2304. } else {
  2305. logmsg("$!");
  2306. $file_errors++;
  2307. }
  2308. }
  2309. }
  2310. }
  2311. return ($files_deleted, $file_errors, $total_files_deleted);
  2312. }
  2313. #Function to extract files from a cab file using a specifiec control file
  2314. #
  2315. # We also add resource checksum to extracted files
  2316. sub ExtractFiles {
  2317. my ($CabRootDir, $ExtractRootDir, $ControlFile, $Incremental);
  2318. my (%ExtractFiles, @ExtractLangs, $files_extracted, $file_errors, $total_files_extracted,$OriginalCabFile);
  2319. my ($SourceFile_Localized, $SourceFile_US,$ContainFusionResource);
  2320. #Pickup parameters
  2321. ($CabRootDir, $ExtractRootDir, $ControlFile, $Incremental) = @_;
  2322. # Set defaults
  2323. $files_extracted = 0;
  2324. $file_errors = 0;
  2325. $total_files_extracted = 0;
  2326. #Create a hash-hash from the control file table
  2327. ParseTable::parse_table_file($ControlFile, \%ExtractFiles);
  2328. #Loop through all control file entries
  2329. foreach $ExtractFile (keys %ExtractFiles) {
  2330. # Create file record hash
  2331. $ExtractFileRecord{ExtractFile} = $ExtractFile;
  2332. $ExtractFileRecord{ExtractDir} = $ExtractFiles{$ExtractFile}{ExtractDir};
  2333. $ExtractFileRecord{CabFile} = $ExtractFiles{$ExtractFile}{CabFile};
  2334. $ExtractFileRecord{CabDir} = $ExtractFiles{$ExtractFile}{CabDir};
  2335. $ExtractFileRecord{Languages} = $ExtractFiles{$ExtractFile}{Languages};
  2336. #Preprocess file record hash
  2337. unless ($ExtractFileRecord = &PreProcessRecord(\%ExtractFileRecord) ) {
  2338. next;
  2339. }
  2340. #Process "-" entry in text file list
  2341. if ($ExtractFileRecord->{CabDir}=~/^-$/i) {
  2342. $CabFileDir="$CabRootDir";
  2343. } else {
  2344. $CabFileDir="$CabRootDir\\$ExtractFileRecord->{CabDir}";
  2345. }
  2346. if ($ExtractFileRecord->{ExtractDir}=~/^-$/i) {
  2347. $ExtractFileDir="$ExtractRootDir";
  2348. } else {
  2349. $ExtractFileDir="$ExtractRootDir\\$ExtractFileRecord->{ExtractDir}";
  2350. }
  2351. #Create the destination dir if it does not exist
  2352. unless (-e $ExtractFileDir) {
  2353. &MakeDir($ExtractFileDir);
  2354. }
  2355. $CabFile = "$CabFileDir\\$ExtractFileRecord->{CabFile}";
  2356. if ($ExtractFileRecord->{ExtractFile}=~/^-$/i) {
  2357. $ExtractFile = "$ExtractFileDir";
  2358. } else {
  2359. $ExtractFile = "$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}";
  2360. }
  2361. #Extract the file
  2362. logmsg ("extract.exe /y /l $ExtractFileDir $CabFile $ExtractFileRecord->{ExtractFile}");
  2363. $SourceFile_Localized="";
  2364. if (-e $CabFile) {
  2365. if (!system ("extract.exe /y /l $ExtractFileDir $CabFile $ExtractFileRecord->{ExtractFile}") ) {
  2366. $files_extracted++;
  2367. if (&IsWin32File($ExtractFileRecord->{ExtractFile})) {
  2368. rename("$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}", "$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}\.mui");
  2369. $SourceFile_Localized ="$ExtractFileDir\\$ExtractFileRecord->{ExtractFile}\.mui";
  2370. }
  2371. $files_extracted++;
  2372. }
  2373. } else {
  2374. logmsg ("Cabinet file:$CabFile not found!");
  2375. }
  2376. #
  2377. # We have to extract Unlocalized version of the files so that we may add resource checksum to it
  2378. #
  2379. if ($BuildChecksum && (length($SourceFile_Localized) > 0) ) {
  2380. # Get unlocalized Cab file
  2381. $OriginalCabFile=&FindOriginalFile($ExtractFileRecord->{CabFile});
  2382. if (length($OriginalCabFile) == 0)
  2383. {
  2384. logmsg("Can't found Original for:$ExtractFileRecord->{CabFile}");
  2385. }
  2386. else
  2387. {
  2388. logmsg("Try to get US files for:$ExtractFileRecord->{CabFile}");
  2389. }
  2390. #
  2391. # We Force Mui'ize every files from Cab
  2392. # We only apply this process for files contain Fusion resource, but now we apply to
  2393. # all files from Cab
  2394. #
  2395. # $ContainFusionResource=&IsFusionResource($SourceFile_Localized);
  2396. $ContainFusionResource=1;
  2397. if (length($OriginalCabFile) > 0) {
  2398. $ExtractFileDir=$UnlocalizedFilesDir;
  2399. unless (-e $ExtractFileDir) {
  2400. &MakeDir($ExtractFileDir);
  2401. }
  2402. if ( -e $OriginalCabFile)
  2403. {
  2404. logmsg("extract.exe /y /l $ExtractFileDir $OriginalCabFile $ExtractFileRecord->{ExtractFile}");
  2405. if (!system ("extract.exe /y /l $ExtractFileDir $OriginalCabFile $ExtractFileRecord->{ExtractFile}") ) {
  2406. logmsg("Unlocalized file $ExtractFileRecord->{ExtractFile} is extracted from $ExtractFileRecord->{CabFile} successfully");
  2407. #
  2408. # Add Resource Checksum here
  2409. #
  2410. $SourceFile_US =$ExtractFileDir."\\$ExtractFileRecord->{ExtractFile}";
  2411. if (! $ContainFusionResource)
  2412. {
  2413. if (system("checksum.exe $SourceFile_Localized") == 0) {
  2414. logmsg("muirct.exe -c $SourceFile_US -z $SourceFile_Localized");
  2415. system("muirct.exe -c $SourceFile_US -z $SourceFile_Localized");
  2416. }
  2417. else {
  2418. logmsg("Resource checksum already in $SourceFile_Localized");
  2419. }
  2420. }
  2421. else # ! $ContainFusionResource
  2422. {
  2423. if (! &DoMUIizedForFiles($SourceFile_Localized,$SourceFile_US))
  2424. {
  2425. logmsg("$SourceFile_Localized contains Fusion but Can't be MUIized");
  2426. }
  2427. }
  2428. }
  2429. else # !system ("extract.exe
  2430. {
  2431. if ($ContainFusionResource)
  2432. {
  2433. if (! &DoMUIizedForFiles($SourceFile_Localized,""))
  2434. {
  2435. logmsg("$SourceFile_Localized contains Fusion but Can't be MUIized");
  2436. }
  2437. }
  2438. }
  2439. }
  2440. else # -e $OriginalCabFile
  2441. {
  2442. if ($ContainFusionResource)
  2443. {
  2444. if (! &DoMUIizedForFiles($SourceFile_Localized,""))
  2445. {
  2446. logmsg("$SourceFile_Localized contains Fusion but Can't be MUIized");
  2447. }
  2448. }
  2449. }
  2450. }
  2451. else # length($OriginalCabFile) > 0
  2452. {
  2453. if ($ContainFusionResource)
  2454. {
  2455. if (! &DoMUIizedForFiles($SourceFile_Localized,""))
  2456. {
  2457. logmsg("$SourceFile_Localized contains Fusion but Can't be MUIized");
  2458. }
  2459. }
  2460. }
  2461. } # if ($BuildChecksum)
  2462. }
  2463. return ($files_extracted, $file_errors, $total_files_extracted);
  2464. }
  2465. sub ExtractMSICabFiles {
  2466. my ($CabRootDir, $ExtractRootDir, $ControlFile, $Incremental);
  2467. my (%ExtractFiles, @ExtractLangs, $files_extracted, $file_errors, $total_files_extracted,$OriginalCabFile);
  2468. my($MyTempFolder,$MSICabFolder,@Items, $Line, $MSICabName, $MSICabPath, $ExtractFileDir_US);
  2469. my($UnlocalizedFile,$LocalizedFile, $LocalizedFolder, $DestFile, $New_LocalizedFile);
  2470. #Pickup parameters
  2471. ($CabRootDir, $ExtractRootDir, $ControlFile, $Incremental) = @_;
  2472. # Set defaults
  2473. $files_extracted = 0;
  2474. $file_errors = 0;
  2475. $total_files_extracted = 0;
  2476. #Create a hash-hash from the control file table
  2477. ParseTable::parse_table_file($ControlFile, \%ExtractFiles);
  2478. #Loop through all control file entries
  2479. #
  2480. # $ExtractFileRecord{ExtractFile} : name of MSI table which contains CAB
  2481. # $ExtractFileRecord{ExtractDir} : Destination Directory
  2482. # $ExtractFileRecord{CabFile} : name of MSI File
  2483. # $ExtractFileRecord{CabDir} : Source folder contains MSI file
  2484. #
  2485. foreach $ExtractFile (keys %ExtractFiles) {
  2486. # Create file record hash
  2487. $ExtractFileRecord{ExtractFile} = $ExtractFiles{$ExtractFile}{ExtractTable};
  2488. $ExtractFileRecord{ExtractDir} = $ExtractFiles{$ExtractFile}{ExtractDir};
  2489. $ExtractFileRecord{CabFile} = $ExtractFile;
  2490. $ExtractFileRecord{CabDir} = $ExtractFiles{$ExtractFile}{MSIDir};
  2491. $ExtractFileRecord{Languages} = $ExtractFiles{$ExtractFile}{Languages};
  2492. logmsg("MSI:$ExtractFileRecord{CabFile} Table:$ExtractFileRecord{ExtractFile}");
  2493. #Preprocess file record hash
  2494. unless ($ExtractFileRecord = &PreProcessRecord(\%ExtractFileRecord) ) {
  2495. next;
  2496. }
  2497. #Process "-" entry in text file list
  2498. if ($ExtractFileRecord->{CabDir}=~/^-$/i) {
  2499. $CabFileDir="$CabRootDir";
  2500. } else {
  2501. $CabFileDir="$CabRootDir\\$ExtractFileRecord->{CabDir}";
  2502. }
  2503. if ($ExtractFileRecord->{ExtractDir}=~/^-$/i) {
  2504. $ExtractFileDir="$ExtractRootDir";
  2505. } else {
  2506. $ExtractFileDir="$ExtractRootDir\\$ExtractFileRecord->{ExtractDir}";
  2507. }
  2508. $total_files_extracted++;
  2509. #Create the destination dir if it does not exist
  2510. unless (-e $ExtractFileDir) {
  2511. &MakeDir($ExtractFileDir);
  2512. }
  2513. $CabFile = "$CabFileDir\\$ExtractFileRecord->{CabFile}";
  2514. unless (-e $MSITemp) {
  2515. &MakeDir($MSITemp);
  2516. }
  2517. $MyTempFolder=$MSITemp."\\$ExtractFileRecord{CabFile}";
  2518. $LocalizedFolder= $MyTempFolder."\\LocalizedFolder";
  2519. if ( -e $MyTempFolder) {
  2520. if ( system("rd /s /q $MyTempFolder") != 0) {
  2521. errmsg("Can't delete $MyTempFolder for MSI extraction");
  2522. $file_errors++;
  2523. next;
  2524. }
  2525. }
  2526. &MakeDir($MyTempFolder);
  2527. if (! -e $MyTempFolder) {
  2528. errmsg("Can't create $MyTempFolder for MSI extraction");
  2529. next;
  2530. }
  2531. &MakeDir($LocalizedFolder);
  2532. if (! -e $LocalizedFolder) {
  2533. errmsg("Can't create $LocalizedFolder for MSI extraction");
  2534. next;
  2535. }
  2536. #
  2537. # Let's extract Cab from MSI
  2538. #
  2539. if ( ! -e $CabFile)
  2540. {
  2541. logmsg("Warning:$CabFile doesn't exist");
  2542. next;
  2543. }
  2544. logmsg("msidb.exe -d $CabFile -f $MyTempFolder -e $ExtractFileRecord{ExtractFile}");
  2545. if ( system("msidb.exe -d $CabFile -f $MyTempFolder -e $ExtractFileRecord{ExtractFile}") != 0) {
  2546. logmsg("Warning: Can't extract table $ExtractFileRecord{ExtractFile} from $CabFile");
  2547. next;
  2548. }
  2549. #
  2550. # There is a subfolder $ExtractFileRecord{ExtractFile} under $MyTempFolder and the cab file live under this folder
  2551. #
  2552. $MSICabFolder=$MyTempFolder."\\$ExtractFileRecord{ExtractFile}";
  2553. #
  2554. # Get the name of CAB file
  2555. #
  2556. unless (opendir(INDIR,$MSICabFolder)) {
  2557. errmsg("Can't open MSI cab folder: $MSICabFolder");
  2558. $file_errors++;
  2559. next;
  2560. }
  2561. @Items=readdir INDIR;
  2562. close(INDIR);
  2563. undef $MSICabName;
  2564. LINE: foreach $Line (@Items) {
  2565. if ( ($Line eq "." ) || ($Line eq "..") ) {
  2566. next;
  2567. }
  2568. $MSICabName=$Line;
  2569. last LINE;
  2570. }
  2571. #
  2572. # Extract the Cab inside *.MSI
  2573. #
  2574. if (! defined($MSICabName)) {
  2575. errmsg("No CAB file inside $ExtractFileRecord{CabFile}");
  2576. $file_errors++;
  2577. next;
  2578. }
  2579. $MSICabPath="$MSICabFolder\\$MSICabName";
  2580. logmsg("extract /y /L $LocalizedFolder $MSICabPath *.exe *.dll *.cpl *.ocx *.tsp *.scr *.chm *.chq *.hlp *.cnt *.mfl");
  2581. if (system("extract /y /L $LocalizedFolder $MSICabPath *.exe *.dll *.cpl *.ocx *.tsp *.scr *.chm *.chq *.hlp *.cnt *.mfl") != 0) {
  2582. errmsg("extract $MSICabPath failed");
  2583. next;
  2584. }
  2585. $files_extracted++;
  2586. # We have to extract Unlocalized version of the files so that we may add resource checksum to it
  2587. #
  2588. if ($BuildChecksum) {
  2589. $CabFile=&FindOriginalFile($ExtractFileRecord->{CabFile});
  2590. if (length($CabFile) == 0)
  2591. {
  2592. logmsg("Can't found Original for:$ExtractFileRecord->{CabFile}");
  2593. }
  2594. else
  2595. {
  2596. logmsg("Try to get US files for:$ExtractFileRecord->{CabFile}");
  2597. }
  2598. if (length($CabFile) > 0) {
  2599. if ( -e $CabFile) {
  2600. $MyTempFolder=$MSITemp."\\$ExtractFileRecord{CabFile}.unl";
  2601. if ( -e $MyTempFolder) {
  2602. if ( system("rd /s /q $MyTempFolder") != 0) {
  2603. logmsg("Can't delete $MyTempFolder for MSI extraction");
  2604. $file_errors++;
  2605. next;
  2606. }
  2607. }
  2608. &MakeDir($MyTempFolder);
  2609. if (! -e $MyTempFolder) {
  2610. errmsg("Can't create $MyTempFolder");
  2611. next;
  2612. }
  2613. $ExtractFileDir_US=$MyTempFolder."\\UnlocalizedFolder";
  2614. &MakeDir($ExtractFileDir_US);
  2615. if (! -e $ExtractFileDir_US) {
  2616. errmsg("Can't create $ExtractFileDir_US");
  2617. next;
  2618. }
  2619. #
  2620. # Let's extract Cab from MSI
  2621. #
  2622. logmsg("msidb.exe -d $CabFile -f $MyTempFolder -e $ExtractFileRecord{ExtractFile}");
  2623. if ( system("msidb.exe -d $CabFile -f $MyTempFolder -e $ExtractFileRecord{ExtractFile}") != 0) {
  2624. errmsg("Can't extract table $ExtractFileRecord{ExtractFile} from $CabFile");
  2625. $file_errors++;
  2626. next;
  2627. }
  2628. #
  2629. # There is a subfolder $ExtractFileRecord{ExtractFile} under $MyTempFolder and the cab file live under this folder
  2630. #
  2631. $MSICabFolder=$MyTempFolder."\\$ExtractFileRecord{ExtractFile}";
  2632. #
  2633. # Extract the Cab inside *.MSI
  2634. #
  2635. $MSICabPath="$MSICabFolder\\$MSICabName";
  2636. logmsg("extract /y /L $ExtractFileDir_US $MSICabPath *.exe *.dll *.cpl *.ocx *.tsp *.scr");
  2637. if (system("extract /y /L $ExtractFileDir_US $MSICabPath *.exe *.dll *.cpl *.ocx *.tsp *.scr ") != 0) {
  2638. errmsg("extract $MSICabPath failed");
  2639. next;
  2640. }
  2641. #
  2642. # Add Resource Checksum to Files
  2643. #
  2644. unless (opendir(INDIR,$ExtractFileDir_US)) {
  2645. errmsg("Can't open Unlocalized MSI cab folder: $ExtractFileDir_US");
  2646. $file_errors++;
  2647. next;
  2648. }
  2649. @Items=readdir INDIR;
  2650. close(INDIR);
  2651. foreach $Line (@Items) {
  2652. if ( ($Line eq "." ) || ($Line eq "..") ) {
  2653. next;
  2654. }
  2655. $UnlocalizedFile=$ExtractFileDir_US."\\$Line";
  2656. $LocalizedFile=$LocalizedFolder."\\$Line";
  2657. if (system("checksum.exe $LocalizedFile") == 0 ) {
  2658. logmsg("muirct.exe -c $UnlocalizedFile -z $LocalizedFile");
  2659. system("muirct.exe -c $UnlocalizedFile -z $LocalizedFile");
  2660. }
  2661. else {
  2662. logmsg("Resourcechecksum already in $LocalizedFile");
  2663. }
  2664. } # foreach $Line (@Items)
  2665. } # if ( -e $CabFile)
  2666. } # if (length($CabFile)
  2667. } # if ($BuildChecksum)
  2668. #
  2669. # Copy Files to Destination
  2670. #
  2671. unless (opendir(INDIR,$LocalizedFolder)) {
  2672. errmsg("Can't open Unlocalized MSI cab folder: $LocalizedFolder");
  2673. $file_errors++;
  2674. next;
  2675. }
  2676. @Items=readdir INDIR;
  2677. close(INDIR);
  2678. foreach $Line (@Items) {
  2679. if ( ($Line eq "." ) || ($Line eq "..") ) {
  2680. next;
  2681. }
  2682. $LocalizedFile=$LocalizedFolder."\\$Line";
  2683. $DestFile=$ExtractFileDir."\\$Line";
  2684. if ( &IsWin32File($Line)) {
  2685. $DestFile=$DestFile.".mui";
  2686. #
  2687. # We Force Mui'ize every files from MSI
  2688. # We only apply this process for files contain Fusion resource, but now we apply to
  2689. # all files from MSI
  2690. #
  2691. # if (&IsFusionResource($LocalizedFile))
  2692. #
  2693. if(1)
  2694. {
  2695. $UnlocalizedFile=$ExtractFileDir_US."\\$Line";
  2696. if (! -e $UnlocalizedFile)
  2697. {
  2698. $UnlocalizedFile="";
  2699. }
  2700. if (! &DoMUIizedForFiles($LocalizedFile,$UnlocalizedFile))
  2701. {
  2702. logmsg("Warning: $LocalizedFile contains Fusion resource but it can't be MUIized");
  2703. }
  2704. }
  2705. }
  2706. logmsg("Copying $LocalizedFile -> $DestFile");
  2707. if (!copy("$LocalizedFile", "$DestFile")) {
  2708. logmsg("Failed:Copying $LocalizedFile -> $DestFile");
  2709. $file_errors++;
  2710. }
  2711. }
  2712. }
  2713. return ($files_extracted, $file_errors, $total_files_extracted);
  2714. }
  2715. #Function to copy a directory given a filter
  2716. sub CopyDir {
  2717. my ($SrcDir, $DestDir, $FileFilter, $Incremental);
  2718. my (@CopyFiles, $files_copied, $file_errors, $total_files_copied);
  2719. ($SrcDir, $DestDir, $FileFilter, $Incremental) = @_;
  2720. #If a file filter is not defined set a file filter of *.
  2721. if (!defined $FileFilter) {$FileFilter ="*"};
  2722. #Create the destination dir if it does not exist
  2723. unless (-e $DestDir) {
  2724. &MakeDir($DestDir);
  2725. }
  2726. my $LocalDirHandle = DirHandle->new($SrcDir);
  2727. @CopyFiles = sort grep {-f} map {"$SrcDir\\$_"} grep {!/^\./} grep {/\.$FileFilter$/i} $LocalDirHandle->read();
  2728. foreach $SrcCopyFile (@CopyFiles) {
  2729. #Copy the file
  2730. logmsg ("Copying $SrcCopyFile -> $DestDir");
  2731. if (copy("$SrcCopyFile", "$DestDir") ) {
  2732. $files_copied++;
  2733. } else {
  2734. logmsg("$!");
  2735. $file_errors++;
  2736. }
  2737. }
  2738. return;
  2739. }
  2740. # Function to create a directory
  2741. sub MakeDir {
  2742. my ($fulldir) = @_;
  2743. my ($drive, $path) = $fulldir =~ /((?:[a-z]:)|(?:\\\\[\w-]+\\[^\\]+))?(.*)/i;
  2744. logmsg ("Making dir:$fulldir");
  2745. my $thisdir = '';
  2746. for my $part ($path =~ /(\\[^\\]+)/g) {
  2747. $thisdir .= "$part";
  2748. mkdir( "$drive$thisdir", 0777 );
  2749. }
  2750. if ( ! -d $fulldir ) {
  2751. errmsg ("Could not mkdir:$fulldir $!");
  2752. return 0;
  2753. }
  2754. return;
  2755. }
  2756. #-----------------------------------------------------------------------------
  2757. # ModAge - returns (fractional) number of days since file was last modified
  2758. # NOTE: this script is necessary only because x86 and alpha give different
  2759. # answers to perl's file age functions:
  2760. # Alpha:
  2761. # -C = days since creation
  2762. # -M = days since last modification
  2763. # -A = days since last access
  2764. # X86:
  2765. # -C = days since last modification
  2766. # -M = days since last access
  2767. # -A = ???
  2768. #-----------------------------------------------------------------------------
  2769. sub ModAge {
  2770. my($file, $mod_age);
  2771. # Get input arguments
  2772. ($file) = @_;
  2773. # i386 uses -C when alpha uses -M
  2774. if($PROCESSOR =~ /^[iI]386$/) {
  2775. $mod_age = -C $file;
  2776. }
  2777. elsif($PROCESSOR =~ /^(ALPHA|Alpha|alpha)$/) {
  2778. $mod_age = -M $file;
  2779. }
  2780. return $mod_age;
  2781. } # ModAge
  2782. sub ValidateParams {
  2783. #<Add your code for validating the parameters here>
  2784. }
  2785. # <Add your usage here>
  2786. sub Usage {
  2787. print <<USAGE;
  2788. $0 - creates resource dlls for all files in relbins\<lang>
  2789. and populates the %_nt_bindir%\\mui tree
  2790. Creates language-specific resource only DLLs from localized
  2791. 32-bit images. These DLLs are used for the Multilingual User
  2792. Interface (MUI), aka pluggable UI product for NT5.
  2793. By default, does not create a resource-only-dll if there already
  2794. is one of the same name and it is newer than the localized binary.
  2795. Also Creates a language-specific version of ie5ui.inf,
  2796. and updates mui.inf to contain the current build number.
  2797. perl $0 [-f] [-v] <lang>
  2798. -f: Force option - overrides the incremental behavior of this script.
  2799. Overwrites output files (such as resource-only dlls) even if
  2800. they already exist and are newer than their input files (such as
  2801. the localized binaries).
  2802. -v: Verbose option - gives extra messages describing what is happening
  2803. to each file. By default, the only messages displayed are successes
  2804. and errors which abort the process.
  2805. lang: valid 2-letter (Dublin) or 3-letter (Redmond) code for a
  2806. language (There is no default value for lang)
  2807. OUTPUT
  2808. The language-specific resource-only DLLs are placed in:
  2809. %_NTBINDIR%\\mui\\<lang>\\%_BuildArch%
  2810. The language-specific resource files are placed in:
  2811. %_NTBINDIR%\\mui\\<lang>\\res
  2812. A logfile is created, named:
  2813. %_NTBINDIR%\\logs\\muigen.<lang>.log
  2814. Safemode: if you want the command echoed to stdout and not run,
  2815. set safemode=1
  2816. (This also turns off the logfile)
  2817. EXAMPLE
  2818. perl $0 ger
  2819. USAGE
  2820. }
  2821. sub GetParams {
  2822. # Step 1: Call pm getparams with specified arguments
  2823. &GetParams::getparams(@_);
  2824. # Step 2: Set the language into the enviroment
  2825. $ENV{lang}=$lang;
  2826. # Step 3: Call the usage if specified by /?
  2827. if ($HELP) {
  2828. &Usage();
  2829. exit 1;
  2830. }
  2831. }
  2832. # Cmd entry point for script.
  2833. if (eval("\$0 =~ /" . __PACKAGE__ . "\\.pm\$/i")) {
  2834. # Step 1: Parse the command line
  2835. # <run perl.exe GetParams.pm /? to get the complete usage for GetParams.pm>
  2836. &GetParams ('-o', 'fvl:', '-p', 'FORCE VERBOSE lang', @ARGV);
  2837. # Include local environment extensions
  2838. &LocalEnvEx::localenvex('initialize');
  2839. # Set lang from the environment
  2840. $LANG=$ENV{lang};
  2841. # Validate the option given as parameter.
  2842. &ValidateParams;
  2843. # Step 4: Call the main function
  2844. &muimake::Main();
  2845. # End local environment extensions.
  2846. &LocalEnvEx::localenvex('end');
  2847. }
  2848. # Copy MUI root files
  2849. sub CopyMUIRootFiles {
  2850. my ($layout);
  2851. my ($us_muisetup);
  2852. $layout = GetCDLayOut();
  2853. logmsg("Copy MUI root files");
  2854. system "xcopy /vy $MUIDIR\\*.* $MUI_RELEASE_DIR\\$layout\\*.*";
  2855. system "xcopy /vy $MUIDIR\\*.* $MUI_RELEASE_DIR2\\$layout\\*.*"; #temp fix to copy it to another dir for msi
  2856. #copy over valueadd tools to MUI CD1
  2857. if (-e "$MUIDIR\\$MUI_VALUEADD_DIR" && uc($layout) eq "CD1" ) {
  2858. unless (-e "$MUI_RELEASE_DIR\\$layout\\$MUI_VALUEADD_DIR") {
  2859. &MakeDir("$MUI_RELEASE_DIR\\$layout\\$MUI_VALUEADD_DIR");
  2860. }
  2861. system "xcopy /svy $MUIDIR\\$MUI_VALUEADD_DIR $MUI_RELEASE_DIR\\$layout\\$MUI_VALUEADD_DIR";
  2862. unless (-e "$MUI_RELEASE_DIR2\\$layout\\$MUI_VALUEADD_DIR") {
  2863. &MakeDir("$MUI_RELEASE_DIR2\\$layout\\$MUI_VALUEADD_DIR");
  2864. }
  2865. system "xcopy /svy $MUIDIR\\$MUI_VALUEADD_DIR $MUI_RELEASE_DIR2\\$layout\\$MUI_VALUEADD_DIR";
  2866. logmsg("Copy valueadd files");
  2867. }
  2868. # copy the far east printer drivers
  2869. if (-e "$MUIDIR\\$MUI_PRINTER_DRIVER_DIR" && uc($layout) eq "CD1" ) {
  2870. unless (-e "$MUI_RELEASE_DIR\\$layout\\$MUI_PRINTER_DRIVER_DIR") {
  2871. &MakeDir("$MUI_RELEASE_DIR\\$layout\\$MUI_PRINTER_DRIVER_DIR");
  2872. }
  2873. system "xcopy /svy $MUIDIR\\$MUI_PRINTER_DRIVER_DIR $MUI_RELEASE_DIR\\$layout\\$MUI_PRINTER_DRIVER_DIR";
  2874. unless (-e "$MUI_RELEASE_DIR2\\$layout\\$MUI_PRINTER_DRIVER_DIR") {
  2875. &MakeDir("$MUI_RELEASE_DIR2\\$layout\\$MUI_PRINTER_DRIVER_DIR");
  2876. }
  2877. system "xcopy /svy $MUIDIR\\$MUI_PRINTER_DRIVER_DIR $MUI_RELEASE_DIR2\\$layout\\$MUI_PRINTER_DRIVER_DIR";
  2878. logmsg("Copy FE printer drivers");
  2879. }
  2880. # copy the .net framework files to the release cd from postbuild bin dir
  2881. # exclude PSU and client languages (which do not have .net framework files)
  2882. if ($ENV{_BuildArch}=~/x86/i && !($LANG=~/^(PSU|MIR|FE|ARA|HEB|DA|FI|NO|EL)/i )) {
  2883. # make the .net framework directory netfx in cd release dir
  2884. unless (-e "$MUI_RELEASE_DIR\\$layout\\$MUI_NETFX_DIR") {
  2885. &MakeDir("$MUI_RELEASE_DIR\\$layout\\$MUI_NETFX_DIR");
  2886. }
  2887. unless (-e "$MUI_RELEASE_DIR2\\$layout\\$MUI_NETFX_DIR") {
  2888. &MakeDir("$MUI_RELEASE_DIR2\\$layout\\$MUI_NETFX_DIR");
  2889. }
  2890. # make the language subfolder under netfx in cd release dir
  2891. unless (-e "$MUI_RELEASE_DIR\\$layout\\$MUI_NETFX_DIR\\$LANG") {
  2892. &MakeDir("$MUI_RELEASE_DIR\\$layout\\$MUI_NETFX_DIR\\$LANG");
  2893. }
  2894. unless (-e "$MUI_RELEASE_DIR2\\$layout\\$MUI_NETFX_DIR\\$LANG") {
  2895. &MakeDir("$MUI_RELEASE_DIR2\\$layout\\$MUI_NETFX_DIR\\$LANG");
  2896. }
  2897. # copy langpack.msi and langpac1.cab to the netfx\lang directory in cd release dir
  2898. if (-e "$LOCBINDIR\\netfx\\langpack.msi" && -e "$LOCBINDIR\\netfx\\langpac1.cab") {
  2899. system "copy /vy $LOCBINDIR\\netfx\\langpack.msi $MUI_RELEASE_DIR\\$layout\\$MUI_NETFX_DIR\\$LANG\\langpack.msi";
  2900. system "copy /vy $LOCBINDIR\\netfx\\langpac1.cab $MUI_RELEASE_DIR\\$layout\\$MUI_NETFX_DIR\\$LANG\\langpac1.cab";
  2901. system "copy /vy $LOCBINDIR\\netfx\\langpack.msi $MUI_RELEASE_DIR2\\$layout\\$MUI_NETFX_DIR\\$LANG\\langpack.msi";
  2902. system "copy /vy $LOCBINDIR\\netfx\\langpac1.cab $MUI_RELEASE_DIR2\\$layout\\$MUI_NETFX_DIR\\$LANG\\langpac1.cab";
  2903. logmsg("Copied .net framework files.");
  2904. }
  2905. else
  2906. {
  2907. errmsg("Cannot find .net framework MUI files.");
  2908. }
  2909. }
  2910. else
  2911. {
  2912. logmsg("NOTE: Skipping .net framework files for language $LANG and platform $ENV{_BuildArch}");
  2913. }
  2914. # muisetup.exe exists under US binary and it is a signed binary
  2915. # so we'll grab US version to prevent file protection issues
  2916. $us_muisetup = &FindOriginalFile("muisetup.exe");
  2917. if (-e $us_muisetup) {
  2918. # system "xcopy /vy $us_muisetup $MUI_RELEASE_DIR\\$layout\\*.*";
  2919. system "xcopy /vy $us_muisetup $MUI_RELEASE_DIR2\\$layout\\*.*"; #temp fix to copy it to another dir for msi
  2920. system "xcopy /vy $us_muisetup $MUIDIR\\*.*";
  2921. logmsg ("Copy signed MUISETUP.EXE from $us_muisetup");
  2922. }
  2923. else
  2924. {
  2925. logmsg ("WARNING: signed MUISETUP.EXE not found");
  2926. }
  2927. # also copy the old muisetup.exe from the mui\msi postbuild directory for the temp build
  2928. $us_muisetup = "$MUIDIR\\MSI\\muisetup.exe";
  2929. if (-e $us_muisetup)
  2930. {
  2931. system "xcopy /vy $us_muisetup $MUI_RELEASE_DIR\\$layout\\*.*";
  2932. }
  2933. else
  2934. {
  2935. logmsg("Can't find old version of muisetup.exe for copying.");
  2936. }
  2937. return 1;
  2938. }
  2939. # Get CD layout from MUI.INF
  2940. sub GetCDLayOut {
  2941. my(@cd_layout, @lang_map, $muilang, $lang_id);
  2942. # Map lang
  2943. @lang_map = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE Languages`;
  2944. foreach $muilang (@lang_map)
  2945. {
  2946. if ($muilang =~ /(.*)=$LANG\.mui/i)
  2947. {
  2948. # Get layout
  2949. $langid = $1;
  2950. # Try ia64 section first if we're building ia64 MUI
  2951. if ($_BuildArch =~ /ia64/i)
  2952. {
  2953. @cd_layout = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE CD_LAYOUT_IA64`;
  2954. foreach $layout (@cd_layout)
  2955. {
  2956. chomp($layout);
  2957. if ($layout =~ /$langid=(\d+)/i)
  2958. {
  2959. return uc("cd$1");
  2960. }
  2961. }
  2962. }
  2963. @cd_layout = `perl $RAZZLETOOLPATH\\PostBuildScripts\\parseinf.pl $INFFILE CD_LAYOUT`;
  2964. foreach $layout (@cd_layout)
  2965. {
  2966. chomp($layout);
  2967. if ($layout =~ /$langid=(\d+)/i)
  2968. {
  2969. return uc("cd$1");
  2970. }
  2971. }
  2972. last;
  2973. }
  2974. }
  2975. return lc("psu");
  2976. }
  2977. # -------------------------------------------------------------------------------------------
  2978. # Script: template_script.pm
  2979. # Purpose: Template perl perl script for the NT postbuild environment
  2980. # SD Location: %sdxroot%\tools\postbuildscripts
  2981. #
  2982. # (1) Code section description:
  2983. # CmdMain - Developer code section. This is where your work gets done.
  2984. # <Implement your subs here> - Developer subs code section. This is where you write subs.
  2985. #
  2986. # (2) Reserved Variables -
  2987. # $ENV{HELP} - Flag that specifies usage.
  2988. # $ENV{lang} - The specified language. Defaults to USA.
  2989. # $ENV{logfile} - The path and filename of the logs file.
  2990. # $ENV{logfile_bak} - The path and filename of the logfile.
  2991. # $ENV{errfile} - The path and filename of the error file.
  2992. # $ENV{tmpfile} - The path and filename of the temp file.
  2993. # $ENV{errors} - The scripts errorlevel.
  2994. # $ENV{script_name} - The script name.
  2995. # $ENV{_NTPostBld} - Abstracts the language from the files path that
  2996. # postbuild operates on.
  2997. # $ENV{_NTPostBld_Bak} - Reserved support var.
  2998. # $ENV{_temp_bak} - Reserved support var.
  2999. #
  3000. # (3) Reserved Subs -
  3001. # Usage - Use this sub to discribe the scripts usage.
  3002. # ValidateParams - Use this sub to verify the parameters passed to the script.
  3003. #
  3004. # (4) Call other executables or command scripts by using:
  3005. # system "foo.exe";
  3006. # Note that the executable/script you're calling with system must return a
  3007. # non-zero value on errors to make the error checking mechanism work.
  3008. #
  3009. # Example
  3010. # if (system("perl.exe foo.pl -l $lang")){
  3011. # errmsg("perl.exe foo.pl -l $lang failed.");
  3012. # # If you need to terminate function's execution on this error
  3013. # goto End;
  3014. # }
  3015. #
  3016. # (5) Log non-error information by using:
  3017. # logmsg "<log message>";
  3018. # and log error information by using:
  3019. # errmsg "<error message>";
  3020. #
  3021. # (6) Have your changes reviewed by a member of the US build team (ntbusa) and
  3022. # by a member of the international build team (ntbintl).
  3023. #
  3024. # -------------------------------------------------------------------------------------------
  3025. =head1 NAME
  3026. B<mypackage> - What this package for
  3027. =head1 SYNOPSIS
  3028. <An code example how to use>
  3029. =head1 DESCRIPTION
  3030. <Use above example to describe this package>
  3031. =head1 INSTANCES
  3032. =head2 <myinstances>
  3033. <Description of myinstances>
  3034. =head1 METHODS
  3035. =head2 <mymathods>
  3036. <Description of mymathods>
  3037. =head1 SEE ALSO
  3038. <Some related package or None>
  3039. =head1 AUTHOR
  3040. <Your Name <your e-mail address>>
  3041. =cut
  3042. 1;