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