aboutsummaryrefslogtreecommitdiff
path: root/src/test/BurnUnitTest/SearchTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/BurnUnitTest/SearchTest.cpp')
-rw-r--r--src/test/BurnUnitTest/SearchTest.cpp721
1 files changed, 721 insertions, 0 deletions
diff --git a/src/test/BurnUnitTest/SearchTest.cpp b/src/test/BurnUnitTest/SearchTest.cpp
new file mode 100644
index 00000000..d03db84c
--- /dev/null
+++ b/src/test/BurnUnitTest/SearchTest.cpp
@@ -0,0 +1,721 @@
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
6static INSTALLSTATE WINAPI MsiComponentSearchTest_MsiGetComponentPathW(
7 __in LPCWSTR szProduct,
8 __in LPCWSTR szComponent,
9 __out_ecount_opt(*pcchBuf) LPWSTR lpPathBuf,
10 __inout_opt LPDWORD pcchBuf
11 );
12static INSTALLSTATE WINAPI MsiComponentSearchTest_MsiLocateComponentW(
13 __in LPCWSTR szComponent,
14 __out_ecount_opt(*pcchBuf) LPWSTR lpPathBuf,
15 __inout_opt LPDWORD pcchBuf
16 );
17static UINT WINAPI MsiProductSearchTest_MsiGetProductInfoW(
18 __in LPCWSTR szProductCode,
19 __in LPCWSTR szProperty,
20 __out_ecount_opt(*pcchValue) LPWSTR szValue,
21 __inout_opt LPDWORD pcchValue
22 );
23static UINT WINAPI MsiProductSearchTest_MsiGetProductInfoExW(
24 __in LPCWSTR szProductCode,
25 __in_opt LPCWSTR szUserSid,
26 __in MSIINSTALLCONTEXT dwContext,
27 __in LPCWSTR szProperty,
28 __out_ecount_opt(*pcchValue) LPWSTR szValue,
29 __inout_opt LPDWORD pcchValue
30 );
31
32using namespace System;
33using namespace Xunit;
34using namespace Microsoft::Win32;
35
36namespace Microsoft
37{
38namespace Tools
39{
40namespace WindowsInstallerXml
41{
42namespace Test
43{
44namespace Bootstrapper
45{
46 public ref class SearchTest : BurnUnitTest
47 {
48 public:
49 [NamedFact]
50 void DirectorySearchTest()
51 {
52 HRESULT hr = S_OK;
53 IXMLDOMElement* pixeBundle = NULL;
54 BURN_VARIABLES variables = { };
55 BURN_SEARCHES searches = { };
56 try
57 {
58 hr = VariableInitialize(&variables);
59 TestThrowOnFailure(hr, L"Failed to initialize variables.");
60
61 pin_ptr<const WCHAR> wzDirectory1 = PtrToStringChars(this->TestContext->TestDirectory);
62 pin_ptr<const WCHAR> wzDirectory2 = PtrToStringChars(System::IO::Path::Combine(this->TestContext->TestDirectory, gcnew String(L"none")));
63
64 VariableSetStringHelper(&variables, L"Directory1", wzDirectory1);
65 VariableSetStringHelper(&variables, L"Directory2", wzDirectory2);
66
67 LPCWSTR wzDocument =
68 L"<Bundle>"
69 L" <DirectorySearch Id='Search1' Type='exists' Path='[Directory1]' Variable='Variable1' />"
70 L" <DirectorySearch Id='Search2' Type='exists' Path='[Directory2]' Variable='Variable2' />"
71 L"</Bundle>";
72
73 // load XML document
74 LoadBundleXmlHelper(wzDocument, &pixeBundle);
75
76 hr = SearchesParseFromXml(&searches, pixeBundle);
77 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
78
79 // execute searches
80 hr = SearchesExecute(&searches, &variables);
81 TestThrowOnFailure(hr, L"Failed to execute searches.");
82
83 // check variable values
84 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable1"));
85 Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable2"));
86 }
87 finally
88 {
89 ReleaseObject(pixeBundle);
90 VariablesUninitialize(&variables);
91 SearchesUninitialize(&searches);
92 }
93 }
94
95 [NamedFact]
96 void FileSearchTest()
97 {
98 HRESULT hr = S_OK;
99 IXMLDOMElement* pixeBundle = NULL;
100 BURN_VARIABLES variables = { };
101 BURN_SEARCHES searches = { };
102 ULARGE_INTEGER uliVersion = { };
103 try
104 {
105 hr = VariableInitialize(&variables);
106 TestThrowOnFailure(hr, L"Failed to initialize variables.");
107
108 pin_ptr<const WCHAR> wzFile1 = PtrToStringChars(System::IO::Path::Combine(this->TestContext->TestDirectory, gcnew String(L"none.txt")));
109 pin_ptr<const WCHAR> wzFile2 = PtrToStringChars(System::Reflection::Assembly::GetExecutingAssembly()->Location);
110
111 hr = FileVersion(wzFile2, &uliVersion.HighPart, &uliVersion.LowPart);
112 TestThrowOnFailure(hr, L"Failed to get DLL version.");
113
114 VariableSetStringHelper(&variables, L"File1", wzFile1);
115 VariableSetStringHelper(&variables, L"File2", wzFile2);
116
117 LPCWSTR wzDocument =
118 L"<Bundle>"
119 L" <FileSearch Id='Search1' Type='exists' Path='[File1]' Variable='Variable1' />"
120 L" <FileSearch Id='Search2' Type='exists' Path='[File2]' Variable='Variable2' />"
121 L" <FileSearch Id='Search3' Type='version' Path='[File2]' Variable='Variable3' />"
122 L"</Bundle>";
123
124 // load XML document
125 LoadBundleXmlHelper(wzDocument, &pixeBundle);
126
127 hr = SearchesParseFromXml(&searches, pixeBundle);
128 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
129
130 // execute searches
131 hr = SearchesExecute(&searches, &variables);
132 TestThrowOnFailure(hr, L"Failed to execute searches.");
133
134 // check variable values
135 Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable1"));
136 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable2"));
137 Assert::Equal(uliVersion.QuadPart, VariableGetVersionHelper(&variables, L"Variable3"));
138 }
139 finally
140 {
141 ReleaseObject(pixeBundle);
142 VariablesUninitialize(&variables);
143 SearchesUninitialize(&searches);
144 }
145 }
146
147 [NamedFact]
148 void RegistrySearchTest()
149 {
150 HRESULT hr = S_OK;
151 IXMLDOMElement* pixeBundle = NULL;
152 BURN_VARIABLES variables = { };
153 BURN_SEARCHES searches = { };
154 HKEY hkey32 = NULL;
155 HKEY hkey64 = NULL;
156 BOOL f64bitMachine = (nullptr != Environment::GetEnvironmentVariable("ProgramFiles(x86)"));
157
158 try
159 {
160 hr = VariableInitialize(&variables);
161 TestThrowOnFailure(hr, L"Failed to initialize variables.");
162
163 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), gcnew String(L"String"), gcnew String(L"String1 %TEMP%"), RegistryValueKind::String);
164 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), gcnew String(L"StringExpand"), gcnew String(L"String1 %TEMP%"), RegistryValueKind::ExpandString);
165 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), gcnew String(L"DWord"), 1, RegistryValueKind::DWord);
166 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), gcnew String(L"QWord"), 1ll, RegistryValueKind::QWord);
167 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), gcnew String(L"VersionString"), gcnew String(L"1.1.1.1"), RegistryValueKind::String);
168 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), gcnew String(L"VersionQWord"), MAKEQWORDVERSION(1,1,1,1), RegistryValueKind::QWord);
169 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\String"), nullptr, gcnew String(L"String1"), RegistryValueKind::String);
170 Registry::SetValue(gcnew String(L"HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Numeric"), nullptr, 1ll, RegistryValueKind::DWord);
171
172 if (f64bitMachine)
173 {
174 hr = RegCreate(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest\\Bitness\\", KEY_WRITE | KEY_WOW64_32KEY, &hkey32);
175 Assert::True(SUCCEEDED(hr));
176
177 hr = RegCreate(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest\\Bitness\\", KEY_WRITE | KEY_WOW64_64KEY, &hkey64);
178 Assert::True(SUCCEEDED(hr));
179
180 hr = RegWriteString(hkey64, L"TestStringSpecificToBitness", L"64-bit");
181 Assert::True(SUCCEEDED(hr));
182
183 hr = RegWriteString(hkey32, L"TestStringSpecificToBitness", L"32-bit");
184 Assert::True(SUCCEEDED(hr));
185 }
186
187 VariableSetStringHelper(&variables, L"MyKey", L"SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value");
188 VariableSetStringHelper(&variables, L"MyValue", L"String");
189
190 LPCWSTR wzDocument =
191 L"<Bundle>"
192 L" <RegistrySearch Id='Search1' Type='exists' Root='HKLM' Key='SOFTWARE\\Microsoft' Variable='Variable1' />"
193 L" <RegistrySearch Id='Search2' Type='exists' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\None' Variable='Variable2' />"
194 L" <RegistrySearch Id='Search3' Type='exists' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='None' Variable='Variable3' />"
195 L" <RegistrySearch Id='Search4' Type='exists' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='String' Variable='Variable4' />"
196 L" <RegistrySearch Id='Search5' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='String' Variable='Variable5' VariableType='string' />"
197 L" <RegistrySearch Id='Search6' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='String' Variable='Variable6' VariableType='string' ExpandEnvironment='no' />"
198 L" <RegistrySearch Id='Search7' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='String' Variable='Variable7' VariableType='string' ExpandEnvironment='yes' />"
199 L" <RegistrySearch Id='Search8' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='StringExpand' Variable='Variable8' VariableType='string' />"
200 L" <RegistrySearch Id='Search9' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='StringExpand' Variable='Variable9' VariableType='string' ExpandEnvironment='no' />"
201 L" <RegistrySearch Id='Search10' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='StringExpand' Variable='Variable10' VariableType='string' ExpandEnvironment='yes' />"
202 L" <RegistrySearch Id='Search11' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='DWord' Variable='Variable11' VariableType='numeric' />"
203 L" <RegistrySearch Id='Search12' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='QWord' Variable='Variable12' VariableType='numeric' />"
204 L" <RegistrySearch Id='Search13' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='VersionString' Variable='Variable13' VariableType='version' />"
205 L" <RegistrySearch Id='Search14' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value' Value='VersionQWord' Variable='Variable14' VariableType='version' />"
206 L" <RegistrySearch Id='Search15' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\String' Variable='Variable15' VariableType='string' />"
207 L" <RegistrySearch Id='Search16' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Numeric' Variable='Variable16' VariableType='numeric' />"
208 L" <RegistrySearch Id='Search17' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\None' Variable='Variable17' VariableType='numeric' />"
209 L" <RegistrySearch Id='Search18' Type='value' Root='HKCU' Key='SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Numeric' Value='None' Variable='Variable18' VariableType='numeric' />"
210 L" <RegistrySearch Id='Search19' Type='exists' Root='HKCU' Key='[MyKey]' Value='[MyValue]' Variable='Variable19' />"
211 L" <RegistrySearch Id='Search20' Type='value' Root='HKCU' Key='[MyKey]' Value='[MyValue]' Variable='Variable20' VariableType='string' />"
212 L" <RegistrySearch Id='Search21' Type='value' Root='HKCU' Key='SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest\\Bitness' Value='TestStringSpecificToBitness' Variable='Variable21' VariableType='string' Win64='no' />"
213 L" <RegistrySearch Id='Search22' Type='value' Root='HKCU' Key='SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest\\Bitness' Value='TestStringSpecificToBitness' Variable='Variable22' VariableType='string' Win64='yes' />"
214 L" <RegistrySearch Id='Search23' Type='exists' Root='HKU' Key='.DEFAULT\\Environment' Variable='Variable23' />"
215 L" <RegistrySearch Id='Search23' Type='exists' Root='HKU' Key='.DEFAULT\\System\\NetworkServiceSidSubkeyDoesNotExist' Variable='Variable24' />"
216 L" <RegistrySearch Id='Search24' Type='value' Root='HKCR' Key='.msi' Variable='Variable25' VariableType='string' />"
217 L"</Bundle>";
218
219 // load XML document
220 LoadBundleXmlHelper(wzDocument, &pixeBundle);
221
222 hr = SearchesParseFromXml(&searches, pixeBundle);
223 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
224
225 // execute searches
226 hr = SearchesExecute(&searches, &variables);
227 TestThrowOnFailure(hr, L"Failed to execute searches.");
228
229 // check variable values
230 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable1"));
231 Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable2"));
232 Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable3"));
233 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable4"));
234 Assert::Equal(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable5"));
235 Assert::Equal(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable6"));
236 Assert::Equal(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable7"));
237 Assert::Equal(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable8"));
238 Assert::Equal(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable9"));
239 Assert::NotEqual(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable10"));
240 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable11"));
241 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable12"));
242 Assert::Equal(MAKEQWORDVERSION(1,1,1,1), VariableGetVersionHelper(&variables, L"Variable13"));
243 Assert::Equal(MAKEQWORDVERSION(1,1,1,1), VariableGetVersionHelper(&variables, L"Variable14"));
244 Assert::Equal(gcnew String(L"String1"), VariableGetStringHelper(&variables, L"Variable15"));
245 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable16"));
246 Assert::False(VariableExistsHelper(&variables, L"Variable17"));
247 Assert::False(VariableExistsHelper(&variables, L"Variable18"));
248 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable19"));
249 Assert::Equal(gcnew String(L"String1 %TEMP%"), VariableGetStringHelper(&variables, L"Variable20"));
250 if (f64bitMachine)
251 {
252 Assert::Equal(gcnew String(L"32-bit"), VariableGetStringHelper(&variables, L"Variable21"));
253 Assert::Equal(gcnew String(L"64-bit"), VariableGetStringHelper(&variables, L"Variable22"));
254 }
255
256 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable23"));
257 Assert::Equal(0ll, VariableGetNumericHelper(&variables, L"Variable24"));
258 Assert::Equal(gcnew String(L"Msi.Package"), VariableGetStringHelper(&variables, L"Variable25"));
259 }
260 finally
261 {
262 ReleaseRegKey(hkey32);
263 ReleaseRegKey(hkey64);
264 ReleaseObject(pixeBundle);
265 VariablesUninitialize(&variables);
266 SearchesUninitialize(&searches);
267
268 Registry::CurrentUser->DeleteSubKeyTree(gcnew String(L"SOFTWARE\\Microsoft\\WiX_Burn_UnitTest"));
269 if (f64bitMachine)
270 {
271 RegDelete(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest\\Bitness", REG_KEY_32BIT, FALSE);
272 RegDelete(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest", REG_KEY_32BIT, FALSE);
273 RegDelete(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest\\Bitness", REG_KEY_64BIT, FALSE);
274 RegDelete(HKEY_CURRENT_USER, L"SOFTWARE\\Classes\\CLSID\\WiX_Burn_UnitTest", REG_KEY_64BIT, FALSE);
275 }
276 }
277 }
278
279 [NamedFact]
280 void MsiComponentSearchTest()
281 {
282 HRESULT hr = S_OK;
283 IXMLDOMElement* pixeBundle = NULL;
284 BURN_VARIABLES variables = { };
285 BURN_SEARCHES searches = { };
286 try
287 {
288 hr = VariableInitialize(&variables);
289 TestThrowOnFailure(hr, L"Failed to initialize variables.");
290
291 // set mock API's
292 WiuFunctionOverride(NULL, MsiComponentSearchTest_MsiGetComponentPathW, MsiComponentSearchTest_MsiLocateComponentW, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
293
294 LPCWSTR wzDocument =
295 L"<Bundle>"
296 L" <MsiComponentSearch Id='Search1' Type='state' ComponentId='{BAD00000-1000-0000-0000-000000000000}' Variable='Variable1' />"
297 L" <MsiComponentSearch Id='Search2' Type='state' ProductCode='{BAD00000-0000-0000-0000-000000000000}' ComponentId='{BAD00000-1000-0000-0000-000000000000}' Variable='Variable2' />"
298 L" <MsiComponentSearch Id='Search3' Type='state' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{BAD00000-1000-0000-0000-000000000000}' Variable='Variable3' />"
299 L" <MsiComponentSearch Id='Search4' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-1000-0000-000000000000}' Variable='Variable4' />"
300 L" <MsiComponentSearch Id='Search5' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-2000-0000-000000000000}' Variable='Variable5' />"
301 L" <MsiComponentSearch Id='Search6' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-3000-0000-000000000000}' Variable='Variable6' />"
302 L" <MsiComponentSearch Id='Search7' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-4000-0000-000000000000}' Variable='Variable7' />"
303 L" <MsiComponentSearch Id='Search8' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-5000-0000-000000000000}' Variable='Variable8' />"
304 L" <MsiComponentSearch Id='Search9' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-6000-0000-000000000000}' Variable='Variable9' />" // todo: value key path
305 L" <MsiComponentSearch Id='Search10' Type='state' ComponentId='{600D0000-1000-1000-0000-000000000000}' Variable='Variable10' />"
306 L" <MsiComponentSearch Id='Search11' Type='state' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-1000-0000-000000000000}' Variable='Variable11' />"
307 L" <MsiComponentSearch Id='Search12' Type='state' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-2000-0000-000000000000}' Variable='Variable12' />"
308 L" <MsiComponentSearch Id='Search13' Type='state' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-3000-0000-000000000000}' Variable='Variable13' />"
309 L" <MsiComponentSearch Id='Search14' Type='state' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-4000-0000-000000000000}' Variable='Variable14' />"
310 L" <MsiComponentSearch Id='Search15' Type='directory' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-1000-0000-000000000000}' Variable='Variable15' />"
311 L" <MsiComponentSearch Id='Search16' Type='directory' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-2000-0000-000000000000}' Variable='Variable16' />"
312 L" <MsiComponentSearch Id='Search17' Type='directory' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-3000-0000-000000000000}' Variable='Variable17' />"
313 L" <MsiComponentSearch Id='Search18' Type='directory' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-4000-0000-000000000000}' Variable='Variable18' />"
314 L" <MsiComponentSearch Id='Search19' Type='keyPath' ProductCode='{600D0000-0000-0000-0000-000000000000}' ComponentId='{600D0000-1000-7000-0000-000000000000}' Variable='Variable19' />"
315 L"</Bundle>";
316
317 // load XML document
318 LoadBundleXmlHelper(wzDocument, &pixeBundle);
319
320 hr = SearchesParseFromXml(&searches, pixeBundle);
321 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
322
323 // execute searches
324 hr = SearchesExecute(&searches, &variables);
325 TestThrowOnFailure(hr, L"Failed to execute searches.");
326
327 // check variable values
328 Assert::Equal(2ll, VariableGetNumericHelper(&variables, L"Variable1"));
329 Assert::Equal(2ll, VariableGetNumericHelper(&variables, L"Variable2"));
330 Assert::Equal(2ll, VariableGetNumericHelper(&variables, L"Variable3"));
331 Assert::Equal(gcnew String(L"C:\\directory\\file1.txt"), VariableGetStringHelper(&variables, L"Variable4"));
332 Assert::Equal(gcnew String(L"C:\\directory\\file2.txt"), VariableGetStringHelper(&variables, L"Variable5"));
333 Assert::Equal(gcnew String(L"C:\\directory\\file3.txt"), VariableGetStringHelper(&variables, L"Variable6"));
334 Assert::Equal(gcnew String(L"C:\\directory\\file4.txt"), VariableGetStringHelper(&variables, L"Variable7"));
335 Assert::Equal(gcnew String(L"02:\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\"), VariableGetStringHelper(&variables, L"Variable8"));
336 Assert::Equal(gcnew String(L"02:\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value"), VariableGetStringHelper(&variables, L"Variable9"));
337 Assert::Equal(3ll, VariableGetNumericHelper(&variables, L"Variable10"));
338 Assert::Equal(3ll, VariableGetNumericHelper(&variables, L"Variable11"));
339 Assert::Equal(4ll, VariableGetNumericHelper(&variables, L"Variable12"));
340 Assert::Equal(4ll, VariableGetNumericHelper(&variables, L"Variable13"));
341 Assert::Equal(2ll, VariableGetNumericHelper(&variables, L"Variable14"));
342 Assert::Equal(gcnew String(L"C:\\directory\\"), VariableGetStringHelper(&variables, L"Variable15"));
343 Assert::Equal(gcnew String(L"C:\\directory\\"), VariableGetStringHelper(&variables, L"Variable16"));
344 Assert::Equal(gcnew String(L"C:\\directory\\"), VariableGetStringHelper(&variables, L"Variable17"));
345 Assert::Equal(gcnew String(L"C:\\directory\\"), VariableGetStringHelper(&variables, L"Variable18"));
346 Assert::Equal(gcnew String(L"C:\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\file5.txt"), VariableGetStringHelper(&variables, L"Variable19"));
347 }
348 finally
349 {
350 ReleaseObject(pixeBundle);
351 VariablesUninitialize(&variables);
352 SearchesUninitialize(&searches);
353 }
354 }
355
356 [NamedFact]
357 void MsiProductSearchTest()
358 {
359 HRESULT hr = S_OK;
360 IXMLDOMElement* pixeBundle = NULL;
361 BURN_VARIABLES variables = { };
362 BURN_SEARCHES searches = { };
363 try
364 {
365 hr = VariableInitialize(&variables);
366 TestThrowOnFailure(hr, L"Failed to initialize variables.");
367
368 // set mock API's
369 WiuFunctionOverride(NULL, NULL, NULL, NULL, MsiProductSearchTest_MsiGetProductInfoW, MsiProductSearchTest_MsiGetProductInfoExW, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
370
371 LPCWSTR wzDocument =
372 L"<Bundle>"
373 L" <MsiProductSearch Id='Search1' Type='state' ProductCode='{BAD00000-0000-0000-0000-000000000000}' Variable='Variable1' />"
374 L" <MsiProductSearch Id='Search2' Type='version' ProductCode='{600D0000-0000-0000-0000-000000000000}' Variable='Variable2' />"
375 L" <MsiProductSearch Id='Search3' Type='language' ProductCode='{600D0000-0000-0000-0000-000000000000}' Variable='Variable3' />"
376 L" <MsiProductSearch Id='Search4' Type='state' ProductCode='{600D0000-0000-0000-0000-000000000000}' Variable='Variable4' />"
377 L" <MsiProductSearch Id='Search5' Type='assignment' ProductCode='{600D0000-0000-0000-0000-000000000000}' Variable='Variable5' />"
378 L" <MsiProductSearch Id='Search6' Type='version' ProductCode='{600D0000-1000-0000-0000-000000000000}' Variable='Variable6' />"
379 L"</Bundle>";
380
381 // load XML document
382 LoadBundleXmlHelper(wzDocument, &pixeBundle);
383
384 hr = SearchesParseFromXml(&searches, pixeBundle);
385 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
386
387 // execute searches
388 hr = SearchesExecute(&searches, &variables);
389 TestThrowOnFailure(hr, L"Failed to execute searches.");
390
391 // check variable values
392 Assert::Equal(2ll, VariableGetNumericHelper(&variables, L"Variable1"));
393 Assert::Equal(MAKEQWORDVERSION(1,0,0,0), VariableGetVersionHelper(&variables, L"Variable2"));
394 Assert::Equal(1033ll, VariableGetNumericHelper(&variables, L"Variable3"));
395 Assert::Equal(5ll, VariableGetNumericHelper(&variables, L"Variable4"));
396 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable5"));
397 Assert::Equal(MAKEQWORDVERSION(1,0,0,0), VariableGetVersionHelper(&variables, L"Variable6"));
398 }
399 finally
400 {
401 ReleaseObject(pixeBundle);
402 VariablesUninitialize(&variables);
403 SearchesUninitialize(&searches);
404 }
405 }
406
407 [NamedFact]
408 void MsiFeatureSearchTest()
409 {
410 HRESULT hr = S_OK;
411 IXMLDOMElement* pixeBundle = NULL;
412 BURN_VARIABLES variables = { };
413 BURN_SEARCHES searches = { };
414 try
415 {
416 LPCWSTR wzDocument =
417 L"<Bundle>"
418 L" <MsiFeatureSearch Id='Search1' Type='state' ProductCode='{BAD00000-0000-0000-0000-000000000000}' FeatureId='' Variable='Variable1' />"
419 L"</Bundle>";
420
421 hr = VariableInitialize(&variables);
422 TestThrowOnFailure(hr, L"Failed to initialize variables.");
423
424 // load XML document
425 LoadBundleXmlHelper(wzDocument, &pixeBundle);
426
427 hr = SearchesParseFromXml(&searches, pixeBundle);
428 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
429
430 // execute searches
431 hr = SearchesExecute(&searches, &variables);
432 TestThrowOnFailure(hr, L"Failed to execute searches.");
433 }
434 finally
435 {
436 ReleaseObject(pixeBundle);
437 VariablesUninitialize(&variables);
438 SearchesUninitialize(&searches);
439 }
440 }
441
442 [NamedFact]
443 void ConditionalSearchTest()
444 {
445 HRESULT hr = S_OK;
446 IXMLDOMElement* pixeBundle = NULL;
447 BURN_VARIABLES variables = { };
448 BURN_SEARCHES searches = { };
449 try
450 {
451 LPCWSTR wzDocument =
452 L"<Bundle>"
453 L" <RegistrySearch Id='Search1' Type='exists' Root='HKLM' Key='SOFTWARE\\Microsoft' Variable='Variable1' Condition='0' />"
454 L" <RegistrySearch Id='Search2' Type='exists' Root='HKLM' Key='SOFTWARE\\Microsoft' Variable='Variable2' Condition='1' />"
455 L" <RegistrySearch Id='Search3' Type='exists' Root='HKLM' Key='SOFTWARE\\Microsoft' Variable='Variable3' Condition='=' />"
456 L"</Bundle>";
457
458 hr = VariableInitialize(&variables);
459 TestThrowOnFailure(hr, L"Failed to initialize variables.");
460
461 // load XML document
462 LoadBundleXmlHelper(wzDocument, &pixeBundle);
463
464 hr = SearchesParseFromXml(&searches, pixeBundle);
465 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
466
467 // execute searches
468 hr = SearchesExecute(&searches, &variables);
469 TestThrowOnFailure(hr, L"Failed to execute searches.");
470
471 // check variable values
472 Assert::False(VariableExistsHelper(&variables, L"Variable1"));
473 Assert::Equal(1ll, VariableGetNumericHelper(&variables, L"Variable2"));
474 Assert::False(VariableExistsHelper(&variables, L"Variable3"));
475 }
476 finally
477 {
478 ReleaseObject(pixeBundle);
479 VariablesUninitialize(&variables);
480 SearchesUninitialize(&searches);
481 }
482 }
483 [NamedFact]
484 void NoSearchesTest()
485 {
486 HRESULT hr = S_OK;
487 IXMLDOMElement* pixeBundle = NULL;
488 BURN_VARIABLES variables = { };
489 BURN_SEARCHES searches = { };
490 try
491 {
492 LPCWSTR wzDocument =
493 L"<Bundle>"
494 L"</Bundle>";
495
496 hr = VariableInitialize(&variables);
497 TestThrowOnFailure(hr, L"Failed to initialize variables.");
498
499 // load XML document
500 LoadBundleXmlHelper(wzDocument, &pixeBundle);
501
502 hr = SearchesParseFromXml(&searches, pixeBundle);
503 TestThrowOnFailure(hr, L"Failed to parse searches from XML.");
504
505 // execute searches
506 hr = SearchesExecute(&searches, &variables);
507 TestThrowOnFailure(hr, L"Failed to execute searches.");
508 }
509 finally
510 {
511 ReleaseObject(pixeBundle);
512 VariablesUninitialize(&variables);
513 SearchesUninitialize(&searches);
514 }
515 }
516 };
517}
518}
519}
520}
521}
522
523
524static INSTALLSTATE WINAPI MsiComponentSearchTest_MsiGetComponentPathW(
525 __in LPCWSTR szProduct,
526 __in LPCWSTR szComponent,
527 __out_ecount_opt(*pcchBuf) LPWSTR lpPathBuf,
528 __inout_opt LPDWORD pcchBuf
529 )
530{
531 INSTALLSTATE is = INSTALLSTATE_INVALIDARG;
532 String^ product = gcnew String(szProduct);
533
534 if (String::Equals(product, gcnew String(L"{BAD00000-0000-0000-0000-000000000000}")))
535 {
536 is = INSTALLSTATE_UNKNOWN;
537 }
538 else if (String::Equals(product, gcnew String(L"{600D0000-0000-0000-0000-000000000000}")))
539 {
540 is = MsiComponentSearchTest_MsiLocateComponentW(szComponent, lpPathBuf, pcchBuf);
541 }
542
543 return is;
544}
545
546static INSTALLSTATE WINAPI MsiComponentSearchTest_MsiLocateComponentW(
547 __in LPCWSTR szComponent,
548 __out_ecount_opt(*pcchBuf) LPWSTR lpPathBuf,
549 __inout_opt LPDWORD pcchBuf
550 )
551{
552 HRESULT hr = S_OK;
553 INSTALLSTATE is = INSTALLSTATE_INVALIDARG;
554 String^ component = gcnew String(szComponent);
555 LPCWSTR wzValue = NULL;
556
557 if (String::Equals(component, gcnew String(L"{BAD00000-1000-0000-0000-000000000000}")))
558 {
559 is = INSTALLSTATE_UNKNOWN;
560 }
561 else if (String::Equals(component, gcnew String(L"{600D0000-1000-1000-0000-000000000000}")))
562 {
563 wzValue = L"C:\\directory\\file1.txt";
564 is = INSTALLSTATE_LOCAL;
565 }
566 else if (String::Equals(component, gcnew String(L"{600D0000-1000-2000-0000-000000000000}")))
567 {
568 wzValue = L"C:\\directory\\file2.txt";
569 is = INSTALLSTATE_SOURCE;
570 }
571 else if (String::Equals(component, gcnew String(L"{600D0000-1000-3000-0000-000000000000}")))
572 {
573 wzValue = L"C:\\directory\\file3.txt";
574 is = INSTALLSTATE_SOURCEABSENT;
575 }
576 else if (String::Equals(component, gcnew String(L"{600D0000-1000-4000-0000-000000000000}")))
577 {
578 wzValue = L"C:\\directory\\file4.txt";
579 is = INSTALLSTATE_ABSENT;
580 }
581 else if (String::Equals(component, gcnew String(L"{600D0000-1000-5000-0000-000000000000}")))
582 {
583 wzValue = L"02:\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\";
584 is = INSTALLSTATE_LOCAL;
585 }
586 else if (String::Equals(component, gcnew String(L"{600D0000-1000-6000-0000-000000000000}")))
587 {
588 wzValue = L"02:\\SOFTWARE\\Microsoft\\WiX_Burn_UnitTest\\Value";
589 is = INSTALLSTATE_LOCAL;
590 }
591 else if (String::Equals(component, gcnew String(L"{600D0000-1000-7000-0000-000000000000}")))
592 {
593 wzValue = L"C:\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\directory\\file5.txt";
594 is = INSTALLSTATE_ABSENT;
595 }
596
597 if (wzValue && lpPathBuf)
598 {
599 hr = ::StringCchCopyW(lpPathBuf, *pcchBuf, wzValue);
600 if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
601 {
602 *pcchBuf = lstrlenW(wzValue);
603 is = INSTALLSTATE_MOREDATA;
604 }
605 else if (FAILED(hr))
606 {
607 is = INSTALLSTATE_INVALIDARG;
608 }
609 }
610
611 return is;
612}
613
614static UINT WINAPI MsiProductSearchTest_MsiGetProductInfoW(
615 __in LPCWSTR szProductCode,
616 __in LPCWSTR szProperty,
617 __out_ecount_opt(*pcchValue) LPWSTR szValue,
618 __inout_opt LPDWORD pcchValue
619 )
620{
621 if (String::Equals(gcnew String(szProductCode), gcnew String(L"{600D0000-0000-0000-0000-000000000000}")) &&
622 String::Equals(gcnew String(szProperty), gcnew String(INSTALLPROPERTY_PRODUCTSTATE)))
623 {
624 // force call to WiuGetProductInfoEx
625 return ERROR_UNKNOWN_PROPERTY;
626 }
627
628 UINT er = MsiProductSearchTest_MsiGetProductInfoExW(szProductCode, NULL, MSIINSTALLCONTEXT_MACHINE, szProperty, szValue, pcchValue);
629 return er;
630}
631
632static UINT WINAPI MsiProductSearchTest_MsiGetProductInfoExW(
633 __in LPCWSTR szProductCode,
634 __in_opt LPCWSTR /*szUserSid*/,
635 __in MSIINSTALLCONTEXT dwContext,
636 __in LPCWSTR szProperty,
637 __out_ecount_opt(*pcchValue) LPWSTR szValue,
638 __inout_opt LPDWORD pcchValue
639 )
640{
641 HRESULT hr = S_OK;
642 DWORD er = ERROR_FUNCTION_FAILED;
643 LPCWSTR wzValue = NULL;
644
645 String^ productCode = gcnew String(szProductCode);
646 String^ _property = gcnew String(szProperty);
647 switch (dwContext)
648 {
649 case MSIINSTALLCONTEXT_USERMANAGED:
650 er = ERROR_UNKNOWN_PRODUCT;
651 break;
652 case MSIINSTALLCONTEXT_USERUNMANAGED:
653 if (String::Equals(productCode, gcnew String(L"{600D0000-0000-0000-0000-000000000000}")))
654 {
655 if (String::Equals(_property, gcnew String(INSTALLPROPERTY_PRODUCTSTATE)))
656 {
657 wzValue = L"5";
658 }
659 }
660 break;
661 case MSIINSTALLCONTEXT_MACHINE:
662 if (String::Equals(productCode, gcnew String(L"{BAD00000-0000-0000-0000-000000000000}")))
663 {
664 er = ERROR_UNKNOWN_PRODUCT;
665 }
666 else if (String::Equals(productCode, gcnew String(L"{600D0000-0000-0000-0000-000000000000}")))
667 {
668 if (String::Equals(_property, gcnew String(INSTALLPROPERTY_VERSIONSTRING)))
669 {
670 wzValue = L"1.0.0.0";
671 }
672 else if (String::Equals(_property, gcnew String(INSTALLPROPERTY_LANGUAGE)))
673 {
674 wzValue = L"1033";
675 }
676 else if (String::Equals(_property, gcnew String(INSTALLPROPERTY_ASSIGNMENTTYPE)))
677 {
678 wzValue = L"1";
679 }
680 else if (String::Equals(_property, gcnew String(INSTALLPROPERTY_PRODUCTSTATE)))
681 {
682 // try again in per-user context
683 er = ERROR_UNKNOWN_PRODUCT;
684 }
685 }
686 else if (String::Equals(productCode, gcnew String(L"{600D0000-1000-0000-0000-000000000000}")))
687 {
688 static BOOL fFlipp = FALSE;
689 if (fFlipp)
690 {
691 if (String::Equals(_property, gcnew String(INSTALLPROPERTY_VERSIONSTRING)))
692 {
693 wzValue = L"1.0.0.0";
694 }
695 }
696 else
697 {
698 *pcchValue = MAX_PATH * 2;
699 er = ERROR_MORE_DATA;
700 }
701 fFlipp = !fFlipp;
702 }
703 break;
704 }
705
706 if (wzValue)
707 {
708 hr = ::StringCchCopyW(szValue, *pcchValue, wzValue);
709 if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
710 {
711 *pcchValue = lstrlenW(wzValue);
712 er = ERROR_MORE_DATA;
713 }
714 else if (SUCCEEDED(hr))
715 {
716 er = ERROR_SUCCESS;
717 }
718 }
719
720 return er;
721}