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