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