[ATL] [3RDPARTY] Updated & moved atlex to sdk/lib/3rdparty
[reactos.git] / reactos / sdk / lib / 3rdparty / atlex / atlmsi.h
1 /*
2 Copyright 1991-2017 Amebis
3
4 This file is part of atlex.
5
6 atlex is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 atlex is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with atlex. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #pragma once
21
22 #include "atlex.h"
23 #include <atlcoll.h>
24 #include <atlstr.h>
25 #include <MsiQuery.h>
26
27 ///
28 /// \defgroup ATLMSIAPI Microsoft Installer API
29 /// Integrates ATL classes with Microsoft Installer API
30 ///
31 /// @{
32
33 ///
34 /// Gets the value for an installer property and stores it in a ATL::CAtlStringA string.
35 ///
36 /// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
37 ///
38 inline UINT MsiGetPropertyA(_In_ MSIHANDLE hInstall, _In_ LPCSTR szName, _Out_ ATL::CAtlStringA &sValue)
39 {
40 CHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(CHAR)];
41 DWORD dwSize = _countof(szStackBuffer);
42 UINT uiResult;
43
44 // Try with stack buffer first.
45 uiResult = ::MsiGetPropertyA(hInstall, szName, szStackBuffer, &dwSize);
46 if (uiResult == NO_ERROR) {
47 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
48 LPSTR szBuffer = sValue.GetBuffer(dwSize);
49 if (!szBuffer) return ERROR_OUTOFMEMORY;
50 memcpy(szBuffer, szStackBuffer, dwSize);
51 sValue.ReleaseBuffer(dwSize);
52 return NO_ERROR;
53 } else if (uiResult == ERROR_MORE_DATA) {
54 // Allocate buffer on heap to read the string data into and read it.
55 LPSTR szBuffer = sValue.GetBuffer(dwSize++);
56 if (!szBuffer) return ERROR_OUTOFMEMORY;
57 uiResult = ::MsiGetPropertyA(hInstall, szName, szBuffer, &dwSize);
58 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
59 return uiResult;
60 } else {
61 // Return error code.
62 return uiResult;
63 }
64 }
65
66
67 ///
68 /// Gets the value for an installer property and stores it in a ATL::CAtlStringW string.
69 ///
70 /// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
71 ///
72 inline UINT MsiGetPropertyW(_In_ MSIHANDLE hInstall, _In_ LPCWSTR szName, _Out_ ATL::CAtlStringW &sValue)
73 {
74 WCHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(WCHAR)];
75 DWORD dwSize = _countof(szStackBuffer);
76 UINT uiResult;
77
78 // Try with stack buffer first.
79 uiResult = ::MsiGetPropertyW(hInstall, szName, szStackBuffer, &dwSize);
80 if (uiResult == NO_ERROR) {
81 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
82 LPWSTR szBuffer = sValue.GetBuffer(dwSize);
83 if (!szBuffer) return ERROR_OUTOFMEMORY;
84 wmemcpy(szBuffer, szStackBuffer, dwSize);
85 sValue.ReleaseBuffer(dwSize);
86 return NO_ERROR;
87 } else if (uiResult == ERROR_MORE_DATA) {
88 // Allocate buffer on heap to read the string data into and read it.
89 LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
90 if (!szBuffer) return ERROR_OUTOFMEMORY;
91 uiResult = ::MsiGetPropertyW(hInstall, szName, szBuffer, &dwSize);
92 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
93 return uiResult;
94 } else {
95 // Return error code.
96 return uiResult;
97 }
98 }
99
100
101 ///
102 /// Returns the string value of a record field and stores it in a ATL::CAtlStringA string.
103 ///
104 /// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
105 ///
106 inline UINT MsiRecordGetStringA(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Out_ ATL::CAtlStringA &sValue)
107 {
108 CHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(CHAR)];
109 DWORD dwSize = _countof(szStackBuffer);
110 UINT uiResult;
111
112 // Try with stack buffer first.
113 uiResult = ::MsiRecordGetStringA(hRecord, iField, szStackBuffer, &dwSize);
114 if (uiResult == NO_ERROR) {
115 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
116 LPSTR szBuffer = sValue.GetBuffer(dwSize);
117 if (!szBuffer) return ERROR_OUTOFMEMORY;
118 memcpy(szBuffer, szStackBuffer, dwSize);
119 sValue.ReleaseBuffer(dwSize);
120 return NO_ERROR;
121 } else if (uiResult == ERROR_MORE_DATA) {
122 // Allocate buffer on heap to read the string data into and read it.
123 LPSTR szBuffer = sValue.GetBuffer(dwSize++);
124 if (!szBuffer) return ERROR_OUTOFMEMORY;
125 uiResult = ::MsiRecordGetStringA(hRecord, iField, szBuffer, &dwSize);
126 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
127 return uiResult;
128 } else {
129 // Return error code.
130 return uiResult;
131 }
132 }
133
134
135 ///
136 /// Returns the string value of a record field and stores it in a ATL::CAtlStringW string.
137 ///
138 /// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
139 ///
140 inline UINT MsiRecordGetStringW(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Out_ ATL::CAtlStringW &sValue)
141 {
142 WCHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(WCHAR)];
143 DWORD dwSize = _countof(szStackBuffer);
144 UINT uiResult;
145
146 // Try with stack buffer first.
147 uiResult = ::MsiRecordGetStringW(hRecord, iField, szStackBuffer, &dwSize);
148 if (uiResult == NO_ERROR) {
149 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
150 LPWSTR szBuffer = sValue.GetBuffer(dwSize);
151 if (!szBuffer) return ERROR_OUTOFMEMORY;
152 wmemcpy(szBuffer, szStackBuffer, dwSize);
153 sValue.ReleaseBuffer(dwSize);
154 return NO_ERROR;
155 } else if (uiResult == ERROR_MORE_DATA) {
156 // Allocate buffer on heap to read the string data into and read it.
157 LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
158 if (!szBuffer) return ERROR_OUTOFMEMORY;
159 uiResult = ::MsiRecordGetStringW(hRecord, iField, szBuffer, &dwSize);
160 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
161 return uiResult;
162 } else {
163 // Return error code.
164 return uiResult;
165 }
166 }
167
168
169 ///
170 /// Formats record field data and properties using a format string and stores it in a ATL::CAtlStringA string.
171 ///
172 /// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
173 ///
174 inline UINT MsiFormatRecordA(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringA &sValue)
175 {
176 CHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(CHAR)];
177 DWORD dwSize = _countof(szStackBuffer);
178 UINT uiResult;
179
180 // Try with stack buffer first.
181 uiResult = ::MsiFormatRecordA(hInstall, hRecord, szStackBuffer, &dwSize);
182 if (uiResult == NO_ERROR) {
183 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
184 LPSTR szBuffer = sValue.GetBuffer(dwSize);
185 if (!szBuffer) return ERROR_OUTOFMEMORY;
186 memcpy(szBuffer, szStackBuffer, dwSize);
187 sValue.ReleaseBuffer(dwSize);
188 return NO_ERROR;
189 } else if (uiResult == ERROR_MORE_DATA) {
190 // Allocate buffer on heap to format the string data into and read it.
191 LPSTR szBuffer = sValue.GetBuffer(dwSize++);
192 if (!szBuffer) return ERROR_OUTOFMEMORY;
193 uiResult = ::MsiFormatRecordA(hInstall, hRecord, szBuffer, &dwSize);
194 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
195 return uiResult;
196 } else {
197 // Return error code.
198 return uiResult;
199 }
200 }
201
202
203 ///
204 /// Formats record field data and properties using a format string and stores it in a ATL::CAtlStringW string.
205 ///
206 /// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
207 ///
208 inline UINT MsiFormatRecordW(MSIHANDLE hInstall, MSIHANDLE hRecord, ATL::CAtlStringW &sValue)
209 {
210 WCHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(WCHAR)];
211 DWORD dwSize = _countof(szStackBuffer);
212 UINT uiResult;
213
214 // Try with stack buffer first.
215 uiResult = ::MsiFormatRecordW(hInstall, hRecord, szStackBuffer, &dwSize);
216 if (uiResult == NO_ERROR) {
217 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
218 LPWSTR szBuffer = sValue.GetBuffer(dwSize);
219 if (!szBuffer) return ERROR_OUTOFMEMORY;
220 wmemcpy(szBuffer, szStackBuffer, dwSize);
221 sValue.ReleaseBuffer(dwSize);
222 return NO_ERROR;
223 } else if (uiResult == ERROR_MORE_DATA) {
224 // Allocate buffer on heap to format the string data into and read it.
225 LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
226 if (!szBuffer) return ERROR_OUTOFMEMORY;
227 uiResult = ::MsiFormatRecordW(hInstall, hRecord, szBuffer, &dwSize);
228 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
229 return uiResult;
230 } else {
231 // Return error code.
232 return uiResult;
233 }
234 }
235
236
237 ///
238 /// Reads bytes from a record stream field into a ATL::CAtlArray<BYTE> buffer.
239 ///
240 /// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
241 ///
242 inline UINT MsiRecordReadStream(_In_ MSIHANDLE hRecord, _In_ unsigned int iField, _Out_ ATL::CAtlArray<BYTE> &binData)
243 {
244 DWORD dwSize = 0;
245 UINT uiResult;
246
247 // Query the actual data length first.
248 uiResult = ::MsiRecordReadStream(hRecord, iField, NULL, &dwSize);
249 if (uiResult == NO_ERROR) {
250 if (!binData.SetCount(dwSize)) return ERROR_OUTOFMEMORY;
251 return ::MsiRecordReadStream(hRecord, iField, (char*)binData.GetData(), &dwSize);
252 } else {
253 // Return error code.
254 return uiResult;
255 }
256 }
257
258
259 ///
260 /// Returns the full target path for a folder in the Directory table and stores it in a ATL::CAtlStringA string.
261 ///
262 /// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
263 ///
264 inline UINT MsiGetTargetPathA(_In_ MSIHANDLE hInstall, _In_ LPCSTR szFolder, _Out_ ATL::CAtlStringA &sValue)
265 {
266 CHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(CHAR)];
267 DWORD dwSize = _countof(szStackBuffer);
268 UINT uiResult;
269
270 // Try with stack buffer first.
271 uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szStackBuffer, &dwSize);
272 if (uiResult == NO_ERROR) {
273 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
274 LPSTR szBuffer = sValue.GetBuffer(dwSize);
275 if (!szBuffer) return ERROR_OUTOFMEMORY;
276 memcpy(szBuffer, szStackBuffer, dwSize);
277 sValue.ReleaseBuffer(dwSize);
278 return NO_ERROR;
279 } else if (uiResult == ERROR_MORE_DATA) {
280 // Allocate buffer on heap to format the string data into and read it.
281 LPSTR szBuffer = sValue.GetBuffer(dwSize++);
282 if (!szBuffer) return ERROR_OUTOFMEMORY;
283 uiResult = ::MsiGetTargetPathA(hInstall, szFolder, szBuffer, &dwSize);
284 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
285 return uiResult;
286 } else {
287 // Return error code.
288 return uiResult;
289 }
290 }
291
292
293 ///
294 /// Returns the full target path for a folder in the Directory table and stores it in a ATL::CAtlStringW string.
295 ///
296 /// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
297 ///
298 inline UINT MsiGetTargetPathW(_In_ MSIHANDLE hInstall, _In_ LPCWSTR szFolder, _Out_ ATL::CAtlStringW &sValue)
299 {
300 WCHAR szStackBuffer[ATL_STACK_BUFFER_BYTES/sizeof(WCHAR)];
301 DWORD dwSize = _countof(szStackBuffer);
302 UINT uiResult;
303
304 // Try with stack buffer first.
305 uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szStackBuffer, &dwSize);
306 if (uiResult == NO_ERROR) {
307 // Allocate buffer on heap, copy from stack buffer, and zero terminate.
308 LPWSTR szBuffer = sValue.GetBuffer(dwSize);
309 if (!szBuffer) return ERROR_OUTOFMEMORY;
310 wmemcpy(szBuffer, szStackBuffer, dwSize);
311 sValue.ReleaseBuffer(dwSize);
312 return NO_ERROR;
313 } else if (uiResult == ERROR_MORE_DATA) {
314 // Allocate buffer on heap to format the string data into and read it.
315 LPWSTR szBuffer = sValue.GetBuffer(dwSize++);
316 if (!szBuffer) return ERROR_OUTOFMEMORY;
317 uiResult = ::MsiGetTargetPathW(hInstall, szFolder, szBuffer, &dwSize);
318 sValue.ReleaseBuffer(uiResult == NO_ERROR ? dwSize : 0);
319 return uiResult;
320 } else {
321 // Return error code.
322 return uiResult;
323 }
324 }
325
326 /// @}