Import deputil from old v4 repo.
Sean Hall committed
Dec 29, 2018 at 14:33 UTC
88cd76dbbcce061f80e234489bc18450f56a6e77
4 files changed
+838
src/dutil/deputil.cpp
new
+688
@@ -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
+}
src/dutil/dutil.vcxproj
+2
@@ -171,6 +171,7 @@
171
<ClCompile Include="condutil.cpp" />
172
<ClCompile Include="conutil.cpp" />
173
<ClCompile Include="cryputil.cpp" />
174
+ <ClCompile Include="deputil.cpp" />
175
<ClCompile Include="dictutil.cpp" />
176
<ClCompile Include="dirutil.cpp" />
177
<ClCompile Include="dlutil.cpp" />
@@ -238,6 +239,7 @@
239
<ClInclude Include="inc\condutil.h" />
240
<ClInclude Include="inc\conutil.h" />
241
<ClInclude Include="inc\cryputil.h" />
242
+ <ClInclude Include="inc\deputil.h" />
243
<ClInclude Include="inc\dictutil.h" />
244
<ClInclude Include="inc\dirutil.h" />
245
<ClInclude Include="inc\dlutil.h" />
src/dutil/inc/deputil.h
new
+147
@@ -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
src/dutil/precomp.h
+1
@@ -56,6 +56,7 @@
56
#include "guidutil.h"
57
#include "gdiputil.h"
58
#include "dictutil.h"
59
+#include "deputil.h" // NOTE: This must come after dictutil.h since it uses it.
60
#include "inetutil.h"
61
#include "iniutil.h"
62
#include "jsonutil.h"