@@ -348,5 +348,106 @@ CxPlatStorageClear(
348
348
_In_ CXPLAT_STORAGE * Storage
349
349
)
350
350
{
351
- return HRESULT_FROM_WIN32 (RegDeleteTreeA (Storage -> RegKey , NULL ));
351
+ //
352
+ // Clear only values in this registry key, not subkeys, to preserve
353
+ // separation between global and per-app settings. RegDeleteTreeA would
354
+ // delete the entire subtree and wipe all app-specific data when clearing
355
+ // global storage.
356
+ //
357
+ QUIC_STATUS Status = QUIC_STATUS_SUCCESS ;
358
+ DWORD Error = NO_ERROR ;
359
+ DWORD AllocatedLength = 0 ;
360
+ PSTR ValueName = NULL ;
361
+
362
+ //
363
+ // Query registry key info to get the maximum value name length
364
+ //
365
+ Error = RegQueryInfoKeyA (
366
+ Storage -> RegKey ,
367
+ NULL , // Class
368
+ NULL , // ClassLength
369
+ NULL , // Reserved
370
+ NULL , // SubKeys
371
+ NULL , // MaxSubKeyLen
372
+ NULL , // MaxClassLen
373
+ NULL , // Values
374
+ & AllocatedLength , // MaxValueNameLen
375
+ NULL , // MaxValueLen
376
+ NULL , // SecurityDescriptor
377
+ NULL ); // LastWriteTime
378
+ if (Error != NO_ERROR ) {
379
+ Status = HRESULT_FROM_WIN32 (Error );
380
+ QuicTraceEvent (
381
+ LibraryErrorStatus ,
382
+ "[ lib] ERROR, %u, %s." ,
383
+ Status ,
384
+ "RegQueryInfoKeyA failed" );
385
+ goto Exit ;
386
+ }
387
+ //
388
+ // Add 1 for null terminator (RegQueryInfoKeyA returns length without null terminator)
389
+ //
390
+ AllocatedLength ++ ;
391
+
392
+ ValueName = CXPLAT_ALLOC_PAGED (AllocatedLength , QUIC_POOL_PLATFORM_TMP_ALLOC );
393
+ if (ValueName == NULL ) {
394
+ Status = QUIC_STATUS_OUT_OF_MEMORY ;
395
+ QuicTraceEvent (
396
+ AllocFailure ,
397
+ "Allocation of '%s' failed. (%llu bytes)" ,
398
+ "RegEnumValueA ValueName" ,
399
+ AllocatedLength );
400
+ goto Exit ;
401
+ }
402
+
403
+ //
404
+ // Iterate through all values and delete them
405
+ // We always use index 0 because deletion shifts the remaining values
406
+ //
407
+ while (TRUE) {
408
+ DWORD NameLength = AllocatedLength ;
409
+ Error =
410
+ RegEnumValueA (
411
+ Storage -> RegKey ,
412
+ 0 , // Always use index 0 since we delete as we go
413
+ ValueName ,
414
+ & NameLength ,
415
+ NULL , // Reserved
416
+ NULL , // Type
417
+ NULL , // Data
418
+ NULL ); // DataLength
419
+
420
+ if (Error == ERROR_NO_MORE_ITEMS ) {
421
+ Status = QUIC_STATUS_SUCCESS ;
422
+ break ;
423
+ } else if (Error != NO_ERROR ) {
424
+ Status = HRESULT_FROM_WIN32 (Error );
425
+ QuicTraceEvent (
426
+ LibraryErrorStatus ,
427
+ "[ lib] ERROR, %u, %s." ,
428
+ Status ,
429
+ "RegEnumValueA failed" );
430
+ goto Exit ;
431
+ }
432
+
433
+ //
434
+ // Delete this value
435
+ //
436
+ Status = RegDeleteValueA (Storage -> RegKey , ValueName );
437
+ if (QUIC_FAILED (Status )) {
438
+ QuicTraceEvent (
439
+ LibraryErrorStatus ,
440
+ "[ lib] ERROR, %u, %s." ,
441
+ Status ,
442
+ "ZwDeleteValueKey failed" );
443
+ goto Exit ;
444
+ }
445
+ }
446
+
447
+ Exit :
448
+ if (ValueName != NULL ) {
449
+ CXPLAT_FREE (ValueName , QUIC_POOL_PLATFORM_TMP_ALLOC );
450
+ }
451
+
452
+ return Status ;
352
453
}
0 commit comments