1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #define _WIN32_WINDOWS 0x0410 25 #ifdef _MSC_VER 26 #pragma warning(push, 1) /* disable warnings within system headers */ 27 #endif 28 #define WIN32_LEAN_AND_MEAN 29 #include <windows.h> 30 #include <msiquery.h> 31 #ifdef _MSC_VER 32 #pragma warning(pop) 33 #endif 34 35 #include <malloc.h> 36 37 #ifdef UNICODE 38 #define _UNICODE 39 #define _tstring wstring 40 #else 41 #define _tstring string 42 #endif 43 #include <tchar.h> 44 #include <string> 45 46 using namespace std; 47 48 namespace 49 { 50 std::_tstring GetMsiProperty( MSIHANDLE handle, const std::_tstring& sProperty ) 51 { 52 std::_tstring result; 53 TCHAR szDummy[1] = TEXT(""); 54 DWORD nChars = 0; 55 56 if ( MsiGetProperty( handle, sProperty.c_str(), szDummy, &nChars ) == ERROR_MORE_DATA ) 57 { 58 DWORD nBytes = ++nChars * sizeof(TCHAR); 59 LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes)); 60 ZeroMemory( buffer, nBytes ); 61 MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars); 62 result = buffer; 63 } 64 65 return result; 66 } 67 } // namespace 68 69 extern "C" UINT __stdcall CompleteInstallPath( MSIHANDLE handle ) 70 { 71 // This CustomAction is necessary for updates from OOo 3.0, OOo 3.1 and OOo 3.2 to versions 72 // OOo 3.3 or later. This is caused by a change of INSTALLLOCATION, that starting with OOo 3.3 73 // contains the name of the product again (instead of only "c:\program files"). Unfortunately 74 // this causes in an update installation, that INSTALLLOCATION is set to "c:\program files", 75 // so that in an OOo 3.3 or later, the directory "program" or "share" are directly created 76 // below "c:\program files". 77 78 TCHAR szValue[8192]; 79 DWORD nValueSize = sizeof(szValue); 80 HKEY hKey; 81 std::_tstring sInstDir; 82 std::_tstring mystr; 83 84 // Reading property OFFICEDIRHOSTNAME_, that contains the part of the path behind 85 // the program files folder. 86 87 std::_tstring sInstallLocation = GetMsiProperty( handle, TEXT("INSTALLLOCATION") ); 88 std::_tstring sOfficeDirHostname = GetMsiProperty( handle, TEXT("OFFICEDIRHOSTNAME_") ); 89 90 // If sInstallLocation ends with (contains) the string sOfficeDirHostname, 91 // INSTALLLOCATION is good and nothing has to be done here. 92 93 bool pathCompletionRequired = true; 94 95 if ( _tcsstr( sInstallLocation.c_str(), sOfficeDirHostname.c_str() ) ) 96 { 97 pathCompletionRequired = false; // nothing to do 98 // mystr = "Nothing to do, officedir is included into installlocation"; 99 // MessageBox( NULL, mystr.c_str(), "It is part of installlocation", MB_OK ); 100 } 101 102 // If the path INSTALLLOCATION does not end with this string, INSTALLLOCATION is maybe 103 // transfered from an OOo 3.0, OOo 3.1 and OOo 3.2 and need to be changed therefore. 104 105 if ( pathCompletionRequired ) 106 { 107 std::_tstring sManufacturer = GetMsiProperty( handle, TEXT("Manufacturer") ); 108 std::_tstring sDefinedName = GetMsiProperty( handle, TEXT("DEFINEDPRODUCT") ); 109 std::_tstring sUpgradeCode = GetMsiProperty( handle, TEXT("UpgradeCode") ); 110 111 // sUpdateVersion can be "3.0", "3.1" or "3.2" 112 113 std::_tstring sProductKey30 = "Software\\" + sManufacturer + "\\" + sDefinedName + 114 "\\" + "3.0" + "\\" + sUpgradeCode; 115 116 std::_tstring sProductKey31 = "Software\\" + sManufacturer + "\\" + sDefinedName + 117 "\\" + "3.1" + "\\" + sUpgradeCode; 118 119 std::_tstring sProductKey32 = "Software\\" + sManufacturer + "\\" + sDefinedName + 120 "\\" + "3.2" + "\\" + sUpgradeCode; 121 122 // mystr = "ProductKey: " + sProductKey; 123 // MessageBox( NULL, mystr.c_str(), "ProductKey", MB_OK ); 124 125 // mystr = "Checking registry"; 126 // MessageBox( NULL, mystr.c_str(), "registry search", MB_OK ); 127 128 bool oldVersionExists = false; 129 130 if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey30.c_str(), &hKey ) ) 131 { 132 oldVersionExists = true; 133 RegCloseKey( hKey ); 134 } 135 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey31.c_str(), &hKey ) ) 136 { 137 oldVersionExists = true; 138 RegCloseKey( hKey ); 139 } 140 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_CURRENT_USER, sProductKey32.c_str(), &hKey ) ) 141 { 142 oldVersionExists = true; 143 RegCloseKey( hKey ); 144 } 145 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey30.c_str(), &hKey ) ) 146 { 147 oldVersionExists = true; 148 RegCloseKey( hKey ); 149 } 150 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey31.c_str(), &hKey ) ) 151 { 152 oldVersionExists = true; 153 RegCloseKey( hKey ); 154 } 155 else if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sProductKey32.c_str(), &hKey ) ) 156 { 157 oldVersionExists = true; 158 RegCloseKey( hKey ); 159 } 160 161 if ( oldVersionExists ) 162 { 163 // Adding the new path content sOfficeDirHostname 164 sInstallLocation = sInstallLocation + sOfficeDirHostname; 165 // Setting the new property value 166 MsiSetProperty(handle, TEXT("INSTALLLOCATION"), sInstallLocation.c_str()); 167 // mystr = "Setting path to: " + sInstallLocation; 168 // MessageBox( NULL, mystr.c_str(), "sInstallLocation", MB_OK ); 169 } 170 } 171 172 // mystr = "Ending with INSTALLLOCATION: " + sInstallLocation; 173 // MessageBox( NULL, mystr.c_str(), "END", MB_OK ); 174 175 return ERROR_SUCCESS; 176 } 177