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