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