PAGED NTSTATUS QueryValueMultisz()

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++;
        }

    }