@echo off REM ------------------------------------------------------------------ REM REM drivercab.cmd REM generates driver.cab for each sku REM REM Copyright (c) Microsoft Corporation. All rights reserved. REM REM ------------------------------------------------------------------ if defined _CPCMAGIC goto CPCBegin perl -x "%~f0" %* goto :EOF #!perl use strict; use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts"; use lib $ENV{RAZZLETOOLPATH}; use PbuildEnv; use ParseArgs; sub Usage { print<] Generates driver.cab for each sku using *drivers.txt files generated by cddata from drvindex.inf. USAGE parseargs('?' => \&Usage); # *** NEXT FEW LINES ARE TEMPLATE *** $ENV{"_CPCMAGIC"}++;exit(system($0)>>8); __END__ :CPCBegin set _CPCMAGIC= setlocal ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS REM *** BEGIN YOUR CMD SCRIPT BELOW *** REM REM drivercab.cmd REM REM this script will generate a driver.cab for each sku appropriate to this REM language. the files to be used are contained in drvindex.inf for each REM sku, which is read by cddata.cmd, and passed through txt files here. REM details: REM we are passed .txt lists for each sku, and then a file called REM commondrivers.txt for all common files. if the commondrivers.txt file REM exists, we can assume that we are not in incremental mode, as the idea REM of a common cab doesn't really make sense in an incremental environment. REM REM if commondrivers.txt does not exist, we will use cabinc.exe to add REM the changed files in each SKU to the appropriate driver.cab REM REM if perdrivers.txt does not exist, then there are no changes for per or REM alternately the per cab is equivalent to the common cab if not in REM incremental mode. REM REM setup REM REM get all appropriate products call logmsg.cmd "Calculating which products to act on ..." set Products= for %%a in (pro per bla sbs srv ads dtc) do ( perl %RazzleToolPath%\cksku.pm -t:%%a -l:%lang% -a:%_BuildArch% if !ErrorLevel! == 0 ( if not defined Products ( set Products=%%a ) else ( set Products=!Products! %%a ) ) ) call logmsg.cmd "Checking for incremental mode ..." set IncMode=TRUE if exist %TMP%\commondrivers.txt set IncMode= REM set up the temp cab locations set TmpCabLocation=%_NTPOSTBLD%\cabs\driver\cabs if not exist %TmpCabLocation% md %TmpCabLocation% REM REM test for incremental mode REM if defined IncMode goto :PerformIncrementalCabbing goto :PerformFullCabbing REM REM PerformIncrementalCabbing REM REM here we just want to go through our product list, and use cabinc.exe REM to replace the old entries in driver.cab with the new ones. REM :PerformIncrementalCabbing call logmsg.cmd "Performing incremental cabbing ..." REM loop over products and cabinc the files in for %%a in (%Products%) do ( REM the call to :SetMyInfDirName just sets the MyInfDirName env var to REM whatever the inf subdir for that product is, like for ads it is entinf set MyInfDirName= call :SetMyInfDirName %%a if not defined MyInfDirName ( call errmsg.cmd "Invalid sku %%a found ..." ) set MyDriverCab=%_NTPOSTBLD%\!MyInfDirName!\driver.cab if not exist !MyDriverCab! ( call errmsg.cmd "Can't perform incremental updates without full cabs ..." goto :End ) set MyFileList=%TMP%\%%adrivers.txt if not exist !MyFileList! ( call logmsg.cmd "No files to change for %%a sku ..." ) else ( call logmsg.cmd "Replacing files for %%a sku ..." set IncCommand= set NewFiles= for /f %%b in (!MyFileList!) do ( set NewFile=%_NTPOSTBLD%\%%b for %%c in (!NewFile!) do set NewFileName=%%~nxc extract.exe -d !MyDriverCab! !NewFileName! | findstr /ic:"No matching files" if !ErrorLevel! NEQ 0 ( REM this file was already in the cab, replace it set IncCommand=!IncCommand! !NewFile! ) else ( REM this file is new to the cab, add it set NewFiles=!NewFiles! mergefile !NewFile! ) ) if defined IncCommand ( call ExecuteCmd.cmd "cabinc.exe -t %NUMBER_OF_PROCESSORS% -q 40 -p 80 !MyDriverCab! !IncCommand!" if !ErrorLevel! NEQ 0 ( call errmsg.cmd "Replace failed for %%a sku, file was !NewFile!," call errmsg.cmd "cab file was !MyDriverCab! ..." ) else ( call logmsg.cmd "!NewFileName! replaced in !MyDriverCab! ..." ) ) if defined NewFiles ( call ExecuteCmd.cmd "cabbench.exe load !MyDriverCab! !NewFiles! save !MyDriverCab!.new" if !ErrorLevel! NEQ 0 ( call errmsg.cmd "Add failed for %%a sku, file was !NewFile!," call errmsg.cmd "cab file was !MyDriverCab! ..." ) else ( call ExecuteCmd.cmd "del !MyDriverCab!" call ExecuteCmd.cmd "ren !MyDriverCab!.new driver.cab" call logmsg.cmd "!NewFileName! added to !MyDriverCab! ..." ) ) ) ) call logmsg.cmd "Finished." goto :End REM REM PerformFullCabbing REM REM here we want to break the common list into NUM_PROCS sublists, then REM multithread generation of those sub cabs. after that, we mash them all REM back together, and then multithread generation of the sku specific cabs. REM finally, we mash the sku specific cabs onto the common cab for each sku, REM and put those in the fooinf\driver.cab position. REM :PerformFullCabbing call logmsg.cmd "Performing full cabbing ..." REM REM first, do the common cab. we want to break the list down into NUM_PROCS REM lists, so we can thread them nicely REM call logmsg.cmd "Finding common drivers list ..." set CommonList=%TMP%\commondrivers.txt if not exist %CommonList% ( call errmsg.cmd "Could not find %CommonList% to generate driver.cab ..." goto :End ) set BackupName=%TMP%\backuplist.txt if exist %BackupName% del /f /q %BackupName% move %CommonList% %BackupName% if exist %CommonList%.* del /f /q %CommonList%.* move %BackupName% %CommonList% set /a NumLists=%NUMBER_OF_PROCESSORS% call logmsg.cmd "Splitting common drivers list into %NumLists% parts ..." perl %RazzleToolPath%\PostBuildScripts\splitlist.pl -n %NumLists% -f %CommonList% -l %lang% REM splitlist.pl creates commondrivers.txt.1, commondrivers.txt.2, etc set /a NumThreads=0 for /l %%a in (1,1,%NumLists%) do ( if exist %CommonList%.%%a set /a NumThreads=%%a ) REM now NumThreads is the list count call logmsg.cmd "Created %NumThreads% sub lists ..." REM set the common cab name and location set CommonCab=%TmpCabLocation%\common.cab if exist %CommonCab% del /f %CommonCab% if exist %CommonCab% ( call errmsg.cmd "Failed to delete old common cab ..." goto :End ) REM REM now, we want to kick off our child processes and wait for them to finish. REM the wrapper script will generate the DDF from the list we pass it on the REM command line, in this case something like %TMP%\commondrivers.txt.1 REM set EventList= for /l %%a in (1,1,%NumThreads%) do ( call logmsg.cmd "Starting %CommonCab%.%%a cab ..." set EventName=commoncab%%a start "PB_CommonCab.%%a" /min cmd /c CabWrapper.cmd %CommonList%.%%a %CommonCab%.%%a !EventName!" set EventList=!EventList! !EventName! ) if not defined EventList ( REM hmmm? call errmsg.cmd "No events to wait on for common cabs ..." ) else ( call logmsg.cmd "Waiting for common cabs ..." perl %RazzleToolPath%\PostBuildScripts\cmdevt.pl -iwv !EventList! ) REM REM check if there were errors in the generation REM call logmsg.cmd "Checking for errors in sub cab generation ..." findstr /ic:"ERROR:" %LOGFILE% >nul 2>nul if %ErrorLevel% == 0 ( REM we found some errors call errmsg.cmd "There were errors generating the sub cabs for driver.cab" call errmsg.cmd "Please investigate or run postbuild -full" goto :End ) REM REM the common cab now needs to be merged together. we will use cabbench.exe REM to do this REM call logmsg.cmd "Merging common cab pieces back together ..." if %NumThreads% == 1 ( REM only one cab, just rename it call logmsg.cmd "Only one common cab, renaming ..." move %TmpCabLocation%\common.cab.1 %CommonCab% ) else ( REM multiple cabs, merge them set MergeCommand=load %TmpCabLocation%\common.cab.1 for /l %%a in (2,1,%NumThreads%) do ( set MergeCommand=!MergeCommand! load %TmpCabLocation%\common.cab.%%a merge ) set MergeCommand=!MergeCommand! save %CommonCab% call logmsg.cmd "Issuing merge ..." call ExecuteCmd.cmd "cabbench.exe !MergeCommand!" if !ErrorLevel! NEQ 0 ( call errmsg.cmd "Merge of common cab failed ..." goto :End ) ) if not exist %CommonCab% ( call errmsg.cmd "Common cab does not exist at %CommonCab% after merge ..." goto :End ) call logmsg.cmd "Merge successful, continuing ..." REM REM now, we get to create the sub cabs for each sku. just kick off as many REM threads as we need to do this, and give the short lists to the wrapper. REM the wrapper will handle creating the DDFs from the lists we pass it. REM call logmsg.cmd "Creating sku specific cabs ..." set EventList= for %%a in (%Products%) do ( if not exist %TMP%\%%adrivers.txt ( call logmsg.cmd "No drivers to cab for %%a sku ..." ) else ( call logmsg.cmd "Starting generation for %%a specific drivers ..." set EventName=%%adrivercab REM syntax for CabWrapper.cmd is: REM list of files REM cab name to create REM event name to signal start "PB_%%adrivercab" /min cmd /c CabWrapper.cmd %TMP%\%%adrivers.txt %TmpCabLocation%\%%adriver.cab !EventName! set EventList=!EventList! !EventName! ) ) if not defined EventList ( REM no events to wait for? okay ... whatever ... call logmsg.cmd "No sku specific cabs to wait for, continuing ..." ) else ( call logmsg.cmd "Waiting for sku specific cabs to generate ..." perl %RazzleToolPath%\PostBuildScripts\cmdevt.pl -iwv %EventList% ) REM REM now we have the common cab and the sku specific cabs, let's merge them REM into full sku particular driver.cab files REM for %%a in (%Products%) do ( set MySkuCab=%_NTPOSTBLD%\%%ainf\driver.cab if /i "%%a" == "pro" set MySkuCab=%_NTPOSTBLD%\driver.cab if /i "%%a" == "ads" set MySkuCab=%_NTPOSTBLD%\entinf\driver.cab if not exist %TmpCabLocation%\%%adriver.cab ( call logmsg.cmd "No %%a specific cab, copying common cab in place ..." copy %CommonCab% !MySkuCab! ) else ( call logmsg.cmd "Merging %%a specific and common cabs ..." set MergeCommand=load %TmpCabLocation%\%%adriver.cab set MergeCommand=!MergeCommand! load %CommonCab% set MergeCommand=!MergeCommand! merge save !MySkuCab! call ExecuteCmd.cmd "cabbench.exe !MergeCommand!" if !ErrorLevel! NEQ 0 ( call errmsg.cmd "Merge of %%a driver.cab failed ..." ) else ( call logmsg.cmd "Merge of %%a driver.cab successful ..." ) ) ) REM REM and we're done REM call logmsg.cmd "Finished." goto :End :SetMyInfDirName set SkuName=%1 set MyInfDirName= if /i "%SkuName%" == "pro" set MyInfDirName=. if /i "%SkuName%" == "per" set MyInfDirName=perinf if /i "%SkuName%" == "bla" set MyInfDirName=blainf if /i "%SkuName%" == "sbs" set MyInfDirName=sbsinf if /i "%SkuName%" == "srv" set MyInfDirName=srvinf if /i "%SkuName%" == "ads" set MyInfDirName=entinf if /i "%SkuName%" == "dtc" set MyInfDirName=dtcinf goto :End :end if "%errors%" == "" set errors=0 seterror.exe "%errors%"& goto :EOF