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