diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2018-12-29 14:33:39 -0600 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2018-12-29 14:37:50 -0600 |
commit | 88cd76dbbcce061f80e234489bc18450f56a6e77 (patch) | |
tree | 411572481b0854166836b46e0fa8d80ffb8db82f | |
parent | 8f18a68edca97a944b2fbfeab7a41596b159f146 (diff) | |
download | wix-88cd76dbbcce061f80e234489bc18450f56a6e77.tar.gz wix-88cd76dbbcce061f80e234489bc18450f56a6e77.tar.bz2 wix-88cd76dbbcce061f80e234489bc18450f56a6e77.zip |
Import deputil from old v4 repo.
-rw-r--r-- | src/dutil/deputil.cpp | 688 | ||||
-rw-r--r-- | src/dutil/dutil.vcxproj | 2 | ||||
-rw-r--r-- | src/dutil/inc/deputil.h | 147 | ||||
-rw-r--r-- | src/dutil/precomp.h | 1 |
4 files changed, 838 insertions, 0 deletions
diff --git a/src/dutil/deputil.cpp b/src/dutil/deputil.cpp new file mode 100644 index 00000000..b2db0dd6 --- /dev/null +++ b/src/dutil/deputil.cpp | |||
@@ -0,0 +1,688 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | #define ARRAY_GROWTH_SIZE 5 | ||
6 | |||
7 | static LPCWSTR vcszVersionValue = L"Version"; | ||
8 | static LPCWSTR vcszDisplayNameValue = L"DisplayName"; | ||
9 | static LPCWSTR vcszMinVersionValue = L"MinVersion"; | ||
10 | static LPCWSTR vcszMaxVersionValue = L"MaxVersion"; | ||
11 | static LPCWSTR vcszAttributesValue = L"Attributes"; | ||
12 | |||
13 | enum eRequiresAttributes { RequiresAttributesMinVersionInclusive = 256, RequiresAttributesMaxVersionInclusive = 512 }; | ||
14 | |||
15 | // We write to Software\Classes explicitly based on the current security context instead of HKCR. | ||
16 | // See http://msdn.microsoft.com/en-us/library/ms724475(VS.85).aspx for more information. | ||
17 | static LPCWSTR vsczRegistryRoot = L"Software\\Classes\\Installer\\Dependencies\\"; | ||
18 | static LPCWSTR vsczRegistryDependents = L"Dependents"; | ||
19 | |||
20 | static HRESULT AllocDependencyKeyName( | ||
21 | __in_z LPCWSTR wzName, | ||
22 | __deref_out_z LPWSTR* psczKeyName | ||
23 | ); | ||
24 | |||
25 | static HRESULT GetDependencyNameFromKey( | ||
26 | __in HKEY hkHive, | ||
27 | __in LPCWSTR wzKey, | ||
28 | __deref_out_z LPWSTR* psczName | ||
29 | ); | ||
30 | |||
31 | DAPI_(HRESULT) DepGetProviderInformation( | ||
32 | __in HKEY hkHive, | ||
33 | __in_z LPCWSTR wzProviderKey, | ||
34 | __deref_out_z_opt LPWSTR* psczId, | ||
35 | __deref_out_z_opt LPWSTR* psczName, | ||
36 | __out_opt DWORD64* pqwVersion | ||
37 | ) | ||
38 | { | ||
39 | HRESULT hr = S_OK; | ||
40 | LPWSTR sczKey = NULL; | ||
41 | HKEY hkKey = NULL; | ||
42 | |||
43 | // Format the provider dependency registry key. | ||
44 | hr = AllocDependencyKeyName(wzProviderKey, &sczKey); | ||
45 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzProviderKey); | ||
46 | |||
47 | // Try to open the dependency key. | ||
48 | hr = RegOpen(hkHive, sczKey, KEY_READ, &hkKey); | ||
49 | if (E_FILENOTFOUND == hr) | ||
50 | { | ||
51 | ExitFunction1(hr = E_NOTFOUND); | ||
52 | } | ||
53 | ExitOnFailure(hr, "Failed to open the registry key for the dependency \"%ls\".", wzProviderKey); | ||
54 | |||
55 | // Get the Id if requested and available. | ||
56 | if (psczId) | ||
57 | { | ||
58 | hr = RegReadString(hkKey, NULL, psczId); | ||
59 | if (E_FILENOTFOUND == hr) | ||
60 | { | ||
61 | hr = S_OK; | ||
62 | } | ||
63 | ExitOnFailure(hr, "Failed to get the id for the dependency \"%ls\".", wzProviderKey); | ||
64 | } | ||
65 | |||
66 | // Get the DisplayName if requested and available. | ||
67 | if (psczName) | ||
68 | { | ||
69 | hr = RegReadString(hkKey, vcszDisplayNameValue, psczName); | ||
70 | if (E_FILENOTFOUND == hr) | ||
71 | { | ||
72 | hr = S_OK; | ||
73 | } | ||
74 | ExitOnFailure(hr, "Failed to get the name for the dependency \"%ls\".", wzProviderKey); | ||
75 | } | ||
76 | |||
77 | // Get the Version if requested and available. | ||
78 | if (pqwVersion) | ||
79 | { | ||
80 | hr = RegReadVersion(hkKey, vcszVersionValue, pqwVersion); | ||
81 | if (E_FILENOTFOUND == hr) | ||
82 | { | ||
83 | hr = S_OK; | ||
84 | } | ||
85 | ExitOnFailure(hr, "Failed to get the version for the dependency \"%ls\".", wzProviderKey); | ||
86 | } | ||
87 | |||
88 | LExit: | ||
89 | ReleaseRegKey(hkKey); | ||
90 | ReleaseStr(sczKey); | ||
91 | |||
92 | return hr; | ||
93 | } | ||
94 | |||
95 | DAPI_(HRESULT) DepCheckDependency( | ||
96 | __in HKEY hkHive, | ||
97 | __in_z LPCWSTR wzProviderKey, | ||
98 | __in_z_opt LPCWSTR wzMinVersion, | ||
99 | __in_z_opt LPCWSTR wzMaxVersion, | ||
100 | __in int iAttributes, | ||
101 | __in STRINGDICT_HANDLE sdDependencies, | ||
102 | __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, | ||
103 | __inout LPUINT pcDependencies | ||
104 | ) | ||
105 | { | ||
106 | HRESULT hr = S_OK; | ||
107 | LPWSTR sczKey = NULL; | ||
108 | HKEY hkKey = NULL; | ||
109 | DWORD64 dw64Version = 0; | ||
110 | int cchMinVersion = 0; | ||
111 | DWORD64 dw64MinVersion = 0; | ||
112 | int cchMaxVersion = 0; | ||
113 | DWORD64 dw64MaxVersion = 0; | ||
114 | BOOL fAllowEqual = FALSE; | ||
115 | LPWSTR sczName = NULL; | ||
116 | |||
117 | // Format the provider dependency registry key. | ||
118 | hr = AllocDependencyKeyName(wzProviderKey, &sczKey); | ||
119 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzProviderKey); | ||
120 | |||
121 | // Try to open the key. If that fails, add the missing dependency key to the dependency array if it doesn't already exist. | ||
122 | hr = RegOpen(hkHive, sczKey, KEY_READ, &hkKey); | ||
123 | if (E_FILENOTFOUND != hr) | ||
124 | { | ||
125 | ExitOnFailure(hr, "Failed to open the registry key for dependency \"%ls\".", wzProviderKey); | ||
126 | |||
127 | // If there are no registry values, consider the key orphaned and treat it as missing. | ||
128 | hr = RegReadVersion(hkKey, vcszVersionValue, &dw64Version); | ||
129 | if (E_FILENOTFOUND != hr) | ||
130 | { | ||
131 | ExitOnFailure(hr, "Failed to read the %ls registry value for dependency \"%ls\".", vcszVersionValue, wzProviderKey); | ||
132 | } | ||
133 | } | ||
134 | |||
135 | // If the key was not found or the Version value was not found, add the missing dependency key to the dependency array. | ||
136 | if (E_FILENOTFOUND == hr) | ||
137 | { | ||
138 | hr = DictKeyExists(sdDependencies, wzProviderKey); | ||
139 | if (E_NOTFOUND != hr) | ||
140 | { | ||
141 | ExitOnFailure(hr, "Failed to check the dictionary for missing dependency \"%ls\".", wzProviderKey); | ||
142 | } | ||
143 | else | ||
144 | { | ||
145 | hr = DepDependencyArrayAlloc(prgDependencies, pcDependencies, wzProviderKey, NULL); | ||
146 | ExitOnFailure(hr, "Failed to add the missing dependency \"%ls\" to the array.", wzProviderKey); | ||
147 | |||
148 | hr = DictAddKey(sdDependencies, wzProviderKey); | ||
149 | ExitOnFailure(hr, "Failed to add the missing dependency \"%ls\" to the dictionary.", wzProviderKey); | ||
150 | } | ||
151 | |||
152 | // Exit since the check already failed. | ||
153 | ExitFunction1(hr = E_NOTFOUND); | ||
154 | } | ||
155 | |||
156 | // Check MinVersion if provided. | ||
157 | if (wzMinVersion) | ||
158 | { | ||
159 | cchMinVersion = lstrlenW(wzMinVersion); | ||
160 | if (0 < cchMinVersion) | ||
161 | { | ||
162 | hr = FileVersionFromStringEx(wzMinVersion, cchMinVersion, &dw64MinVersion); | ||
163 | ExitOnFailure(hr, "Failed to get the 64-bit version number from \"%ls\".", wzMinVersion); | ||
164 | |||
165 | fAllowEqual = iAttributes & RequiresAttributesMinVersionInclusive; | ||
166 | if (!(fAllowEqual && dw64MinVersion <= dw64Version || dw64MinVersion < dw64Version)) | ||
167 | { | ||
168 | hr = DictKeyExists(sdDependencies, wzProviderKey); | ||
169 | if (E_NOTFOUND != hr) | ||
170 | { | ||
171 | ExitOnFailure(hr, "Failed to check the dictionary for the older dependency \"%ls\".", wzProviderKey); | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | hr = RegReadString(hkKey, vcszDisplayNameValue, &sczName); | ||
176 | ExitOnFailure(hr, "Failed to get the display name of the older dependency \"%ls\".", wzProviderKey); | ||
177 | |||
178 | hr = DepDependencyArrayAlloc(prgDependencies, pcDependencies, wzProviderKey, sczName); | ||
179 | ExitOnFailure(hr, "Failed to add the older dependency \"%ls\" to the dependencies array.", wzProviderKey); | ||
180 | |||
181 | hr = DictAddKey(sdDependencies, wzProviderKey); | ||
182 | ExitOnFailure(hr, "Failed to add the older dependency \"%ls\" to the unique dependency string list.", wzProviderKey); | ||
183 | } | ||
184 | |||
185 | // Exit since the check already failed. | ||
186 | ExitFunction1(hr = E_NOTFOUND); | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | // Check MaxVersion if provided. | ||
192 | if (wzMaxVersion) | ||
193 | { | ||
194 | cchMaxVersion = lstrlenW(wzMaxVersion); | ||
195 | if (0 < cchMaxVersion) | ||
196 | { | ||
197 | hr = FileVersionFromStringEx(wzMaxVersion, cchMaxVersion, &dw64MaxVersion); | ||
198 | ExitOnFailure(hr, "Failed to get the 64-bit version number from \"%ls\".", wzMaxVersion); | ||
199 | |||
200 | fAllowEqual = iAttributes & RequiresAttributesMaxVersionInclusive; | ||
201 | if (!(fAllowEqual && dw64Version <= dw64MaxVersion || dw64Version < dw64MaxVersion)) | ||
202 | { | ||
203 | hr = DictKeyExists(sdDependencies, wzProviderKey); | ||
204 | if (E_NOTFOUND != hr) | ||
205 | { | ||
206 | ExitOnFailure(hr, "Failed to check the dictionary for the newer dependency \"%ls\".", wzProviderKey); | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | hr = RegReadString(hkKey, vcszDisplayNameValue, &sczName); | ||
211 | ExitOnFailure(hr, "Failed to get the display name of the newer dependency \"%ls\".", wzProviderKey); | ||
212 | |||
213 | hr = DepDependencyArrayAlloc(prgDependencies, pcDependencies, wzProviderKey, sczName); | ||
214 | ExitOnFailure(hr, "Failed to add the newer dependency \"%ls\" to the dependencies array.", wzProviderKey); | ||
215 | |||
216 | hr = DictAddKey(sdDependencies, wzProviderKey); | ||
217 | ExitOnFailure(hr, "Failed to add the newer dependency \"%ls\" to the unique dependency string list.", wzProviderKey); | ||
218 | } | ||
219 | |||
220 | // Exit since the check already failed. | ||
221 | ExitFunction1(hr = E_NOTFOUND); | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | |||
226 | LExit: | ||
227 | ReleaseStr(sczName); | ||
228 | ReleaseRegKey(hkKey); | ||
229 | ReleaseStr(sczKey); | ||
230 | |||
231 | return hr; | ||
232 | } | ||
233 | |||
234 | DAPI_(HRESULT) DepCheckDependents( | ||
235 | __in HKEY hkHive, | ||
236 | __in_z LPCWSTR wzProviderKey, | ||
237 | __reserved int /*iAttributes*/, | ||
238 | __in C_STRINGDICT_HANDLE sdIgnoredDependents, | ||
239 | __deref_inout_ecount_opt(*pcDependents) DEPENDENCY** prgDependents, | ||
240 | __inout LPUINT pcDependents | ||
241 | ) | ||
242 | { | ||
243 | HRESULT hr = S_OK; | ||
244 | LPWSTR sczKey = NULL; | ||
245 | HKEY hkProviderKey = NULL; | ||
246 | HKEY hkDependentsKey = NULL; | ||
247 | LPWSTR sczDependentKey = NULL; | ||
248 | LPWSTR sczDependentName = NULL; | ||
249 | |||
250 | // Format the provider dependency registry key. | ||
251 | hr = AllocDependencyKeyName(wzProviderKey, &sczKey); | ||
252 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzProviderKey); | ||
253 | |||
254 | // Try to open the key. If that fails, the dependency information is corrupt. | ||
255 | hr = RegOpen(hkHive, sczKey, KEY_READ, &hkProviderKey); | ||
256 | ExitOnFailure(hr, "Failed to open the registry key \"%ls\". The dependency store is corrupt.", sczKey); | ||
257 | |||
258 | // Try to open the dependencies key. If that does not exist, there are no dependents. | ||
259 | hr = RegOpen(hkProviderKey, vsczRegistryDependents, KEY_READ, &hkDependentsKey); | ||
260 | if (E_FILENOTFOUND != hr) | ||
261 | { | ||
262 | ExitOnFailure(hr, "Failed to open the registry key for dependents of \"%ls\".", wzProviderKey); | ||
263 | } | ||
264 | else | ||
265 | { | ||
266 | ExitFunction1(hr = S_OK); | ||
267 | } | ||
268 | |||
269 | // Now enumerate the dependent keys. If they are not defined in the ignored list, add them to the array. | ||
270 | for (DWORD dwIndex = 0; ; ++dwIndex) | ||
271 | { | ||
272 | hr = RegKeyEnum(hkDependentsKey, dwIndex, &sczDependentKey); | ||
273 | if (E_NOMOREITEMS != hr) | ||
274 | { | ||
275 | ExitOnFailure(hr, "Failed to enumerate the dependents key of \"%ls\".", wzProviderKey); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | hr = S_OK; | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | // If the key isn't ignored, add it to the dependent array. | ||
284 | hr = DictKeyExists(sdIgnoredDependents, sczDependentKey); | ||
285 | if (E_NOTFOUND != hr) | ||
286 | { | ||
287 | ExitOnFailure(hr, "Failed to check the dictionary of ignored dependents."); | ||
288 | } | ||
289 | else | ||
290 | { | ||
291 | // Get the name of the dependent from the key. | ||
292 | hr = GetDependencyNameFromKey(hkHive, sczDependentKey, &sczDependentName); | ||
293 | ExitOnFailure(hr, "Failed to get the name of the dependent from the key \"%ls\".", sczDependentKey); | ||
294 | |||
295 | hr = DepDependencyArrayAlloc(prgDependents, pcDependents, sczDependentKey, sczDependentName); | ||
296 | ExitOnFailure(hr, "Failed to add the dependent key \"%ls\" to the string array.", sczDependentKey); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | LExit: | ||
301 | ReleaseStr(sczDependentName); | ||
302 | ReleaseStr(sczDependentKey); | ||
303 | ReleaseRegKey(hkDependentsKey); | ||
304 | ReleaseRegKey(hkProviderKey); | ||
305 | ReleaseStr(sczKey); | ||
306 | |||
307 | return hr; | ||
308 | } | ||
309 | |||
310 | DAPI_(HRESULT) DepRegisterDependency( | ||
311 | __in HKEY hkHive, | ||
312 | __in_z LPCWSTR wzProviderKey, | ||
313 | __in_z LPCWSTR wzVersion, | ||
314 | __in_z LPCWSTR wzDisplayName, | ||
315 | __in_z_opt LPCWSTR wzId, | ||
316 | __in int iAttributes | ||
317 | ) | ||
318 | { | ||
319 | HRESULT hr = S_OK; | ||
320 | LPWSTR sczKey = NULL; | ||
321 | HKEY hkKey = NULL; | ||
322 | BOOL fCreated = FALSE; | ||
323 | |||
324 | // Format the provider dependency registry key. | ||
325 | hr = AllocDependencyKeyName(wzProviderKey, &sczKey); | ||
326 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzProviderKey); | ||
327 | |||
328 | // Create the dependency key (or open it if it already exists). | ||
329 | hr = RegCreateEx(hkHive, sczKey, KEY_WRITE, FALSE, NULL, &hkKey, &fCreated); | ||
330 | ExitOnFailure(hr, "Failed to create the dependency registry key \"%ls\".", sczKey); | ||
331 | |||
332 | // Set the id if it was provided. | ||
333 | if (wzId) | ||
334 | { | ||
335 | hr = RegWriteString(hkKey, NULL, wzId); | ||
336 | ExitOnFailure(hr, "Failed to set the %ls registry value to \"%ls\".", L"default", wzId); | ||
337 | } | ||
338 | |||
339 | // Set the version. | ||
340 | hr = RegWriteString(hkKey, vcszVersionValue, wzVersion); | ||
341 | ExitOnFailure(hr, "Failed to set the %ls registry value to \"%ls\".", vcszVersionValue, wzVersion); | ||
342 | |||
343 | // Set the display name. | ||
344 | hr = RegWriteString(hkKey, vcszDisplayNameValue, wzDisplayName); | ||
345 | ExitOnFailure(hr, "Failed to set the %ls registry value to \"%ls\".", vcszDisplayNameValue, wzDisplayName); | ||
346 | |||
347 | // Set the attributes if non-zero. | ||
348 | if (0 != iAttributes) | ||
349 | { | ||
350 | hr = RegWriteNumber(hkKey, vcszAttributesValue, static_cast<DWORD>(iAttributes)); | ||
351 | ExitOnFailure(hr, "Failed to set the %ls registry value to %d.", vcszAttributesValue, iAttributes); | ||
352 | } | ||
353 | |||
354 | LExit: | ||
355 | ReleaseRegKey(hkKey); | ||
356 | ReleaseStr(sczKey); | ||
357 | |||
358 | return hr; | ||
359 | } | ||
360 | |||
361 | DAPI_(HRESULT) DepDependentExists( | ||
362 | __in HKEY hkHive, | ||
363 | __in_z LPCWSTR wzDependencyProviderKey, | ||
364 | __in_z LPCWSTR wzProviderKey | ||
365 | ) | ||
366 | { | ||
367 | HRESULT hr = S_OK; | ||
368 | LPWSTR sczDependentKey = NULL; | ||
369 | HKEY hkDependentKey = NULL; | ||
370 | |||
371 | // Format the provider dependents registry key. | ||
372 | hr = StrAllocFormatted(&sczDependentKey, L"%ls%ls\\%ls\\%ls", vsczRegistryRoot, wzDependencyProviderKey, vsczRegistryDependents, wzProviderKey); | ||
373 | ExitOnFailure(hr, "Failed to format registry key to dependent."); | ||
374 | |||
375 | hr = RegOpen(hkHive, sczDependentKey, KEY_READ, &hkDependentKey); | ||
376 | if (E_FILENOTFOUND != hr) | ||
377 | { | ||
378 | ExitOnFailure(hr, "Failed to open the dependent registry key at: \"%ls\".", sczDependentKey); | ||
379 | } | ||
380 | |||
381 | LExit: | ||
382 | ReleaseRegKey(hkDependentKey); | ||
383 | ReleaseStr(sczDependentKey); | ||
384 | |||
385 | return hr; | ||
386 | } | ||
387 | |||
388 | DAPI_(HRESULT) DepRegisterDependent( | ||
389 | __in HKEY hkHive, | ||
390 | __in_z LPCWSTR wzDependencyProviderKey, | ||
391 | __in_z LPCWSTR wzProviderKey, | ||
392 | __in_z_opt LPCWSTR wzMinVersion, | ||
393 | __in_z_opt LPCWSTR wzMaxVersion, | ||
394 | __in int iAttributes | ||
395 | ) | ||
396 | { | ||
397 | HRESULT hr = S_OK; | ||
398 | LPWSTR sczDependencyKey = NULL; | ||
399 | HKEY hkDependencyKey = NULL; | ||
400 | LPWSTR sczKey = NULL; | ||
401 | HKEY hkKey = NULL; | ||
402 | BOOL fCreated = FALSE; | ||
403 | |||
404 | // Format the provider dependency registry key. | ||
405 | hr = AllocDependencyKeyName(wzDependencyProviderKey, &sczDependencyKey); | ||
406 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzDependencyProviderKey); | ||
407 | |||
408 | // Create the dependency key (or open it if it already exists). | ||
409 | hr = RegCreateEx(hkHive, sczDependencyKey, KEY_WRITE, FALSE, NULL, &hkDependencyKey, &fCreated); | ||
410 | ExitOnFailure(hr, "Failed to create the dependency registry key \"%ls\".", sczDependencyKey); | ||
411 | |||
412 | // Create the subkey to register the dependent. | ||
413 | hr = StrAllocFormatted(&sczKey, L"%ls\\%ls", vsczRegistryDependents, wzProviderKey); | ||
414 | ExitOnFailure(hr, "Failed to allocate dependent subkey \"%ls\" under dependency \"%ls\".", wzProviderKey, wzDependencyProviderKey); | ||
415 | |||
416 | hr = RegCreateEx(hkDependencyKey, sczKey, KEY_WRITE, FALSE, NULL, &hkKey, &fCreated); | ||
417 | ExitOnFailure(hr, "Failed to create the dependency subkey \"%ls\".", sczKey); | ||
418 | |||
419 | // Set the minimum version if not NULL. | ||
420 | hr = RegWriteString(hkKey, vcszMinVersionValue, wzMinVersion); | ||
421 | ExitOnFailure(hr, "Failed to set the %ls registry value to \"%ls\".", vcszMinVersionValue, wzMinVersion); | ||
422 | |||
423 | // Set the maximum version if not NULL. | ||
424 | hr = RegWriteString(hkKey, vcszMaxVersionValue, wzMaxVersion); | ||
425 | ExitOnFailure(hr, "Failed to set the %ls registry value to \"%ls\".", vcszMaxVersionValue, wzMaxVersion); | ||
426 | |||
427 | // Set the attributes if non-zero. | ||
428 | if (0 != iAttributes) | ||
429 | { | ||
430 | hr = RegWriteNumber(hkKey, vcszAttributesValue, static_cast<DWORD>(iAttributes)); | ||
431 | ExitOnFailure(hr, "Failed to set the %ls registry value to %d.", vcszAttributesValue, iAttributes); | ||
432 | } | ||
433 | |||
434 | LExit: | ||
435 | ReleaseRegKey(hkKey); | ||
436 | ReleaseStr(sczKey); | ||
437 | ReleaseRegKey(hkDependencyKey); | ||
438 | ReleaseStr(sczDependencyKey); | ||
439 | |||
440 | return hr; | ||
441 | } | ||
442 | |||
443 | DAPI_(HRESULT) DepUnregisterDependency( | ||
444 | __in HKEY hkHive, | ||
445 | __in_z LPCWSTR wzProviderKey | ||
446 | ) | ||
447 | { | ||
448 | HRESULT hr = S_OK; | ||
449 | LPWSTR sczKey = NULL; | ||
450 | HKEY hkKey = NULL; | ||
451 | |||
452 | // Format the provider dependency registry key. | ||
453 | hr = AllocDependencyKeyName(wzProviderKey, &sczKey); | ||
454 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzProviderKey); | ||
455 | |||
456 | // Delete the entire key including all sub-keys. | ||
457 | hr = RegDelete(hkHive, sczKey, REG_KEY_DEFAULT, TRUE); | ||
458 | if (E_FILENOTFOUND != hr) | ||
459 | { | ||
460 | ExitOnFailure(hr, "Failed to delete the key \"%ls\".", sczKey); | ||
461 | } | ||
462 | |||
463 | LExit: | ||
464 | ReleaseRegKey(hkKey); | ||
465 | ReleaseStr(sczKey); | ||
466 | |||
467 | return hr; | ||
468 | } | ||
469 | |||
470 | DAPI_(HRESULT) DepUnregisterDependent( | ||
471 | __in HKEY hkHive, | ||
472 | __in_z LPCWSTR wzDependencyProviderKey, | ||
473 | __in_z LPCWSTR wzProviderKey | ||
474 | ) | ||
475 | { | ||
476 | HRESULT hr = S_OK; | ||
477 | HKEY hkRegistryRoot = NULL; | ||
478 | HKEY hkDependencyProviderKey = NULL; | ||
479 | HKEY hkRegistryDependents = NULL; | ||
480 | DWORD cSubKeys = 0; | ||
481 | DWORD cValues = 0; | ||
482 | |||
483 | // Open the root key. We may delete the wzDependencyProviderKey during clean up. | ||
484 | hr = RegOpen(hkHive, vsczRegistryRoot, KEY_READ, &hkRegistryRoot); | ||
485 | if (E_FILENOTFOUND != hr) | ||
486 | { | ||
487 | ExitOnFailure(hr, "Failed to open root registry key \"%ls\".", vsczRegistryRoot); | ||
488 | } | ||
489 | else | ||
490 | { | ||
491 | ExitFunction(); | ||
492 | } | ||
493 | |||
494 | // Try to open the dependency key. If that does not exist, simply return. | ||
495 | hr = RegOpen(hkRegistryRoot, wzDependencyProviderKey, KEY_READ, &hkDependencyProviderKey); | ||
496 | if (E_FILENOTFOUND != hr) | ||
497 | { | ||
498 | ExitOnFailure(hr, "Failed to open the registry key for the dependency \"%ls\".", wzDependencyProviderKey); | ||
499 | } | ||
500 | else | ||
501 | { | ||
502 | ExitFunction(); | ||
503 | } | ||
504 | |||
505 | // Try to open the dependents subkey to enumerate. | ||
506 | hr = RegOpen(hkDependencyProviderKey, vsczRegistryDependents, KEY_READ, &hkRegistryDependents); | ||
507 | if (E_FILENOTFOUND != hr) | ||
508 | { | ||
509 | ExitOnFailure(hr, "Failed to open the dependents subkey under the dependency \"%ls\".", wzDependencyProviderKey); | ||
510 | } | ||
511 | else | ||
512 | { | ||
513 | ExitFunction(); | ||
514 | } | ||
515 | |||
516 | // Delete the wzProviderKey dependent sub-key. | ||
517 | hr = RegDelete(hkRegistryDependents, wzProviderKey, REG_KEY_DEFAULT, TRUE); | ||
518 | ExitOnFailure(hr, "Failed to delete the dependent \"%ls\" under the dependency \"%ls\".", wzProviderKey, wzDependencyProviderKey); | ||
519 | |||
520 | // If there are no remaining dependents, delete the Dependents subkey. | ||
521 | hr = RegQueryKey(hkRegistryDependents, &cSubKeys, NULL); | ||
522 | ExitOnFailure(hr, "Failed to get the number of dependent subkeys under the dependency \"%ls\".", wzDependencyProviderKey); | ||
523 | |||
524 | if (0 < cSubKeys) | ||
525 | { | ||
526 | ExitFunction(); | ||
527 | } | ||
528 | |||
529 | // Release the handle to make sure it's deleted immediately. | ||
530 | ReleaseRegKey(hkRegistryDependents); | ||
531 | |||
532 | // Fail if there are any subkeys since we just checked. | ||
533 | hr = RegDelete(hkDependencyProviderKey, vsczRegistryDependents, REG_KEY_DEFAULT, FALSE); | ||
534 | ExitOnFailure(hr, "Failed to delete the dependents subkey under the dependency \"%ls\".", wzDependencyProviderKey); | ||
535 | |||
536 | // If there are no values, delete the provider dependency key. | ||
537 | hr = RegQueryKey(hkDependencyProviderKey, NULL, &cValues); | ||
538 | ExitOnFailure(hr, "Failed to get the number of values under the dependency \"%ls\".", wzDependencyProviderKey); | ||
539 | |||
540 | if (0 == cValues) | ||
541 | { | ||
542 | // Release the handle to make sure it's deleted immediately. | ||
543 | ReleaseRegKey(hkDependencyProviderKey); | ||
544 | |||
545 | // Fail if there are any subkeys since we just checked. | ||
546 | hr = RegDelete(hkRegistryRoot, wzDependencyProviderKey, REG_KEY_DEFAULT, FALSE); | ||
547 | ExitOnFailure(hr, "Failed to delete the dependency \"%ls\".", wzDependencyProviderKey); | ||
548 | } | ||
549 | |||
550 | LExit: | ||
551 | ReleaseRegKey(hkRegistryDependents); | ||
552 | ReleaseRegKey(hkDependencyProviderKey); | ||
553 | ReleaseRegKey(hkRegistryRoot); | ||
554 | |||
555 | return hr; | ||
556 | } | ||
557 | |||
558 | DAPI_(HRESULT) DepDependencyArrayAlloc( | ||
559 | __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, | ||
560 | __inout LPUINT pcDependencies, | ||
561 | __in_z LPCWSTR wzKey, | ||
562 | __in_z_opt LPCWSTR wzName | ||
563 | ) | ||
564 | { | ||
565 | HRESULT hr = S_OK; | ||
566 | UINT cRequired = 0; | ||
567 | DEPENDENCY* pDependency = NULL; | ||
568 | |||
569 | hr = ::UIntAdd(*pcDependencies, 1, &cRequired); | ||
570 | ExitOnFailure(hr, "Failed to increment the number of elements required in the dependency array."); | ||
571 | |||
572 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgDependencies), cRequired, sizeof(DEPENDENCY), ARRAY_GROWTH_SIZE); | ||
573 | ExitOnFailure(hr, "Failed to allocate memory for the dependency array."); | ||
574 | |||
575 | pDependency = static_cast<DEPENDENCY*>(&(*prgDependencies)[*pcDependencies]); | ||
576 | ExitOnNull(pDependency, hr, E_POINTER, "The dependency element in the array is invalid."); | ||
577 | |||
578 | hr = StrAllocString(&(pDependency->sczKey), wzKey, 0); | ||
579 | ExitOnFailure(hr, "Failed to allocate the string key in the dependency array."); | ||
580 | |||
581 | if (wzName) | ||
582 | { | ||
583 | hr = StrAllocString(&(pDependency->sczName), wzName, 0); | ||
584 | ExitOnFailure(hr, "Failed to allocate the string name in the dependency array."); | ||
585 | } | ||
586 | |||
587 | // Update the number of current elements in the dependency array. | ||
588 | *pcDependencies = cRequired; | ||
589 | |||
590 | LExit: | ||
591 | return hr; | ||
592 | } | ||
593 | |||
594 | DAPI_(void) DepDependencyArrayFree( | ||
595 | __in_ecount(cDependencies) DEPENDENCY* rgDependencies, | ||
596 | __in UINT cDependencies | ||
597 | ) | ||
598 | { | ||
599 | for (UINT i = 0; i < cDependencies; ++i) | ||
600 | { | ||
601 | ReleaseStr(rgDependencies[i].sczKey); | ||
602 | ReleaseStr(rgDependencies[i].sczName); | ||
603 | } | ||
604 | |||
605 | ReleaseMem(rgDependencies); | ||
606 | } | ||
607 | |||
608 | /*************************************************************************** | ||
609 | AllocDependencyKeyName - Allocates and formats the root registry key name. | ||
610 | |||
611 | ***************************************************************************/ | ||
612 | static HRESULT AllocDependencyKeyName( | ||
613 | __in_z LPCWSTR wzName, | ||
614 | __deref_out_z LPWSTR* psczKeyName | ||
615 | ) | ||
616 | { | ||
617 | HRESULT hr = S_OK; | ||
618 | size_t cchName = 0; | ||
619 | size_t cchKeyName = 0; | ||
620 | |||
621 | // Get the length of the static registry root once. | ||
622 | static size_t cchRegistryRoot = ::lstrlenW(vsczRegistryRoot); | ||
623 | |||
624 | // Get the length of the dependency, and add to the length of the root. | ||
625 | hr = ::StringCchLengthW(wzName, STRSAFE_MAX_CCH, &cchName); | ||
626 | ExitOnFailure(hr, "Failed to get string length of dependency name."); | ||
627 | |||
628 | // Add the sizes together to allocate memory once (callee will add space for nul). | ||
629 | hr = ::SizeTAdd(cchRegistryRoot, cchName, &cchKeyName); | ||
630 | ExitOnFailure(hr, "Failed to add the string lengths together."); | ||
631 | |||
632 | // Allocate and concat the strings together. | ||
633 | hr = StrAllocString(psczKeyName, vsczRegistryRoot, cchKeyName); | ||
634 | ExitOnFailure(hr, "Failed to allocate string for dependency registry root."); | ||
635 | |||
636 | hr = StrAllocConcat(psczKeyName, wzName, cchName); | ||
637 | ExitOnFailure(hr, "Failed to concatenate the dependency key name."); | ||
638 | |||
639 | LExit: | ||
640 | return hr; | ||
641 | } | ||
642 | |||
643 | /*************************************************************************** | ||
644 | GetDependencyNameFromKey - Attempts to name of the dependency from the key. | ||
645 | |||
646 | ***************************************************************************/ | ||
647 | static HRESULT GetDependencyNameFromKey( | ||
648 | __in HKEY hkHive, | ||
649 | __in LPCWSTR wzProviderKey, | ||
650 | __deref_out_z LPWSTR* psczName | ||
651 | ) | ||
652 | { | ||
653 | HRESULT hr = S_OK; | ||
654 | LPWSTR sczKey = NULL; | ||
655 | HKEY hkKey = NULL; | ||
656 | |||
657 | // Format the provider dependency registry key. | ||
658 | hr = AllocDependencyKeyName(wzProviderKey, &sczKey); | ||
659 | ExitOnFailure(hr, "Failed to allocate the registry key for dependency \"%ls\".", wzProviderKey); | ||
660 | |||
661 | // Try to open the dependency key. | ||
662 | hr = RegOpen(hkHive, sczKey, KEY_READ, &hkKey); | ||
663 | if (E_FILENOTFOUND != hr) | ||
664 | { | ||
665 | ExitOnFailure(hr, "Failed to open the registry key for the dependency \"%ls\".", wzProviderKey); | ||
666 | } | ||
667 | else | ||
668 | { | ||
669 | ExitFunction1(hr = S_OK); | ||
670 | } | ||
671 | |||
672 | // Get the DisplayName if available. | ||
673 | hr = RegReadString(hkKey, vcszDisplayNameValue, psczName); | ||
674 | if (E_FILENOTFOUND != hr) | ||
675 | { | ||
676 | ExitOnFailure(hr, "Failed to get the dependency name for the dependency \"%ls\".", wzProviderKey); | ||
677 | } | ||
678 | else | ||
679 | { | ||
680 | ExitFunction1(hr = S_OK); | ||
681 | } | ||
682 | |||
683 | LExit: | ||
684 | ReleaseRegKey(hkKey); | ||
685 | ReleaseStr(sczKey); | ||
686 | |||
687 | return hr; | ||
688 | } | ||
diff --git a/src/dutil/dutil.vcxproj b/src/dutil/dutil.vcxproj index 95b90665..606eb87b 100644 --- a/src/dutil/dutil.vcxproj +++ b/src/dutil/dutil.vcxproj | |||
@@ -171,6 +171,7 @@ | |||
171 | <ClCompile Include="condutil.cpp" /> | 171 | <ClCompile Include="condutil.cpp" /> |
172 | <ClCompile Include="conutil.cpp" /> | 172 | <ClCompile Include="conutil.cpp" /> |
173 | <ClCompile Include="cryputil.cpp" /> | 173 | <ClCompile Include="cryputil.cpp" /> |
174 | <ClCompile Include="deputil.cpp" /> | ||
174 | <ClCompile Include="dictutil.cpp" /> | 175 | <ClCompile Include="dictutil.cpp" /> |
175 | <ClCompile Include="dirutil.cpp" /> | 176 | <ClCompile Include="dirutil.cpp" /> |
176 | <ClCompile Include="dlutil.cpp" /> | 177 | <ClCompile Include="dlutil.cpp" /> |
@@ -238,6 +239,7 @@ | |||
238 | <ClInclude Include="inc\condutil.h" /> | 239 | <ClInclude Include="inc\condutil.h" /> |
239 | <ClInclude Include="inc\conutil.h" /> | 240 | <ClInclude Include="inc\conutil.h" /> |
240 | <ClInclude Include="inc\cryputil.h" /> | 241 | <ClInclude Include="inc\cryputil.h" /> |
242 | <ClInclude Include="inc\deputil.h" /> | ||
241 | <ClInclude Include="inc\dictutil.h" /> | 243 | <ClInclude Include="inc\dictutil.h" /> |
242 | <ClInclude Include="inc\dirutil.h" /> | 244 | <ClInclude Include="inc\dirutil.h" /> |
243 | <ClInclude Include="inc\dlutil.h" /> | 245 | <ClInclude Include="inc\dlutil.h" /> |
diff --git a/src/dutil/inc/deputil.h b/src/dutil/inc/deputil.h new file mode 100644 index 00000000..a08d2eb5 --- /dev/null +++ b/src/dutil/inc/deputil.h | |||
@@ -0,0 +1,147 @@ | |||
1 | #pragma once | ||
2 | // 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. | ||
3 | |||
4 | |||
5 | #ifdef __cplusplus | ||
6 | extern "C" { | ||
7 | #endif | ||
8 | |||
9 | #define ReleaseDependencyArray(rg, c) if (rg) { DepDependencyArrayFree(rg, c); } | ||
10 | #define ReleaseNullDependencyArray(rg, c) if (rg) { DepDependencyArrayFree(rg, c); rg = NULL; } | ||
11 | |||
12 | typedef struct _DEPENDENCY | ||
13 | { | ||
14 | LPWSTR sczKey; | ||
15 | LPWSTR sczName; | ||
16 | } DEPENDENCY; | ||
17 | |||
18 | |||
19 | /*************************************************************************** | ||
20 | DepGetProviderInformation - gets the various pieces of data registered | ||
21 | with a dependency. | ||
22 | |||
23 | Note: Returns E_NOTFOUND if the dependency was not found. | ||
24 | ***************************************************************************/ | ||
25 | DAPI_(HRESULT) DepGetProviderInformation( | ||
26 | __in HKEY hkHive, | ||
27 | __in_z LPCWSTR wzProviderKey, | ||
28 | __deref_out_z_opt LPWSTR* psczId, | ||
29 | __deref_out_z_opt LPWSTR* psczName, | ||
30 | __out_opt DWORD64* pqwVersion | ||
31 | ); | ||
32 | |||
33 | /*************************************************************************** | ||
34 | DepCheckDependency - Checks that the dependency is registered and within | ||
35 | the proper version range. | ||
36 | |||
37 | Note: Returns E_NOTFOUND if the dependency was not found. | ||
38 | ***************************************************************************/ | ||
39 | DAPI_(HRESULT) DepCheckDependency( | ||
40 | __in HKEY hkHive, | ||
41 | __in_z LPCWSTR wzProviderKey, | ||
42 | __in_z_opt LPCWSTR wzMinVersion, | ||
43 | __in_z_opt LPCWSTR wzMaxVersion, | ||
44 | __in int iAttributes, | ||
45 | __in STRINGDICT_HANDLE sdDependencies, | ||
46 | __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, | ||
47 | __inout LPUINT pcDependencies | ||
48 | ); | ||
49 | |||
50 | /*************************************************************************** | ||
51 | DepCheckDependents - Checks if any dependents are still installed for the | ||
52 | given provider key. | ||
53 | |||
54 | ***************************************************************************/ | ||
55 | DAPI_(HRESULT) DepCheckDependents( | ||
56 | __in HKEY hkHive, | ||
57 | __in_z LPCWSTR wzProviderKey, | ||
58 | __in int iAttributes, | ||
59 | __in C_STRINGDICT_HANDLE sdIgnoredDependents, | ||
60 | __deref_inout_ecount_opt(*pcDependents) DEPENDENCY** prgDependents, | ||
61 | __inout LPUINT pcDependents | ||
62 | ); | ||
63 | |||
64 | /*************************************************************************** | ||
65 | DepRegisterDependency - Registers the dependency provider. | ||
66 | |||
67 | ***************************************************************************/ | ||
68 | DAPI_(HRESULT) DepRegisterDependency( | ||
69 | __in HKEY hkHive, | ||
70 | __in_z LPCWSTR wzProviderKey, | ||
71 | __in_z LPCWSTR wzVersion, | ||
72 | __in_z LPCWSTR wzDisplayName, | ||
73 | __in_z_opt LPCWSTR wzId, | ||
74 | __in int iAttributes | ||
75 | ); | ||
76 | |||
77 | /*************************************************************************** | ||
78 | DepDependentExists - Determines if a dependent is registered. | ||
79 | |||
80 | Note: Returns S_OK if dependent is registered. | ||
81 | Returns E_FILENOTFOUND if dependent is not registered | ||
82 | ***************************************************************************/ | ||
83 | DAPI_(HRESULT) DepDependentExists( | ||
84 | __in HKEY hkHive, | ||
85 | __in_z LPCWSTR wzDependencyProviderKey, | ||
86 | __in_z LPCWSTR wzProviderKey | ||
87 | ); | ||
88 | |||
89 | /*************************************************************************** | ||
90 | DepRegisterDependent - Registers a dependent under the dependency provider. | ||
91 | |||
92 | ***************************************************************************/ | ||
93 | DAPI_(HRESULT) DepRegisterDependent( | ||
94 | __in HKEY hkHive, | ||
95 | __in_z LPCWSTR wzDependencyProviderKey, | ||
96 | __in_z LPCWSTR wzProviderKey, | ||
97 | __in_z_opt LPCWSTR wzMinVersion, | ||
98 | __in_z_opt LPCWSTR wzMaxVersion, | ||
99 | __in int iAttributes | ||
100 | ); | ||
101 | |||
102 | /*************************************************************************** | ||
103 | DepUnregisterDependency - Removes the dependency provider. | ||
104 | |||
105 | Note: Caller should call CheckDependents prior to remove a dependency. | ||
106 | Returns E_FILENOTFOUND if the dependency is not registered. | ||
107 | ***************************************************************************/ | ||
108 | DAPI_(HRESULT) DepUnregisterDependency( | ||
109 | __in HKEY hkHive, | ||
110 | __in_z LPCWSTR wzProviderKey | ||
111 | ); | ||
112 | |||
113 | /*************************************************************************** | ||
114 | DepUnregisterDependent - Removes a dependent under the dependency provider. | ||
115 | |||
116 | Note: Returns E_FILENOTFOUND if neither the dependency or dependent are | ||
117 | registered. | ||
118 | ***************************************************************************/ | ||
119 | DAPI_(HRESULT) DepUnregisterDependent( | ||
120 | __in HKEY hkHive, | ||
121 | __in_z LPCWSTR wzDependencyProviderKey, | ||
122 | __in_z LPCWSTR wzProviderKey | ||
123 | ); | ||
124 | |||
125 | /*************************************************************************** | ||
126 | DependencyArrayAlloc - Allocates or expands an array of DEPENDENCY structs. | ||
127 | |||
128 | ***************************************************************************/ | ||
129 | DAPI_(HRESULT) DepDependencyArrayAlloc( | ||
130 | __deref_inout_ecount_opt(*pcDependencies) DEPENDENCY** prgDependencies, | ||
131 | __inout LPUINT pcDependencies, | ||
132 | __in_z LPCWSTR wzKey, | ||
133 | __in_z_opt LPCWSTR wzName | ||
134 | ); | ||
135 | |||
136 | /*************************************************************************** | ||
137 | DepDependencyArrayFree - Frees an array of DEPENDENCY structs. | ||
138 | |||
139 | ***************************************************************************/ | ||
140 | DAPI_(void) DepDependencyArrayFree( | ||
141 | __in_ecount(cDependencies) DEPENDENCY* rgDependencies, | ||
142 | __in UINT cDependencies | ||
143 | ); | ||
144 | |||
145 | #ifdef __cplusplus | ||
146 | } | ||
147 | #endif | ||
diff --git a/src/dutil/precomp.h b/src/dutil/precomp.h index 3acbca43..c305573d 100644 --- a/src/dutil/precomp.h +++ b/src/dutil/precomp.h | |||
@@ -56,6 +56,7 @@ | |||
56 | #include "guidutil.h" | 56 | #include "guidutil.h" |
57 | #include "gdiputil.h" | 57 | #include "gdiputil.h" |
58 | #include "dictutil.h" | 58 | #include "dictutil.h" |
59 | #include "deputil.h" // NOTE: This must come after dictutil.h since it uses it. | ||
59 | #include "inetutil.h" | 60 | #include "inetutil.h" |
60 | #include "iniutil.h" | 61 | #include "iniutil.h" |
61 | #include "jsonutil.h" | 62 | #include "jsonutil.h" |