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