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