Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 113 additions & 2 deletions src/platform/storage_winuser.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,5 +348,116 @@ CxPlatStorageClear(
_In_ CXPLAT_STORAGE* Storage
)
{
return HRESULT_FROM_WIN32(RegDeleteTreeA(Storage->RegKey, NULL));
}
QUIC_STATUS Status = QUIC_STATUS_SUCCESS;
DWORD Error = NO_ERROR;
DWORD AllocatedLength = 255;
PSTR ValueName = NULL;

ValueName = CXPLAT_ALLOC_PAGED(AllocatedLength, QUIC_POOL_PLATFORM_TMP_ALLOC);
if (ValueName == NULL) {
Status = QUIC_STATUS_OUT_OF_MEMORY;
QuicTraceEvent(
AllocFailure,
"Allocation of '%s' failed. (%llu bytes)",
"RegEnumValueA ValueName",
AllocatedLength);
goto Exit;
}

//
// Iterate through all values and delete them
Comment thread
gaurav2699 marked this conversation as resolved.
// We always use index 0 because deletion shifts the remaining values
//
while (TRUE) {
DWORD NameLength = AllocatedLength;
Error =
RegEnumValueA(
Storage->RegKey,
0, // Always use index 0 since we delete as we go
ValueName,
&NameLength,
NULL, // Reserved
NULL, // Type
NULL, // Data
NULL); // DataLength

while (Error == ERROR_MORE_DATA && AllocatedLength < 32767) {
//
// Reallocate buffer only if current buffer is too small
//
CXPLAT_DBG_ASSERT(ValueName != NULL);

CXPLAT_FREE(ValueName, QUIC_POOL_PLATFORM_TMP_ALLOC);

AllocatedLength *= 2; // The API doesn't tell us the needed length; just double it.

@mtfriesen mtfriesen Jun 26, 2025

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently the RegQueryInfoKeyA function returns lpcbMaxValueNameLen which is the answer.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, so at the top call RegQueryInfoKeyA to get the initial value to use for AllocatedLength?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, that's the theory.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on using it then, it seems to me like a more natural pattern!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have modified it according to the suggested method, please see if it looks fine. Thanks.

if (AllocatedLength > 32767) {
Comment thread
gaurav2699 marked this conversation as resolved.
Outdated
//
// The registry API interprets this value as a SHORT, so
// values larger than 32,767 will cause it to overflow and
// return ERROR_MORE_DATA. So limit allocation to this length.
//
AllocatedLength = 32767;
}

ValueName = CXPLAT_ALLOC_PAGED(AllocatedLength, QUIC_POOL_PLATFORM_TMP_ALLOC);
if (ValueName == NULL) {
Status = QUIC_STATUS_OUT_OF_MEMORY;
QuicTraceEvent(
AllocFailure,
"Allocation of '%s' failed. (%llu bytes)",
"RegEnumValueA ValueName (realloc)",
AllocatedLength);
goto Exit;
}

NameLength = AllocatedLength;

//
// Get the value name
//
Error =
RegEnumValueA(
Storage->RegKey,
0, // Always use index 0 since we delete as we go
ValueName,
&NameLength,
NULL, // Reserved
NULL, // Type
NULL, // Data
NULL); // DataLength
}

if (Error == ERROR_NO_MORE_ITEMS) {
Status = QUIC_STATUS_SUCCESS;
break;
} else if (Error != NO_ERROR) {
Status = HRESULT_FROM_WIN32(Error);
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"RegEnumValueA failed");
goto Exit;
}

//
// Delete this value
//
Status = RegDeleteValueA(Storage->RegKey, ValueName);
if (QUIC_FAILED(Status)) {
QuicTraceEvent(
LibraryErrorStatus,
"[ lib] ERROR, %u, %s.",
Status,
"ZwDeleteValueKey failed");
goto Exit;
}
}

Exit:
if (ValueName != NULL) {
CXPLAT_FREE(ValueName, QUIC_POOL_PLATFORM_TMP_ALLOC);
}

return Status;
}
Comment thread
gaurav2699 marked this conversation as resolved.
Outdated
Loading