1#************************************************************************* 2# 3# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4# 5# Copyright 2000, 2010 Oracle and/or its affiliates. 6# 7# OpenOffice.org - a multi-platform office productivity suite 8# 9# This file is part of OpenOffice.org. 10# 11# OpenOffice.org is free software: you can redistribute it and/or modify 12# it under the terms of the GNU Lesser General Public License version 3 13# only, as published by the Free Software Foundation. 14# 15# OpenOffice.org is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU Lesser General Public License version 3 for more details 19# (a copy is included in the LICENSE file that accompanied this code). 20# 21# You should have received a copy of the GNU Lesser General Public License 22# version 3 along with OpenOffice.org. If not, see 23# <http://www.openoffice.org/license.html> 24# for a copy of the LGPLv3 License. 25# 26#************************************************************************* 27 28package installer::windows::registry; 29 30use installer::files; 31use installer::globals; 32use installer::worker; 33use installer::windows::idtglobal; 34 35##################################################### 36# Generating the component name from a registryitem 37##################################################### 38 39sub get_registry_component_name 40{ 41 my ($registryref, $allvariables) = @_; 42 43 # In this function exists the rule to create components from registryitems 44 # Rule: 45 # The componentname can be directly taken from the ModuleID. 46 # All registryitems belonging to one module can get the same component. 47 48 my $componentname = ""; 49 my $isrootmodule = 0; 50 51 if ( $registryref->{'ModuleID'} ) { $componentname = $registryref->{'ModuleID'}; } 52 53 $componentname =~ s/\\/\_/g; 54 $componentname =~ s/\//\_/g; 55 $componentname =~ s/\-/\_/g; 56 $componentname =~ s/\_\s*$//g; 57 58 $componentname = lc($componentname); # componentnames always lowercase 59 60 if ( $componentname eq "gid_module_root" ) { $isrootmodule = 1; } 61 62 # Attention: Maximum length for the componentname is 72 63 64 # identifying this component as registryitem component 65 $componentname = "registry_" . $componentname; 66 67 $componentname =~ s/gid_module_/g_m_/g; 68 $componentname =~ s/_optional_/_o_/g; 69 $componentname =~ s/_javafilter_/_jf_/g; 70 71 # This componentname must be more specific 72 my $addon = "_"; 73 if ( $allvariables->{'PRODUCTNAME'} ) { $addon = $addon . $allvariables->{'PRODUCTNAME'}; } 74 if ( $allvariables->{'PRODUCTVERSION'} ) { $addon = $addon . $allvariables->{'PRODUCTVERSION'}; } 75 $addon = lc($addon); 76 $addon =~ s/ //g; 77 $addon =~ s/-//g; 78 $addon =~ s/\.//g; 79 80 my $styles = ""; 81 if ( $registryref->{'Styles'} ) { $styles = $registryref->{'Styles'}; } 82 83 # Layer links must have unique Component GUID for all products. This is necessary, because only the 84 # uninstallation of the last product has to delete registry keys. 85 if ( $styles =~ /\bLAYER_REGISTRY\b/ ) 86 { 87 $componentname = "g_m_root_registry_layer_ooo_reglayer"; 88 # Styles USE_URELAYERVERSION, USE_OOOBASEVERSION 89 if ( $styles =~ /\bUSE_URELAYERVERSION\b/ ) { $addon = "_ure_" . $allvariables->{'URELAYERVERSION'}; } 90 if ( $styles =~ /\bUSE_OOOBASEVERSION\b/ ) { $addon = "_basis_" . $allvariables->{'OOOBASEVERSION'}; } 91 $addon =~ s/\.//g; 92 } 93 94 $componentname = $componentname . $addon; 95 96 if (( $styles =~ /\bLANGUAGEPACK\b/ ) && ( $installer::globals::languagepack )) { $componentname = $componentname . "_lang"; } 97 if ( $styles =~ /\bALWAYS_REQUIRED\b/ ) { $componentname = $componentname . "_forced"; } 98 99 # Attention: Maximum length for the componentname is 72 100 # %installer::globals::allregistrycomponents_in_this_database_ : resetted for each database 101 # %installer::globals::allregistrycomponents_ : not resetted for each database 102 # Component strings must be unique for the complete product, because they are used for 103 # the creation of the globally unique identifier. 104 105 my $fullname = $componentname; # This can be longer than 72 106 107 if (( exists($installer::globals::allregistrycomponents_{$fullname}) ) && ( ! exists($installer::globals::allregistrycomponents_in_this_database_{$fullname}) )) 108 { 109 # This is not allowed: One component cannot be installed with different packages. 110 installer::exiter::exit_program("ERROR: Windows registry component \"$fullname\" is already included into another package. This is not allowed.", "get_registry_component_name"); 111 } 112 113 if ( exists($installer::globals::allregistrycomponents_{$fullname}) ) 114 { 115 $componentname = $installer::globals::allregistrycomponents_{$fullname}; 116 } 117 else 118 { 119 if ( length($componentname) > 60 ) 120 { 121 $componentname = generate_new_short_registrycomponentname($componentname); # This has to be unique for the complete product, not only one package 122 } 123 124 $installer::globals::allregistrycomponents_{$fullname} = $componentname; 125 $installer::globals::allregistrycomponents_in_this_database_{$fullname} = 1; 126 } 127 128 if ( $isrootmodule ) { $installer::globals::registryrootcomponent = $componentname; } 129 130 return $componentname; 131} 132 133######################################################### 134# Create a shorter version of a long component name, 135# because maximum length in msi database is 72. 136# Attention: In multi msi installation sets, the short 137# names have to be unique over all packages, because 138# this string is used to create the globally unique id 139# -> no resetting of 140# %installer::globals::allshortregistrycomponents 141# after a package was created. 142######################################################### 143 144sub generate_new_short_registrycomponentname 145{ 146 my ($componentname) = @_; 147 148 my $shortcomponentname = ""; 149 my $counter = 1; 150 151 my $startversion = substr($componentname, 0, 60); # taking only the first 60 characters 152 $startversion = $startversion . "_"; 153 154 $shortcomponentname = $startversion . $counter; 155 156 while ( exists($installer::globals::allshortregistrycomponents{$shortcomponentname}) ) 157 { 158 $counter++; 159 $shortcomponentname = $startversion . $counter; 160 } 161 162 $installer::globals::allshortregistrycomponents{$shortcomponentname} = 1; 163 164 return $shortcomponentname; 165} 166 167############################################################## 168# Returning identifier for registry table. 169############################################################## 170 171sub get_registry_identifier 172{ 173 my ($registry) = @_; 174 175 my $identifier = ""; 176 177 if ( $registry->{'gid'} ) { $identifier = $registry->{'gid'}; } 178 179 $identifier = lc($identifier); # always lower case 180 181 # Attention: Maximum length is 72 182 183 $identifier =~ s/gid_regitem_/g_r_/; 184 $identifier =~ s/_soffice_/_s_/; 185 $identifier =~ s/_clsid_/_c_/; 186 $identifier =~ s/_currentversion_/_cv_/; 187 $identifier =~ s/_microsoft_/_ms_/; 188 $identifier =~ s/_manufacturer_/_mf_/; 189 $identifier =~ s/_productname_/_pn_/; 190 $identifier =~ s/_productversion_/_pv_/; 191 $identifier =~ s/_staroffice_/_so_/; 192 $identifier =~ s/_software_/_sw_/; 193 $identifier =~ s/_capabilities_/_cap_/; 194 $identifier =~ s/_classpath_/_cp_/; 195 $identifier =~ s/_extension_/_ex_/; 196 $identifier =~ s/_fileassociations_/_fa_/; 197 $identifier =~ s/_propertysheethandlers_/_psh_/; 198 $identifier =~ s/__/_/g; 199 200 # Saving this in the registry collector 201 202 $registry->{'uniquename'} = $identifier; 203 204 return $identifier; 205} 206 207################################################################## 208# Returning root value for registry table. 209################################################################## 210 211sub get_registry_root 212{ 213 my ($registry) = @_; 214 215 my $rootvalue = 0; # Default: Parent is KKEY_CLASSES_ROOT 216 my $scproot = ""; 217 218 if ( $registry->{'ParentID'} ) { $scproot = $registry->{'ParentID'}; } 219 220 if ( $scproot eq "PREDEFINED_HKEY_LOCAL_MACHINE" ) { $rootvalue = -1; } 221 222 if ( $scproot eq "PREDEFINED_HKEY_CLASSES_ROOT" ) { $rootvalue = 0; } 223 224 if ( $scproot eq "PREDEFINED_HKEY_CURRENT_USER_ONLY" ) { $rootvalue = 1; } 225 226 if ( $scproot eq "PREDEFINED_HKEY_LOCAL_MACHINE_ONLY" ) { $rootvalue = 2; } 227 228 return $rootvalue; 229} 230 231############################################################## 232# Returning key for registry table. 233############################################################## 234 235sub get_registry_key 236{ 237 my ($registry, $allvariableshashref) = @_; 238 239 my $key = ""; 240 241 if ( $registry->{'Subkey'} ) { $key = $registry->{'Subkey'}; } 242 243 if ( $key =~ /\%/ ) { $key = installer::worker::replace_variables_in_string($key, $allvariableshashref); } 244 245 return $key; 246} 247 248############################################################## 249# Returning name for registry table. 250############################################################## 251 252sub get_registry_name 253{ 254 my ($registry, $allvariableshashref) = @_; 255 256 my $name = ""; 257 258 if ( $registry->{'Name'} ) { $name = $registry->{'Name'}; } 259 260 if ( $name =~ /\%/ ) { $name = installer::worker::replace_variables_in_string($name, $allvariableshashref); } 261 262 return $name; 263} 264 265############################################################## 266# Returning value for registry table. 267############################################################## 268 269sub get_registry_value 270{ 271 my ($registry, $allvariableshashref) = @_; 272 273 my $value = ""; 274 275 if ( $registry->{'Value'} ) { $value = $registry->{'Value'}; } 276 277 $value =~ s/\\\"/\"/g; # no more masquerading of '"' 278 $value =~ s/\\\\\s*$/\\/g; # making "\\" at end of value to "\" 279 $value =~ s/\<progpath\>/\[INSTALLLOCATION\]/; 280 $value =~ s/\[INSTALLLOCATION\]\\/\[INSTALLLOCATION\]/; # removing "\" after "[INSTALLLOCATION]" 281 282 if ( $value =~ /\%/ ) { $value = installer::worker::replace_variables_in_string($value, $allvariableshashref); } 283 284 return $value; 285} 286 287############################################################## 288# Returning 64 bit value for registry table. 289############################################################## 290 291sub get_registry_val64 292{ 293 my ($registry, $allvariableshashref) = @_; 294 295 my $value = ""; 296 297 if ( $registry->{'Val64'} ) { $value = $registry->{'Val64'}; } 298 299 $value =~ s/\\\"/\"/g; # no more masquerading of '"' 300 $value =~ s/\\\\\s*$/\\/g; # making "\\" at end of value to "\" 301 $value =~ s/\<progpath\>/\[INSTALLLOCATION\]/; 302 $value =~ s/\[INSTALLLOCATION\]\\/\[INSTALLLOCATION\]/; # removing "\" after "[INSTALLLOCATION]" 303 304 if ( $value =~ /\%/ ) { $value = installer::worker::replace_variables_in_string($value, $allvariableshashref); } 305 306 return $value; 307} 308 309############################################################## 310# Returning component for registry table. 311############################################################## 312 313sub get_registry_component 314{ 315 my ($registry, $allvariables) = @_; 316 317 # All registry items belonging to one module can 318 # be included into one component 319 320 my $componentname = get_registry_component_name($registry, $allvariables); 321 322 # saving componentname in the registryitem collector 323 324 $registry->{'componentname'} = $componentname; 325 326 return $componentname; 327} 328 329###################################################### 330# Adding the content of 331# @installer::globals::userregistrycollector 332# to the registry table. The content was collected 333# in create_files_table() in file.pm. 334###################################################### 335 336sub add_userregs_to_registry_table 337{ 338 my ( $registrytable, $allvariables ) = @_; 339 340 for ( my $i = 0; $i <= $#installer::globals::userregistrycollector; $i++ ) 341 { 342 my $onefile = $installer::globals::userregistrycollector[$i]; 343 344 my $styles = ""; 345 if ( $onefile->{'Styles'} ) { $styles = $onefile->{'Styles'}; } 346 347 my %registry = (); 348 349 $registry{'Registry'} = $onefile->{'userregkeypath'}; 350 $registry{'Root'} = "1"; # always HKCU 351 $registry{'Key'} = "Software\\$allvariables->{'MANUFACTURER'}\\$allvariables->{'PRODUCTNAME'} $allvariables->{'PRODUCTVERSION'}\\"; 352 if ( $onefile->{'needs_user_registry_key'} ) { $registry{'Key'} = $registry{'Key'} . "StartMenu"; } 353 else { $registry{'Key'} = $registry{'Key'} . "ShellNew"; } 354 $registry{'Name'} = $onefile->{'Name'}; 355 $registry{'Value'} = "1"; 356 $registry{'Component_'} = $onefile->{'componentname'}; 357 358 my $oneline = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" 359 . $registry{'Name'} . "\t" . $registry{'Value'} . "\t" . $registry{'Component_'} . "\n"; 360 361 push(@{$registrytable}, $oneline); 362 } 363} 364 365###################################################### 366# Creating the file Registry.idt dynamically 367# Content: 368# Registry Root Key Name Value Component_ 369###################################################### 370 371sub create_registry_table 372{ 373 my ($registryref, $allregistrycomponentsref, $basedir, $languagesarrayref, $allvariableshashref) = @_; 374 375 for ( my $m = 0; $m <= $#{$languagesarrayref}; $m++ ) 376 { 377 my $onelanguage = ${$languagesarrayref}[$m]; 378 379 my @registrytable = (); 380 my @reg64table = (); 381 382 installer::windows::idtglobal::write_idt_header(\@registrytable, "registry"); 383 installer::windows::idtglobal::write_idt_header(\@reg64table, "reg64"); 384 385 for ( my $i = 0; $i <= $#{$registryref}; $i++ ) 386 { 387 my $oneregistry = ${$registryref}[$i]; 388 389 # Controlling the language! 390 # Only language independent folderitems or folderitems with the correct language 391 # will be included into the table 392 393 if (! (!(( $oneregistry->{'ismultilingual'} )) || ( $oneregistry->{'specificlanguage'} eq $onelanguage )) ) { next; } 394 395 my %registry = (); 396 397 $registry{'Registry'} = get_registry_identifier($oneregistry); 398 $registry{'Root'} = get_registry_root($oneregistry); 399 $registry{'Key'} = get_registry_key($oneregistry, $allvariableshashref); 400 $registry{'Name'} = get_registry_name($oneregistry, $allvariableshashref); 401 $registry{'Value'} = get_registry_value($oneregistry, $allvariableshashref); 402 $registry{'Val64'} = get_registry_val64($oneregistry, $allvariableshashref); 403 $registry{'Component_'} = get_registry_component($oneregistry, $allvariableshashref); 404 405 # Collecting all components 406 if (!(installer::existence::exists_in_array($registry{'Component_'}, $allregistrycomponentsref))) 407 { 408 push(@{$allregistrycomponentsref}, $registry{'Component_'}); 409 } 410 411 # Collecting all components with DONT_DELETE style 412 my $style = ""; 413 if ( $oneregistry->{'Styles'} ) { $style = $oneregistry->{'Styles'}; } 414 if ( $style =~ /\bDONT_DELETE\b/ ) { $installer::globals::dontdeletecomponents{$registry{'Component_'}} = 1; } 415 416 # Saving upgradekey to write this into setup.ini for minor upgrades 417 if ( $style =~ /\bUPGRADEKEY\b/ ) { $installer::globals::minorupgradekey = $registry{'Key'}; } 418 419 # Collecting all registry components with ALWAYS_REQUIRED style 420 if ( ! ( $style =~ /\bALWAYS_REQUIRED\b/ )) 421 { 422 # Setting a component condition for unforced registry components! 423 # Only write into registry, if WRITE_REGISTRY is set. 424 if ( $oneregistry->{'ComponentCondition'} ) { $oneregistry->{'ComponentCondition'} = "(" . $oneregistry->{'ComponentCondition'} . ") AND (WRITE_REGISTRY=1)"; } 425 else { $oneregistry->{'ComponentCondition'} = "WRITE_REGISTRY=1"; } 426 } 427 428 # Collecting all component conditions 429 if ( $oneregistry->{'ComponentCondition'} ) 430 { 431 if ( ! exists($installer::globals::componentcondition{$registry{'Component_'}})) 432 { 433 $installer::globals::componentcondition{$registry{'Component_'}} = $oneregistry->{'ComponentCondition'}; 434 } 435 } 436 437 my $oneline = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" 438 . $registry{'Name'} . "\t" . $registry{'Value'} . "\t" . $registry{'Component_'} . "\n"; 439 440 my $oneline64 = $registry{'Registry'} . "\t" . $registry{'Root'} . "\t" . $registry{'Key'} . "\t" 441 . $registry{'Name'} . "\t" . $registry{'Val64'} . "\t" . $registry{'Component_'} . "\n"; 442 443 if ( ! ( $style =~ /\bX64_ONLY\b/ )) { push(@registrytable, $oneline); } # standard registry table for 32 Bit 444 if (( $style =~ /\bX64\b/ ) || ( $style =~ /\bX64_ONLY\b/ )) { push(@reg64table , $oneline64); } 445 } 446 447 # If there are added user registry keys for files collected in 448 # @installer::globals::userregistrycollector (file.pm), then 449 # this registry keys have to be added now. This is necessary for 450 # files in PREDEFINED_OSSHELLNEWDIR, because their component 451 # needs as KeyPath a RegistryItem in HKCU. 452 453 if ( $installer::globals::addeduserregitrykeys ) { add_userregs_to_registry_table(\@registrytable, $allvariableshashref); } 454 455 # Saving the file 456 457 my $registrytablename = $basedir . $installer::globals::separator . "Registry.idt" . "." . $onelanguage; 458 installer::files::save_file($registrytablename ,\@registrytable); 459 my $infoline = "Created idt file: $registrytablename\n"; 460 push(@installer::globals::logfileinfo, $infoline); 461 462 $registrytablename = $basedir . $installer::globals::separator . "Reg64.idt" . "." . $onelanguage; 463 installer::files::save_file($registrytablename ,\@reg64table ); 464 $infoline = "Created idt file: $registrytablename\n"; 465 push(@installer::globals::logfileinfo, $infoline); 466 } 467} 468 4691; 470