1*cdf0e10cSrcweir#************************************************************************* 2*cdf0e10cSrcweir# 3*cdf0e10cSrcweir# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir# 5*cdf0e10cSrcweir# Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir# 7*cdf0e10cSrcweir# OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir# 9*cdf0e10cSrcweir# This file is part of OpenOffice.org. 10*cdf0e10cSrcweir# 11*cdf0e10cSrcweir# OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir# it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir# only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir# 15*cdf0e10cSrcweir# OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir# but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir# GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir# (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir# 21*cdf0e10cSrcweir# You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir# version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir# <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir# for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir# 26*cdf0e10cSrcweir#************************************************************************* 27*cdf0e10cSrcweir 28*cdf0e10cSrcweirpackage installer::windows::admin; 29*cdf0e10cSrcweir 30*cdf0e10cSrcweiruse File::Copy; 31*cdf0e10cSrcweiruse installer::exiter; 32*cdf0e10cSrcweiruse installer::files; 33*cdf0e10cSrcweiruse installer::globals; 34*cdf0e10cSrcweiruse installer::pathanalyzer; 35*cdf0e10cSrcweiruse installer::systemactions; 36*cdf0e10cSrcweiruse installer::worker; 37*cdf0e10cSrcweiruse installer::windows::idtglobal; 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir################################################################################# 40*cdf0e10cSrcweir# Unpacking cabinet files with expand 41*cdf0e10cSrcweir################################################################################# 42*cdf0e10cSrcweir 43*cdf0e10cSrcweirsub unpack_cabinet_file 44*cdf0e10cSrcweir{ 45*cdf0e10cSrcweir my ($cabfilename, $unpackdir) = @_; 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir my $infoline = "Unpacking cabinet file: $cabfilename\n"; 48*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir my $expandfile = "expand.exe"; # Has to be in the path 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir # expand.exe has to be located in the system directory. 53*cdf0e10cSrcweir # Cygwin has another tool expand.exe, that converts tabs to spaces. This cannot be used of course. 54*cdf0e10cSrcweir # But this wrong expand.exe is typically in the PATH before this expand.exe, to unpack 55*cdf0e10cSrcweir # cabinet files. 56*cdf0e10cSrcweir 57*cdf0e10cSrcweir# if ( $^O =~ /cygwin/i ) 58*cdf0e10cSrcweir# { 59*cdf0e10cSrcweir# $expandfile = $ENV{'SYSTEMROOT'} . "/system32/expand.exe"; # Has to be located in the systemdirectory 60*cdf0e10cSrcweir# $expandfile =~ s/\\/\//; 61*cdf0e10cSrcweir# if ( ! -f $expandfile ) { exit_program("ERROR: Did not find file $expandfile in the Windows system folder!"); } 62*cdf0e10cSrcweir# } 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir $expandfile = qx(cygpath -u "$ENV{WINDIR}"/System32/expand.exe); 67*cdf0e10cSrcweir chomp $expandfile; 68*cdf0e10cSrcweir } 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir my $expandlogfile = $unpackdir . $installer::globals::separator . "expand.log"; 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir # exclude cabinet file 73*cdf0e10cSrcweir # my $systemcall = $cabarc . " -o X " . $mergemodulehash->{'cabinetfile'}; 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir my $systemcall = ""; 76*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { 77*cdf0e10cSrcweir my $localunpackdir = qx{cygpath -w "$unpackdir"}; 78*cdf0e10cSrcweir chomp ($localunpackdir); 79*cdf0e10cSrcweir $localunpackdir =~ s/\\/\\\\/g; 80*cdf0e10cSrcweir $cabfilename =~ s/\\/\\\\/g; 81*cdf0e10cSrcweir $cabfilename =~ s/\s*$//g; 82*cdf0e10cSrcweir $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $localunpackdir . " \> " . $expandlogfile; 83*cdf0e10cSrcweir } 84*cdf0e10cSrcweir else 85*cdf0e10cSrcweir { 86*cdf0e10cSrcweir $systemcall = $expandfile . " " . $cabfilename . " -F:\* " . $unpackdir . " \> " . $expandlogfile; 87*cdf0e10cSrcweir } 88*cdf0e10cSrcweir 89*cdf0e10cSrcweir my $returnvalue = system($systemcall); 90*cdf0e10cSrcweir $infoline = "Systemcall: $systemcall\n"; 91*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir if ($returnvalue) 94*cdf0e10cSrcweir { 95*cdf0e10cSrcweir $infoline = "ERROR: Could not execute $systemcall !\n"; 96*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 97*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: Could not extract cabinet file: $mergemodulehash->{'cabinetfile'} !", "change_file_table"); 98*cdf0e10cSrcweir } 99*cdf0e10cSrcweir else 100*cdf0e10cSrcweir { 101*cdf0e10cSrcweir $infoline = "Success: Executed $systemcall successfully!\n"; 102*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 103*cdf0e10cSrcweir } 104*cdf0e10cSrcweir} 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir################################################################################# 107*cdf0e10cSrcweir# Include tables into a msi database 108*cdf0e10cSrcweir################################################################################# 109*cdf0e10cSrcweir 110*cdf0e10cSrcweirsub include_tables_into_pcpfile 111*cdf0e10cSrcweir{ 112*cdf0e10cSrcweir my ($fullmsidatabasepath, $workdir, $tables) = @_; 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir my $msidb = "msidb.exe"; # Has to be in the path 115*cdf0e10cSrcweir my $infoline = ""; 116*cdf0e10cSrcweir my $systemcall = ""; 117*cdf0e10cSrcweir my $returnvalue = ""; 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir # Make all table 8+3 conform 120*cdf0e10cSrcweir my $alltables = installer::converter::convert_stringlist_into_array(\$tables, " "); 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$alltables}; $i++ ) 123*cdf0e10cSrcweir { 124*cdf0e10cSrcweir my $tablename = ${$alltables}[$i]; 125*cdf0e10cSrcweir $tablename =~ s/\s*$//; 126*cdf0e10cSrcweir my $namelength = length($tablename); 127*cdf0e10cSrcweir if ( $namelength > 8 ) 128*cdf0e10cSrcweir { 129*cdf0e10cSrcweir my $newtablename = substr($tablename, 0, 8); # name, offset, length 130*cdf0e10cSrcweir my $oldfile = $workdir . $installer::globals::separator . $tablename . ".idt"; 131*cdf0e10cSrcweir my $newfile = $workdir . $installer::globals::separator . $newtablename . ".idt"; 132*cdf0e10cSrcweir if ( -f $newfile ) { unlink $newfile; } 133*cdf0e10cSrcweir installer::systemactions::copy_one_file($oldfile, $newfile); 134*cdf0e10cSrcweir my $savfile = $oldfile . ".orig"; 135*cdf0e10cSrcweir installer::systemactions::copy_one_file($oldfile, $savfile); 136*cdf0e10cSrcweir } 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir # Import of tables 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir $systemcall = $msidb . " -d " . $fullmsidatabasepath . " -f " . $workdir . " -i " . $tables; 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir $returnvalue = system($systemcall); 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir $infoline = "Systemcall: $systemcall\n"; 146*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir if ($returnvalue) 149*cdf0e10cSrcweir { 150*cdf0e10cSrcweir $infoline = "ERROR: Could not execute $systemcall !\n"; 151*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 152*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: Could not include tables into msi database: $fullmsidatabasepath !", "include_tables_into_pcpfile"); 153*cdf0e10cSrcweir } 154*cdf0e10cSrcweir else 155*cdf0e10cSrcweir { 156*cdf0e10cSrcweir $infoline = "Success: Executed $systemcall successfully!\n"; 157*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 158*cdf0e10cSrcweir } 159*cdf0e10cSrcweir} 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir################################################################################# 162*cdf0e10cSrcweir# Extracting tables from msi database 163*cdf0e10cSrcweir################################################################################# 164*cdf0e10cSrcweir 165*cdf0e10cSrcweirsub extract_tables_from_pcpfile 166*cdf0e10cSrcweir{ 167*cdf0e10cSrcweir my ($fullmsidatabasepath, $workdir, $tablelist) = @_; 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir my $msidb = "msidb.exe"; # Has to be in the path 170*cdf0e10cSrcweir my $infoline = ""; 171*cdf0e10cSrcweir my $systemcall = ""; 172*cdf0e10cSrcweir my $returnvalue = ""; 173*cdf0e10cSrcweir 174*cdf0e10cSrcweir my $localfullmsidatabasepath = $fullmsidatabasepath; 175*cdf0e10cSrcweir 176*cdf0e10cSrcweir # Export of all tables by using "*" 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { 179*cdf0e10cSrcweir # Copying the msi database locally guarantees the format of the directory. 180*cdf0e10cSrcweir # Otherwise it is defined in the file of UPDATE_DATABASE_LISTNAME 181*cdf0e10cSrcweir 182*cdf0e10cSrcweir my $msifilename = $localfullmsidatabasepath; 183*cdf0e10cSrcweir installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$msifilename); 184*cdf0e10cSrcweir my $destdatabasename = $workdir . $installer::globals::separator . $msifilename; 185*cdf0e10cSrcweir installer::systemactions::copy_one_file($localfullmsidatabasepath, $destdatabasename); 186*cdf0e10cSrcweir $localfullmsidatabasepath = $destdatabasename; 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir chomp( $localfullmsidatabasepath = qx{cygpath -w "$localfullmsidatabasepath"} ); 189*cdf0e10cSrcweir chomp( $workdir = qx{cygpath -w "$workdir"} ); 190*cdf0e10cSrcweir 191*cdf0e10cSrcweir # msidb.exe really wants backslashes. (And double escaping because system() expands the string.) 192*cdf0e10cSrcweir $localfullmsidatabasepath =~ s/\\/\\\\/g; 193*cdf0e10cSrcweir $workdir =~ s/\\/\\\\/g; 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir # and if there are still slashes, they also need to be double backslash 196*cdf0e10cSrcweir $localfullmsidatabasepath =~ s/\//\\\\/g; 197*cdf0e10cSrcweir $workdir =~ s/\//\\\\/g; 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir $systemcall = $msidb . " -d " . $localfullmsidatabasepath . " -f " . $workdir . " -e $tablelist"; 201*cdf0e10cSrcweir $returnvalue = system($systemcall); 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir $infoline = "Systemcall: $systemcall\n"; 204*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir if ($returnvalue) 207*cdf0e10cSrcweir { 208*cdf0e10cSrcweir $infoline = "ERROR: Could not execute $systemcall !\n"; 209*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 210*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: Could not exclude tables from pcp file: $localfullmsidatabasepath !", "extract_tables_from_pcpfile"); 211*cdf0e10cSrcweir } 212*cdf0e10cSrcweir else 213*cdf0e10cSrcweir { 214*cdf0e10cSrcweir $infoline = "Success: Executed $systemcall successfully!\n"; 215*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir} 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir################################################################################ 220*cdf0e10cSrcweir# Analyzing the content of Directory.idt 221*cdf0e10cSrcweir################################################################################# 222*cdf0e10cSrcweir 223*cdf0e10cSrcweirsub analyze_directory_file 224*cdf0e10cSrcweir{ 225*cdf0e10cSrcweir my ($filecontent) = @_; 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir my %table = (); 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\s*$/ ) 234*cdf0e10cSrcweir { 235*cdf0e10cSrcweir my $dir = $1; 236*cdf0e10cSrcweir my $parent = $2; 237*cdf0e10cSrcweir my $name = $3; 238*cdf0e10cSrcweir 239*cdf0e10cSrcweir if ( $name =~ /^\s*(.*?)\s*\:\s*(.*?)\s*$/ ) { $name = $2; } 240*cdf0e10cSrcweir if ( $name =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $name = $2; } 241*cdf0e10cSrcweir 242*cdf0e10cSrcweir my %helphash = (); 243*cdf0e10cSrcweir $helphash{'Directory_Parent'} = $parent; 244*cdf0e10cSrcweir $helphash{'DefaultDir'} = $name; 245*cdf0e10cSrcweir $table{$dir} = \%helphash; 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir } 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir return \%table; 250*cdf0e10cSrcweir} 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir################################################################################# 253*cdf0e10cSrcweir# Analyzing the content of Component.idt 254*cdf0e10cSrcweir################################################################################# 255*cdf0e10cSrcweir 256*cdf0e10cSrcweirsub analyze_component_file 257*cdf0e10cSrcweir{ 258*cdf0e10cSrcweir my ($filecontent) = @_; 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir my %table = (); 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir my $component = $1; 269*cdf0e10cSrcweir my $dir = $3; 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir $table{$component} = $dir; 272*cdf0e10cSrcweir } 273*cdf0e10cSrcweir } 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir return \%table; 276*cdf0e10cSrcweir} 277*cdf0e10cSrcweir 278*cdf0e10cSrcweir################################################################################# 279*cdf0e10cSrcweir# Analyzing the full content of Component.idt 280*cdf0e10cSrcweir################################################################################# 281*cdf0e10cSrcweir 282*cdf0e10cSrcweirsub analyze_keypath_component_file 283*cdf0e10cSrcweir{ 284*cdf0e10cSrcweir my ($filecontent) = @_; 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir my %keypathtable = (); 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 293*cdf0e10cSrcweir { 294*cdf0e10cSrcweir my $component = $1; 295*cdf0e10cSrcweir my $keypath = $6; 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir $keypathtable{$keypath} = $component; 298*cdf0e10cSrcweir } 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir return (\%keypathtable); 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir} 304*cdf0e10cSrcweir 305*cdf0e10cSrcweir################################################################################# 306*cdf0e10cSrcweir# Analyzing the content of Registry.idt 307*cdf0e10cSrcweir################################################################################# 308*cdf0e10cSrcweir 309*cdf0e10cSrcweirsub analyze_registry_file 310*cdf0e10cSrcweir{ 311*cdf0e10cSrcweir my ($filecontent) = @_; 312*cdf0e10cSrcweir 313*cdf0e10cSrcweir my %table = (); 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 316*cdf0e10cSrcweir { 317*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 318*cdf0e10cSrcweir 319*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 320*cdf0e10cSrcweir { 321*cdf0e10cSrcweir my $registry = $1; 322*cdf0e10cSrcweir my $root = $2; 323*cdf0e10cSrcweir my $key = $3; 324*cdf0e10cSrcweir my $name = $4; 325*cdf0e10cSrcweir my $value = $5; 326*cdf0e10cSrcweir my $component = $6; 327*cdf0e10cSrcweir 328*cdf0e10cSrcweir my %helphash = (); 329*cdf0e10cSrcweir # $helphash{'Registry'} = $registry; 330*cdf0e10cSrcweir $helphash{'Root'} = $root; 331*cdf0e10cSrcweir $helphash{'Key'} = $key; 332*cdf0e10cSrcweir $helphash{'Name'} = $name; 333*cdf0e10cSrcweir $helphash{'Value'} = $value; 334*cdf0e10cSrcweir $helphash{'Component'} = $component; 335*cdf0e10cSrcweir 336*cdf0e10cSrcweir $table{$registry} = \%helphash; 337*cdf0e10cSrcweir } 338*cdf0e10cSrcweir } 339*cdf0e10cSrcweir 340*cdf0e10cSrcweir return \%table; 341*cdf0e10cSrcweir} 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir################################################################################# 344*cdf0e10cSrcweir# Analyzing the content of File.idt 345*cdf0e10cSrcweir################################################################################# 346*cdf0e10cSrcweir 347*cdf0e10cSrcweirsub analyze_file_file 348*cdf0e10cSrcweir{ 349*cdf0e10cSrcweir my ($filecontent) = @_; 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir my %table = (); 352*cdf0e10cSrcweir my %fileorder = (); 353*cdf0e10cSrcweir my $maxsequence = 0; 354*cdf0e10cSrcweir 355*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$filecontent}; $i++ ) 356*cdf0e10cSrcweir { 357*cdf0e10cSrcweir if (( $i == 0 ) || ( $i == 1 ) || ( $i == 2 )) { next; } 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir if ( ${$filecontent}[$i] =~ /^\s*(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\t(.*?)\s*$/ ) 360*cdf0e10cSrcweir { 361*cdf0e10cSrcweir my $file = $1; 362*cdf0e10cSrcweir my $comp = $2; 363*cdf0e10cSrcweir my $filename = $3; 364*cdf0e10cSrcweir my $sequence = $8; 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir if ( $filename =~ /^\s*(.*?)\s*\|\s*(.*?)\s*$/ ) { $filename = $2; } 367*cdf0e10cSrcweir 368*cdf0e10cSrcweir my %helphash = (); 369*cdf0e10cSrcweir $helphash{'Component'} = $comp; 370*cdf0e10cSrcweir $helphash{'FileName'} = $filename; 371*cdf0e10cSrcweir $helphash{'Sequence'} = $sequence; 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir $table{$file} = \%helphash; 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir $fileorder{$sequence} = $file; 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir if ( $sequence > $maxsequence ) { $maxsequence = $sequence; } 378*cdf0e10cSrcweir } 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir return (\%table, \%fileorder, $maxsequence); 382*cdf0e10cSrcweir} 383*cdf0e10cSrcweir 384*cdf0e10cSrcweir#################################################################################### 385*cdf0e10cSrcweir# Recursively creating the directory tree 386*cdf0e10cSrcweir#################################################################################### 387*cdf0e10cSrcweir 388*cdf0e10cSrcweirsub create_directory_tree 389*cdf0e10cSrcweir{ 390*cdf0e10cSrcweir my ($parent, $pathcollector, $fulldir, $dirhash) = @_; 391*cdf0e10cSrcweir 392*cdf0e10cSrcweir foreach my $dir ( keys %{$dirhash} ) 393*cdf0e10cSrcweir { 394*cdf0e10cSrcweir if (( $dirhash->{$dir}->{'Directory_Parent'} eq $parent ) && ( $dirhash->{$dir}->{'DefaultDir'} ne "." )) 395*cdf0e10cSrcweir { 396*cdf0e10cSrcweir my $dirname = $dirhash->{$dir}->{'DefaultDir'}; 397*cdf0e10cSrcweir # Create the directory 398*cdf0e10cSrcweir my $newdir = $fulldir . $installer::globals::separator . $dirname; 399*cdf0e10cSrcweir if ( ! -f $newdir ) { mkdir $newdir; } 400*cdf0e10cSrcweir # Saving in collector 401*cdf0e10cSrcweir $pathcollector->{$dir} = $newdir; 402*cdf0e10cSrcweir # Iteration 403*cdf0e10cSrcweir create_directory_tree($dir, $pathcollector, $newdir, $dirhash); 404*cdf0e10cSrcweir } 405*cdf0e10cSrcweir } 406*cdf0e10cSrcweir} 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir#################################################################################### 409*cdf0e10cSrcweir# Creating the directory tree 410*cdf0e10cSrcweir#################################################################################### 411*cdf0e10cSrcweir 412*cdf0e10cSrcweirsub create_directory_structure 413*cdf0e10cSrcweir{ 414*cdf0e10cSrcweir my ($dirhash, $targetdir) = @_; 415*cdf0e10cSrcweir 416*cdf0e10cSrcweir my %fullpathhash = (); 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir my @startparents = ("TARGETDIR", "INSTALLLOCATION"); 419*cdf0e10cSrcweir 420*cdf0e10cSrcweir foreach $dir (@startparents) { create_directory_tree($dir, \%fullpathhash, $targetdir, $dirhash); } 421*cdf0e10cSrcweir 422*cdf0e10cSrcweir # Also adding the pathes of the startparents 423*cdf0e10cSrcweir foreach $dir (@startparents) 424*cdf0e10cSrcweir { 425*cdf0e10cSrcweir if ( ! exists($fullpathhash{$dir}) ) { $fullpathhash{$dir} = $targetdir; } 426*cdf0e10cSrcweir } 427*cdf0e10cSrcweir 428*cdf0e10cSrcweir return \%fullpathhash; 429*cdf0e10cSrcweir} 430*cdf0e10cSrcweir 431*cdf0e10cSrcweir#################################################################################### 432*cdf0e10cSrcweir# Copying files into installation set 433*cdf0e10cSrcweir#################################################################################### 434*cdf0e10cSrcweir 435*cdf0e10cSrcweirsub copy_files_into_directory_structure 436*cdf0e10cSrcweir{ 437*cdf0e10cSrcweir my ($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash) = @_; 438*cdf0e10cSrcweir 439*cdf0e10cSrcweir my $unopkgfile = ""; 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir for ( my $i = 1; $i <= $maxsequence; $i++ ) 442*cdf0e10cSrcweir { 443*cdf0e10cSrcweir if ( exists($fileorder->{$i}) ) 444*cdf0e10cSrcweir { 445*cdf0e10cSrcweir my $file = $fileorder->{$i}; 446*cdf0e10cSrcweir if ( ! exists($filehash->{$file}->{'Component'}) ) { installer::exiter::exit_program("ERROR: Did not find component for file: \"$file\".", "copy_files_into_directory_structure"); } 447*cdf0e10cSrcweir my $component = $filehash->{$file}->{'Component'}; 448*cdf0e10cSrcweir if ( ! exists($componenthash->{$component}) ) { installer::exiter::exit_program("ERROR: Did not find directory for component: \"$component\".", "copy_files_into_directory_structure"); } 449*cdf0e10cSrcweir my $dirname = $componenthash->{$component}; 450*cdf0e10cSrcweir if ( ! exists($fullpathhash->{$dirname}) ) { installer::exiter::exit_program("ERROR: Did not find full directory path for dir: \"$dirname\".", "copy_files_into_directory_structure"); } 451*cdf0e10cSrcweir my $destdir = $fullpathhash->{$dirname}; 452*cdf0e10cSrcweir if ( ! exists($filehash->{$file}->{'FileName'}) ) { installer::exiter::exit_program("ERROR: Did not find \"FileName\" for file: \"$file\".", "copy_files_into_directory_structure"); } 453*cdf0e10cSrcweir my $destfile = $filehash->{$file}->{'FileName'}; 454*cdf0e10cSrcweir 455*cdf0e10cSrcweir $destfile = $destdir . $installer::globals::separator . $destfile; 456*cdf0e10cSrcweir my $sourcefile = $unpackdir . $installer::globals::separator . $file; 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir if ( ! -f $sourcefile ) 459*cdf0e10cSrcweir { 460*cdf0e10cSrcweir # It is possible, that this was an unpacked file 461*cdf0e10cSrcweir # Looking in the dirhash, to find the subdirectory in the installation set (the id is $dirname) 462*cdf0e10cSrcweir # subdir is not recursively analyzed, only one directory. 463*cdf0e10cSrcweir 464*cdf0e10cSrcweir my $oldsourcefile = $sourcefile; 465*cdf0e10cSrcweir my $subdir = ""; 466*cdf0e10cSrcweir if ( exists($dirhash->{$dirname}->{'DefaultDir'}) ) { $subdir = $dirhash->{$dirname}->{'DefaultDir'} . $installer::globals::separator; } 467*cdf0e10cSrcweir my $realfilename = $filehash->{$file}->{'FileName'}; 468*cdf0e10cSrcweir my $localinstalldir = $installdir; 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir $localinstalldir =~ s/\\\s*$//; 471*cdf0e10cSrcweir $localinstalldir =~ s/\/\s*$//; 472*cdf0e10cSrcweir 473*cdf0e10cSrcweir $sourcefile = $localinstalldir . $installer::globals::separator . $subdir . $realfilename; 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir if ( ! -f $sourcefile ) 476*cdf0e10cSrcweir { 477*cdf0e10cSrcweir installer::exiter::exit_program("ERROR: File not found: \"$oldsourcefile\" (or \"$sourcefile\").", "copy_files_into_directory_structure"); 478*cdf0e10cSrcweir } 479*cdf0e10cSrcweir } 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir my $copyreturn = copy($sourcefile, $destfile); 482*cdf0e10cSrcweir 483*cdf0e10cSrcweir if ( ! $copyreturn) # only logging problems 484*cdf0e10cSrcweir { 485*cdf0e10cSrcweir my $infoline = "ERROR: Could not copy $sourcefile to $destfile (insufficient disc space for $destfile ?)\n"; 486*cdf0e10cSrcweir $returnvalue = 0; 487*cdf0e10cSrcweir push(@installer::globals::logfileinfo, $infoline); 488*cdf0e10cSrcweir installer::exiter::exit_program($infoline, "copy_files_into_directory_structure"); 489*cdf0e10cSrcweir } 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir if ( $destfile =~ /unopkg\.exe\s*$/ ) { $unopkgfile = $destfile; } 492*cdf0e10cSrcweir 493*cdf0e10cSrcweir # installer::systemactions::copy_one_file($sourcefile, $destfile); 494*cdf0e10cSrcweir } 495*cdf0e10cSrcweir # else # allowing missing sequence numbers ? 496*cdf0e10cSrcweir # { 497*cdf0e10cSrcweir # installer::exiter::exit_program("ERROR: No file assigned to sequence $i", "copy_files_into_directory_structure"); 498*cdf0e10cSrcweir # } 499*cdf0e10cSrcweir } 500*cdf0e10cSrcweir 501*cdf0e10cSrcweir return $unopkgfile; 502*cdf0e10cSrcweir} 503*cdf0e10cSrcweir 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir############################################################### 506*cdf0e10cSrcweir# Setting the time string for the 507*cdf0e10cSrcweir# Summary Information stream in the 508*cdf0e10cSrcweir# msi database of the admin installations. 509*cdf0e10cSrcweir############################################################### 510*cdf0e10cSrcweir 511*cdf0e10cSrcweirsub get_sis_time_string 512*cdf0e10cSrcweir{ 513*cdf0e10cSrcweir # Syntax: <yyyy/mm/dd hh:mm:ss> 514*cdf0e10cSrcweir my $second = (localtime())[0]; 515*cdf0e10cSrcweir my $minute = (localtime())[1]; 516*cdf0e10cSrcweir my $hour = (localtime())[2]; 517*cdf0e10cSrcweir my $day = (localtime())[3]; 518*cdf0e10cSrcweir my $month = (localtime())[4]; 519*cdf0e10cSrcweir my $year = 1900 + (localtime())[5]; 520*cdf0e10cSrcweir 521*cdf0e10cSrcweir $month++; # zero based month 522*cdf0e10cSrcweir 523*cdf0e10cSrcweir if ( $second < 10 ) { $second = "0" . $second; } 524*cdf0e10cSrcweir if ( $minute < 10 ) { $minute = "0" . $minute; } 525*cdf0e10cSrcweir if ( $hour < 10 ) { $hour = "0" . $hour; } 526*cdf0e10cSrcweir if ( $day < 10 ) { $day = "0" . $day; } 527*cdf0e10cSrcweir if ( $month < 10 ) { $month = "0" . $month; } 528*cdf0e10cSrcweir 529*cdf0e10cSrcweir my $timestring = $year . "/" . $month . "/" . $day . " " . $hour . ":" . $minute . ":" . $second; 530*cdf0e10cSrcweir 531*cdf0e10cSrcweir return $timestring; 532*cdf0e10cSrcweir} 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir############################################################### 535*cdf0e10cSrcweir# Windows registry entries containing properties are not set 536*cdf0e10cSrcweir# correctly during msp patch process. The properties are 537*cdf0e10cSrcweir# empty or do get their default values. This destroys the 538*cdf0e10cSrcweir# values of many entries in Windows registry. 539*cdf0e10cSrcweir# This can be fixed by removing all entries in Registry table, 540*cdf0e10cSrcweir# containing a property before starting msimsp.exe. 541*cdf0e10cSrcweir############################################################### 542*cdf0e10cSrcweir 543*cdf0e10cSrcweirsub remove_properties_from_registry_table 544*cdf0e10cSrcweir{ 545*cdf0e10cSrcweir my ($registryhash, $componentkeypathhash, $registryfilecontent) = @_; 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir installer::logger::include_timestamp_into_logfile("\nPerformance Info: Start remove_properties_from_registry_table"); 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir my @registrytable = (); 550*cdf0e10cSrcweir 551*cdf0e10cSrcweir # Registry hash 552*cdf0e10cSrcweir # Collecting all RegistryItems with values containing a property: [...] 553*cdf0e10cSrcweir # To which component do they belong 554*cdf0e10cSrcweir # Is this after removal an empty component? Create a replacement, so that 555*cdf0e10cSrcweir # no Component has to be removed. 556*cdf0e10cSrcweir # Is this RegistryItem a KeyPath of a component. Then it cannot be removed. 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir my %problemitems = (); 559*cdf0e10cSrcweir my %problemcomponents = (); 560*cdf0e10cSrcweir my %securecomponents = (); 561*cdf0e10cSrcweir my $changevalue = ""; 562*cdf0e10cSrcweir my $changeroot = ""; 563*cdf0e10cSrcweir my $infoline = ""; 564*cdf0e10cSrcweir 565*cdf0e10cSrcweir my $newitemcounter = 0; 566*cdf0e10cSrcweir my $olditemcounter = 0; 567*cdf0e10cSrcweir 568*cdf0e10cSrcweir foreach my $regitem ( keys %{$registryhash} ) 569*cdf0e10cSrcweir { 570*cdf0e10cSrcweir my $value = ""; 571*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Value'}) ) { $value = $registryhash->{$regitem}->{'Value'}; } 572*cdf0e10cSrcweir 573*cdf0e10cSrcweir if ( $value =~ /^.*(\[.*?\]).*$/ ) 574*cdf0e10cSrcweir { 575*cdf0e10cSrcweir my $property = $1; 576*cdf0e10cSrcweir 577*cdf0e10cSrcweir # Collecting registry item 578*cdf0e10cSrcweir $problemitems{$regitem} = 1; # "1" -> can be removed 579*cdf0e10cSrcweir if ( exists($componentkeypathhash->{$regitem}) ) { $problemitems{$regitem} = 2; } # "2" -> cannot be removed, KeyPath 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir # Collecting component (and number of problematic registry items 582*cdf0e10cSrcweir # my $component = $registryhash->{$regitem}->{'Component'}; 583*cdf0e10cSrcweir # if ( exists($problemcomponents{$regitem}) ) { $problemcomponents{$regitem} = $problemcomponents{$regitem} + 1; } 584*cdf0e10cSrcweir # else { $problemcomponents{$regitem} = 1; } 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir else 587*cdf0e10cSrcweir { 588*cdf0e10cSrcweir # Collecting all components with secure regisry items 589*cdf0e10cSrcweir my $component = ""; 590*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Component'}) ) { $component = $registryhash->{$regitem}->{'Component'}; } 591*cdf0e10cSrcweir if ( $component eq "" ) { installer::exiter::exit_program("ERROR: Did not find component for registry item \"$regitem\".", "remove_properties_from_registry_table"); } 592*cdf0e10cSrcweir $securecomponents{$component} = 1; 593*cdf0e10cSrcweir } 594*cdf0e10cSrcweir 595*cdf0e10cSrcweir # Searching for change value 596*cdf0e10cSrcweir my $localkey = ""; 597*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Key'}) ) { $localkey = $registryhash->{$regitem}->{'Key'}; } 598*cdf0e10cSrcweir if (( $localkey =~ /^\s*(Software\\.*\\)StartMenu\s*$/ ) && ( $changevalue eq "" )) 599*cdf0e10cSrcweir { 600*cdf0e10cSrcweir $changevalue = $1; 601*cdf0e10cSrcweir $changeroot = $registryhash->{$regitem}->{'Root'}; 602*cdf0e10cSrcweir } 603*cdf0e10cSrcweir 604*cdf0e10cSrcweir $olditemcounter++; 605*cdf0e10cSrcweir } 606*cdf0e10cSrcweir 607*cdf0e10cSrcweir my $removecounter = 0; 608*cdf0e10cSrcweir my $renamecounter = 0; 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir foreach my $regitem ( keys %{$registryhash} ) 611*cdf0e10cSrcweir { 612*cdf0e10cSrcweir my $value = ""; 613*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Value'}) ) { $value = $registryhash->{$regitem}->{'Value'}; } 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir if ( $value =~ /^.*(\[.*?\]).*$/ ) 616*cdf0e10cSrcweir { 617*cdf0e10cSrcweir # Removing registry items, that are no KeyPath and that belong to components, 618*cdf0e10cSrcweir # that have other secure registry items. 619*cdf0e10cSrcweir 620*cdf0e10cSrcweir my $component = ""; 621*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Component'}) ) { $component = $registryhash->{$regitem}->{'Component'}; } 622*cdf0e10cSrcweir if ( $component eq "" ) { installer::exiter::exit_program("ERROR: Did not find component for registry item (2) \"$regitem\".", "remove_properties_from_registry_table"); } 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir if (( $problemitems{$regitem} == 1 ) && ( exists($securecomponents{$component}) )) 625*cdf0e10cSrcweir { 626*cdf0e10cSrcweir # remove complete registry item 627*cdf0e10cSrcweir delete($registryhash->{$regitem}); 628*cdf0e10cSrcweir $removecounter++; 629*cdf0e10cSrcweir $infoline = "Removing registry item: $regitem : $value\n"; 630*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 631*cdf0e10cSrcweir } 632*cdf0e10cSrcweir else 633*cdf0e10cSrcweir { 634*cdf0e10cSrcweir # Changing values of registry items, that are KeyPath or that contain to 635*cdf0e10cSrcweir # components with only unsecure registry items. 636*cdf0e10cSrcweir 637*cdf0e10cSrcweir if (( $problemitems{$regitem} == 2 ) || ( ! exists($securecomponents{$component}) )) 638*cdf0e10cSrcweir { 639*cdf0e10cSrcweir # change value of registry item 640*cdf0e10cSrcweir if ( $changevalue eq "" ) { installer::exiter::exit_program("ERROR: Did not find good change value for registry items", "remove_properties_from_registry_table"); } 641*cdf0e10cSrcweir 642*cdf0e10cSrcweir my $oldkey = ""; 643*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Key'}) ) { $oldkey = $registryhash->{$regitem}->{'Key'}; }; 644*cdf0e10cSrcweir my $oldname = ""; 645*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Name'}) ) { $oldname = $registryhash->{$regitem}->{'Name'}; } 646*cdf0e10cSrcweir my $oldvalue = ""; 647*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Value'}) ) { $oldvalue = $registryhash->{$regitem}->{'Value'}; } 648*cdf0e10cSrcweir 649*cdf0e10cSrcweir $registryhash->{$regitem}->{'Key'} = $changevalue . "RegistryItem"; 650*cdf0e10cSrcweir $registryhash->{$regitem}->{'Root'} = $changeroot; 651*cdf0e10cSrcweir $registryhash->{$regitem}->{'Name'} = $regitem; 652*cdf0e10cSrcweir $registryhash->{$regitem}->{'Value'} = 1; 653*cdf0e10cSrcweir $renamecounter++; 654*cdf0e10cSrcweir 655*cdf0e10cSrcweir $infoline = "Changing registry item: $regitem\n"; 656*cdf0e10cSrcweir $infoline = "Old: $oldkey : $oldname : $oldvalue\n"; 657*cdf0e10cSrcweir $infoline = "New: $registryhash->{$regitem}->{'Key'} : $registryhash->{$regitem}->{'Name'} : $registryhash->{$regitem}->{'Value'}\n"; 658*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 659*cdf0e10cSrcweir } 660*cdf0e10cSrcweir } 661*cdf0e10cSrcweir } 662*cdf0e10cSrcweir } 663*cdf0e10cSrcweir 664*cdf0e10cSrcweir $infoline = "Number of removed registry items: $removecounter\n"; 665*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 666*cdf0e10cSrcweir $infoline = "Number of changed registry items: $renamecounter\n"; 667*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 668*cdf0e10cSrcweir 669*cdf0e10cSrcweir # Creating the new content of Registry table 670*cdf0e10cSrcweir # First three lines from $registryfilecontent 671*cdf0e10cSrcweir # All further files from changed $registryhash 672*cdf0e10cSrcweir 673*cdf0e10cSrcweir for ( my $i = 0; $i <= 2; $i++ ) { push(@registrytable, ${$registryfilecontent}[$i]); } 674*cdf0e10cSrcweir 675*cdf0e10cSrcweir foreach my $regitem ( keys %{$registryhash} ) 676*cdf0e10cSrcweir { 677*cdf0e10cSrcweir my $root = ""; 678*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Root'}) ) { $root = $registryhash->{$regitem}->{'Root'}; } 679*cdf0e10cSrcweir else { installer::exiter::exit_program("ERROR: Did not find root in registry table for item: \"$regitem\".", "remove_properties_from_registry_table"); } 680*cdf0e10cSrcweir my $localkey = ""; 681*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Key'}) ) { $localkey = $registryhash->{$regitem}->{'Key'}; } 682*cdf0e10cSrcweir my $name = ""; 683*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Name'}) ) { $name = $registryhash->{$regitem}->{'Name'}; } 684*cdf0e10cSrcweir my $value = ""; 685*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Value'}) ) { $value = $registryhash->{$regitem}->{'Value'}; } 686*cdf0e10cSrcweir my $comp = ""; 687*cdf0e10cSrcweir if ( exists($registryhash->{$regitem}->{'Component'}) ) { $comp = $registryhash->{$regitem}->{'Component'}; } 688*cdf0e10cSrcweir 689*cdf0e10cSrcweir my $oneline = $regitem . "\t" . $root . "\t" . $localkey . "\t" . $name . "\t" . $value . "\t" . $comp . "\n"; 690*cdf0e10cSrcweir push(@registrytable, $oneline); 691*cdf0e10cSrcweir 692*cdf0e10cSrcweir $newitemcounter++; 693*cdf0e10cSrcweir } 694*cdf0e10cSrcweir 695*cdf0e10cSrcweir $infoline = "Number of registry items: $newitemcounter. Old value: $olditemcounter.\n"; 696*cdf0e10cSrcweir push( @installer::globals::logfileinfo, $infoline); 697*cdf0e10cSrcweir 698*cdf0e10cSrcweir installer::logger::include_timestamp_into_logfile("\nPerformance Info: End remove_properties_from_registry_table"); 699*cdf0e10cSrcweir 700*cdf0e10cSrcweir return (\@registrytable); 701*cdf0e10cSrcweir} 702*cdf0e10cSrcweir 703*cdf0e10cSrcweir############################################################### 704*cdf0e10cSrcweir# Writing content of administrative installations into 705*cdf0e10cSrcweir# Summary Information Stream of msi database. 706*cdf0e10cSrcweir# This is required for example for following 707*cdf0e10cSrcweir# patch processes using Windows Installer service. 708*cdf0e10cSrcweir############################################################### 709*cdf0e10cSrcweir 710*cdf0e10cSrcweirsub write_sis_info 711*cdf0e10cSrcweir{ 712*cdf0e10cSrcweir my ($msidatabase) = @_ ; 713*cdf0e10cSrcweir 714*cdf0e10cSrcweir if ( ! -f $msidatabase ) { installer::exiter::exit_program("ERROR: Cannot find file $msidatabase", "write_sis_info"); } 715*cdf0e10cSrcweir 716*cdf0e10cSrcweir my $msiinfo = "msiinfo.exe"; # Has to be in the path 717*cdf0e10cSrcweir my $infoline = ""; 718*cdf0e10cSrcweir my $systemcall = ""; 719*cdf0e10cSrcweir my $returnvalue = ""; 720*cdf0e10cSrcweir 721*cdf0e10cSrcweir # Required setting for administrative installations: 722*cdf0e10cSrcweir # -w 4 (source files are unpacked), wordcount 723*cdf0e10cSrcweir # -s <date of admin installation>, LastPrinted, Syntax: <yyyy/mm/dd hh:mm:ss> 724*cdf0e10cSrcweir # -l <person_making_admin_installation>, LastSavedBy 725*cdf0e10cSrcweir 726*cdf0e10cSrcweir my $wordcount = 4; # Unpacked files 727*cdf0e10cSrcweir my $lastprinted = get_sis_time_string(); 728*cdf0e10cSrcweir my $lastsavedby = "Installer"; 729*cdf0e10cSrcweir 730*cdf0e10cSrcweir my $localmsidatabase = $msidatabase; 731*cdf0e10cSrcweir 732*cdf0e10cSrcweir if( $^O =~ /cygwin/i ) 733*cdf0e10cSrcweir { 734*cdf0e10cSrcweir $localmsidatabase = qx{cygpath -w "$localmsidatabase"}; 735*cdf0e10cSrcweir $localmsidatabase =~ s/\\/\\\\/g; 736*cdf0e10cSrcweir $localmsidatabase =~ s/\s*$//g; 737*cdf0e10cSrcweir } 738*cdf0e10cSrcweir 739*cdf0e10cSrcweir $systemcall = $msiinfo . " " . "\"" . $localmsidatabase . "\"" . " -w " . $wordcount . " -s " . "\"" . $lastprinted . "\"" . " -l $lastsavedby"; 740*cdf0e10cSrcweir push(@installer::globals::logfileinfo, $systemcall); 741*cdf0e10cSrcweir $returnvalue = system($systemcall); 742*cdf0e10cSrcweir 743*cdf0e10cSrcweir if ($returnvalue) 744*cdf0e10cSrcweir { 745*cdf0e10cSrcweir $infoline = "ERROR: Could not execute $systemcall !\n"; 746*cdf0e10cSrcweir push(@installer::globals::logfileinfo, $infoline); 747*cdf0e10cSrcweir installer::exiter::exit_program($infoline, "write_sis_info"); 748*cdf0e10cSrcweir } 749*cdf0e10cSrcweir} 750*cdf0e10cSrcweir 751*cdf0e10cSrcweir#################################################### 752*cdf0e10cSrcweir# Detecting the directory with extensions 753*cdf0e10cSrcweir#################################################### 754*cdf0e10cSrcweir 755*cdf0e10cSrcweirsub get_extensions_dir 756*cdf0e10cSrcweir{ 757*cdf0e10cSrcweir my ( $unopkgfile ) = @_; 758*cdf0e10cSrcweir 759*cdf0e10cSrcweir my $localbranddir = $unopkgfile; 760*cdf0e10cSrcweir installer::pathanalyzer::get_path_from_fullqualifiedname(\$localbranddir); # "program" dir in brand layer 761*cdf0e10cSrcweir installer::pathanalyzer::get_path_from_fullqualifiedname(\$localbranddir); # root dir in brand layer 762*cdf0e10cSrcweir $localbranddir =~ s/\Q$installer::globals::separator\E\s*$//; 763*cdf0e10cSrcweir my $extensiondir = $localbranddir . $installer::globals::separator . "share" . $installer::globals::separator . "extensions"; 764*cdf0e10cSrcweir 765*cdf0e10cSrcweir return $extensiondir; 766*cdf0e10cSrcweir} 767*cdf0e10cSrcweir 768*cdf0e10cSrcweir############################################################## 769*cdf0e10cSrcweir# Removing all empty directories below a specified directory 770*cdf0e10cSrcweir############################################################## 771*cdf0e10cSrcweir 772*cdf0e10cSrcweirsub remove_empty_dirs_in_folder 773*cdf0e10cSrcweir{ 774*cdf0e10cSrcweir my ( $dir, $firstrun ) = @_; 775*cdf0e10cSrcweir 776*cdf0e10cSrcweir if ( $firstrun ) 777*cdf0e10cSrcweir { 778*cdf0e10cSrcweir print "Removing superfluous directories\n"; 779*cdf0e10cSrcweir } 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir my @content = (); 782*cdf0e10cSrcweir 783*cdf0e10cSrcweir $dir =~ s/\Q$installer::globals::separator\E\s*$//; 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir if ( -d $dir ) 786*cdf0e10cSrcweir { 787*cdf0e10cSrcweir opendir(DIR, $dir); 788*cdf0e10cSrcweir @content = readdir(DIR); 789*cdf0e10cSrcweir closedir(DIR); 790*cdf0e10cSrcweir 791*cdf0e10cSrcweir my $oneitem; 792*cdf0e10cSrcweir 793*cdf0e10cSrcweir foreach $oneitem (@content) 794*cdf0e10cSrcweir { 795*cdf0e10cSrcweir if ((!($oneitem eq ".")) && (!($oneitem eq ".."))) 796*cdf0e10cSrcweir { 797*cdf0e10cSrcweir my $item = $dir . $installer::globals::separator . $oneitem; 798*cdf0e10cSrcweir 799*cdf0e10cSrcweir if ( -d $item ) # recursive 800*cdf0e10cSrcweir { 801*cdf0e10cSrcweir remove_empty_dirs_in_folder($item, 0); 802*cdf0e10cSrcweir } 803*cdf0e10cSrcweir } 804*cdf0e10cSrcweir } 805*cdf0e10cSrcweir 806*cdf0e10cSrcweir # try to remove empty directory 807*cdf0e10cSrcweir my $returnvalue = rmdir $dir; 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir # if ( $returnvalue ) { print "Successfully removed empty dir $dir\n"; } 810*cdf0e10cSrcweir } 811*cdf0e10cSrcweir} 812*cdf0e10cSrcweir 813*cdf0e10cSrcweir#################################################################################### 814*cdf0e10cSrcweir# Simulating an administrative installation 815*cdf0e10cSrcweir#################################################################################### 816*cdf0e10cSrcweir 817*cdf0e10cSrcweirsub make_admin_install 818*cdf0e10cSrcweir{ 819*cdf0e10cSrcweir my ($databasepath, $targetdir) = @_; 820*cdf0e10cSrcweir 821*cdf0e10cSrcweir # Create helper directory 822*cdf0e10cSrcweir 823*cdf0e10cSrcweir installer::logger::print_message( "... installing $databasepath in directory $targetdir ...\n" ); 824*cdf0e10cSrcweir 825*cdf0e10cSrcweir my $helperdir = $targetdir . $installer::globals::separator . "installhelper"; 826*cdf0e10cSrcweir installer::systemactions::create_directory($helperdir); 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir # Get File.idt, Component.idt and Directory.idt from database 829*cdf0e10cSrcweir 830*cdf0e10cSrcweir my $tablelist = "File Directory Component Registry"; 831*cdf0e10cSrcweir extract_tables_from_pcpfile($databasepath, $helperdir, $tablelist); 832*cdf0e10cSrcweir 833*cdf0e10cSrcweir # Unpack all cab files into $helperdir, cab files must be located next to msi database 834*cdf0e10cSrcweir my $installdir = $databasepath; 835*cdf0e10cSrcweir 836*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { $installdir =~ s/\\/\//g; } # backslash to slash 837*cdf0e10cSrcweir 838*cdf0e10cSrcweir installer::pathanalyzer::get_path_from_fullqualifiedname(\$installdir); 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) { $installdir =~ s/\//\\/g; } # slash to backslash 841*cdf0e10cSrcweir 842*cdf0e10cSrcweir my $databasefilename = $databasepath; 843*cdf0e10cSrcweir installer::pathanalyzer::make_absolute_filename_to_relative_filename(\$databasefilename); 844*cdf0e10cSrcweir 845*cdf0e10cSrcweir my $cabfiles = installer::systemactions::find_file_with_file_extension("cab", $installdir); 846*cdf0e10cSrcweir 847*cdf0e10cSrcweir if ( $#{$cabfiles} < 0 ) { installer::exiter::exit_program("ERROR: Did not find any cab file in directory $installdir", "make_admin_install"); } 848*cdf0e10cSrcweir 849*cdf0e10cSrcweir # Set unpackdir 850*cdf0e10cSrcweir my $unpackdir = $helperdir . $installer::globals::separator . "unpack"; 851*cdf0e10cSrcweir installer::systemactions::create_directory($unpackdir); 852*cdf0e10cSrcweir 853*cdf0e10cSrcweir for ( my $i = 0; $i <= $#{$cabfiles}; $i++ ) 854*cdf0e10cSrcweir { 855*cdf0e10cSrcweir my $cabfile = ""; 856*cdf0e10cSrcweir if ( $^O =~ /cygwin/i ) 857*cdf0e10cSrcweir { 858*cdf0e10cSrcweir $cabfile = $installdir . ${$cabfiles}[$i]; 859*cdf0e10cSrcweir } 860*cdf0e10cSrcweir else 861*cdf0e10cSrcweir { 862*cdf0e10cSrcweir $cabfile = $installdir . $installer::globals::separator . ${$cabfiles}[$i]; 863*cdf0e10cSrcweir } 864*cdf0e10cSrcweir unpack_cabinet_file($cabfile, $unpackdir); 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir 867*cdf0e10cSrcweir # Reading tables 868*cdf0e10cSrcweir my $filename = $helperdir . $installer::globals::separator . "Directory.idt"; 869*cdf0e10cSrcweir my $filecontent = installer::files::read_file($filename); 870*cdf0e10cSrcweir my $dirhash = analyze_directory_file($filecontent); 871*cdf0e10cSrcweir 872*cdf0e10cSrcweir $filename = $helperdir . $installer::globals::separator . "Component.idt"; 873*cdf0e10cSrcweir my $componentfilecontent = installer::files::read_file($filename); 874*cdf0e10cSrcweir my $componenthash = analyze_component_file($componentfilecontent); 875*cdf0e10cSrcweir 876*cdf0e10cSrcweir $filename = $helperdir . $installer::globals::separator . "File.idt"; 877*cdf0e10cSrcweir $filecontent = installer::files::read_file($filename); 878*cdf0e10cSrcweir my ( $filehash, $fileorder, $maxsequence ) = analyze_file_file($filecontent); 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir # Creating the directory structure 881*cdf0e10cSrcweir my $fullpathhash = create_directory_structure($dirhash, $targetdir); 882*cdf0e10cSrcweir 883*cdf0e10cSrcweir # Copying files 884*cdf0e10cSrcweir my $unopkgfile = copy_files_into_directory_structure($fileorder, $filehash, $componenthash, $fullpathhash, $maxsequence, $unpackdir, $installdir, $dirhash); 885*cdf0e10cSrcweir 886*cdf0e10cSrcweir my $msidatabase = $targetdir . $installer::globals::separator . $databasefilename; 887*cdf0e10cSrcweir installer::systemactions::copy_one_file($databasepath, $msidatabase); 888*cdf0e10cSrcweir 889*cdf0e10cSrcweir if ( $unopkgfile ne "" ) 890*cdf0e10cSrcweir { 891*cdf0e10cSrcweir # Removing empty dirs in extension folder 892*cdf0e10cSrcweir my $extensionfolder = get_extensions_dir($unopkgfile); 893*cdf0e10cSrcweir if ( -d $extensionfolder ) { remove_empty_dirs_in_folder($extensionfolder, 1); } 894*cdf0e10cSrcweir } 895*cdf0e10cSrcweir 896*cdf0e10cSrcweir # Editing registry table because of wrong Property value 897*cdf0e10cSrcweir # my $registryfilename = $helperdir . $installer::globals::separator . "Registry.idt"; 898*cdf0e10cSrcweir # my $componentfilename = $helperdir . $installer::globals::separator . "Component.idt"; 899*cdf0e10cSrcweir # my $componentkeypathhash = analyze_keypath_component_file($componentfilecontent); 900*cdf0e10cSrcweir 901*cdf0e10cSrcweir # my $registryfilecontent = installer::files::read_file($registryfilename); 902*cdf0e10cSrcweir # my $registryhash = analyze_registry_file($registryfilecontent); 903*cdf0e10cSrcweir 904*cdf0e10cSrcweir # $registryfilecontent = remove_properties_from_registry_table($registryhash, $componentkeypathhash, $registryfilecontent); 905*cdf0e10cSrcweir 906*cdf0e10cSrcweir # installer::files::save_file($registryfilename, $registryfilecontent); 907*cdf0e10cSrcweir # $tablelist = "Registry"; 908*cdf0e10cSrcweir # include_tables_into_pcpfile($msidatabase, $helperdir, $tablelist); 909*cdf0e10cSrcweir 910*cdf0e10cSrcweir # Saving info in Summary Information Stream of msi database (required for following patches) 911*cdf0e10cSrcweir write_sis_info($msidatabase); 912*cdf0e10cSrcweir 913*cdf0e10cSrcweir return $msidatabase; 914*cdf0e10cSrcweir} 915*cdf0e10cSrcweir 916*cdf0e10cSrcweir1; 917