|
|
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;
|