WinStd
Additional templates and function helpers for Microsoft Windows using Standard C++ classes
MSI.h
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 1991-2022 Amebis
4 Copyright © 2016 GÉANT
5*/
6
7#pragma once
8
9#include "Common.h"
10#include <MsiQuery.h>
11#include <string>
12#include <vector>
13
20
22template<class _Traits, class _Ax>
23static UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szName, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
24{
25 assert(0); // TODO: Test this code.
26
27 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
28 DWORD dwSize = _countof(szStackBuffer);
29 UINT uiResult;
30
31 // Try with stack buffer first.
32 uiResult = ::MsiGetPropertyA(hInstall, szName, szStackBuffer, &dwSize);
33 if (uiResult == ERROR_SUCCESS) {
34 // Copy from stack.
35 sValue.assign(szStackBuffer, dwSize);
36 return ERROR_SUCCESS;
37 } else if (uiResult == ERROR_MORE_DATA) {
38 // Allocate buffer on heap to read the string data into and read it.
39 std::unique_ptr<char[]> szBuffer(new char[++dwSize]);
40 uiResult = ::MsiGetPropertyA(hInstall, szName, szBuffer.get(), &dwSize);
41 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
42 return uiResult;
43 } else {
44 // Return error code.
45 return uiResult;
46 }
47}
48
54template<class _Traits, class _Ax>
55static UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szName, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
56{
57 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
58 DWORD dwSize = _countof(szStackBuffer);
59 UINT uiResult;
60
61 // Try with stack buffer first.
62 uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize);
63 if (uiResult == ERROR_SUCCESS) {
64 // Copy from stack.
65 sValue.assign(szStackBuffer, dwSize);
66 return ERROR_SUCCESS;
67 } else if (uiResult == ERROR_MORE_DATA) {
68 // Allocate buffer on heap to read the string data into and read it.
69 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++dwSize]);
70 uiResult = ::MsiGetPropertyW(hInstall, szName, szBuffer.get(), &dwSize);
71 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
72 return uiResult;
73 } else {
74 // Return error code.
75 return uiResult;
76 }
77}
78
80template<class _Traits, class _Ax>
81static UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
82{
83 assert(0); // TODO: Test this code.
84
85 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
86 DWORD dwSize = _countof(szStackBuffer);
87 UINT uiResult;
88
89 // Try with stack buffer first.
90 uiResult = ::MsiRecordGetStringA(hRecord, iField, szStackBuffer, &dwSize);
91 if (uiResult == ERROR_SUCCESS) {
92 // Copy from stack.
93 sValue.assign(szStackBuffer, dwSize);
94 return ERROR_SUCCESS;
95 } else if (uiResult == ERROR_MORE_DATA) {
96 // Allocate buffer on heap to read the string data into and read it.
97 std::unique_ptr<char[]> szBuffer(new char[++dwSize]);
98 uiResult = ::MsiRecordGetStringA(hRecord, iField, szBuffer.get(), &dwSize);
99 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
100 return uiResult;
101 } else {
102 // Return error code.
103 return uiResult;
104 }
105}
106
112template<class _Traits, class _Ax>
113static UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
114{
115 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
116 DWORD dwSize = _countof(szStackBuffer);
117 UINT uiResult;
118
119 // Try with stack buffer first.
120 uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize);
121 if (uiResult == ERROR_SUCCESS) {
122 // Copy from stack.
123 sValue.assign(szStackBuffer, dwSize);
124 return ERROR_SUCCESS;
125 } else if (uiResult == ERROR_MORE_DATA) {
126 // Allocate buffer on heap to read the string data into and read it.
127 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++dwSize]);
128 uiResult = ::MsiRecordGetStringW(hRecord, iField, szBuffer.get(), &dwSize);
129 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
130 return uiResult;
131 } else {
132 // Return error code.
133 return uiResult;
134 }
135}
136
138template<class _Traits, class _Ax>
139static UINT MsiFormatRecordA(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
140{
141 assert(0); // TODO: Test this code.
142
143 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
144 DWORD dwSize = _countof(szStackBuffer);
145 UINT uiResult;
146
147 // Try with stack buffer first.
148 uiResult = ::MsiFormatRecordA(hInstall, hRecord, szStackBuffer, &dwSize);
149 if (uiResult == ERROR_SUCCESS) {
150 // Copy from stack.
151 sValue.assign(szStackBuffer, dwSize);
152 return ERROR_SUCCESS;
153 } else if (uiResult == ERROR_MORE_DATA) {
154 // Allocate buffer on heap to format the string data into and read it.
155 std::unique_ptr<char[]> szBuffer(new char[++dwSize]);
156 uiResult = ::MsiFormatRecordA(hInstall, hRecord, szBuffer.get(), &dwSize);
157 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
158 return uiResult;
159 } else {
160 // Return error code.
161 return uiResult;
162 }
163}
164
170template<class _Traits, class _Ax>
171static UINT MsiFormatRecordW(_In_ MSIHANDLE hInstall, _In_ MSIHANDLE hRecord, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
172{
173 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
174 DWORD dwSize = _countof(szStackBuffer);
175 UINT uiResult;
176
177 // Try with stack buffer first.
178 uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize);
179 if (uiResult == ERROR_SUCCESS) {
180 // Copy from stack.
181 sValue.assign(szStackBuffer, dwSize);
182 return ERROR_SUCCESS;
183 } else if (uiResult == ERROR_MORE_DATA) {
184 // Allocate buffer on heap to format the string data into and read it.
185 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++dwSize]);
186 uiResult = ::MsiFormatRecordW(hInstall, hRecord, szBuffer.get(), &dwSize);
187 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
188 return uiResult;
189 } else {
190 // Return error code.
191 return uiResult;
192 }
193}
194
200template<class _Ty, class _Ax>
201static UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Inout_ std::vector<_Ty, _Ax> &binData)
202{
203 assert(0); // TODO: Test this code.
204
205 DWORD dwSize = 0;
206 UINT uiResult;
207
208 // Query the actual data length first.
209 uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
210 if (uiResult == ERROR_SUCCESS) {
211 binData.resize((dwSize + sizeof(_Ty) - 1) / sizeof(_Ty));
212 return ::MsiRecordReadStream(hRecord, iField, reinterpret_cast<char*>(binData.data()), &dwSize);
213 } else {
214 // Return error code.
215 return uiResult;
216 }
217}
218
220template<class _Traits, class _Ax>
221static UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_z_ LPCSTR szFolder, _Out_ std::basic_string<char, _Traits, _Ax> &sValue)
222{
223 assert(0); // TODO: Test this code.
224
225 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
226 DWORD dwSize = _countof(szStackBuffer);
227 UINT uiResult;
228
229 // Try with stack buffer first.
230 uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szStackBuffer, &dwSize);
231 if (uiResult == ERROR_SUCCESS) {
232 // Copy from stack.
233 sValue.assign(szStackBuffer, dwSize);
234 return ERROR_SUCCESS;
235 } else if (uiResult == ERROR_MORE_DATA) {
236 // Allocate buffer on heap to format the string data into and read it.
237 std::unique_ptr<char[]> szBuffer(new char[++dwSize]);
238 uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szBuffer.get(), &dwSize);
239 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
240 return uiResult;
241 } else {
242 // Return error code.
243 return uiResult;
244 }
245}
246
252template<class _Traits, class _Ax>
253static UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_z_ LPCWSTR szFolder, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
254{
255 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
256 DWORD dwSize = _countof(szStackBuffer);
257 UINT uiResult;
258
259 // Try with stack buffer first.
260 uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize);
261 if (uiResult == ERROR_SUCCESS) {
262 // Copy from stack.
263 sValue.assign(szStackBuffer, dwSize);
264 return ERROR_SUCCESS;
265 } else if (uiResult == ERROR_MORE_DATA) {
266 // Allocate buffer on heap to format the string data into and read it.
267 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++dwSize]);
268 uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szBuffer.get(), &dwSize);
269 sValue.assign(szBuffer.get(), uiResult == ERROR_SUCCESS ? dwSize : 0);
270 return uiResult;
271 } else {
272 // Return error code.
273 return uiResult;
274 }
275}
276
278template<class _Traits, class _Ax>
279static INSTALLSTATE MsiGetComponentPathA(_In_z_ LPCSTR szProduct, _In_z_ LPCSTR szComponent, _Inout_ std::basic_string<char, _Traits, _Ax> &sValue)
280{
281 char szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(char)];
282 DWORD dwSize = _countof(szStackBuffer);
283 INSTALLSTATE state;
284
285 // Try with stack buffer first.
286 state = ::MsiGetComponentPathA(szProduct, szComponent, szStackBuffer, &dwSize);
287 if (state >= INSTALLSTATE_BROKEN) {
288 // Copy from stack.
289 sValue.assign(szStackBuffer, dwSize);
290 return state;
291 } else if (state == INSTALLSTATE_MOREDATA) {
292 // Allocate buffer on heap to format the string data into and read it.
293 std::unique_ptr<char[]> szBuffer(new char[++dwSize]);
294 state = ::MsiGetComponentPathA(szProduct, szComponent, szBuffer.get(), &dwSize);
295 sValue.assign(szBuffer.get(), state >= INSTALLSTATE_BROKEN ? dwSize : 0);
296 return state;
297 } else {
298 // Return error code.
299 return state;
300 }
301}
302
308template<class _Traits, class _Ax>
309static INSTALLSTATE MsiGetComponentPathW(_In_z_ LPCWSTR szProduct, _In_z_ LPCWSTR szComponent, _Inout_ std::basic_string<wchar_t, _Traits, _Ax> &sValue)
310{
311 wchar_t szStackBuffer[WINSTD_STACK_BUFFER_BYTES/sizeof(wchar_t)];
312 DWORD dwSize = _countof(szStackBuffer);
313 INSTALLSTATE state;
314
315 // Try with stack buffer first.
316 state = ::MsiGetComponentPathW(szProduct, szComponent, szStackBuffer, &dwSize);
317 if (state >= INSTALLSTATE_BROKEN) {
318 // Copy from stack.
319 sValue.assign(szStackBuffer, dwSize);
320 return state;
321 } else if (state == INSTALLSTATE_MOREDATA) {
322 // Allocate buffer on heap to format the string data into and read it.
323 std::unique_ptr<wchar_t[]> szBuffer(new wchar_t[++dwSize]);
324 state = ::MsiGetComponentPathW(szProduct, szComponent, szBuffer.get(), &dwSize);
325 sValue.assign(szBuffer.get(), state >= INSTALLSTATE_BROKEN ? dwSize : 0);
326 return state;
327 } else {
328 // Return error code.
329 return state;
330 }
331}
332
#define WINSTD_STACK_BUFFER_BYTES
Size of the stack buffer in bytes used for initial system function call.
Definition: Common.h:79