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