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 {
GetMsiProperty(MSIHANDLE handle,const string & sProperty)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 
SetMsiProperty(MSIHANDLE handle,const string & sProperty,const string & sValue)69     inline void SetMsiProperty(MSIHANDLE handle, const string& sProperty, const string& sValue)
70     {
71         MsiSetProperty(handle, sProperty.c_str(), sValue.c_str());
72     }
73 
stripFinalBackslash(std::string * path)74     void stripFinalBackslash(std::string * path) {
75         std::string::size_type i = path->size();
76         if (i > 1) {
77             --i;
78             if ((*path)[i] == '\\') {
79                 path->erase(i);
80             }
81         }
82     }
83 
84 // Copied more or less verbatim from
85 // desktop/source/deployment/inc/dp_version.hxx:1.5 and
86 // desktop/source/deployment/misc/dp_version.cxx:1.5:
87 
88 enum Order { ORDER_LESS, ORDER_EQUAL, ORDER_GREATER };
89 
getElement(string const & version,string::size_type * index)90 string getElement(string const & version, string::size_type * index) {
91     while (*index < version.size() && version[*index] == '0') {
92         ++*index;
93     }
94     string::size_type i = *index;
95     *index = version.find('.', i);
96     if (*index == string::npos) {
97         *index = version.size();
98         return string(version, i);
99     } else {
100         ++*index;
101         return string(version, i, *index - 1 - i);
102     }
103 }
104 
compareVersions(string const & version1,string const & version2)105 Order compareVersions(string const & version1, string const & version2) {
106     for (string::size_type i1 = 0, i2 = 0;
107          i1 < version1.size() || i2 < version2.size();)
108     {
109         string e1(getElement(version1, &i1));
110         string e2(getElement(version2, &i2));
111 
112 	    // string myText1 = TEXT("e1: ") + e1;
113 	    // string myText2 = TEXT("e2: ") + e2;
114 	    // MessageBox(NULL, myText1.c_str(), "DEBUG", MB_OK);
115 	    // MessageBox(NULL, myText2.c_str(), "DEBUG", MB_OK);
116 
117         if (e1.size() < e2.size()) {
118             return ORDER_LESS;
119         } else if (e1.size() > e2.size()) {
120             return ORDER_GREATER;
121         } else if (e1 < e2) {
122             return ORDER_LESS;
123         } else if (e1 > e2) {
124             return ORDER_GREATER;
125         }
126     }
127     return ORDER_EQUAL;
128 }
129 
130 } // namespace
131 
DotNetCheck(MSIHANDLE handle)132 extern "C" UINT __stdcall DotNetCheck(MSIHANDLE handle) {
133     string present(GetMsiProperty(handle, TEXT("MsiNetAssemblySupport")));
134     string required(GetMsiProperty(handle, TEXT("REQUIRED_DOTNET_VERSION")));
135 
136     // string myText1 = TEXT("MsiNetAssemblySupport: ") + present;
137     // string myText2 = TEXT("REQUIRED_DOTNET_VERSION: ") + required;
138     // MessageBox(NULL, myText1.c_str(), "DEBUG", MB_OK);
139     // MessageBox(NULL, myText2.c_str(), "DEBUG", MB_OK);
140 
141     SetMsiProperty(
142         handle, TEXT("DOTNET_SUFFICIENT"),
143         (present.empty() || compareVersions(present, required) == ORDER_LESS ?
144          TEXT("0") : TEXT("1")));
145 
146     // string result(GetMsiProperty(handle, TEXT("DOTNET_SUFFICIENT")));
147     // string myText3 = TEXT("DOTNET_SUFFICIENT: ") + result;
148     // MessageBox(NULL, myText3.c_str(), "DEBUG", MB_OK);
149 
150 
151     return ERROR_SUCCESS;
152 }
153 
ShowProperties(MSIHANDLE handle)154 extern "C" UINT __stdcall ShowProperties(MSIHANDLE handle)
155 {
156     string property = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
157     string myText = TEXT("INSTALLLOCATION: ") + property;
158 	MessageBox(NULL, myText.c_str(), "INSTALLLOCATION", MB_OK);
159 
160     property = GetMsiProperty(handle, TEXT("Installed"));
161     myText = TEXT("Installed: ") + property;
162 	MessageBox(NULL, myText.c_str(), "Installed", MB_OK);
163 
164     property = GetMsiProperty(handle, TEXT("PATCH"));
165     myText = TEXT("PATCH: ") + property;
166 	MessageBox(NULL, myText.c_str(), "PATCH", MB_OK);
167 
168     property = GetMsiProperty(handle, TEXT("REMOVE"));
169     myText = TEXT("REMOVE: ") + property;
170 	MessageBox(NULL, myText.c_str(), "REMOVE", MB_OK);
171 
172     property = GetMsiProperty(handle, TEXT("ALLUSERS"));
173     myText = TEXT("ALLUSERS: ") + property;
174 	MessageBox(NULL, myText.c_str(), "ALLUSERS", MB_OK);
175 
176     return ERROR_SUCCESS;
177 }
178