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