Windows-Server-2003/tools/postbuildscripts/symmake.pm

475 lines
11 KiB
Perl

package SymMake;
use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
use lib $ENV{RAZZLETOOLPATH};
use strict;
use Carp;
use IO::File;
use Data::Dumper;
use File::Basename;
use File::Find;
use Logmsg;
# Data structure
# pdbname.binext => [(var)pdbpath,size,$binext]
my ($DDFHandle, $CATHandle, $INFHandle);
my %pktypes = (
FULL => 'ARCH',
UPDATE => 'NTPB'
);
my %revpktypes = reverse %pktypes;
sub new {
my $class = shift;
my $instance = {
KB => {
"$pktypes{'FULL'}" => $_[0],
"$pktypes{'UPDATE'}" => $_[1]
},
SYM => {},
EXT => {},
HANDLE => {},
PKTYPE => undef
};
return bless $instance, $class;
}
sub ReadSource
{
my ($self, $symbolcd) = @_;
my ($fh, $kbterm, $mykey, @mylist);
local $_;
$kbterm = $pktypes{$self->{'PKTYPE'}};
$symbolcd = "$self->{'KB'}->{$kbterm}\\symbolcd\\symbolcd.txt" if (!defined $symbolcd);
$symbolcd = "$ENV{TEMP}\\symbolcd.txt" if (!-e $symbolcd);
if ($self->{'PKTYPE'} =~ /FULL/i) {
if (-e $symbolcd) { # reuse
($self->{'SYM'}, $self->{'EXT'}) = @{do $symbolcd};
} else { # create one
$self->HashArchServer($self->{'KB'}->{$kbterm});
# reuse
$Data::Dumper::Indent=1;
$Data::Dumper::Terse=1;
$fh = new IO::File $symbolcd, 'w';
if (!defined $fh) {
logmsg "Cannot open $symbolcd\.";
} else {
print $fh 'return [';
print $fh Dumper($self->{'SYM'});
print $fh ",\n";
print $fh Dumper($self->{'EXT'});
print $fh '];';
$fh->close();
}
}
} else {
$self->HashSymbolCD($symbolcd);
}
return;
#
# $Data::Dumper::Indent=1;
# $Data::T
# print Dumper($self->{'SYM'}, qw(sym)
}
sub HashSymbolCD
{
my ($self, $file) = @_;
my ($fh, $bin, $symbol, $subpath, $installpath, $kbterm);
local $_;
$kbterm = $pktypes{$self->{'PKTYPE'}};
$fh = new IO::File $file;
if (!defined $fh) {
logmsg "Cannot open symbolcd.txt ($file)";
return;
}
while(<$fh>) {
chomp;
($bin,$symbol,$subpath,$installpath)=split(/\,/,$_);
next if (!defined $installpath);
$self->{'SYM'}->{lc"$symbol\.$installpath"} = [$kbterm, "\\" . $subpath, (-s $self->{'KB'}->{$kbterm} . '\\' . $subpath), lc$installpath];
for (keys %pktypes) {
$self->{'EXT'}->{$_}->{lc$installpath} = 1;
}
}
$fh->close();
}
sub HashArchServer
{
my ($self, $path) = @_;
my ($fh, $bin, $symbol, $subpath, $installpath, $kbterm, $pdbsize);
local $_;
$kbterm = $pktypes{$self->{'PKTYPE'}};
$fh = new IO::File "dir /s/b/a-d $path\\*.*|";
if (!defined $fh) {
logmsg "Cannot access to $path\.";
}
while (<$fh>) {
chomp;
$pdbsize = (-s);
$_ = substr($_, length($path) + 1);
/\\/;
($symbol, $subpath, $installpath) = ($',$_,$`);
$self->{'SYM'}->{lc"$symbol\.$installpath"} = [$kbterm, '\\' . $subpath, $pdbsize, $installpath];
$self->{'EXT'}->{$self->{'PKTYPE'}}->{$installpath} = 1;
}
$fh->close();
}
#
# pkinfoptr->
# FULL ->
# CDFNAME =>
# INFNAME =>
#
sub Create_Symbols_CDF
{
my ($self, $pkinfoptr) = @_;
my ($mykbterm, $mypkname, $fhandle, $fullpdb, %mywriter);
local $_;
&Open_Private_Handle($pkinfoptr, 'CDF');
for $mypkname (keys %{$pkinfoptr}) {
if ($mypkname ne 'FULL') {
$mywriter{$mypkname} = &Writer($pkinfoptr->{$mypkname}->{'CDFHANDLE'}, $pkinfoptr->{'FULL'}->{'CDFHANDLE'});
} else {
$mywriter{$mypkname} = &Writer($pkinfoptr->{'FULL'}->{'CDFHANDLE'});
}
&Create_CDF_Head($pkinfoptr->{$mypkname}->{'CDFHANDLE'}, $pkinfoptr->{$mypkname}->{'CATNAME'}, $pkinfoptr->{$mypkname}->{'INFNAME'});
}
for (sort keys %{$self->{'SYM'}}) {
$mykbterm = $self->{'SYM'}->{$_}->[0];
$mypkname = $revpktypes{$mykbterm};
$fullpdb = $self->{'KB'}->{$mykbterm} . $self->{'SYM'}->{$_}->[1];
&{$mywriter{$mypkname}}("\<HASH\>" . $fullpdb . '=' . $fullpdb . "\n");
}
&Close_Private_Handle($pkinfoptr, 'CDF');
}
#
# pkinfoptr->
# FULL ->
# CABNAME =>
# CABDEST =>
# CABSIZE =>
# DDFLIST => (return cab list)
#
sub Create_Symbols_DDF
{
my ($self, $pkinfoptr) = @_;
my ($symkey, $symptr, $kbterm, $subpath, $pktype, $mypkinfoptr, $cabname, $ddfname, $cabcount, $DDFHandle, $myddfname, $mycabname);
local $_;
# initialization
map({$_->{'CURSIZE'} = $_->{'CABSIZE'}} values %{$pkinfoptr});
for (sort keys %{$self->{'SYM'}}) {
$symkey = $_;
$symptr = $self->{'SYM'}->{$_};
($kbterm, $subpath) = ($symptr->[0],$symptr->[1]);
$pktype = $revpktypes{$kbterm};
# don't generate something not specify
next if (!exists $pkinfoptr->{$pktype});
$mypkinfoptr = $pkinfoptr->{$pktype};
$mypkinfoptr->{'CURSIZE'}+=$symptr->[2];
if ($mypkinfoptr->{'CURSIZE'} >= $mypkinfoptr->{'CABSIZE'}) {
$mypkinfoptr->{'CURSIZE'} = $symptr->[2];
($cabname, $ddfname, $cabcount) = (
$mypkinfoptr->{'CABNAME'},
$mypkinfoptr->{'DDFNAME'},
++$mypkinfoptr->{'CABCOUNT'}
);
$myddfname = $ddfname . $cabcount . '.ddf';
$mycabname = $cabname . $cabcount . '.cab';
$mypkinfoptr->{'DDFHANDLE'} = new IO::File $myddfname, 'w';
if (!defined $mypkinfoptr->{'DDFHANDLE'}) {
logmsg "Cannot open DDF file $myddfname\.";
}
&Create_DDF_Head($mypkinfoptr->{'DDFHANDLE'}, $mycabname);
$mypkinfoptr->{'DDFLIST'}->{$myddfname} = $mycabname;
}
$DDFHandle = $mypkinfoptr->{'DDFHANDLE'};
print $DDFHandle '"' . $self->{'KB'}->{$kbterm} . $subpath . '" "' . $symkey . "\"\n";
}
&Close_Private_Handle($pkinfoptr, 'DDF');
}
#
# pkinfoptr->
# FULL ->
# INFNAME =>
# CDFNAME =>
#
sub Create_Symbols_INF
{
my ($self, $pkinfoptr) = @_;
my ($mypkname, $mypkinfoptr, $INFHandle, %mywriter, %mysepwriter, %h, %cabnames);
local $_;
&Open_Private_Handle($pkinfoptr, 'INF');
for $mypkname (keys %{$pkinfoptr}) {
($mypkinfoptr, $INFHandle) = ($pkinfoptr->{$mypkname}, $pkinfoptr->{$mypkname}->{'INFHANDLE'});
if ($mypkname ne 'FULL') {
$mywriter{$mypkname} = &Writer($INFHandle, $pkinfoptr->{'FULL'}->{'INFHANDLE'});
} else {
$mywriter{$mypkname} = &Writer($INFHandle);
}
$mysepwriter{$mypkname} = &Writer($INFHandle);
&Create_INF_Version($INFHandle, $mypkinfoptr->{'CATNAME'});
&Create_INF_Install($INFHandle, $self->{'EXT'}->{$mypkname});
$cabnames{$mypkname} = (FileParse($mypkinfoptr->{'CABNAME'}))[0];
}
&Create_INF_Files($self->{'SYM'}, \%mysepwriter, \%mywriter);
&Create_INF_SourceDisks($self->{'SYM'}, \%cabnames, \%mysepwriter, \%mywriter);
&Close_Private_Handle($pkinfoptr, 'INF');
}
sub Create_DDF_Head
{
my ($DDFHandle, $cabname) = @_;
my ($mycabname, $mycabdest) = FileParse($cabname);
print $DDFHandle <<DDFHEAD;
.option explicit
.Set DiskDirectoryTemplate=$mycabdest
.Set RptFileName=nul
.Set InfFileName=nul
.Set CabinetNameTemplate=$mycabname\.cab
.Set CompressionType=MSZIP
.Set MaxDiskSize=CDROM
.Set ReservePerCabinetSize=0
.Set Compress=on
.Set CompressionMemory=21
.Set Cabinet=ON
.Set MaxCabinetSize=999999999
.Set FolderSizeThreshold=1000000
DDFHEAD
}
sub Create_CDF_Head
{
my ($CDFHandle, $catname, $infname) = @_;
$catname = (FileParse($catname))[0];
print $CDFHandle <<CDFHEAD;
[CatalogHeader]
Name=$catname
PublicVersion=0x00000001
EncodingType=0x00010001
CATATTR1=0x10010001:OSAttr:2:5.X
[CatalogFiles]
\<HASH\>$infname\.inf=$infname\.inf
CDFHEAD
}
sub Create_INF_Version
{
my ($INFHandle, $catname) = @_;
$catname = (FileParse($catname))[0];
print $INFHandle <<INFVERSION;
[Version]
AdvancedInf= 2.5
Signature= "\$CHICAGO\$"
CatalogFile= $catname\.CAT
INFVERSION
}
sub Create_INF_Install
{
my ($INFHandle, $exthptr) = @_;
my $CopyFiles = 'Files.' . join(", Files\.", sort keys %{$exthptr});
print $INFHandle <<INF_INSTALL;
[DefaultInstall]
CustomDestination= CustDest
AddReg= RegVersion
BeginPrompt= BeginPromptSection
EndPrompt= EndPromptSection
RequireEngine= Setupapi;
CopyFiles= $CopyFiles
[DefaultInstall.Quiet]
CustomDestination=CustDest.2
AddReg= RegVersion
RequireEngine= Setupapi;
CopyFiles= $CopyFiles
[BeginPromptSection]
Title= "Microsoft Windows Symbols"
[EndPromptSection]
Title= "Microsoft Windows Symbols"
Prompt= "Installation is complete"
[RegVersion]
"HKLM","SOFTWARE\\Microsoft\\Symbols\\Directories","Symbol Dir",0,"\%49100\%"
"HKCU","SOFTWARE\\Microsoft\\Symbols\\Directories","Symbol Dir",0,"\%49100\%"
"HKCU","SOFTWARE\\Microsoft\\Symbols\\SymbolInstall","Symbol Install",,"1"
[SymCust]
"HKCU", "Software\\Microsoft\\Symbols\\Directories","Symbol Dir","Symbols install directory","\%25\%\\Symbols"
[CustDest]
49100=SymCust,1
[CustDest.2]
49100=SymCust,5
[DestinationDirs]
;49100 is \%systemroot\%\\symbols
Files.inf = 17
Files.system32 = 11
INF_INSTALL
for (sort keys %{$exthptr}) {
printf $INFHandle ("Files\.%-6s\t\t\= 49100,\"%s\"\n", $_, $_);
}
}
sub Create_INF_Files
{
my ($symptr, $sepwriter, $popwriter) = @_;
my ($mykbterm, $mypkname, %tags);
local $_;
for (sort {($symptr->{$a}->[3] cmp $symptr->{$b}->[3]) or ($a cmp $b)} keys %{$symptr}) {
$mykbterm = $symptr->{$_}->[0];
$mypkname = $revpktypes{$mykbterm};
if ($symptr->{$_}->[3] ne $tags{$mypkname}->[0]) {
$tags{$mypkname} = [$symptr->{$_}->[3], - length($symptr->{$_}->[3]) -1];
&{$sepwriter->{$mypkname}}("\n\[Files\.$tags{$mypkname}->[0]\]\n");
}
if ($symptr->{$_}->[3] ne $tags{'FULL'}->[0]) {
$tags{'FULL'} = [$symptr->{$_}->[3], - length($symptr->{$_}->[3]) -1];
&{$sepwriter->{'FULL'}}("\n\[Files\.$tags{'FULL'}->[0]\]\n");
}
&{$popwriter->{$mypkname}}(substr($_, 0, $tags{$mypkname}->[1]) . "\,$_\,\,4\n");
}
}
sub Create_INF_SourceDisks
{
my ($symptr, $cabnameptr, $sepwriter, $popwriter) = @_; # $pkinfoptr) = @_;
my ($INFHandle, $cabname, $mypkname);
local $_;
for (keys %{$cabnameptr}) {
$cabname = $cabnameptr->{$_};
&{$sepwriter->{$_}}(<<SOURCE_DISKS);
[SourceDisksNames]
1="$cabname\.cab",$cabname\.cab,0
[SourceDisksFiles]
SOURCE_DISKS
}
for (sort keys %{$symptr}) {
$mypkname = $revpktypes{$symptr->{$_}->[0]};
&{$popwriter->{$mypkname}}($_ . "=1\n");
}
}
#
# $pkinfoptr->
# $pktype ->
# CABNAME
# DDFNAME
# INFNAME
# CDFNAME
# CATNAME
# CABSIZE
#
# CABHANDLE
# DDFHANDLE
# INFHANDLE
#
# CABLIST
#
sub RegisterPackage
{
my ($pkinfoptr, $pktype, $hptr) = @_;
my ($mykey);
my @chklists = qw(CABNAME DDFNAME INFNAME CDFNAME CATNAME CABSIZE);
$pkinfoptr->{$pktype} = $hptr;
for $mykey (@chklists) {
die "$mykey not defined in $pktype" if (!exists $pkinfoptr->{$pktype}->{$mykey});
}
}
sub Writer {
my (@handles) = @_;
my ($hptr)=\@handles;
return sub {
my ($myhandle);
for $myhandle (@{$hptr}) {
print $myhandle $_[0];
}
};
}
sub Open_Private_Handle
{
my ($pkinfoptr, $ftype) = @_;
my ($pkname);
for $pkname (keys %{$pkinfoptr}) {
$pkinfoptr->{$pkname}->{$ftype . 'HANDLE'} = new IO::File $pkinfoptr->{$pkname}->{$ftype . 'NAME'} . '.' . $ftype, 'w';
if (!defined $pkinfoptr->{$pkname}->{$ftype . 'HANDLE'}) {
logmsg "Cannot open " . $pkinfoptr->{$pkname}->{$ftype . 'NAME'} . '.' . $ftype . ".";
}
}
}
sub Close_Private_Handle
{
my ($pkinfoptr, $ftype) = @_;
my ($pkname);
for $pkname (keys %{$pkinfoptr}) {
$pkinfoptr->{$pkname}->{$ftype . 'HANDLE'}->close() if (defined $pkinfoptr->{$pkname}->{$ftype . 'HANDLE'});
delete $pkinfoptr->{$pkname}->{$ftype . 'HANDLE'};
}
}
sub FileParse
{
my ($name, $path, $ext) = fileparse(shift, '\.[^\.]+$');
$ext =~ s/^\.//;
return $name, $path, $ext;
}
1;