2 Copyright 1991-2017 Amebis
4 This file is part of atlex.
6 Setup 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 3 of the License, or
9 (at your option) any later version.
11 Setup 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.
16 You should have received a copy of the GNU General Public License
17 along with Setup. If not, see <http://www.gnu.org/licenses/>.
28 /// \defgroup ATLMSIAPI Microsoft Installer API
29 /// Integrates ATL classes with Microsoft Installer API
34 /// Gets the value for an installer property and stores it in a ATL::CAtlStringA string.
36 /// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
38 inline UINT
MsiGetPropertyA(_In_ MSIHANDLE hInstall
, _In_ LPCSTR szName
, _Out_
ATL::CAtlStringA
&sValue
)
40 CHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(CHAR
)];
41 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
68 /// Gets the value for an installer property and stores it in a ATL::CAtlStringW string.
70 /// \sa [MsiGetProperty function](https://msdn.microsoft.com/en-us/library/aa370134.aspx)
72 inline UINT
MsiGetPropertyW(_In_ MSIHANDLE hInstall
, _In_ LPCWSTR szName
, _Out_
ATL::CAtlStringW
&sValue
)
74 WCHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(WCHAR
)];
75 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
102 /// Returns the string value of a record field and stores it in a ATL::CAtlStringA string.
104 /// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
106 inline UINT
MsiRecordGetStringA(_In_ MSIHANDLE hRecord
, _In_
unsigned int iField
, _Out_
ATL::CAtlStringA
&sValue
)
108 CHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(CHAR
)];
109 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
129 // Return error code.
136 /// Returns the string value of a record field and stores it in a ATL::CAtlStringW string.
138 /// \sa [MsiRecordGetString function](https://msdn.microsoft.com/en-us/library/aa370368.aspx)
140 inline UINT
MsiRecordGetStringW(_In_ MSIHANDLE hRecord
, _In_
unsigned int iField
, _Out_
ATL::CAtlStringW
&sValue
)
142 WCHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(WCHAR
)];
143 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
163 // Return error code.
170 /// Formats record field data and properties using a format string and stores it in a ATL::CAtlStringA string.
172 /// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
174 inline UINT
MsiFormatRecordA(MSIHANDLE hInstall
, MSIHANDLE hRecord
, ATL::CAtlStringA
&sValue
)
176 CHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(CHAR
)];
177 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
197 // Return error code.
204 /// Formats record field data and properties using a format string and stores it in a ATL::CAtlStringW string.
206 /// \sa [MsiFormatRecord function](https://msdn.microsoft.com/en-us/library/aa370109.aspx)
208 inline UINT
MsiFormatRecordW(MSIHANDLE hInstall
, MSIHANDLE hRecord
, ATL::CAtlStringW
&sValue
)
210 WCHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(WCHAR
)];
211 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
231 // Return error code.
238 /// Reads bytes from a record stream field into a ATL::CAtlArray<BYTE> buffer.
240 /// \sa [MsiRecordReadStream function](https://msdn.microsoft.com/en-us/library/aa370370.aspx)
242 inline UINT
MsiRecordReadStream(_In_ MSIHANDLE hRecord
, _In_
unsigned int iField
, _Out_
ATL::CAtlArray
<BYTE
> &binData
)
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
);
253 // Return error code.
260 /// Returns the full target path for a folder in the Directory table and stores it in a ATL::CAtlStringA string.
262 /// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
264 inline UINT
MsiGetTargetPathA(_In_ MSIHANDLE hInstall
, _In_ LPCSTR szFolder
, _Out_
ATL::CAtlStringA
&sValue
)
266 CHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(CHAR
)];
267 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
287 // Return error code.
294 /// Returns the full target path for a folder in the Directory table and stores it in a ATL::CAtlStringW string.
296 /// \sa [MsiGetTargetPath function](https://msdn.microsoft.com/en-us/library/aa370303.aspx)
298 inline UINT
MsiGetTargetPathW(_In_ MSIHANDLE hInstall
, _In_ LPCWSTR szFolder
, _Out_
ATL::CAtlStringW
&sValue
)
300 WCHAR szStackBuffer
[ATL_STACK_BUFFER_BYTES
/sizeof(WCHAR
)];
301 DWORD dwSize
= _countof(szStackBuffer
);
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
);
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);
321 // Return error code.