main
cpp 219 lines 8.72 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 static HRESULT CALLBACK CacheTestEventRoutine(
6 __in BURN_CACHE_MESSAGE* pMessage,
7 __in LPVOID pvContext
8 );
9
10 static DWORD CALLBACK CacheTestProgressRoutine(
11 __in LARGE_INTEGER TotalFileSize,
12 __in LARGE_INTEGER TotalBytesTransferred,
13 __in LARGE_INTEGER StreamSize,
14 __in LARGE_INTEGER StreamBytesTransferred,
15 __in DWORD dwStreamNumber,
16 __in DWORD dwCallbackReason,
17 __in HANDLE hSourceFile,
18 __in HANDLE hDestinationFile,
19 __in_opt LPVOID lpData
20 );
21
22 typedef struct _CACHE_TEST_CONTEXT
23 {
24 } CACHE_TEST_CONTEXT;
25
26 namespace Microsoft
27 {
28 namespace Tools
29 {
30 namespace WindowsInstallerXml
31 {
32 namespace Test
33 {
34 namespace Bootstrapper
35 {
36 using namespace System;
37 using namespace System::IO;
38 using namespace Xunit;
39
40 public ref class CacheTest : BurnUnitTest, IClassFixture<TestRegistryFixture^>
41 {
42 private:
43 TestRegistryFixture^ testRegistry;
44 public:
45 CacheTest(BurnTestFixture^ fixture, TestRegistryFixture^ registryFixture) : BurnUnitTest(fixture)
46 {
47 this->testRegistry = registryFixture;
48 }
49
50 [Fact]
51 void CacheElevatedTempFallbacksTest()
52 {
53 HRESULT hr = S_OK;
54 BURN_CACHE cache = { };
55 BURN_ENGINE_COMMAND internalCommand = { };
56 HKEY hkSystemEnvironment = NULL;
57 HKEY hkBurnPolicy = NULL;
58
59 internalCommand.fInitiallyElevated = TRUE;
60
61 try
62 {
63 this->testRegistry->SetUp();
64
65 // No registry keys, so should fallback to %windir%\TEMP.
66 hr = CacheInitialize(&cache, &internalCommand);
67 NativeAssert::Succeeded(hr, "Failed to initialize cache.");
68 Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders);
69 VerifyBaseWorkingFolder(L"%windir%\\TEMP\\", cache.rgsczPotentialBaseWorkingFolders[0]);
70 CacheUninitialize(&cache);
71
72 hr = RegCreate(HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Session Manager\\Environment", GENERIC_WRITE, &hkSystemEnvironment);
73 NativeAssert::Succeeded(hr, "Failed to create system environment key.");
74
75 // Third fallback is system-level %TEMP%.
76 hr = RegWriteExpandString(hkSystemEnvironment, L"TEMP", L"A:\\TEST\\TEMP");
77 NativeAssert::Succeeded(hr, "Failed to write TEMP system environment value.");
78
79 hr = CacheInitialize(&cache, &internalCommand);
80 NativeAssert::Succeeded(hr, "Failed to initialize cache.");
81 Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders);
82 VerifyBaseWorkingFolder(L"A:\\TEST\\TEMP\\", cache.rgsczPotentialBaseWorkingFolders[0]);
83 CacheUninitialize(&cache);
84
85 // Second fallback is system-level %TMP%.
86 hr = RegWriteString(hkSystemEnvironment, L"TMP", L"B:\\TEST\\TMP\\");
87 NativeAssert::Succeeded(hr, "Failed to write TEMP system environment value.");
88
89 hr = CacheInitialize(&cache, &internalCommand);
90 NativeAssert::Succeeded(hr, "Failed to initialize cache.");
91 Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders);
92 VerifyBaseWorkingFolder(L"B:\\TEST\\TMP\\", cache.rgsczPotentialBaseWorkingFolders[0]);
93 CacheUninitialize(&cache);
94
95 // First fallback is impractical to mock out - %windir%\SystemTemp on Win11 when running as SYSTEM.
96
97 hr = RegCreate(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Policies\\WiX\\Burn", GENERIC_WRITE, &hkBurnPolicy);
98 NativeAssert::Succeeded(hr, "Failed to create Burn policy key.");
99
100 // Default source is Burn policy.
101 hr = RegWriteExpandString(hkBurnPolicy, L"EngineWorkingDirectory", L"D:\\TEST\\POLICY\\");
102 NativeAssert::Succeeded(hr, "Failed to write EngineWorkingDirectory Burn policy value.");
103
104 hr = CacheInitialize(&cache, &internalCommand);
105 NativeAssert::Succeeded(hr, "Failed to initialize cache.");
106 Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders);
107 VerifyBaseWorkingFolder(L"D:\\TEST\\POLICY\\", cache.rgsczPotentialBaseWorkingFolders[0]);
108 CacheUninitialize(&cache);
109
110 // Command line parameter overrides everything else.
111 hr = StrAllocString(&internalCommand.sczEngineWorkingDirectory, L"E:\\TEST\\COMMANDLINE\\", 0);
112 NativeAssert::Succeeded(hr, "Failed to copy command line working directory.");
113
114 hr = CacheInitialize(&cache, &internalCommand);
115 NativeAssert::Succeeded(hr, "Failed to initialize cache.");
116 Assert::NotEqual<DWORD>(0, cache.cPotentialBaseWorkingFolders);
117 VerifyBaseWorkingFolder(L"E:\\TEST\\COMMANDLINE\\", cache.rgsczPotentialBaseWorkingFolders[0]);
118 CacheUninitialize(&cache);
119 }
120 finally
121 {
122 ReleaseRegKey(hkBurnPolicy);
123 ReleaseRegKey(hkSystemEnvironment);
124 ReleaseStr(internalCommand.sczEngineWorkingDirectory);
125
126 CacheUninitialize(&cache);
127
128 this->testRegistry->TearDown();
129 }
130 }
131
132 void VerifyBaseWorkingFolder(LPCWSTR wzExpectedUnexpanded, LPCWSTR wzActual)
133 {
134 String^ expected = Environment::ExpandEnvironmentVariables(gcnew String(wzExpectedUnexpanded));
135 WixAssert::StringEqual(expected, gcnew String(wzActual), true);
136 }
137
138 [Fact]
139 void CacheSignatureTest()
140 {
141 HRESULT hr = S_OK;
142 BURN_CACHE cache = { };
143 BURN_ENGINE_COMMAND internalCommand = { };
144 BURN_PACKAGE package = { };
145 BURN_PAYLOAD payload = { };
146 LPWSTR sczPayloadPath = NULL;
147 BYTE* pb = NULL;
148 DWORD cb = NULL;
149 CACHE_TEST_CONTEXT context = { };
150
151 try
152 {
153 pin_ptr<const wchar_t> dataDirectory = PtrToStringChars(this->TestContext->TestDirectory);
154 hr = PathConcat(dataDirectory, L"TestData\\CacheTest\\CacheSignatureTest.File", &sczPayloadPath);
155 Assert::True(S_OK == hr, "Failed to get path to test file.");
156 Assert::True(FileExistsEx(sczPayloadPath, NULL), "Test file does not exist.");
157
158 hr = StrAllocHexDecode(L"25e61cd83485062b70713aebddd3fe4992826cb121466fddc8de3eacb1e42f39d4bdd8455d95eec8c9529ced4c0296ab861931fe2c86df2f2b4e8d259a6d9223", &pb, &cb);
159 Assert::Equal(S_OK, hr);
160
161 package.fPerMachine = FALSE;
162 package.sczCacheId = L"Bootstrapper.CacheTest.CacheSignatureTest";
163 payload.sczKey = L"CacheSignatureTest.PayloadKey";
164 payload.sczFilePath = L"CacheSignatureTest.File";
165 payload.pbHash = pb;
166 payload.cbHash = cb;
167 payload.qwFileSize = 27;
168 payload.verification = BURN_PAYLOAD_VERIFICATION_HASH;
169
170 hr = CacheInitialize(&cache, &internalCommand);
171 TestThrowOnFailure(hr, L"Failed initialize cache.");
172
173 hr = CacheCompletePayload(&cache, package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE, CacheTestEventRoutine, CacheTestProgressRoutine, &context);
174 Assert::Equal(S_OK, hr);
175 }
176 finally
177 {
178 ReleaseMem(pb);
179 ReleaseStr(sczPayloadPath);
180
181 String^ filePath = Path::Combine(Environment::GetFolderPath(Environment::SpecialFolder::LocalApplicationData), "Package Cache\\Bootstrapper.CacheTest.CacheSignatureTest\\CacheSignatureTest.File");
182 if (File::Exists(filePath))
183 {
184 File::SetAttributes(filePath, FileAttributes::Normal);
185 File::Delete(filePath);
186 }
187
188 CacheUninitialize(&cache);
189 }
190 }
191 };
192 }
193 }
194 }
195 }
196 }
197
198 static HRESULT CALLBACK CacheTestEventRoutine(
199 __in BURN_CACHE_MESSAGE* /*pMessage*/,
200 __in LPVOID /*pvContext*/
201 )
202 {
203 return S_OK;
204 }
205
206 static DWORD CALLBACK CacheTestProgressRoutine(
207 __in LARGE_INTEGER /*TotalFileSize*/,
208 __in LARGE_INTEGER /*TotalBytesTransferred*/,
209 __in LARGE_INTEGER /*StreamSize*/,
210 __in LARGE_INTEGER /*StreamBytesTransferred*/,
211 __in DWORD /*dwStreamNumber*/,
212 __in DWORD /*dwCallbackReason*/,
213 __in HANDLE /*hSourceFile*/,
214 __in HANDLE /*hDestinationFile*/,
215 __in_opt LPVOID /*lpData*/
216 )
217 {
218 return PROGRESS_QUIET;
219 }