1*32b1fd08SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*32b1fd08SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*32b1fd08SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*32b1fd08SAndrew Rist  * distributed with this work for additional information
6*32b1fd08SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*32b1fd08SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*32b1fd08SAndrew Rist  * "License"); you may not use this file except in compliance
9*32b1fd08SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*32b1fd08SAndrew Rist  *
11*32b1fd08SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*32b1fd08SAndrew Rist  *
13*32b1fd08SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*32b1fd08SAndrew Rist  * software distributed under the License is distributed on an
15*32b1fd08SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*32b1fd08SAndrew Rist  * KIND, either express or implied.  See the License for the
17*32b1fd08SAndrew Rist  * specific language governing permissions and limitations
18*32b1fd08SAndrew Rist  * under the License.
19*32b1fd08SAndrew Rist  *
20*32b1fd08SAndrew Rist  *************************************************************/
21*32b1fd08SAndrew Rist 
22*32b1fd08SAndrew 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 #include <systools/win32/uwinapi.h>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir #include <../tools/seterror.hxx>
47cdf0e10cSrcweir 
48cdf0e10cSrcweir using namespace std;
49cdf0e10cSrcweir 
50cdf0e10cSrcweir namespace
51cdf0e10cSrcweir {
GetMsiProperty(MSIHANDLE handle,const string & sProperty)52cdf0e10cSrcweir     string GetMsiProperty(MSIHANDLE handle, const string& sProperty)
53cdf0e10cSrcweir     {
54cdf0e10cSrcweir         string  result;
55cdf0e10cSrcweir         TCHAR   szDummy[1] = TEXT("");
56cdf0e10cSrcweir         DWORD   nChars = 0;
57cdf0e10cSrcweir 
58cdf0e10cSrcweir         if (MsiGetProperty(handle, sProperty.c_str(), szDummy, &nChars) == ERROR_MORE_DATA)
59cdf0e10cSrcweir         {
60cdf0e10cSrcweir             DWORD nBytes = ++nChars * sizeof(TCHAR);
61cdf0e10cSrcweir             LPTSTR buffer = reinterpret_cast<LPTSTR>(_alloca(nBytes));
62cdf0e10cSrcweir             ZeroMemory( buffer, nBytes );
63cdf0e10cSrcweir             MsiGetProperty(handle, sProperty.c_str(), buffer, &nChars);
64cdf0e10cSrcweir             result = buffer;
65cdf0e10cSrcweir         }
66cdf0e10cSrcweir         return result;
67cdf0e10cSrcweir     }
68cdf0e10cSrcweir 
SetMsiProperty(MSIHANDLE handle,const string & sProperty,const string & sValue)69cdf0e10cSrcweir     inline void SetMsiProperty(MSIHANDLE handle, const string& sProperty, const string& sValue)
70cdf0e10cSrcweir     {
71cdf0e10cSrcweir         MsiSetProperty(handle, sProperty.c_str(), sValue.c_str());
72cdf0e10cSrcweir     }
73cdf0e10cSrcweir 
stripFinalBackslash(std::string * path)74cdf0e10cSrcweir     void stripFinalBackslash(std::string * path) {
75cdf0e10cSrcweir         std::string::size_type i = path->size();
76cdf0e10cSrcweir         if (i > 1) {
77cdf0e10cSrcweir             --i;
78cdf0e10cSrcweir             if ((*path)[i] == '\\') {
79cdf0e10cSrcweir                 path->erase(i);
80cdf0e10cSrcweir             }
81cdf0e10cSrcweir         }
82cdf0e10cSrcweir     }
83cdf0e10cSrcweir 
84cdf0e10cSrcweir // Copied more or less verbatim from
85cdf0e10cSrcweir // desktop/source/deployment/inc/dp_version.hxx:1.5 and
86cdf0e10cSrcweir // desktop/source/deployment/misc/dp_version.cxx:1.5:
87cdf0e10cSrcweir 
88cdf0e10cSrcweir enum Order { ORDER_LESS, ORDER_EQUAL, ORDER_GREATER };
89cdf0e10cSrcweir 
getElement(string const & version,string::size_type * index)90cdf0e10cSrcweir string getElement(string const & version, string::size_type * index) {
91cdf0e10cSrcweir     while (*index < version.size() && version[*index] == '0') {
92cdf0e10cSrcweir         ++*index;
93cdf0e10cSrcweir     }
94cdf0e10cSrcweir     string::size_type i = *index;
95cdf0e10cSrcweir     *index = version.find('.', i);
96cdf0e10cSrcweir     if (*index == string::npos) {
97cdf0e10cSrcweir         *index = version.size();
98cdf0e10cSrcweir         return string(version, i);
99cdf0e10cSrcweir     } else {
100cdf0e10cSrcweir         ++*index;
101cdf0e10cSrcweir         return string(version, i, *index - 1 - i);
102cdf0e10cSrcweir     }
103cdf0e10cSrcweir }
104cdf0e10cSrcweir 
compareVersions(string const & version1,string const & version2)105cdf0e10cSrcweir Order compareVersions(string const & version1, string const & version2) {
106cdf0e10cSrcweir     for (string::size_type i1 = 0, i2 = 0;
107cdf0e10cSrcweir          i1 < version1.size() || i2 < version2.size();)
108cdf0e10cSrcweir     {
109cdf0e10cSrcweir         string e1(getElement(version1, &i1));
110cdf0e10cSrcweir         string e2(getElement(version2, &i2));
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 	    // string myText1 = TEXT("e1: ") + e1;
113cdf0e10cSrcweir 	    // string myText2 = TEXT("e2: ") + e2;
114cdf0e10cSrcweir 	    // MessageBox(NULL, myText1.c_str(), "DEBUG", MB_OK);
115cdf0e10cSrcweir 	    // MessageBox(NULL, myText2.c_str(), "DEBUG", MB_OK);
116cdf0e10cSrcweir 
117cdf0e10cSrcweir         if (e1.size() < e2.size()) {
118cdf0e10cSrcweir             return ORDER_LESS;
119cdf0e10cSrcweir         } else if (e1.size() > e2.size()) {
120cdf0e10cSrcweir             return ORDER_GREATER;
121cdf0e10cSrcweir         } else if (e1 < e2) {
122cdf0e10cSrcweir             return ORDER_LESS;
123cdf0e10cSrcweir         } else if (e1 > e2) {
124cdf0e10cSrcweir             return ORDER_GREATER;
125cdf0e10cSrcweir         }
126cdf0e10cSrcweir     }
127cdf0e10cSrcweir     return ORDER_EQUAL;
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
130cdf0e10cSrcweir } // namespace
131cdf0e10cSrcweir 
DotNetCheck(MSIHANDLE handle)132cdf0e10cSrcweir extern "C" UINT __stdcall DotNetCheck(MSIHANDLE handle) {
133cdf0e10cSrcweir     string present(GetMsiProperty(handle, TEXT("MsiNetAssemblySupport")));
134cdf0e10cSrcweir     string required(GetMsiProperty(handle, TEXT("REQUIRED_DOTNET_VERSION")));
135cdf0e10cSrcweir 
136cdf0e10cSrcweir     // string myText1 = TEXT("MsiNetAssemblySupport: ") + present;
137cdf0e10cSrcweir     // string myText2 = TEXT("REQUIRED_DOTNET_VERSION: ") + required;
138cdf0e10cSrcweir     // MessageBox(NULL, myText1.c_str(), "DEBUG", MB_OK);
139cdf0e10cSrcweir     // MessageBox(NULL, myText2.c_str(), "DEBUG", MB_OK);
140cdf0e10cSrcweir 
141cdf0e10cSrcweir     SetMsiProperty(
142cdf0e10cSrcweir         handle, TEXT("DOTNET_SUFFICIENT"),
143cdf0e10cSrcweir         (present.empty() || compareVersions(present, required) == ORDER_LESS ?
144cdf0e10cSrcweir          TEXT("0") : TEXT("1")));
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     // string result(GetMsiProperty(handle, TEXT("DOTNET_SUFFICIENT")));
147cdf0e10cSrcweir     // string myText3 = TEXT("DOTNET_SUFFICIENT: ") + result;
148cdf0e10cSrcweir     // MessageBox(NULL, myText3.c_str(), "DEBUG", MB_OK);
149cdf0e10cSrcweir 
150cdf0e10cSrcweir 
151cdf0e10cSrcweir     return ERROR_SUCCESS;
152cdf0e10cSrcweir }
153cdf0e10cSrcweir 
ShowProperties(MSIHANDLE handle)154cdf0e10cSrcweir extern "C" UINT __stdcall ShowProperties(MSIHANDLE handle)
155cdf0e10cSrcweir {
156cdf0e10cSrcweir     string property = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
157cdf0e10cSrcweir     string myText = TEXT("INSTALLLOCATION: ") + property;
158cdf0e10cSrcweir 	MessageBox(NULL, myText.c_str(), "INSTALLLOCATION", MB_OK);
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     property = GetMsiProperty(handle, TEXT("Installed"));
161cdf0e10cSrcweir     myText = TEXT("Installed: ") + property;
162cdf0e10cSrcweir 	MessageBox(NULL, myText.c_str(), "Installed", MB_OK);
163cdf0e10cSrcweir 
164cdf0e10cSrcweir     property = GetMsiProperty(handle, TEXT("PATCH"));
165cdf0e10cSrcweir     myText = TEXT("PATCH: ") + property;
166cdf0e10cSrcweir 	MessageBox(NULL, myText.c_str(), "PATCH", MB_OK);
167cdf0e10cSrcweir 
168cdf0e10cSrcweir     property = GetMsiProperty(handle, TEXT("REMOVE"));
169cdf0e10cSrcweir     myText = TEXT("REMOVE: ") + property;
170cdf0e10cSrcweir 	MessageBox(NULL, myText.c_str(), "REMOVE", MB_OK);
171cdf0e10cSrcweir 
172cdf0e10cSrcweir     property = GetMsiProperty(handle, TEXT("ALLUSERS"));
173cdf0e10cSrcweir     myText = TEXT("ALLUSERS: ") + property;
174cdf0e10cSrcweir 	MessageBox(NULL, myText.c_str(), "ALLUSERS", MB_OK);
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     return ERROR_SUCCESS;
177cdf0e10cSrcweir }
178