main
cpp 722 lines 22.2 KB
Raw
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 using namespace System;
6 using namespace System::Collections::Generic;
7 using namespace System::Runtime::InteropServices;
8 using namespace Xunit;
9 using namespace WixInternal::TestSupport;
10
11 LPCWSTR wzBaseRegKey = L"Software\\RegUtilTest\\";
12 LPWSTR rgwzMultiValue[2] = { L"First", L"Second" };
13 LPWSTR rgwzEmptyMultiValue[2] = { L"", L"" };
14
15 HKEY hkBase;
16
17 namespace DutilTests
18 {
19 public ref class RegUtil : IDisposable
20 {
21 private:
22
23 void CreateBaseKey()
24 {
25 HRESULT hr = RegCreate(HKEY_CURRENT_USER, wzBaseRegKey, KEY_ALL_ACCESS, &hkBase);
26 NativeAssert::Succeeded(hr, "Failed to create base key.");
27 }
28
29 public:
30 RegUtil()
31 {
32 HRESULT hr = RegInitialize();
33 NativeAssert::Succeeded(hr, "RegInitialize failed.");
34 }
35
36 ~RegUtil()
37 {
38 RegFunctionOverride(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
39
40 if (hkBase)
41 {
42 RegDelete(hkBase, NULL, REG_KEY_DEFAULT, TRUE);
43 }
44
45 ReleaseRegKey(hkBase);
46
47 RegUninitialize();
48 }
49
50 [Fact]
51 void RegUtilStringValueTest()
52 {
53 this->StringValueTest();
54 }
55
56 [Fact]
57 void RegUtilStringValueFallbackTest()
58 {
59 RegFunctionForceFallback();
60 this->StringValueTest();
61 }
62
63 void StringValueTest()
64 {
65 HRESULT hr = S_OK;
66 LPWSTR sczValue = NULL;
67 LPCWSTR wzValue = L"Value";
68
69 try
70 {
71 this->CreateBaseKey();
72
73 hr = RegWriteString(hkBase, L"String", wzValue);
74 NativeAssert::Succeeded(hr, "Failed to write string value.");
75
76 hr = RegReadString(hkBase, L"String", &sczValue);
77 NativeAssert::Succeeded(hr, "Failed to read string value.");
78 NativeAssert::StringEqual(wzValue, sczValue);
79
80 ReleaseNullStr(sczValue);
81 hr = StrAllocString(&sczValue, L"e", 0);
82 NativeAssert::Succeeded(hr, "Failed to reallocate string value.");
83
84 hr = RegReadString(hkBase, L"String", &sczValue);
85 NativeAssert::Succeeded(hr, "Failed to read string value.");
86 NativeAssert::StringEqual(wzValue, sczValue);
87 }
88 finally
89 {
90 ReleaseStr(sczValue);
91 }
92 }
93
94 [Fact]
95 void RegUtilPartialStringValueTest()
96 {
97 this->PartialStringValueTest();
98 }
99
100 [Fact]
101 void RegUtilPartialStringValueFallbackTest()
102 {
103 RegFunctionForceFallback();
104 this->PartialStringValueTest();
105 }
106
107 void PartialStringValueTest()
108 {
109 HRESULT hr = S_OK;
110 LPWSTR sczValue = NULL;
111 LPCWSTR wzValue = L"Value";
112 BOOL fNeedsExpansion = FALSE;
113
114 try
115 {
116 this->CreateBaseKey();
117
118 // Use API directly to write non-null terminated string.
119 hr = HRESULT_FROM_WIN32(::RegSetValueExW(hkBase, L"PartialString", 0, REG_SZ, reinterpret_cast<const BYTE*>(wzValue), 4 * sizeof(WCHAR)));
120 NativeAssert::Succeeded(hr, "Failed to write partial string value.");
121
122 hr = RegReadString(hkBase, L"PartialString", &sczValue);
123 NativeAssert::Succeeded(hr, "Failed to read partial string value.");
124 NativeAssert::StringEqual(L"Valu", sczValue);
125
126 hr = RegReadUnexpandedString(hkBase, L"PartialString", &fNeedsExpansion, &sczValue);
127 NativeAssert::Succeeded(hr, "Failed to read partial unexpanded string value.");
128 NativeAssert::StringEqual(L"Valu", sczValue);
129 Assert::False(fNeedsExpansion);
130 }
131 finally
132 {
133 ReleaseStr(sczValue);
134 }
135 }
136
137 [Fact]
138 void RegUtilEmptyStringValueTest()
139 {
140 this->EmptyStringValueTest();
141 }
142
143 [Fact]
144 void RegUtilEmptyStringValueFallbackTest()
145 {
146 RegFunctionForceFallback();
147 this->EmptyStringValueTest();
148 }
149
150 void EmptyStringValueTest()
151 {
152 HRESULT hr = S_OK;
153 LPWSTR sczValue = NULL;
154
155 try
156 {
157 this->CreateBaseKey();
158
159 // Use API directly to write non-null terminated string.
160 hr = HRESULT_FROM_WIN32(::RegSetValueExW(hkBase, L"EmptyString", 0, REG_SZ, reinterpret_cast<const BYTE*>(L""), 0));
161 NativeAssert::Succeeded(hr, "Failed to write partial string value.");
162
163 hr = RegReadString(hkBase, L"EmptyString", &sczValue);
164 NativeAssert::Succeeded(hr, "Failed to read partial string value.");
165 NativeAssert::StringEqual(L"", sczValue);
166 }
167 finally
168 {
169 ReleaseStr(sczValue);
170 }
171 }
172
173 [Fact]
174 void RegUtilExpandStringValueTest()
175 {
176 this->ExpandStringValueTest();
177 }
178
179 [Fact]
180 void RegUtilExpandStringValueFallbackTest()
181 {
182 RegFunctionForceFallback();
183 this->ExpandStringValueTest();
184 }
185
186 void ExpandStringValueTest()
187 {
188 HRESULT hr = S_OK;
189 LPWSTR sczValue = NULL;
190 LPCWSTR wzValue = L"Value_%USERNAME%";
191 String^ expandedValue = Environment::ExpandEnvironmentVariables(gcnew String(wzValue));
192
193 try
194 {
195 this->CreateBaseKey();
196
197 hr = RegWriteExpandString(hkBase, L"ExpandString", wzValue);
198 NativeAssert::Succeeded(hr, "Failed to write expand string value.");
199
200 hr = RegReadString(hkBase, L"ExpandString", &sczValue);
201 NativeAssert::Succeeded(hr, "Failed to read expand string value.");
202 WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false);
203 }
204 finally
205 {
206 ReleaseStr(sczValue);
207 }
208 }
209
210 [Fact]
211 void RegUtilExpandLongStringValueTest()
212 {
213 this->ExpandLongStringValueTest();
214 }
215
216 [Fact]
217 void RegUtilExpandLongStringValueFallbackTest()
218 {
219 RegFunctionForceFallback();
220 this->ExpandLongStringValueTest();
221 }
222
223 void ExpandLongStringValueTest()
224 {
225 HRESULT hr = S_OK;
226 LPWSTR sczValue = NULL;
227 LPCWSTR wzValue = L"%TEMP%;%PATH%;C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789";
228 String^ expandedValue = Environment::ExpandEnvironmentVariables(gcnew String(wzValue));
229
230 try
231 {
232 this->CreateBaseKey();
233
234 hr = RegWriteExpandString(hkBase, L"ExpandString", wzValue);
235 NativeAssert::Succeeded(hr, "Failed to write expand string value.");
236
237 hr = RegReadString(hkBase, L"ExpandString", &sczValue);
238 NativeAssert::Succeeded(hr, "Failed to read expand string value.");
239 WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false);
240
241 ReleaseNullStr(sczValue);
242
243 hr = RegReadString(hkBase, L"ExpandString", &sczValue);
244 NativeAssert::Succeeded(hr, "Failed to read expand string value.");
245 WixAssert::StringEqual(expandedValue, gcnew String(sczValue), false);
246 }
247 finally
248 {
249 ReleaseStr(sczValue);
250 }
251 }
252
253 [Fact]
254 void RegUtilNotExpandStringValueTest()
255 {
256 this->NotExpandStringValueTest();
257 }
258
259 [Fact]
260 void RegUtilNotExpandStringValueFallbackTest()
261 {
262 RegFunctionForceFallback();
263 this->NotExpandStringValueTest();
264 }
265
266 void NotExpandStringValueTest()
267 {
268 HRESULT hr = S_OK;
269 LPWSTR sczValue = NULL;
270 BOOL fNeedsExpansion = FALSE;
271 LPCWSTR wzValue = L"Value_%USERNAME%";
272
273 try
274 {
275 this->CreateBaseKey();
276
277 hr = RegWriteExpandString(hkBase, L"NotExpandString", wzValue);
278 NativeAssert::Succeeded(hr, "Failed to write expand string value.");
279
280 hr = RegReadUnexpandedString(hkBase, L"NotExpandString", &fNeedsExpansion, &sczValue);
281 NativeAssert::Succeeded(hr, "Failed to read expand string value.");
282 NativeAssert::StringEqual(wzValue, sczValue);
283 Assert::True(fNeedsExpansion);
284 }
285 finally
286 {
287 ReleaseStr(sczValue);
288 }
289 }
290
291 [Fact]
292 void RegUtilMultiStringValueTest()
293 {
294 this->MultiStringValueTest();
295 }
296
297 [Fact]
298 void RegUtilMultiStringValueFallbackTest()
299 {
300 RegFunctionForceFallback();
301 this->MultiStringValueTest();
302 }
303
304 void MultiStringValueTest()
305 {
306 HRESULT hr = S_OK;
307 LPWSTR* rgsczStrings = NULL;
308 DWORD cStrings = 0;
309
310 try
311 {
312 this->CreateBaseKey();
313
314 hr = RegWriteStringArray(hkBase, L"MultiString", rgwzMultiValue, 2);
315 NativeAssert::Succeeded(hr, "Failed to write multi string value.");
316
317 hr = RegReadStringArray(hkBase, L"MultiString", &rgsczStrings, &cStrings);
318 NativeAssert::Succeeded(hr, "Failed to read multi string value.");
319 Assert::Equal<DWORD>(2, cStrings);
320 NativeAssert::StringEqual(L"First", rgsczStrings[0]);
321 NativeAssert::StringEqual(L"Second", rgsczStrings[1]);
322 }
323 finally
324 {
325 ReleaseStrArray(rgsczStrings, cStrings);
326 }
327 }
328
329 [Fact]
330 void RegUtilPartialMultiStringValueTest()
331 {
332 this->PartialMultiStringValueTest();
333 }
334
335 [Fact]
336 void RegUtilPartialMultiStringValueFallbackTest()
337 {
338 RegFunctionForceFallback();
339 this->PartialMultiStringValueTest();
340 }
341
342 void PartialMultiStringValueTest()
343 {
344 HRESULT hr = S_OK;
345 LPWSTR* rgsczStrings = NULL;
346 DWORD cStrings = 0;
347
348 try
349 {
350 this->CreateBaseKey();
351
352 // Use API directly to write non-double-null terminated string.
353 hr = HRESULT_FROM_WIN32(::RegSetValueExW(hkBase, L"PartialMultiString", 0, REG_MULTI_SZ, reinterpret_cast<const BYTE*>(L"First\0Second"), 13 * sizeof(WCHAR)));
354 NativeAssert::Succeeded(hr, "Failed to write partial multi string value.");
355
356 hr = RegReadStringArray(hkBase, L"PartialMultiString", &rgsczStrings, &cStrings);
357 NativeAssert::Succeeded(hr, "Failed to read partial multi string value.");
358 Assert::Equal<DWORD>(2, cStrings);
359 NativeAssert::StringEqual(L"First", rgsczStrings[0]);
360 NativeAssert::StringEqual(L"Second", rgsczStrings[1]);
361 }
362 finally
363 {
364 ReleaseStrArray(rgsczStrings, cStrings);
365 }
366 }
367
368 [Fact]
369 void RegUtilEmptyMultiStringValueTest()
370 {
371 this->EmptyMultiStringValueTest();
372 }
373
374 [Fact]
375 void RegUtilEmptyMultiStringValueFallbackTest()
376 {
377 RegFunctionForceFallback();
378 this->EmptyMultiStringValueTest();
379 }
380
381 void EmptyMultiStringValueTest()
382 {
383 HRESULT hr = S_OK;
384 LPWSTR* rgsczStrings = NULL;
385 DWORD cStrings = 0;
386
387 try
388 {
389 this->CreateBaseKey();
390
391 hr = RegWriteStringArray(hkBase, L"EmptyMultiString", rgwzMultiValue, 0);
392 NativeAssert::Succeeded(hr, "Failed to write empty multi string value.");
393
394 hr = RegReadStringArray(hkBase, L"EmptyMultiString", &rgsczStrings, &cStrings);
395 NativeAssert::Succeeded(hr, "Failed to read empty multi string value.");
396 Assert::Equal<DWORD>(0, cStrings);
397 }
398 finally
399 {
400 ReleaseStrArray(rgsczStrings, cStrings);
401 }
402 }
403
404 [Fact]
405 void RegUtilOneEmptyMultiStringValueTest()
406 {
407 this->OneEmptyMultiStringValueTest();
408 }
409
410 [Fact]
411 void RegUtilOneEmptyMultiStringValueFallbackTest()
412 {
413 RegFunctionForceFallback();
414 this->OneEmptyMultiStringValueTest();
415 }
416
417 void OneEmptyMultiStringValueTest()
418 {
419 HRESULT hr = S_OK;
420 LPWSTR* rgsczStrings = NULL;
421 DWORD cStrings = 0;
422
423 try
424 {
425 this->CreateBaseKey();
426
427 hr = RegWriteStringArray(hkBase, L"OneEmptyMultiString", rgwzEmptyMultiValue, 1);
428 NativeAssert::Succeeded(hr, "Failed to write one empty multi string value.");
429
430 hr = RegReadStringArray(hkBase, L"OneEmptyMultiString", &rgsczStrings, &cStrings);
431 NativeAssert::Succeeded(hr, "Failed to read one empty multi string value.");
432 Assert::Equal<DWORD>(0, cStrings);
433 }
434 finally
435 {
436 ReleaseStrArray(rgsczStrings, cStrings);
437 }
438 }
439
440 [Fact]
441 void RegUtilTwoEmptyMultiStringValueTest()
442 {
443 this->TwoEmptyMultiStringValueTest();
444 }
445
446 [Fact]
447 void RegUtilTwoEmptyMultiStringValueFallbackTest()
448 {
449 RegFunctionForceFallback();
450 this->TwoEmptyMultiStringValueTest();
451 }
452
453 void TwoEmptyMultiStringValueTest()
454 {
455 HRESULT hr = S_OK;
456 LPWSTR* rgsczStrings = NULL;
457 DWORD cStrings = 0;
458
459 try
460 {
461 this->CreateBaseKey();
462
463 hr = RegWriteStringArray(hkBase, L"OneEmptyMultiString", rgwzEmptyMultiValue, 2);
464 NativeAssert::Succeeded(hr, "Failed to write one empty multi string value.");
465
466 hr = RegReadStringArray(hkBase, L"OneEmptyMultiString", &rgsczStrings, &cStrings);
467 NativeAssert::Succeeded(hr, "Failed to read one empty multi string value.");
468 Assert::Equal<DWORD>(2, cStrings);
469 NativeAssert::StringEqual(L"", rgsczStrings[0]);
470 NativeAssert::StringEqual(L"", rgsczStrings[1]);
471 }
472 finally
473 {
474 ReleaseStrArray(rgsczStrings, cStrings);
475 }
476 }
477
478 [Fact]
479 void RegUtilOnePartialEmptyMultiStringValueTest()
480 {
481 this->OnePartialEmptyMultiStringValueTest();
482 }
483
484 [Fact]
485 void RegUtilOnePartialEmptyMultiStringValueFallbackTest()
486 {
487 RegFunctionForceFallback();
488 this->OnePartialEmptyMultiStringValueTest();
489 }
490
491 void OnePartialEmptyMultiStringValueTest()
492 {
493 HRESULT hr = S_OK;
494 LPWSTR* rgsczStrings = NULL;
495 DWORD cStrings = 0;
496
497 try
498 {
499 this->CreateBaseKey();
500
501 // Use API directly to write non-double-null terminated string.
502 hr = HRESULT_FROM_WIN32(::RegSetValueExW(hkBase, L"OnePartialEmptyMultiString", 0, REG_MULTI_SZ, reinterpret_cast<const BYTE*>(L""), 1 * sizeof(WCHAR)));
503 NativeAssert::Succeeded(hr, "Failed to write partial empty multi string value.");
504
505 hr = RegReadStringArray(hkBase, L"OnePartialEmptyMultiString", &rgsczStrings, &cStrings);
506 NativeAssert::Succeeded(hr, "Failed to read partial empty multi string value.");
507 Assert::Equal<DWORD>(0, cStrings);
508 }
509 finally
510 {
511 ReleaseStrArray(rgsczStrings, cStrings);
512 }
513 }
514
515 [Fact]
516 void RegUtilBinaryValueTest()
517 {
518 this->BinaryValueTest();
519 }
520
521 [Fact]
522 void RegUtilBinaryValueFallbackTest()
523 {
524 RegFunctionForceFallback();
525 this->BinaryValueTest();
526 }
527
528 void BinaryValueTest()
529 {
530 HRESULT hr = S_OK;
531 BYTE pbSource[4] = { 1, 2, 3, 4 };
532 BYTE* pbBuffer = NULL;
533 SIZE_T cbBuffer = 0;
534
535 try
536 {
537 this->CreateBaseKey();
538
539 hr = RegWriteBinary(hkBase, L"Binary", pbSource, 4);
540 NativeAssert::Succeeded(hr, "Failed to write binary value.");
541
542 hr = RegReadBinary(hkBase, L"Binary", &pbBuffer, &cbBuffer);
543 NativeAssert::Succeeded(hr, "Failed to read binary value.");
544 Assert::Equal<SIZE_T>(4, cbBuffer);
545 Assert::Equal<BYTE>(1, pbBuffer[0]);
546 Assert::Equal<BYTE>(2, pbBuffer[1]);
547 Assert::Equal<BYTE>(3, pbBuffer[2]);
548 Assert::Equal<BYTE>(4, pbBuffer[3]);
549 }
550 finally
551 {
552 ReleaseMem(pbBuffer);
553 }
554 }
555
556 [Fact]
557 void RegUtilEmptyBinaryValueTest()
558 {
559 this->EmptyBinaryValueTest();
560 }
561
562 [Fact]
563 void RegUtilEmptyBinaryValueFallbackTest()
564 {
565 RegFunctionForceFallback();
566 this->EmptyBinaryValueTest();
567 }
568
569 void EmptyBinaryValueTest()
570 {
571 HRESULT hr = S_OK;
572 BYTE* pbBuffer = NULL;
573 SIZE_T cbBuffer = 0;
574
575 try
576 {
577 this->CreateBaseKey();
578
579 hr = RegWriteBinary(hkBase, L"Binary", NULL, 0);
580 NativeAssert::Succeeded(hr, "Failed to write binary value.");
581
582 hr = RegReadBinary(hkBase, L"Binary", &pbBuffer, &cbBuffer);
583 NativeAssert::Succeeded(hr, "Failed to read binary value.");
584 Assert::Equal<SIZE_T>(0, cbBuffer);
585 }
586 finally
587 {
588 ReleaseMem(pbBuffer);
589 }
590 }
591
592 [Fact]
593 void RegUtilQwordVersionValueTest()
594 {
595 this->QwordVersionValueTest();
596 }
597
598 [Fact]
599 void RegUtilQwordVersionValueFallbackTest()
600 {
601 RegFunctionForceFallback();
602 this->QwordVersionValueTest();
603 }
604
605 void QwordVersionValueTest()
606 {
607 HRESULT hr = S_OK;
608 DWORD64 qwVersion = FILEMAKEVERSION(1, 2, 3, 4);
609 DWORD64 qwValue = 0;
610
611 this->CreateBaseKey();
612
613 hr = RegWriteQword(hkBase, L"QwordVersion", qwVersion);
614 NativeAssert::Succeeded(hr, "Failed to write qword version value.");
615
616 hr = RegReadVersion(hkBase, L"QwordVersion", &qwValue);
617 NativeAssert::Succeeded(hr, "Failed to read qword version value.");
618 Assert::Equal<DWORD64>(qwVersion, qwValue);
619 }
620
621 [Fact]
622 void RegUtilStringVersionValueTest()
623 {
624 this->StringVersionValueTest();
625 }
626
627 [Fact]
628 void RegUtilStringVersionValueFallbackTest()
629 {
630 RegFunctionForceFallback();
631 this->StringVersionValueTest();
632 }
633
634 void StringVersionValueTest()
635 {
636 HRESULT hr = S_OK;
637 LPCWSTR wzVersion = L"65535.65535.65535.65535";
638 DWORD64 qwValue = 0;
639
640 this->CreateBaseKey();
641
642 hr = RegWriteString(hkBase, L"StringVersion", wzVersion);
643 NativeAssert::Succeeded(hr, "Failed to write string version value.");
644
645 hr = RegReadVersion(hkBase, L"StringVersion", &qwValue);
646 NativeAssert::Succeeded(hr, "Failed to read string version value.");
647 Assert::Equal<DWORD64>(MAXDWORD64, qwValue);
648 }
649
650 [Fact]
651 void RegUtilQwordWixVersionValueTest()
652 {
653 this->QwordWixVersionValueTest();
654 }
655
656 [Fact]
657 void RegUtilQwordWixVersionValueFallbackTest()
658 {
659 RegFunctionForceFallback();
660 this->QwordWixVersionValueTest();
661 }
662
663 void QwordWixVersionValueTest()
664 {
665 HRESULT hr = S_OK;
666 DWORD64 qwVersion = FILEMAKEVERSION(1, 2, 3, 4);
667 VERUTIL_VERSION* pVersion = NULL;
668
669 try
670 {
671 this->CreateBaseKey();
672
673 hr = RegWriteQword(hkBase, L"QwordWixVersion", qwVersion);
674 NativeAssert::Succeeded(hr, "Failed to write qword wix version value.");
675
676 hr = RegReadWixVersion(hkBase, L"QwordWixVersion", &pVersion);
677 NativeAssert::Succeeded(hr, "Failed to read qword wix version value.");
678 NativeAssert::StringEqual(L"1.2.3.4", pVersion->sczVersion);
679 }
680 finally
681 {
682 ReleaseVerutilVersion(pVersion);
683 }
684 }
685
686 [Fact]
687 void RegUtilStringWixVersionValueTest()
688 {
689 this->StringWixVersionValueTest();
690 }
691
692 [Fact]
693 void RegUtilStringWixVersionValueFallbackTest()
694 {
695 RegFunctionForceFallback();
696 this->StringWixVersionValueTest();
697 }
698
699 void StringWixVersionValueTest()
700 {
701 HRESULT hr = S_OK;
702 LPCWSTR wzVersion = L"65535.65535.65535.65535-abc+def";
703 VERUTIL_VERSION* pVersion = NULL;
704
705 try
706 {
707 this->CreateBaseKey();
708
709 hr = RegWriteString(hkBase, L"StringWixVersion", wzVersion);
710 NativeAssert::Succeeded(hr, "Failed to write string wix version value.");
711
712 hr = RegReadWixVersion(hkBase, L"StringWixVersion", &pVersion);
713 NativeAssert::Succeeded(hr, "Failed to read string wix version value.");
714 NativeAssert::StringEqual(wzVersion, pVersion->sczVersion);
715 }
716 finally
717 {
718 ReleaseVerutilVersion(pVersion);
719 }
720 }
721 };
722 }