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