132b1fd08SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 332b1fd08SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 432b1fd08SAndrew Rist * or more contributor license agreements. See the NOTICE file 532b1fd08SAndrew Rist * distributed with this work for additional information 632b1fd08SAndrew Rist * regarding copyright ownership. The ASF licenses this file 732b1fd08SAndrew Rist * to you under the Apache License, Version 2.0 (the 832b1fd08SAndrew Rist * "License"); you may not use this file except in compliance 932b1fd08SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 1132b1fd08SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 1332b1fd08SAndrew Rist * Unless required by applicable law or agreed to in writing, 1432b1fd08SAndrew Rist * software distributed under the License is distributed on an 1532b1fd08SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1632b1fd08SAndrew Rist * KIND, either express or implied. See the License for the 1732b1fd08SAndrew Rist * specific language governing permissions and limitations 1832b1fd08SAndrew Rist * under the License. 19cdf0e10cSrcweir * 2032b1fd08SAndrew Rist *************************************************************/ 2132b1fd08SAndrew Rist 2232b1fd08SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #undef UNICODE 25cdf0e10cSrcweir #undef _UNICODE 26cdf0e10cSrcweir 27cdf0e10cSrcweir #define _WIN32_WINDOWS 0x0410 28cdf0e10cSrcweir 29cdf0e10cSrcweir #ifdef _MSC_VER 30cdf0e10cSrcweir #pragma warning(push, 1) /* disable warnings within system headers */ 31cdf0e10cSrcweir #endif 32cdf0e10cSrcweir #define WIN32_LEAN_AND_MEAN 33cdf0e10cSrcweir #include <windows.h> 34cdf0e10cSrcweir #include <msiquery.h> 35cdf0e10cSrcweir #ifdef _MSC_VER 36cdf0e10cSrcweir #pragma warning(pop) 37cdf0e10cSrcweir #endif 38cdf0e10cSrcweir 39cdf0e10cSrcweir #include <malloc.h> 40cdf0e10cSrcweir #include <assert.h> 41cdf0e10cSrcweir 42cdf0e10cSrcweir #include <tchar.h> 43cdf0e10cSrcweir #include <string> 44cdf0e10cSrcweir 45cdf0e10cSrcweir using namespace std; 46cdf0e10cSrcweir 47cdf0e10cSrcweir namespace 48cdf0e10cSrcweir { 4986e1cf34SPedro Giffuni // The provided GUID must be without surrounding '{}' 50cdf0e10cSrcweir string GetGuidPart(const string& guid, int index) 51cdf0e10cSrcweir { 52cdf0e10cSrcweir assert((guid.length() == 36) && "No GUID or wrong format!"); 53cdf0e10cSrcweir assert(((index > -1) && (index < 5)) && "Out of range!"); 54cdf0e10cSrcweir 55cdf0e10cSrcweir if (index == 0) return string(guid.c_str(), 8); 56cdf0e10cSrcweir if (index == 1) return string(guid.c_str() + 9, 4); 57cdf0e10cSrcweir if (index == 2) return string(guid.c_str() + 14, 4); 58cdf0e10cSrcweir if (index == 3) return string(guid.c_str() + 19, 4); 59cdf0e10cSrcweir if (index == 4) return string(guid.c_str() + 24, 12); 60cdf0e10cSrcweir 61cdf0e10cSrcweir return string(); 62cdf0e10cSrcweir } 63cdf0e10cSrcweir 64cdf0e10cSrcweir void Swap(char* p1, char* p2) 65cdf0e10cSrcweir { 66cdf0e10cSrcweir char tmp = *p1; 67cdf0e10cSrcweir *p1 = *p2; 68cdf0e10cSrcweir *p2 = tmp; 69cdf0e10cSrcweir } 70cdf0e10cSrcweir 71cdf0e10cSrcweir string Invert(const string& str) 72cdf0e10cSrcweir { 73cdf0e10cSrcweir char* buff = reinterpret_cast<char*>(_alloca(str.length())); 74cdf0e10cSrcweir strncpy(buff, str.c_str(), str.length()); 75cdf0e10cSrcweir 76cdf0e10cSrcweir char* front = buff; 77cdf0e10cSrcweir char* back = buff + str.length() - 1; 78cdf0e10cSrcweir 79cdf0e10cSrcweir while (front < back) 80cdf0e10cSrcweir Swap(front++, back--); 81cdf0e10cSrcweir 82cdf0e10cSrcweir return string(buff, str.length()); 83cdf0e10cSrcweir } 84cdf0e10cSrcweir 85cdf0e10cSrcweir // Convert the upgrade code (which is a GUID) according 86cdf0e10cSrcweir // to the way the windows installer does when writing it 87cdf0e10cSrcweir // to the registry 88*7950f2afSmseidel // The first 8 bytes will be inverted, from the last 89cdf0e10cSrcweir // 8 bytes always the nibbles will be inverted for further 90cdf0e10cSrcweir // details look in the MSDN under compressed registry keys 91cdf0e10cSrcweir string ConvertGuid(const string& guid) 92cdf0e10cSrcweir { 93cdf0e10cSrcweir string convertedGuid; 94cdf0e10cSrcweir 95cdf0e10cSrcweir string part = GetGuidPart(guid, 0); 96cdf0e10cSrcweir convertedGuid = Invert(part); 97cdf0e10cSrcweir 98cdf0e10cSrcweir part = GetGuidPart(guid, 1); 99cdf0e10cSrcweir convertedGuid += Invert(part); 100cdf0e10cSrcweir 101cdf0e10cSrcweir part = GetGuidPart(guid, 2); 102cdf0e10cSrcweir convertedGuid += Invert(part); 103cdf0e10cSrcweir 104cdf0e10cSrcweir part = GetGuidPart(guid, 3); 105cdf0e10cSrcweir convertedGuid += Invert(string(part.c_str(), 2)); 106cdf0e10cSrcweir convertedGuid += Invert(string(part.c_str() + 2, 2)); 107cdf0e10cSrcweir 108cdf0e10cSrcweir part = GetGuidPart(guid, 4); 109cdf0e10cSrcweir int pos = 0; 110cdf0e10cSrcweir for (int i = 0; i < 6; i++) 111cdf0e10cSrcweir { 112cdf0e10cSrcweir convertedGuid += Invert(string(part.c_str() + pos, 2)); 113cdf0e10cSrcweir pos += 2; 114cdf0e10cSrcweir } 115cdf0e10cSrcweir return convertedGuid; 116cdf0e10cSrcweir } 117cdf0e10cSrcweir 118cdf0e10cSrcweir string GetMsiProperty(MSIHANDLE handle, const string& sProperty) 119cdf0e10cSrcweir { 120cdf0e10cSrcweir string result; 121cdf0e10cSrcweir TCHAR szDummy[1] = TEXT(""); 122cdf0e10cSrcweir DWORD nChars = 0; 123cdf0e10cSrcweir 124cdf0e10cSrcweir if (MsiGetProperty(handle, sProperty.c_str(), szDummy, &nChars) == ERROR_MORE_DATA) 125cdf0e10cSrcweir { 126cdf0e10cSrcweir DWORD nBytes = ++nChars * sizeof(TCHAR); 127cdf0e10cSrcweir LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes)); 128cdf0e10cSrcweir ZeroMemory( buffer, nBytes ); 129cdf0e10cSrcweir MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars); 130cdf0e10cSrcweir result = buffer; 131cdf0e10cSrcweir } 132cdf0e10cSrcweir return result; 133cdf0e10cSrcweir } 134cdf0e10cSrcweir 135cdf0e10cSrcweir inline bool IsSetMsiProperty(MSIHANDLE handle, const string& sProperty) 136cdf0e10cSrcweir { 137cdf0e10cSrcweir return (GetMsiProperty(handle, sProperty).length() > 0); 138cdf0e10cSrcweir } 139cdf0e10cSrcweir 140cdf0e10cSrcweir inline void UnsetMsiProperty(MSIHANDLE handle, const string& sProperty) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir MsiSetProperty(handle, sProperty.c_str(), NULL); 143cdf0e10cSrcweir } 144cdf0e10cSrcweir 145cdf0e10cSrcweir inline void SetMsiProperty(MSIHANDLE handle, const string& sProperty) 146cdf0e10cSrcweir { 147cdf0e10cSrcweir MsiSetProperty(handle, sProperty.c_str(), TEXT("1")); 148cdf0e10cSrcweir } 149cdf0e10cSrcweir 150cdf0e10cSrcweir bool RegistryKeyHasUpgradeSubKey( 151cdf0e10cSrcweir HKEY hRootKey, const string& regKey, const string& upgradeKey) 152cdf0e10cSrcweir { 153cdf0e10cSrcweir HKEY hKey; 154cdf0e10cSrcweir if (RegOpenKey(hRootKey, regKey.c_str(), &hKey) == ERROR_SUCCESS) 155cdf0e10cSrcweir { 156cdf0e10cSrcweir DWORD nSubKeys; 157cdf0e10cSrcweir DWORD lLongestSubKey; 158cdf0e10cSrcweir 159cdf0e10cSrcweir if (RegQueryInfoKey( 160cdf0e10cSrcweir hKey, NULL, NULL, NULL, &nSubKeys, &lLongestSubKey, NULL, NULL, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) 161cdf0e10cSrcweir { 162cdf0e10cSrcweir LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(lLongestSubKey + 1)); 163cdf0e10cSrcweir 164cdf0e10cSrcweir for (DWORD i = 0; i < nSubKeys; i++) 165cdf0e10cSrcweir { 166cdf0e10cSrcweir LONG ret = RegEnumKey(hKey, i, buffer, lLongestSubKey + 1); 167cdf0e10cSrcweir if ((ret == ERROR_SUCCESS) && (buffer == upgradeKey)) 168cdf0e10cSrcweir return true; 169cdf0e10cSrcweir } 170cdf0e10cSrcweir } 171cdf0e10cSrcweir } 172cdf0e10cSrcweir return false; 173cdf0e10cSrcweir } 174cdf0e10cSrcweir } // namespace 175cdf0e10cSrcweir 176cdf0e10cSrcweir extern "C" UINT __stdcall SetProductInstallMode(MSIHANDLE handle) 177cdf0e10cSrcweir { 178cdf0e10cSrcweir string upgradeCode = GetMsiProperty(handle, TEXT("UpgradeCode")); 179cdf0e10cSrcweir upgradeCode = ConvertGuid(string(upgradeCode.c_str() + 1, upgradeCode.length() - 2)); 180cdf0e10cSrcweir 181cdf0e10cSrcweir //MessageBox(NULL, upgradeCode.c_str(), TEXT("Debug"), MB_OK); 182cdf0e10cSrcweir 183cdf0e10cSrcweir if (RegistryKeyHasUpgradeSubKey( 184cdf0e10cSrcweir HKEY_CURRENT_USER, 185cdf0e10cSrcweir TEXT("Software\\Microsoft\\Installer\\UpgradeCodes"), 186cdf0e10cSrcweir upgradeCode) && IsSetMsiProperty(handle, TEXT("ALLUSERS"))) 187cdf0e10cSrcweir { 188cdf0e10cSrcweir UnsetMsiProperty(handle, TEXT("ALLUSERS")); 189cdf0e10cSrcweir //MessageBox(NULL, "ALLUSERS removed", "DEBUG", MB_OK); 190cdf0e10cSrcweir } 191cdf0e10cSrcweir else if (RegistryKeyHasUpgradeSubKey( 192cdf0e10cSrcweir HKEY_LOCAL_MACHINE, 193cdf0e10cSrcweir TEXT("Software\\Classes\\Installer\\UpgradeCodes"), 194cdf0e10cSrcweir upgradeCode) && !IsSetMsiProperty(handle, TEXT("ALLUSERS"))) 195cdf0e10cSrcweir { 196cdf0e10cSrcweir SetMsiProperty(handle, TEXT("ALLUSERS")); 197cdf0e10cSrcweir //MessageBox(NULL, "ALLUSERS set", "DEBUG", MB_OK); 198cdf0e10cSrcweir } 199cdf0e10cSrcweir return ERROR_SUCCESS; 200cdf0e10cSrcweir } 201