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 {
GetMsiProperty(MSIHANDLE handle,const std::_tstring & sProperty)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
CompleteInstallPath(MSIHANDLE handle)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 // transferred 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