in rtl/inc/kregkey.h [212:318]
PAGED NTSTATUS QueryValueMultisz(
_In_ PCUNICODE_STRING Name,
_In_ CountLambda CountCallback,
_In_ PerStringLambda PerStringCallback,
_In_ ULONG ExpectedDataType = REG_MULTI_SZ)
{
NTSTATUS NtStatus;
union
{
KEY_VALUE_PARTIAL_INFORMATION StackInformation;
UCHAR Buffer[256];
};
KEY_VALUE_PARTIAL_INFORMATION *Information = &StackInformation;
wistd::unique_ptr<UCHAR[]> HeapBuffer;
ULONG BytesNeeded;
NtStatus = ZwQueryValueKey(
*this,
const_cast<PUNICODE_STRING>(Name),
KeyValuePartialInformation,
Buffer,
sizeof(Buffer),
&BytesNeeded);
if (NtStatus == STATUS_BUFFER_OVERFLOW)
{
HeapBuffer.reset(new(std::nothrow, 'zSlM') UCHAR[BytesNeeded]);
if (!HeapBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
NtStatus = ZwQueryValueKey(
*this,
const_cast<PUNICODE_STRING>(Name),
KeyValuePartialInformation,
HeapBuffer.get(),
BytesNeeded,
&BytesNeeded);
if (!NT_SUCCESS(NtStatus))
return NtStatus;
Information = reinterpret_cast<KEY_VALUE_PARTIAL_INFORMATION*>(HeapBuffer.get());
}
else if (!NT_SUCCESS(NtStatus))
{
return NtStatus;
}
if (Information->Type != ExpectedDataType)
return STATUS_OBJECT_TYPE_MISMATCH;
if (Information->DataLength % sizeof(WCHAR))
return STATUS_INVALID_PARAMETER;
PCWSTR CurrentStart = (PCWSTR)Information->Data;
PCWSTR End = (PCWSTR)(Information->Data + Information->DataLength);
ULONG NumStrings = 0;
while (true)
{
if (CurrentStart >= End)
return STATUS_BUFFER_TOO_SMALL;
if (*CurrentStart == L'\0')
break;
PCWSTR CurrentEnd = CurrentStart;
do
{
++CurrentEnd;
if (CurrentEnd >= End)
return STATUS_BUFFER_TOO_SMALL;
} while (*CurrentEnd != L'\0');
++NumStrings;
CurrentStart = CurrentEnd + 1;
}
NtStatus = CountCallback(NumStrings);
if (!NT_SUCCESS(NtStatus))
return NtStatus;
CurrentStart = (PCWSTR)Information->Data;
ULONG Index = 0;
while (true)
{
if (*CurrentStart == L'\0')
return STATUS_SUCCESS;
PCWSTR CurrentEnd = CurrentStart;
do
{
++CurrentEnd;
} while (*CurrentEnd != L'\0');
NtStatus = PerStringCallback(CurrentStart, Index);
if (!NT_SUCCESS(NtStatus))
return NtStatus;
CurrentStart = CurrentEnd + 1;
Index++;
}
}