xref: /trunk/main/solenv/bin/modules/installer/windows/admin.pm (revision ec6d9e159f5d40bf5d1f27b0b525436f7e942929)
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