aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/SfxCA/RemoteMsi.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-03-31 11:56:14 -0700
committerRob Mensching <rob@firegiant.com>2022-03-31 18:01:06 -0700
commit47582b162368e8edf7a3b11c13b8e9dabc5f0a26 (patch)
tree2c4063eff325684bed39de0edacd7866a257ae02 /src/dtf/SfxCA/RemoteMsi.cpp
parent167296c42497c4e95f0d5d71168542d747655981 (diff)
downloadwix-47582b162368e8edf7a3b11c13b8e9dabc5f0a26.tar.gz
wix-47582b162368e8edf7a3b11c13b8e9dabc5f0a26.tar.bz2
wix-47582b162368e8edf7a3b11c13b8e9dabc5f0a26.zip
Provide managed CA and Embedded UI DTF libraries via NuGet
Lots of refactoring to bring the SFX tooling back into the 'dtf' layer since they are (in the end) tightly coupled to some DTF assemblies. Also refactored the DTF tests into their own folder and added a couple integration tests to build using the new CA/UI NuGet package. Closes wixtoolset/issues#6080
Diffstat (limited to 'src/dtf/SfxCA/RemoteMsi.cpp')
-rw-r--r--src/dtf/SfxCA/RemoteMsi.cpp629
1 files changed, 629 insertions, 0 deletions
diff --git a/src/dtf/SfxCA/RemoteMsi.cpp b/src/dtf/SfxCA/RemoteMsi.cpp
new file mode 100644
index 00000000..ba59fdf7
--- /dev/null
+++ b/src/dtf/SfxCA/RemoteMsi.cpp
@@ -0,0 +1,629 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4#include "RemoteMsiSession.h"
5
6
7//
8// Ensures that the request buffer is large enough to hold a request,
9// reallocating the buffer if necessary.
10// It will also reduce the buffer size if the previous allocation was very large.
11//
12static __success(return == 0) UINT EnsureBufSize(__deref_out_ecount(*pcchBuf) wchar_t** pszBuf, __deref_inout DWORD* pcchBuf, DWORD cchRequired)
13{
14 // It will also reduce the buffer size if the previous allocation was very large.
15 if (*pcchBuf < cchRequired || (LARGE_BUFFER_THRESHOLD/2 < *pcchBuf && cchRequired < *pcchBuf))
16 {
17 if (*pszBuf != NULL)
18 {
19 SecureZeroMemory(*pszBuf, *pcchBuf);
20 delete[] *pszBuf;
21 }
22
23 *pcchBuf = max(MIN_BUFFER_STRING_SIZE, cchRequired);
24 *pszBuf = new wchar_t[*pcchBuf];
25
26 if (*pszBuf == NULL)
27 {
28 return ERROR_OUTOFMEMORY;
29 }
30 }
31
32 return ERROR_SUCCESS;
33}
34
35typedef int (WINAPI *PMsiFunc_I_I)(int in1, __out int* out1);
36typedef int (WINAPI *PMsiFunc_II_I)(int in1, int in2, __out int* out1);
37typedef int (WINAPI *PMsiFunc_IS_I)(int in1, __in_z wchar_t* in2, __out int* out1);
38typedef int (WINAPI *PMsiFunc_ISI_I)(int in1, __in_z wchar_t* in2, int in3, __out int* out1);
39typedef int (WINAPI *PMsiFunc_ISII_I)(int in1, __in_z wchar_t* in2, int in3, int in4, __out int* out1);
40typedef int (WINAPI *PMsiFunc_IS_II)(int in1, __in_z wchar_t* in2, __out int* out1, __out int* out2);
41typedef MSIDBERROR (WINAPI *PMsiEFunc_I_S)(int in1, __out_ecount_full(*cchOut1) wchar_t* out1, __inout DWORD* cchOut1);
42typedef int (WINAPI *PMsiFunc_I_S)(int in1, __out_ecount_full(*cchOut1) wchar_t* out1, __inout DWORD* cchOut1);
43typedef int (WINAPI *PMsiFunc_II_S)(int in1, int in2, __out_ecount_full(*cchOut1) wchar_t* out1, __inout DWORD* cchOut1);
44typedef int (WINAPI *PMsiFunc_IS_S)(int in1, __in_z wchar_t* in2, __out_ecount_full(*cchOut1) wchar_t* out1, __inout DWORD* cchOut1);
45typedef int (WINAPI *PMsiFunc_ISII_SII)(int in1, __in_z wchar_t* in2, int in3, int in4, __out_ecount_full(*cchOut1) wchar_t* out1, __inout DWORD* cchOut1, __out int* out2, __out int* out3);
46
47UINT MsiFunc_I_I(PMsiFunc_I_I func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp)
48{
49 int in1 = pReq->fields[0].iValue;
50 int out1;
51 UINT ret = (UINT) func(in1, &out1);
52 if (ret == 0)
53 {
54 pResp->fields[1].vt = VT_I4;
55 pResp->fields[1].iValue = out1;
56 }
57 return ret;
58}
59
60UINT MsiFunc_II_I(PMsiFunc_II_I func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp)
61{
62 int in1 = pReq->fields[0].iValue;
63 int in2 = pReq->fields[1].iValue;
64 int out1;
65 UINT ret = (UINT) func(in1, in2, &out1);
66 if (ret == 0)
67 {
68 pResp->fields[1].vt = VT_I4;
69 pResp->fields[1].iValue = out1;
70 }
71 return ret;
72}
73
74UINT MsiFunc_IS_I(PMsiFunc_IS_I func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp)
75{
76 int in1 = pReq->fields[0].iValue;
77 wchar_t* in2 = pReq->fields[1].szValue;
78 int out1;
79 UINT ret = (UINT) func(in1, in2, &out1);
80 if (ret == 0)
81 {
82 pResp->fields[1].vt = VT_I4;
83 pResp->fields[1].iValue = out1;
84 }
85 return ret;
86}
87
88UINT MsiFunc_ISI_I(PMsiFunc_ISI_I func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp)
89{
90 int in1 = pReq->fields[0].iValue;
91 wchar_t* in2 = pReq->fields[1].szValue;
92 int in3 = pReq->fields[2].iValue;
93 int out1;
94 UINT ret = (UINT) func(in1, in2, in3, &out1);
95 if (ret == 0)
96 {
97 pResp->fields[1].vt = VT_I4;
98 pResp->fields[1].iValue = out1;
99 }
100 return ret;
101}
102
103UINT MsiFunc_ISII_I(PMsiFunc_ISII_I func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp)
104{
105 int in1 = pReq->fields[0].iValue;
106 wchar_t* in2 = pReq->fields[1].szValue;
107 int in3 = pReq->fields[2].iValue;
108 int in4 = pReq->fields[3].iValue;
109 int out1;
110 UINT ret = (UINT) func(in1, in2, in3, in4, &out1);
111 if (ret == 0)
112 {
113 pResp->fields[1].vt = VT_I4;
114 pResp->fields[1].iValue = out1;
115 }
116 return ret;
117}
118
119UINT MsiFunc_IS_II(PMsiFunc_IS_II func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp)
120{
121 int in1 = pReq->fields[0].iValue;
122 wchar_t* in2 = pReq->fields[1].szValue;
123 int out1, out2;
124 UINT ret = (UINT) func(in1, in2, &out1, &out2);
125 if (ret == 0)
126 {
127 pResp->fields[1].vt = VT_I4;
128 pResp->fields[1].iValue = out1;
129 pResp->fields[2].vt = VT_I4;
130 pResp->fields[2].iValue = out2;
131 }
132 return ret;
133}
134
135UINT MsiFunc_I_S(PMsiFunc_I_S func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp, __deref_inout_ecount(cchBuf) wchar_t*& szBuf, __inout DWORD& cchBuf)
136{
137 int in1 = pReq->fields[0].iValue;
138 szBuf[0] = L'\0';
139 DWORD cchValue = cchBuf;
140 UINT ret = (UINT) func(in1, szBuf, &cchValue);
141 if (ret == ERROR_MORE_DATA)
142 {
143 ret = EnsureBufSize(&szBuf, &cchBuf, ++cchValue);
144 if (ret == 0)
145 {
146 ret = (UINT) func(in1, szBuf, &cchValue);
147 }
148 }
149 if (ret == 0)
150 {
151 pResp->fields[1].vt = VT_LPWSTR;
152 pResp->fields[1].szValue = szBuf;
153 }
154 return ret;
155}
156
157MSIDBERROR MsiEFunc_I_S(PMsiEFunc_I_S func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp, __deref_inout_ecount(cchBuf) wchar_t*& szBuf, __inout DWORD& cchBuf)
158{
159 int in1 = pReq->fields[0].iValue;
160 szBuf[0] = L'\0';
161 DWORD cchValue = cchBuf;
162 MSIDBERROR ret = func(in1, szBuf, &cchValue);
163 if (ret == MSIDBERROR_MOREDATA)
164 {
165 if (0 == EnsureBufSize(&szBuf, &cchBuf, ++cchValue))
166 {
167 ret = func(in1, szBuf, &cchValue);
168 }
169 }
170 if (ret != MSIDBERROR_MOREDATA)
171 {
172 pResp->fields[1].vt = VT_LPWSTR;
173 pResp->fields[1].szValue = szBuf;
174 }
175 return ret;
176}
177
178UINT MsiFunc_II_S(PMsiFunc_II_S func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp, __deref_inout_ecount(cchBuf) wchar_t*& szBuf, __inout DWORD& cchBuf)
179{
180 int in1 = pReq->fields[0].iValue;
181 int in2 = pReq->fields[1].iValue;
182 szBuf[0] = L'\0';
183 DWORD cchValue = cchBuf;
184 UINT ret = (UINT) func(in1, in2, szBuf, &cchValue);
185 if (ret == ERROR_MORE_DATA)
186 {
187 ret = EnsureBufSize(&szBuf, &cchBuf, ++cchValue);
188 if (ret == 0)
189 {
190 ret = (UINT) func(in1, in2, szBuf, &cchValue);
191 }
192 }
193 if (ret == 0)
194 {
195 pResp->fields[1].vt = VT_LPWSTR;
196 pResp->fields[1].szValue = szBuf;
197 }
198 return ret;
199}
200
201UINT MsiFunc_IS_S(PMsiFunc_IS_S func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp, __deref_inout_ecount(cchBuf) wchar_t*& szBuf, __inout DWORD& cchBuf)
202{
203 int in1 = pReq->fields[0].iValue;
204 wchar_t* in2 = pReq->fields[1].szValue;
205 szBuf[0] = L'\0';
206 DWORD cchValue = cchBuf;
207 UINT ret = (UINT) func(in1, in2, szBuf, &cchValue);
208 if (ret == ERROR_MORE_DATA)
209 {
210 ret = EnsureBufSize(&szBuf, &cchBuf, ++cchValue);
211 if (ret == 0)
212 {
213 ret = (UINT) func(in1, in2, szBuf, &cchValue);
214 }
215 }
216 if (ret == 0)
217 {
218 pResp->fields[1].vt = VT_LPWSTR;
219 pResp->fields[1].szValue = szBuf;
220 }
221 return ret;
222}
223
224UINT MsiFunc_ISII_SII(PMsiFunc_ISII_SII func, const RemoteMsiSession::RequestData* pReq, RemoteMsiSession::RequestData* pResp, __deref_inout_ecount(cchBuf) wchar_t*& szBuf, __inout DWORD& cchBuf)
225{
226 int in1 = pReq->fields[0].iValue;
227 wchar_t* in2 = pReq->fields[1].szValue;
228 int in3 = pReq->fields[2].iValue;
229 int in4 = pReq->fields[3].iValue;
230 szBuf[0] = L'\0';
231 DWORD cchValue = cchBuf;
232 int out2, out3;
233 UINT ret = (UINT) func(in1, in2, in3, in4, szBuf, &cchValue, &out2, &out3);
234 if (ret == ERROR_MORE_DATA)
235 {
236 ret = EnsureBufSize(&szBuf, &cchBuf, ++cchValue);
237 if (ret == 0)
238 {
239 ret = (UINT) func(in1, in2, in3, in4, szBuf, &cchValue, &out2, &out3);
240 }
241 }
242 if (ret == 0)
243 {
244 pResp->fields[1].vt = VT_LPWSTR;
245 pResp->fields[1].szValue = szBuf;
246 pResp->fields[2].vt = VT_I4;
247 pResp->fields[2].iValue = out2;
248 pResp->fields[3].vt = VT_I4;
249 pResp->fields[3].iValue = out3;
250 }
251 return ret;
252}
253
254void RemoteMsiSession::ProcessRequest(RequestId id, const RequestData* pReq, RequestData* pResp)
255{
256 SecureZeroMemory(pResp, sizeof(RequestData));
257
258 UINT ret = EnsureBufSize(&m_pBufSend, &m_cbBufSend, 1024);
259
260 if (0 == ret)
261 {
262 switch (id)
263 {
264 case RemoteMsiSession::EndSession:
265 {
266 this->ExitCode = pReq->fields[0].iValue;
267 }
268 break;
269 case RemoteMsiSession::MsiCloseHandle:
270 {
271 MSIHANDLE h = (MSIHANDLE) pReq->fields[0].iValue;
272 ret = ::MsiCloseHandle(h);
273 }
274 break;
275 case RemoteMsiSession::MsiProcessMessage:
276 {
277 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
278 INSTALLMESSAGE eMessageType = (INSTALLMESSAGE) pReq->fields[1].iValue;
279 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[2].iValue;
280 ret = ::MsiProcessMessage(hInstall, eMessageType, hRecord);
281 }
282 break;
283 case RemoteMsiSession::MsiGetProperty:
284 {
285 ret = MsiFunc_IS_S((PMsiFunc_IS_S) ::MsiGetProperty, pReq, pResp, m_pBufSend, m_cbBufSend);
286 }
287 break;
288 case RemoteMsiSession::MsiSetProperty:
289 {
290 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
291 const wchar_t* szName = pReq->fields[1].szValue;
292 const wchar_t* szValue = pReq->fields[2].szValue;
293 ret = ::MsiSetProperty(hInstall, szName, szValue);
294 }
295 break;
296 case RemoteMsiSession::MsiCreateRecord:
297 {
298 UINT cParams = pReq->fields[0].uiValue;
299 ret = ::MsiCreateRecord(cParams);
300 }
301 break;
302 case RemoteMsiSession::MsiRecordGetFieldCount:
303 {
304 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
305 ret = ::MsiRecordGetFieldCount(hRecord);
306 }
307 break;
308 case RemoteMsiSession::MsiRecordGetInteger:
309 {
310 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
311 UINT iField = pReq->fields[1].uiValue;
312 ret = ::MsiRecordGetInteger(hRecord, iField);
313 }
314 break;
315 case RemoteMsiSession::MsiRecordSetInteger:
316 {
317 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
318 UINT iField = pReq->fields[1].uiValue;
319 int iValue = pReq->fields[2].iValue;
320 ret = ::MsiRecordSetInteger(hRecord, iField, iValue);
321 }
322 break;
323 case RemoteMsiSession::MsiRecordGetString:
324 {
325 ret = MsiFunc_II_S((PMsiFunc_II_S) ::MsiRecordGetString, pReq, pResp, m_pBufSend, m_cbBufSend);
326 }
327 break;
328 case RemoteMsiSession::MsiRecordSetString:
329 {
330 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
331 UINT iField = pReq->fields[1].uiValue;
332 const wchar_t* szValue = pReq->fields[2].szValue;
333 ret = ::MsiRecordSetString(hRecord, iField, szValue);
334 }
335 break;
336 case RemoteMsiSession::MsiRecordClearData:
337 {
338 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
339 ret = ::MsiRecordClearData(hRecord);
340 }
341 break;
342 case RemoteMsiSession::MsiRecordIsNull:
343 {
344 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
345 UINT iField = pReq->fields[1].uiValue;
346 ret = ::MsiRecordIsNull(hRecord, iField);
347 }
348 break;
349 case RemoteMsiSession::MsiFormatRecord:
350 {
351 ret = MsiFunc_II_S((PMsiFunc_II_S) ::MsiFormatRecord, pReq, pResp, m_pBufSend, m_cbBufSend);
352 }
353 break;
354 case RemoteMsiSession::MsiGetActiveDatabase:
355 {
356 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
357 ret = (UINT) ::MsiGetActiveDatabase(hInstall);
358 }
359 break;
360 case RemoteMsiSession::MsiDatabaseOpenView:
361 {
362 ret = MsiFunc_IS_I((PMsiFunc_IS_I) ::MsiDatabaseOpenView, pReq, pResp);
363 }
364 break;
365 case RemoteMsiSession::MsiViewExecute:
366 {
367 MSIHANDLE hView = (MSIHANDLE) pReq->fields[0].iValue;
368 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[1].iValue;
369 ret = ::MsiViewExecute(hView, hRecord);
370 }
371 break;
372 case RemoteMsiSession::MsiViewFetch:
373 {
374 ret = MsiFunc_I_I((PMsiFunc_I_I) ::MsiViewFetch, pReq, pResp);
375 }
376 break;
377 case RemoteMsiSession::MsiViewModify:
378 {
379 MSIHANDLE hView = (MSIHANDLE) pReq->fields[0].iValue;
380 MSIMODIFY eModifyMode = (MSIMODIFY) pReq->fields[1].iValue;
381 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[2].iValue;
382 ret = ::MsiViewModify(hView, eModifyMode, hRecord);
383 }
384 break;
385 case RemoteMsiSession::MsiViewGetError:
386 {
387 ret = MsiEFunc_I_S((PMsiEFunc_I_S) ::MsiViewGetError, pReq, pResp, m_pBufSend, m_cbBufSend);
388 }
389 break;
390 case RemoteMsiSession::MsiViewGetColumnInfo:
391 {
392 ret = MsiFunc_II_I((PMsiFunc_II_I) ::MsiViewGetColumnInfo, pReq, pResp);
393 }
394 break;
395 case RemoteMsiSession::MsiDatabaseGetPrimaryKeys:
396 {
397 ret = MsiFunc_IS_I((PMsiFunc_IS_I) ::MsiDatabaseGetPrimaryKeys, pReq, pResp);
398 }
399 break;
400 case RemoteMsiSession::MsiDatabaseIsTablePersistent:
401 {
402 MSIHANDLE hDb = (MSIHANDLE) pReq->fields[0].iValue;
403 const wchar_t* szTable = pReq->fields[1].szValue;
404 ret = ::MsiDatabaseIsTablePersistent(hDb, szTable);
405 }
406 break;
407 case RemoteMsiSession::MsiDoAction:
408 {
409 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
410 const wchar_t* szAction = pReq->fields[1].szValue;
411 ret = ::MsiDoAction(hInstall, szAction);
412 }
413 break;
414 case RemoteMsiSession::MsiEnumComponentCosts:
415 {
416 ret = MsiFunc_ISII_SII((PMsiFunc_ISII_SII) ::MsiEnumComponentCosts, pReq, pResp, m_pBufSend, m_cbBufSend);
417 }
418 break;
419 case RemoteMsiSession::MsiEvaluateCondition:
420 {
421 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
422 const wchar_t* szCondition = pReq->fields[1].szValue;
423 ret = ::MsiEvaluateCondition(hInstall, szCondition);
424 }
425 break;
426 case RemoteMsiSession::MsiGetComponentState:
427 {
428 ret = MsiFunc_IS_II((PMsiFunc_IS_II) ::MsiGetComponentState, pReq, pResp);
429 }
430 break;
431 case RemoteMsiSession::MsiGetFeatureCost:
432 {
433 ret = MsiFunc_ISII_I((PMsiFunc_ISII_I) ::MsiGetFeatureCost, pReq, pResp);
434 }
435 break;
436 case RemoteMsiSession::MsiGetFeatureState:
437 {
438 ret = MsiFunc_IS_II((PMsiFunc_IS_II) ::MsiGetFeatureState, pReq, pResp);
439 }
440 break;
441 case RemoteMsiSession::MsiGetFeatureValidStates:
442 {
443 ret = MsiFunc_IS_I((PMsiFunc_IS_I) ::MsiGetFeatureValidStates, pReq, pResp);
444 }
445 break;
446 case RemoteMsiSession::MsiGetLanguage:
447 {
448 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
449 ret = ::MsiGetLanguage(hInstall);
450 }
451 break;
452 case RemoteMsiSession::MsiGetLastErrorRecord:
453 {
454 ret = ::MsiGetLastErrorRecord();
455 }
456 break;
457 case RemoteMsiSession::MsiGetMode:
458 {
459 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
460 MSIRUNMODE iRunMode = (MSIRUNMODE) pReq->fields[1].iValue;
461 ret = ::MsiGetMode(hInstall, iRunMode);
462 }
463 break;
464 case RemoteMsiSession::MsiGetSourcePath:
465 {
466 ret = MsiFunc_IS_S((PMsiFunc_IS_S) ::MsiGetSourcePath, pReq, pResp, m_pBufSend, m_cbBufSend);
467 }
468 break;
469 case RemoteMsiSession::MsiGetSummaryInformation:
470 {
471 ret = MsiFunc_ISI_I((PMsiFunc_ISI_I) ::MsiGetSummaryInformation, pReq, pResp);
472 }
473 break;
474 case RemoteMsiSession::MsiGetTargetPath:
475 {
476 ret = MsiFunc_IS_S((PMsiFunc_IS_S) ::MsiGetTargetPath, pReq, pResp, m_pBufSend, m_cbBufSend);
477 }
478 break;
479 case RemoteMsiSession::MsiRecordDataSize:
480 {
481 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
482 UINT iField = pReq->fields[1].uiValue;
483 ret = ::MsiRecordDataSize(hRecord, iField);
484 }
485 break;
486 case RemoteMsiSession::MsiRecordReadStream:
487 {
488 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
489 UINT iField = pReq->fields[1].uiValue;
490 DWORD cbRead = (DWORD) pReq->fields[2].uiValue;
491 ret = EnsureBufSize(&m_pBufSend, &m_cbBufSend, (cbRead + 1) / 2);
492 if (ret == 0)
493 {
494 ret = ::MsiRecordReadStream(hRecord, iField, (char*) m_pBufSend, &cbRead);
495 if (ret == 0)
496 {
497 pResp->fields[1].vt = VT_STREAM;
498 pResp->fields[1].szValue = m_pBufSend;
499 pResp->fields[2].vt = VT_I4;
500 pResp->fields[2].uiValue = (UINT) cbRead;
501 }
502 }
503 }
504 break;
505 case RemoteMsiSession::MsiRecordSetStream:
506 {
507 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
508 UINT iField = pReq->fields[1].uiValue;
509 const wchar_t* szFilePath = pReq->fields[2].szValue;
510 ret = ::MsiRecordSetStream(hRecord, iField, szFilePath);
511 }
512 break;
513 case RemoteMsiSession::MsiSequence:
514 {
515 MSIHANDLE hRecord = (MSIHANDLE) pReq->fields[0].iValue;
516 const wchar_t* szTable = pReq->fields[1].szValue;
517 UINT iSequenceMode = pReq->fields[2].uiValue;
518 ret = ::MsiSequence(hRecord, szTable, iSequenceMode);
519 }
520 break;
521 case RemoteMsiSession::MsiSetComponentState:
522 {
523 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
524 const wchar_t* szComponent = pReq->fields[1].szValue;
525 INSTALLSTATE iState = (INSTALLSTATE) pReq->fields[2].iValue;
526 ret = ::MsiSetComponentState(hInstall, szComponent, iState);
527 }
528 break;
529 case RemoteMsiSession::MsiSetFeatureAttributes:
530 {
531 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
532 const wchar_t* szFeature = pReq->fields[1].szValue;
533 DWORD dwAttrs = (DWORD) pReq->fields[2].uiValue;
534 ret = ::MsiSetFeatureAttributes(hInstall, szFeature, dwAttrs);
535 }
536 break;
537 case RemoteMsiSession::MsiSetFeatureState:
538 {
539 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
540 const wchar_t* szFeature = pReq->fields[1].szValue;
541 INSTALLSTATE iState = (INSTALLSTATE) pReq->fields[2].iValue;
542 ret = ::MsiSetFeatureState(hInstall, szFeature, iState);
543 }
544 break;
545 case RemoteMsiSession::MsiSetInstallLevel:
546 {
547 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
548 int iInstallLevel = pReq->fields[1].iValue;
549 ret = ::MsiSetInstallLevel(hInstall, iInstallLevel);
550 }
551 break;
552 case RemoteMsiSession::MsiSetMode:
553 {
554 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
555 MSIRUNMODE iRunMode = (MSIRUNMODE) pReq->fields[1].uiValue;
556 BOOL fState = (BOOL) pReq->fields[2].iValue;
557 ret = ::MsiSetMode(hInstall, iRunMode, fState);
558 }
559 break;
560 case RemoteMsiSession::MsiSetTargetPath:
561 {
562 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
563 const wchar_t* szFolder = pReq->fields[1].szValue;
564 const wchar_t* szFolderPath = pReq->fields[2].szValue;
565 ret = ::MsiSetTargetPath(hInstall, szFolder, szFolderPath);
566 }
567 break;
568 case RemoteMsiSession::MsiSummaryInfoGetProperty:
569 {
570 MSIHANDLE hSummaryInfo = (MSIHANDLE) pReq->fields[0].iValue;
571 UINT uiProperty = pReq->fields[1].uiValue;
572 UINT uiDataType;
573 int iValue;
574 FILETIME ftValue;
575 m_pBufSend[0] = L'\0';
576 DWORD cchValue = m_cbBufSend;
577 ret = ::MsiSummaryInfoGetProperty(hSummaryInfo, uiProperty, &uiDataType, &iValue, &ftValue, m_pBufSend, &cchValue);
578 if (ret == ERROR_MORE_DATA)
579 {
580 ret = EnsureBufSize(&m_pBufSend, &m_cbBufSend, ++cchValue);
581 if (ret == 0)
582 {
583 ret = ::MsiSummaryInfoGetProperty(hSummaryInfo, uiProperty, &uiDataType, &iValue, &ftValue, m_pBufSend, &cchValue);
584 }
585 }
586 if (ret == 0)
587 {
588 pResp->fields[1].vt = VT_UI4;
589 pResp->fields[1].uiValue = uiDataType;
590
591 switch (uiDataType)
592 {
593 case VT_I2:
594 case VT_I4:
595 pResp->fields[2].vt = VT_I4;
596 pResp->fields[2].iValue = iValue;
597 break;
598 case VT_FILETIME:
599 pResp->fields[2].vt = VT_UI4;
600 pResp->fields[2].iValue = ftValue.dwHighDateTime;
601 pResp->fields[3].vt = VT_UI4;
602 pResp->fields[3].iValue = ftValue.dwLowDateTime;
603 break;
604 case VT_LPSTR:
605 pResp->fields[2].vt = VT_LPWSTR;
606 pResp->fields[2].szValue = m_pBufSend;
607 break;
608 }
609 }
610 }
611 break;
612 case RemoteMsiSession::MsiVerifyDiskSpace:
613 {
614 MSIHANDLE hInstall = (MSIHANDLE) pReq->fields[0].iValue;
615 ret = ::MsiVerifyDiskSpace(hInstall);
616 }
617 break;
618
619 default:
620 {
621 ret = ERROR_INVALID_FUNCTION;
622 }
623 break;
624 }
625 }
626
627 pResp->fields[0].vt = VT_UI4;
628 pResp->fields[0].uiValue = ret;
629}