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 #undef UNICODE 23 #undef _UNICODE 24 25 #define _WIN32_WINDOWS 0x0410 26 27 #ifdef _MSC_VER 28 #pragma warning(push, 1) /* disable warnings within system headers */ 29 #endif 30 #define WIN32_LEAN_AND_MEAN 31 #include <windows.h> 32 #include <msiquery.h> 33 #ifdef _MSC_VER 34 #pragma warning(pop) 35 #endif 36 37 #include <malloc.h> 38 #include <assert.h> 39 40 #include <tchar.h> 41 #include <string> 42 #include <systools/win32/uwinapi.h> 43 44 #include <../tools/seterror.hxx> 45 46 using namespace std; 47 48 namespace 49 { 50 string GetMsiProperty(MSIHANDLE handle, const string& sProperty) 51 { 52 string 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 return result; 65 } 66 67 inline bool IsSetMsiProperty(MSIHANDLE handle, const string& sProperty) 68 { 69 return (GetMsiProperty(handle, sProperty).length() > 0); 70 } 71 72 inline void UnsetMsiProperty(MSIHANDLE handle, const string& sProperty) 73 { 74 MsiSetProperty(handle, sProperty.c_str(), NULL); 75 } 76 77 inline void SetMsiProperty(MSIHANDLE handle, const string& sProperty, const string&) 78 { 79 MsiSetProperty(handle, sProperty.c_str(), TEXT("1")); 80 } 81 } // namespace 82 83 extern "C" UINT __stdcall GetUserInstallMode(MSIHANDLE handle) 84 { 85 string sOfficeInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION")); 86 87 // MessageBox(NULL, sOfficeInstallPath.c_str(), "DEBUG", MB_OK); 88 89 // unsetting all properties 90 91 UnsetMsiProperty( handle, TEXT("INVALIDDIRECTORY") ); 92 UnsetMsiProperty( handle, TEXT("ISWRONGPRODUCT") ); 93 UnsetMsiProperty( handle, TEXT("PATCHISOLDER") ); 94 UnsetMsiProperty( handle, TEXT("ALLUSERS") ); 95 96 // 1. Searching for "ProductCode" in setup.ini 97 98 string sSetupiniPath = sOfficeInstallPath + TEXT("program\\setup.ini"); 99 100 TCHAR szValue[32767]; 101 102 GetPrivateProfileString( 103 TEXT("Bootstrap"), 104 TEXT("ProductCode"), 105 TEXT("INVALIDDIRECTORY"), 106 szValue, 107 elementsof(szValue), 108 sSetupiniPath.c_str() 109 ); 110 111 if ( !_tcsicmp( szValue, TEXT("INVALIDDIRECTORY") ) ) 112 { 113 // No setup.ini or no "ProductCode" in setup.ini. This is an invalid directory. 114 SetMsiProperty( handle, TEXT("INVALIDDIRECTORY"), TEXT("YES") ); 115 // MessageBox(NULL, "INVALIDDIRECTORY set, no setup.ini or ProductCode in setup.ini.", "DEBUG", MB_OK); 116 SetMsiErrorCode( MSI_ERROR_INVALIDDIRECTORY ); 117 return ERROR_SUCCESS; 118 } 119 120 // 2. Comparing first three characters of "PRODUCTMAJOR" from property table and "buildid" from InfoFile 121 122 szValue[0] = '\0'; 123 124 GetPrivateProfileString( 125 TEXT("Bootstrap"), 126 TEXT("buildid"), 127 TEXT("ISWRONGPRODUCT"), 128 szValue, 129 elementsof(szValue), 130 sSetupiniPath.c_str() 131 ); 132 133 if ( !_tcsicmp( szValue, TEXT("ISWRONGPRODUCT") ) ) 134 { 135 SetMsiProperty( handle, TEXT("ISWRONGPRODUCT"), TEXT("YES") ); 136 // MessageBox(NULL, "ISWRONGPRODUCT 1 set after searching buildid", "DEBUG", MB_OK); 137 SetMsiErrorCode( MSI_ERROR_ISWRONGPRODUCT ); 138 return ERROR_SUCCESS; 139 } 140 141 string ProductMajor = GetMsiProperty(handle, TEXT("PRODUCTMAJOR")); 142 143 // Comparing the first three characters, for example "680" 144 // If not equal, this version is not suited for patch or language pack 145 146 if (_tcsnicmp(ProductMajor.c_str(), szValue, 3)) 147 { 148 SetMsiProperty( handle, TEXT("ISWRONGPRODUCT"), TEXT("YES") ); 149 // MessageBox(NULL, "ISWRONGPRODUCT 2 set after searching PRODUCTMAJOR", "DEBUG", MB_OK); 150 SetMsiErrorCode( MSI_ERROR_ISWRONGPRODUCT ); 151 return ERROR_SUCCESS; 152 } 153 154 // 3. Only for patch: Comparing "PRODUCTMINOR from property table and "ProductMinor" from InfoFile 155 156 string isPatch = GetMsiProperty(handle, TEXT("ISPATCH")); 157 158 if (isPatch=="1") 159 { 160 string ProductMinor = GetMsiProperty(handle, TEXT("PRODUCTBUILDID")); 161 int PatchProductMinor = atoi(ProductMinor.c_str()); 162 163 szValue[0] = '\0'; 164 165 GetPrivateProfileString( 166 TEXT("Bootstrap"), 167 TEXT("ProductBuildid"), 168 TEXT("8918"), 169 szValue, 170 elementsof(szValue), 171 sSetupiniPath.c_str() 172 ); 173 174 int InstalledProductMinor = atoi(szValue); 175 176 if ( InstalledProductMinor >= PatchProductMinor ) 177 { 178 SetMsiProperty( handle, TEXT("PATCHISOLDER"), TEXT("YES") ); 179 // MessageBox(NULL, "PATCHISOLDER set", "DEBUG", MB_OK); 180 SetMsiErrorCode( MSI_ERROR_PATCHISOLDER ); 181 return ERROR_SUCCESS; 182 } 183 } 184 185 // 4. Setting property ALLUSERS with value from "setup.ini" 186 187 szValue[0] = '\0'; 188 189 GetPrivateProfileString( 190 TEXT("Bootstrap"), 191 TEXT("ALLUSERS"), 192 TEXT(""), 193 szValue, 194 elementsof(szValue), 195 sSetupiniPath.c_str() 196 ); 197 198 if ( szValue[0] ) 199 { 200 SetMsiProperty( handle, TEXT("ALLUSERS"), szValue ); 201 // MessageBox(NULL, "ALLUSERS set", "DEBUG", MB_OK); 202 } 203 204 return ERROR_SUCCESS; 205 } 206 207 /* vim: set noet sw=4 ts=4: */ 208