aboutsummaryrefslogtreecommitdiff
path: root/src/engine/variant.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2018-12-29 22:12:08 -0600
committerSean Hall <r.sean.hall@gmail.com>2018-12-29 22:12:08 -0600
commit61847dddd4fd497057c780658e383c4627de19ec (patch)
treef85a845182922538ab9aa6ee85b0db3ab40c1f6e /src/engine/variant.cpp
parent8295f5f8fd28042e1a0a172d5afbba79178064c2 (diff)
downloadwix-61847dddd4fd497057c780658e383c4627de19ec.tar.gz
wix-61847dddd4fd497057c780658e383c4627de19ec.tar.bz2
wix-61847dddd4fd497057c780658e383c4627de19ec.zip
Import code from old v4 repo
Diffstat (limited to 'src/engine/variant.cpp')
-rw-r--r--src/engine/variant.cpp601
1 files changed, 601 insertions, 0 deletions
diff --git a/src/engine/variant.cpp b/src/engine/variant.cpp
new file mode 100644
index 00000000..2a9f08ed
--- /dev/null
+++ b/src/engine/variant.cpp
@@ -0,0 +1,601 @@
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
5#define VARIANT_ENCRYPTION_SCOPE CRYPTPROTECTMEMORY_SAME_PROCESS
6
7// internal function declarations
8
9static HRESULT BVariantEncryptNumeric(
10 __in BURN_VARIANT* pVariant,
11 __in BOOL fEncrypt
12 );
13
14static HRESULT BVariantEncryptString(
15 __in BURN_VARIANT* pVariant,
16 __in BOOL fEncrypt
17 );
18
19static HRESULT BVariantEncryptVersion(
20 __in BURN_VARIANT* pVariant,
21 __in BOOL fEncrypt
22 );
23
24static HRESULT BVariantRetrieveDecryptedNumeric(
25 __in BURN_VARIANT* pVariant,
26 __out LONGLONG* pllValue
27 );
28
29static HRESULT BVariantRetrieveDecryptedString(
30 __in BURN_VARIANT* pVariant,
31 __out LPWSTR* psczValue
32 );
33
34static HRESULT BVariantRetrieveDecryptedVersion(
35 __in BURN_VARIANT* pVariant,
36 __out DWORD64* pqwValue
37 );
38
39// function definitions
40
41extern "C" void BVariantUninitialize(
42 __in BURN_VARIANT* pVariant
43 )
44{
45 if (BURN_VARIANT_TYPE_STRING == pVariant->Type)
46 {
47 StrSecureZeroFreeString(pVariant->sczValue);
48 }
49 SecureZeroMemory(pVariant, sizeof(BURN_VARIANT));
50}
51
52// The contents of pllValue may be sensitive, should keep encrypted and SecureZeroMemory.
53extern "C" HRESULT BVariantGetNumeric(
54 __in BURN_VARIANT* pVariant,
55 __out LONGLONG* pllValue
56 )
57{
58 HRESULT hr = S_OK;
59 LPWSTR sczValue = NULL;
60
61 switch (pVariant->Type)
62 {
63 case BURN_VARIANT_TYPE_NUMERIC:
64 BVariantRetrieveDecryptedNumeric(pVariant, pllValue);
65 break;
66 case BURN_VARIANT_TYPE_STRING:
67 hr = BVariantRetrieveDecryptedString(pVariant, &sczValue);
68 if (SUCCEEDED(hr))
69 {
70 hr = StrStringToInt64(sczValue, 0, pllValue);
71 if (FAILED(hr))
72 {
73 hr = DISP_E_TYPEMISMATCH;
74 }
75 }
76 StrSecureZeroFreeString(sczValue);
77 break;
78 case BURN_VARIANT_TYPE_VERSION:
79 BVariantRetrieveDecryptedVersion(pVariant, (DWORD64*)pllValue);
80 break;
81 default:
82 hr = E_INVALIDARG;
83 break;
84 }
85
86 return hr;
87}
88
89// The contents of psczValue may be sensitive, should keep encrypted and SecureZeroFree.
90extern "C" HRESULT BVariantGetString(
91 __in BURN_VARIANT* pVariant,
92 __out_z LPWSTR* psczValue
93 )
94{
95 HRESULT hr = S_OK;
96 LONGLONG llValue = 0;
97 DWORD64 qwValue = 0;
98
99 switch (pVariant->Type)
100 {
101 case BURN_VARIANT_TYPE_NUMERIC:
102 hr = BVariantRetrieveDecryptedNumeric(pVariant, &llValue);
103 if (SUCCEEDED(hr))
104 {
105 hr = StrAllocFormattedSecure(psczValue, L"%I64d", llValue);
106 ExitOnFailure(hr, "Failed to convert int64 to string.");
107 }
108 SecureZeroMemory(&llValue, sizeof(llValue));
109 break;
110 case BURN_VARIANT_TYPE_STRING:
111 hr = BVariantRetrieveDecryptedString(pVariant, psczValue);
112 break;
113 case BURN_VARIANT_TYPE_VERSION:
114 hr = BVariantRetrieveDecryptedVersion(pVariant, &qwValue);
115 if (SUCCEEDED(hr))
116 {
117 hr = StrAllocFormattedSecure(psczValue, L"%hu.%hu.%hu.%hu",
118 (WORD)(qwValue >> 48),
119 (WORD)(qwValue >> 32),
120 (WORD)(qwValue >> 16),
121 (WORD)qwValue);
122 ExitOnFailure(hr, "Failed to convert version to string.");
123 }
124 SecureZeroMemory(&qwValue, sizeof(qwValue));
125 break;
126 default:
127 hr = E_INVALIDARG;
128 break;
129 }
130
131LExit:
132 return hr;
133}
134
135// The contents of pqwValue may be sensitive, should keep encrypted and SecureZeroMemory.
136extern "C" HRESULT BVariantGetVersion(
137 __in BURN_VARIANT* pVariant,
138 __out DWORD64* pqwValue
139 )
140{
141 HRESULT hr = S_OK;
142 LPWSTR sczValue = NULL;
143
144 switch (pVariant->Type)
145 {
146 case BURN_VARIANT_TYPE_NUMERIC:
147 BVariantRetrieveDecryptedNumeric(pVariant, (LONGLONG*)pqwValue);
148 break;
149 case BURN_VARIANT_TYPE_STRING:
150 hr = BVariantRetrieveDecryptedString(pVariant, &sczValue);
151 if (SUCCEEDED(hr))
152 {
153 hr = FileVersionFromStringEx(sczValue, 0, pqwValue);
154 if (FAILED(hr))
155 {
156 hr = DISP_E_TYPEMISMATCH;
157 }
158 }
159 StrSecureZeroFreeString(sczValue);
160 break;
161 case BURN_VARIANT_TYPE_VERSION:
162 BVariantRetrieveDecryptedVersion(pVariant, pqwValue);
163 break;
164 default:
165 hr = E_INVALIDARG;
166 break;
167 }
168
169 return hr;
170}
171
172extern "C" HRESULT BVariantSetNumeric(
173 __in BURN_VARIANT* pVariant,
174 __in LONGLONG llValue
175 )
176{
177 HRESULT hr = S_OK;
178 BOOL fEncryptValue = pVariant->fEncryptValue;
179
180 if (BURN_VARIANT_TYPE_STRING == pVariant->Type)
181 {
182 StrSecureZeroFreeString(pVariant->sczValue);
183 }
184 memset(pVariant, 0, sizeof(BURN_VARIANT));
185 pVariant->llValue = llValue;
186 pVariant->Type = BURN_VARIANT_TYPE_NUMERIC;
187 BVariantSetEncryption(pVariant, fEncryptValue);
188
189 return hr;
190}
191
192extern "C" HRESULT BVariantSetString(
193 __in BURN_VARIANT* pVariant,
194 __in_z_opt LPCWSTR wzValue,
195 __in DWORD_PTR cchValue
196 )
197{
198 HRESULT hr = S_OK;
199 BOOL fEncryptValue = pVariant->fEncryptValue;
200
201 if (!wzValue) // if we're nulling out the string, make the variable NONE.
202 {
203 BVariantUninitialize(pVariant);
204 }
205 else // assign the value.
206 {
207 if (BURN_VARIANT_TYPE_STRING != pVariant->Type)
208 {
209 memset(pVariant, 0, sizeof(BURN_VARIANT));
210 }
211 else
212 {
213 // We're about to copy an unencrypted value.
214 pVariant->fEncryptValue = FALSE;
215 }
216
217 hr = StrAllocStringSecure(&pVariant->sczValue, wzValue, cchValue);
218 ExitOnFailure(hr, "Failed to copy string.");
219
220 pVariant->Type = BURN_VARIANT_TYPE_STRING;
221 }
222
223LExit:
224 BVariantSetEncryption(pVariant, fEncryptValue);
225 return hr;
226}
227
228extern "C" HRESULT BVariantSetVersion(
229 __in BURN_VARIANT* pVariant,
230 __in DWORD64 qwValue
231 )
232{
233 HRESULT hr = S_OK;
234 BOOL fEncryptValue = pVariant->fEncryptValue;
235
236 if (BURN_VARIANT_TYPE_STRING == pVariant->Type)
237 {
238 StrSecureZeroFreeString(pVariant->sczValue);
239 }
240 memset(pVariant, 0, sizeof(BURN_VARIANT));
241 pVariant->qwValue = qwValue;
242 pVariant->Type = BURN_VARIANT_TYPE_VERSION;
243 BVariantSetEncryption(pVariant, fEncryptValue);
244
245 return hr;
246}
247
248extern "C" HRESULT BVariantSetValue(
249 __in BURN_VARIANT* pVariant,
250 __in BURN_VARIANT* pValue
251 )
252{
253 HRESULT hr = S_OK;
254 LONGLONG llValue = 0;
255 LPWSTR sczValue = NULL;
256 DWORD64 qwValue = 0;
257 BOOL fEncrypt = pVariant->fEncryptValue;
258
259 switch (pValue->Type)
260 {
261 case BURN_VARIANT_TYPE_NONE:
262 BVariantUninitialize(pVariant);
263 break;
264 case BURN_VARIANT_TYPE_NUMERIC:
265 hr = BVariantGetNumeric(pValue, &llValue);
266 if (SUCCEEDED(hr))
267 {
268 hr = BVariantSetNumeric(pVariant, llValue);
269 }
270 SecureZeroMemory(&llValue, sizeof(llValue));
271 break;
272 case BURN_VARIANT_TYPE_STRING:
273 hr = BVariantGetString(pValue, &sczValue);
274 if (SUCCEEDED(hr))
275 {
276 hr = BVariantSetString(pVariant, sczValue, 0);
277 }
278 StrSecureZeroFreeString(sczValue);
279 break;
280 case BURN_VARIANT_TYPE_VERSION:
281 hr = BVariantGetVersion(pValue, &qwValue);
282 if (SUCCEEDED(hr))
283 {
284 hr = BVariantSetVersion(pVariant, qwValue);
285 }
286 SecureZeroMemory(&qwValue, sizeof(qwValue));
287 break;
288 default:
289 hr = E_INVALIDARG;
290 }
291 ExitOnFailure(hr, "Failed to copy variant.");
292
293 hr = BVariantSetEncryption(pVariant, fEncrypt);
294
295LExit:
296 return hr;
297}
298
299extern "C" HRESULT BVariantCopy(
300 __in BURN_VARIANT* pSource,
301 __out BURN_VARIANT* pTarget
302 )
303{
304 HRESULT hr = S_OK;
305 LONGLONG llValue = 0;
306 LPWSTR sczValue = NULL;
307 DWORD64 qwValue = 0;
308
309 BVariantUninitialize(pTarget);
310
311 switch (pSource->Type)
312 {
313 case BURN_VARIANT_TYPE_NONE:
314 break;
315 case BURN_VARIANT_TYPE_NUMERIC:
316 hr = BVariantGetNumeric(pSource, &llValue);
317 if (SUCCEEDED(hr))
318 {
319 hr = BVariantSetNumeric(pTarget, llValue);
320 }
321 SecureZeroMemory(&llValue, sizeof(llValue));
322 break;
323 case BURN_VARIANT_TYPE_STRING:
324 hr = BVariantGetString(pSource, &sczValue);
325 if (SUCCEEDED(hr))
326 {
327 hr = BVariantSetString(pTarget, sczValue, 0);
328 }
329 StrSecureZeroFreeString(sczValue);
330 break;
331 case BURN_VARIANT_TYPE_VERSION:
332 hr = BVariantGetVersion(pSource, &qwValue);
333 if (SUCCEEDED(hr))
334 {
335 hr = BVariantSetVersion(pTarget, qwValue);
336 }
337 SecureZeroMemory(&qwValue, sizeof(qwValue));
338 break;
339 default:
340 hr = E_INVALIDARG;
341 }
342 ExitOnFailure(hr, "Failed to copy variant.");
343
344 hr = BVariantSetEncryption(pTarget, pSource->fEncryptValue);
345
346LExit:
347 return hr;
348}
349
350extern "C" HRESULT BVariantChangeType(
351 __in BURN_VARIANT* pVariant,
352 __in BURN_VARIANT_TYPE type
353 )
354{
355 HRESULT hr = S_OK;
356 BURN_VARIANT variant = { };
357 BOOL fEncryptValue = pVariant->fEncryptValue;
358
359 if (pVariant->Type == type)
360 {
361 ExitFunction(); // variant already is of the requested type
362 }
363
364 switch (type)
365 {
366 case BURN_VARIANT_TYPE_NONE:
367 hr = S_OK;
368 break;
369 case BURN_VARIANT_TYPE_NUMERIC:
370 hr = BVariantGetNumeric(pVariant, &variant.llValue);
371 break;
372 case BURN_VARIANT_TYPE_STRING:
373 hr = BVariantGetString(pVariant, &variant.sczValue);
374 break;
375 case BURN_VARIANT_TYPE_VERSION:
376 hr = BVariantGetVersion(pVariant, &variant.qwValue);
377 break;
378 default:
379 ExitFunction1(hr = E_INVALIDARG);
380 }
381 ExitOnFailure(hr, "Failed to copy variant value.");
382 variant.Type = type;
383
384 BVariantUninitialize(pVariant);
385 memcpy_s(pVariant, sizeof(BURN_VARIANT), &variant, sizeof(BURN_VARIANT));
386 SecureZeroMemory(&variant, sizeof(BURN_VARIANT));
387 BVariantSetEncryption(pVariant, fEncryptValue);
388
389LExit:
390 return hr;
391}
392
393extern "C" HRESULT BVariantSetEncryption(
394 __in BURN_VARIANT* pVariant,
395 __in BOOL fEncrypt
396 )
397{
398 HRESULT hr = S_OK;
399
400 if (pVariant->fEncryptValue == fEncrypt)
401 {
402 // The requested encryption state is already applied.
403 ExitFunction();
404 }
405
406 switch (pVariant->Type)
407 {
408 case BURN_VARIANT_TYPE_NONE:
409 hr = S_OK;
410 break;
411 case BURN_VARIANT_TYPE_NUMERIC:
412 hr = BVariantEncryptNumeric(pVariant, fEncrypt);
413 break;
414 case BURN_VARIANT_TYPE_STRING:
415 hr = BVariantEncryptString(pVariant, fEncrypt);
416 break;
417 case BURN_VARIANT_TYPE_VERSION:
418 hr = BVariantEncryptVersion(pVariant, fEncrypt);
419 break;
420 default:
421 hr = E_INVALIDARG;
422 }
423 ExitOnFailure(hr, "Failed to set the variant's encryption state");
424 pVariant->fEncryptValue = fEncrypt;
425
426LExit:
427 return hr;
428}
429
430static HRESULT BVariantEncryptNumeric(
431 __in BURN_VARIANT* pVariant,
432 __in BOOL fEncrypt
433 )
434{
435 HRESULT hr = S_OK;
436
437 if (fEncrypt)
438 {
439 hr = CrypEncryptMemory(&pVariant->llValue, sizeof(pVariant->encryptionPadding), VARIANT_ENCRYPTION_SCOPE);
440 }
441 else
442 {
443 hr = CrypDecryptMemory(&pVariant->llValue, sizeof(pVariant->encryptionPadding), VARIANT_ENCRYPTION_SCOPE);
444 }
445
446//LExit:
447 return hr;
448}
449
450static HRESULT BVariantEncryptString(
451 __in BURN_VARIANT* pVariant,
452 __in BOOL fEncrypt
453 )
454{
455 HRESULT hr = S_OK;
456 SIZE_T cbData = 0;
457
458 if (NULL == pVariant->sczValue)
459 {
460 ExitFunction();
461 }
462
463 cbData = MemSize(pVariant->sczValue);
464 if (-1 == cbData)
465 {
466 hr = E_INVALIDARG;
467 ExitOnFailure(hr, "Failed to get the size of the string");
468 }
469
470 DWORD remainder = fEncrypt ? cbData % CRYP_ENCRYPT_MEMORY_SIZE : 0;
471 DWORD extraNeeded = 0 < remainder ? CRYP_ENCRYPT_MEMORY_SIZE - remainder : 0;
472 if ((MAXDWORD - extraNeeded) < cbData)
473 {
474 hr = E_INVALIDDATA;
475 ExitOnFailure(hr, "The string is too big: size %u", cbData);
476 }
477 else if (0 < extraNeeded)
478 {
479 cbData += extraNeeded;
480 LPVOID pvNew = NULL;
481 hr = MemReAllocSecure(static_cast<LPVOID>(pVariant->sczValue), cbData, TRUE, &pvNew);
482 ExitOnFailure(hr, "Failed to resize the string so it could be encrypted");
483 pVariant->sczValue = static_cast<LPWSTR>(pvNew);
484 }
485
486 if (fEncrypt)
487 {
488 hr = CrypEncryptMemory(pVariant->sczValue, static_cast<DWORD>(cbData), VARIANT_ENCRYPTION_SCOPE);
489 }
490 else
491 {
492 hr = CrypDecryptMemory(pVariant->sczValue, static_cast<DWORD>(cbData), VARIANT_ENCRYPTION_SCOPE);
493 }
494
495LExit:
496 return hr;
497}
498
499static HRESULT BVariantEncryptVersion(
500 __in BURN_VARIANT* pVariant,
501 __in BOOL fEncrypt
502 )
503{
504 HRESULT hr = S_OK;
505
506 if (fEncrypt)
507 {
508 hr = CrypEncryptMemory(&pVariant->qwValue, sizeof(pVariant->encryptionPadding), VARIANT_ENCRYPTION_SCOPE);
509 }
510 else
511 {
512 hr = CrypDecryptMemory(&pVariant->qwValue, sizeof(pVariant->encryptionPadding), VARIANT_ENCRYPTION_SCOPE);
513 }
514
515//LExit:
516 return hr;
517}
518
519// The contents of pllValue may be sensitive, should keep encrypted and SecureZeroMemory.
520static HRESULT BVariantRetrieveDecryptedNumeric(
521 __in BURN_VARIANT* pVariant,
522 __out LONGLONG* pllValue
523 )
524{
525 HRESULT hr = S_OK;
526
527 Assert(NULL != pllValue);
528 if (pVariant->fEncryptValue)
529 {
530 hr = BVariantEncryptNumeric(pVariant, FALSE);
531 ExitOnFailure(hr, "Failed to decrypt numeric");
532 }
533
534 *pllValue = pVariant->llValue;
535
536 if (pVariant->fEncryptValue)
537 {
538 hr = BVariantEncryptNumeric(pVariant, TRUE);
539 }
540
541LExit:
542 return hr;
543}
544
545// The contents of psczValue may be sensitive, should keep encrypted and SecureZeroFree.
546static HRESULT BVariantRetrieveDecryptedString(
547 __in BURN_VARIANT* pVariant,
548 __out LPWSTR* psczValue
549 )
550{
551 HRESULT hr = S_OK;
552
553 if (NULL == pVariant->sczValue)
554 {
555 *psczValue = NULL;
556 ExitFunction();
557 }
558
559 if (pVariant->fEncryptValue)
560 {
561 hr = BVariantEncryptString(pVariant, FALSE);
562 ExitOnFailure(hr, "Failed to decrypt string");
563 }
564
565 hr = StrAllocStringSecure(psczValue, pVariant->sczValue, 0);
566 ExitOnFailure(hr, "Failed to copy value.");
567
568 if (pVariant->fEncryptValue)
569 {
570 hr = BVariantEncryptString(pVariant, TRUE);
571 }
572
573LExit:
574 return hr;
575}
576
577// The contents of pqwValue may be sensitive, should keep encrypted and SecureZeroMemory.
578static HRESULT BVariantRetrieveDecryptedVersion(
579 __in BURN_VARIANT* pVariant,
580 __out DWORD64* pqwValue
581 )
582{
583 HRESULT hr = S_OK;
584
585 Assert(NULL != pqwValue);
586 if (pVariant->fEncryptValue)
587 {
588 hr = BVariantEncryptVersion(pVariant, FALSE);
589 ExitOnFailure(hr, "Failed to decrypt version");
590 }
591
592 *pqwValue = pVariant->qwValue;
593
594 if (pVariant->fEncryptValue)
595 {
596 hr = BVariantEncryptVersion(pVariant, TRUE);
597 }
598
599LExit:
600 return hr;
601}