lngpckinsthelper.cxx (ff3f4ebc) lngpckinsthelper.cxx (0cf988a7)
1/**************************************************************
1/**************************************************************
2 *
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
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 *
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
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.
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 *
19 *
20 *************************************************************/
21
22
20 *************************************************************/
21
22
23
23
24#ifdef _MSC_VER
25#pragma warning(push, 1) /* disable warnings within system headers */
26#endif
27#define WIN32_LEAN_AND_MEAN
28#include <windows.h>
29#include <msiquery.h>
30#ifdef _MSC_VER
31#pragma warning(pop)
32#endif
33
34#include <malloc.h>
35#include <tchar.h>
36#include <string>
37#include <stdexcept>
38#include <vector>
39
40class RegistryKeyGuard
41{
24#ifdef _MSC_VER
25#pragma warning(push, 1) /* disable warnings within system headers */
26#endif
27#define WIN32_LEAN_AND_MEAN
28#include <windows.h>
29#include <msiquery.h>
30#ifdef _MSC_VER
31#pragma warning(pop)
32#endif
33
34#include <malloc.h>
35#include <tchar.h>
36#include <string>
37#include <stdexcept>
38#include <vector>
39
40class RegistryKeyGuard
41{
42public:
42public:
43 RegistryKeyGuard(HKEY hkey = 0) :
44 hkey_(hkey)
45 {
46 }
43 RegistryKeyGuard(HKEY hkey = 0) :
44 hkey_(hkey)
45 {
46 }
47
47
48 ~RegistryKeyGuard()
49 {
50 if (hkey_)
51 RegCloseKey(hkey_);
48 ~RegistryKeyGuard()
49 {
50 if (hkey_)
51 RegCloseKey(hkey_);
52 }
52 }
53private:
54 HKEY hkey_;
55
56private:
57 RegistryKeyGuard(const RegistryKeyGuard&);
53private:
54 HKEY hkey_;
55
56private:
57 RegistryKeyGuard(const RegistryKeyGuard&);
58 RegistryKeyGuard& operator=(const RegistryKeyGuard&);
58 RegistryKeyGuard& operator=(const RegistryKeyGuard&);
59};
60
61typedef std::vector<TCHAR> CharacterBuffer_t;
62
63/* throws std::runtime_error when the value "Path" could
59};
60
61typedef std::vector<TCHAR> CharacterBuffer_t;
62
63/* throws std::runtime_error when the value "Path" could
64 not be found or contains an empty string or is not of
65 type REG_SZ. All such conditions are invalid for a
64 not be found or contains an empty string or is not of
65 type REG_SZ. All such conditions are invalid for a
66 properly installed product. */
66 properly installed product. */
67std::string FindProductInstallationPath(HKEY hkey)
68{
67std::string FindProductInstallationPath(HKEY hkey)
68{
69 DWORD nSubKeys;
70 DWORD lLongestSubKey;
69 DWORD nSubKeys;
70 DWORD lLongestSubKey;
71
72 if (RegQueryInfoKey(hkey, NULL, NULL, NULL, &nSubKeys, &lLongestSubKey, NULL, NULL, NULL, NULL, NULL, NULL) !=
71
72 if (RegQueryInfoKey(hkey, NULL, NULL, NULL, &nSubKeys, &lLongestSubKey, NULL, NULL, NULL, NULL, NULL, NULL) !=
73 ERROR_SUCCESS)
74 throw std::runtime_error("Cannot query info for registery key");
73 ERROR_SUCCESS)
74 throw std::runtime_error("Cannot query info for registery key");
75
75
76 CharacterBuffer_t buff(lLongestSubKey + 1);
76 CharacterBuffer_t buff(lLongestSubKey + 1);
77
77
78 for (DWORD i = 0; i < nSubKeys; i++)
79 {
80 buff[0] = 0;
81 LONG ret = RegEnumKey(hkey, i, &buff[0], buff.size());
78 for (DWORD i = 0; i < nSubKeys; i++)
79 {
80 buff[0] = 0;
81 LONG ret = RegEnumKey(hkey, i, &buff[0], buff.size());
82
82
83 if ((ret != ERROR_SUCCESS) && (ret != ERROR_MORE_DATA))
84 throw std::runtime_error("Error enumerating registry key");
83 if ((ret != ERROR_SUCCESS) && (ret != ERROR_MORE_DATA))
84 throw std::runtime_error("Error enumerating registry key");
85
85
86 HKEY hSubKey;
86 HKEY hSubKey;
87 if (RegOpenKey(hkey, &buff[0], &hSubKey) != ERROR_SUCCESS)
88 continue;
89
87 if (RegOpenKey(hkey, &buff[0], &hSubKey) != ERROR_SUCCESS)
88 continue;
89
90 RegistryKeyGuard guard(hSubKey);
90 RegistryKeyGuard guard(hSubKey);
91
91
92 DWORD type;
93 TCHAR pbuff[MAX_PATH];
94 DWORD size = sizeof(pbuff);
95 if ((RegQueryValueEx(
96 hSubKey, TEXT("Path"), NULL, &type, reinterpret_cast<LPBYTE>(pbuff), &size) != ERROR_SUCCESS) ||
92 DWORD type;
93 TCHAR pbuff[MAX_PATH];
94 DWORD size = sizeof(pbuff);
95 if ((RegQueryValueEx(
96 hSubKey, TEXT("Path"), NULL, &type, reinterpret_cast<LPBYTE>(pbuff), &size) != ERROR_SUCCESS) ||
97 (type != REG_SZ))
97 (type != REG_SZ))
98 continue;
98 continue;
99
100 std::string path(pbuff);
99
100 std::string path(pbuff);
101 std::string::size_type idx = path.rfind("program\\soffice.exe");
101 std::string::size_type idx = path.rfind("program\\soffice.exe");
102 if (idx != std::string::npos)
103 return path.substr(0, idx);
104 } // for
105
106 throw std::runtime_error("No valid product path found");
102 if (idx != std::string::npos)
103 return path.substr(0, idx);
104 } // for
105
106 throw std::runtime_error("No valid product path found");
107}
108
109UINT GetInstallProperty(MSIHANDLE handle, LPCTSTR name, CharacterBuffer_t* buffer)
107}
108
109UINT GetInstallProperty(MSIHANDLE handle, LPCTSTR name, CharacterBuffer_t* buffer)
110{
110{
111 DWORD size = buffer->size();
112 UINT ret = MsiGetProperty(handle, name, &(*buffer)[0], &size);
111 DWORD size = buffer->size();
112 UINT ret = MsiGetProperty(handle, name, &(*buffer)[0], &size);
113
113
114 if (ret == ERROR_MORE_DATA)
115 {
116 buffer->resize(size + 1);
117 size = buffer->size();
118 ret = MsiGetProperty(handle, name, &(*buffer)[0], &size);
114 if (ret == ERROR_MORE_DATA)
115 {
116 buffer->resize(size + 1);
117 size = buffer->size();
118 ret = MsiGetProperty(handle, name, &(*buffer)[0], &size);
119 }
119 }
120 return ret;
121}
122
120 return ret;
121}
122
123/*
123/*
124 Try to find the installation path to an already installed product.
125 The installation path will be written in the Windows registry
124 Try to find the installation path to an already installed product.
125 The installation path will be written in the Windows registry
126 during the installation. There may exist different products in
126 during the installation. There may exist different products in
127 parallel e.g. StarOffice, StarSuite, OpenOffice.org, Apache OpenOffice.
127 parallel e.g. StarOffice, StarSuite, OpenOffice.org, Apache OpenOffice.
128 It will be searched in this order for an installed product. If a product
128 It will be searched in this order for an installed product. If a product
129 will be found the path to the product will be set in the property
130 "INSTALLLOCATION" else nothing will be done.
131*/
132extern "C" UINT __stdcall SetProductInstallationPath(MSIHANDLE handle)
133{
134 //MessageBox(NULL, TEXT("SetProductInstallationPath"), TEXT("Language Pack Installation Helper"), MB_OK | MB_ICONINFORMATION);
129 will be found the path to the product will be set in the property
130 "INSTALLLOCATION" else nothing will be done.
131*/
132extern "C" UINT __stdcall SetProductInstallationPath(MSIHANDLE handle)
133{
134 //MessageBox(NULL, TEXT("SetProductInstallationPath"), TEXT("Language Pack Installation Helper"), MB_OK | MB_ICONINFORMATION);
135
135
136 try
136 try
137 {
138 CharacterBuffer_t regKeyProdPath(MAX_PATH);
139
137 {
138 CharacterBuffer_t regKeyProdPath(MAX_PATH);
139
140 GetInstallProperty(handle, TEXT("REGKEYPRODPATH"), &regKeyProdPath);
140 GetInstallProperty(handle, TEXT("REGKEYPRODPATH"), &regKeyProdPath);
141
141
142 HKEY hKey;
143 if ((RegOpenKey(HKEY_CURRENT_USER, &regKeyProdPath[0], &hKey) == ERROR_SUCCESS) ||
144 (RegOpenKey(HKEY_LOCAL_MACHINE, &regKeyProdPath[0], &hKey) == ERROR_SUCCESS))
142 HKEY hKey;
143 if ((RegOpenKey(HKEY_CURRENT_USER, &regKeyProdPath[0], &hKey) == ERROR_SUCCESS) ||
144 (RegOpenKey(HKEY_LOCAL_MACHINE, &regKeyProdPath[0], &hKey) == ERROR_SUCCESS))
145 {
145 {
146 RegistryKeyGuard guard(hKey);
146 RegistryKeyGuard guard(hKey);
147 std::string path = FindProductInstallationPath(hKey);
148 MsiSetProperty(handle, TEXT("INSTALLLOCATION"), path.c_str());
149 }
147 std::string path = FindProductInstallationPath(hKey);
148 MsiSetProperty(handle, TEXT("INSTALLLOCATION"), path.c_str());
149 }
150 }
151 catch(std::runtime_error& ex)
152 {
153 ex = ex; // no warnings
150 }
151 catch(std::runtime_error& ex)
152 {
153 ex = ex; // no warnings
154 }
155 return ERROR_SUCCESS;
154 }
155 return ERROR_SUCCESS;
156}
157
158void MakeCfgimportCommandLine(CharacterBuffer_t* productPath)
156}
157
158void MakeCfgimportCommandLine(CharacterBuffer_t* productPath)
159{
159{
160 char* p = &(*productPath)[0] + lstrlen(&(*productPath)[0]) - 1;
161
160 char* p = &(*productPath)[0] + lstrlen(&(*productPath)[0]) - 1;
161
162 if (*p != '\\')
163 lstrcat(&(*productPath)[0], "\\program\\configimport.exe --spool");
162 if (*p != '\\')
163 lstrcat(&(*productPath)[0], "\\program\\configimport.exe --spool");
164 else
164 else
165 lstrcat(&(*productPath)[0], "program\\configimport.exe --spool");
165 lstrcat(&(*productPath)[0], "program\\configimport.exe --spool");
166}
167
168/*
169 Calls configimport.exe --spool
170*/
171extern "C" UINT __stdcall RegisterLanguagePack(MSIHANDLE handle)
172{
173 //MessageBox(NULL, TEXT("RegisterLanguagePack"), TEXT("Language Pack Installation Helper"), MB_OK | MB_ICONINFORMATION);
166}
167
168/*
169 Calls configimport.exe --spool
170*/
171extern "C" UINT __stdcall RegisterLanguagePack(MSIHANDLE handle)
172{
173 //MessageBox(NULL, TEXT("RegisterLanguagePack"), TEXT("Language Pack Installation Helper"), MB_OK | MB_ICONINFORMATION);
174
175 CharacterBuffer_t productPath(MAX_PATH);
176 GetInstallProperty(handle, TEXT("INSTALLLOCATION"), &productPath);
177 MakeCfgimportCommandLine(&productPath);
178
179 STARTUPINFO si;
174
175 CharacterBuffer_t productPath(MAX_PATH);
176 GetInstallProperty(handle, TEXT("INSTALLLOCATION"), &productPath);
177 MakeCfgimportCommandLine(&productPath);
178
179 STARTUPINFO si;
180 ZeroMemory(&si, sizeof(si));
181 si.cb = sizeof(si);
180 ZeroMemory(&si, sizeof(si));
181 si.cb = sizeof(si);
182
182
183 PROCESS_INFORMATION pi;
184 ZeroMemory(&pi, sizeof(pi));
183 PROCESS_INFORMATION pi;
184 ZeroMemory(&pi, sizeof(pi));
185
185
186 if (CreateProcess(
187 NULL, &productPath[0], NULL, NULL,
188 FALSE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL,
189 NULL, &si, &pi))
190 {
191 // Wait until child process exits.
192 WaitForSingleObject(pi.hProcess, INFINITE);
193
186 if (CreateProcess(
187 NULL, &productPath[0], NULL, NULL,
188 FALSE, CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL,
189 NULL, &si, &pi))
190 {
191 // Wait until child process exits.
192 WaitForSingleObject(pi.hProcess, INFINITE);
193
194 // Close process and thread handles.
194 // Close process and thread handles.
195 CloseHandle(pi.hProcess);
195 CloseHandle(pi.hProcess);
196 CloseHandle(pi.hThread);
197 }
198 return ERROR_SUCCESS;
196 CloseHandle(pi.hThread);
197 }
198 return ERROR_SUCCESS;
199}
200
199}
200