ZwQueryValueKey returns STATUS_BUFFER_TOO_SMALL

Hi, this is the old NT driver code,

NTSTATUS Status;
ULONG Len=0;
PKEY_VALUE_PARTIAL_INFORMATION pInfo_Partial;
ULONG Size =0;

KdPrint((“… 1 %wZ …\n”, lpValueName));
*lpLastError = NO_ERROR;

Status = ZwQueryValueKey(hKey,
lpValueName,
KeyValuePartialInformation,
NULL,
0,
&Len);

But the status is BUFFER_TOO_SMALL. Is this ok ?

The last parameter on input needs to contain the size of the output buffer. After calling ZwQueryValueKey, the passed-by-reference value will contain the minimum required buffer size.

You should first call ZwQueryValueKey with a NULL pointer and the last parameter set to 0, then dynamically allocate a buffer with the size it returns and call it again, this time with a non-zero buffer size param.

And you should also read the documentation: http://www.osronline.com/DDKx/kmarch/k111_9qya.htm

Err, I got my parameters mixed up.

The “Length” parameter is the size of your buffer, should be zero the first time, and the returned value the second time.

The “ResultLength” parameter is the actual size of the buffer. Use the value returned by the first call as the “Length” value in the second.

(And, of course, there is no pass-by-reference so much as it is a pointer; and it’s the non-kernel function that uses IN_OUT for the last param instead of separate IN and OUT params)

xxxxx@hotmail.com wrote:

Hi, this is the old NT driver code,

NTSTATUS Status;
ULONG Len=0;
PKEY_VALUE_PARTIAL_INFORMATION pInfo_Partial;
ULONG Size =0;

KdPrint((“… 1 %wZ …\n”, lpValueName));
*lpLastError = NO_ERROR;

Status = ZwQueryValueKey(hKey,
lpValueName,
KeyValuePartialInformation,
NULL,
0,
&Len);

But the status is BUFFER_TOO_SMALL. Is this ok ?

You are telling it that your buffer is 0 bytes long. That’s going to be
too small for most registry keys. :wink:

Did you read the documentation for ZwQueryValueKey? Yes, that’s
expected. It will tell you how large the buffer needs to be in “Len”.
The next step should be to allocate a buffer Len bytes long in
pInfo_Partial, then call the API again passing that buffer to fetch the
real data.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks everyone, i’m surprised that MS didn’t provide a 1 step call.

Any one step call would require a step to free the result, depending on
what the use model is this is a one step call if you know how large a
buffer to use. The model is the standard one for Microsoft, learn the
basics.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@hotmail.com” wrote in message
news:xxxxx@ntdev:

> Thanks everyone, i’m surprised that MS didn’t provide a 1 step call.

With data of non-fixed size, wouldn’t the correct way be a loop to find
out the size and allocate the buffer on the first iteration, to hopefully
retrieve the data on the second iteration, and to reallocate and retry in
the unlikely event that the data’s size has increased in between those
previous calls on subsequent iterations?

> With data of non-fixed size, wouldn’t the correct way be a loop to find

out the size and allocate the buffer on the first iteration, to hopefully
retrieve the data on the second iteration, and to reallocate and retry in
the unlikely event that the data’s size has increased in between those
previous calls on subsequent iterations?

Absolutely. In fact, some MS APIs force you to use this approach as they don’t actually ever give you the right size, only a BUFFER_TOO_SMALL return code, and you need to “grow” your buffer in a loop until you have one big enough. IIRC, some of the volume management APIs work that way, for getting the volume label or something.

BULLSHIT, they give you the right size in the ResultLength value after
the first call which will return one of the buffer error codes. If you
are doing the loop you need to go back and take programming 101, and
please tell us the products you work on so we can avoid them like the
plague they are.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@NeoSmart.net” wrote in message
news:xxxxx@ntdev:

> > With data of non-fixed size, wouldn’t the correct way be a loop to find
> > out the size and allocate the buffer on the first iteration, to hopefully
> > retrieve the data on the second iteration, and to reallocate and retry in
> > the unlikely event that the data’s size has increased in between those
> > previous calls on subsequent iterations?
>
> Absolutely. In fact, some MS APIs force you to use this approach as they don’t actually ever give you the right size, only a BUFFER_TOO_SMALL return code, and you need to “grow” your buffer in a loop until you have one big enough. IIRC, some of the volume management APIs work that way, for getting the volume label or something.

99% of the time, there is no need for a loop, but to be safe, you do actually need a loop in case between the time of the query for size and the alloc, the size of the value could change. We actually had to fix wdfldr to accommodate this subtlety.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Don Burn
Sent: Thursday, November 11, 2010 4:32 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] ZwQueryValueKey returns STATUS_BUFFER_TOO_SMALL

BULLSHIT, they give you the right size in the ResultLength value after
the first call which will return one of the buffer error codes. If you
are doing the loop you need to go back and take programming 101, and please tell us the products you work on so we can avoid them like the plague they are.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@NeoSmart.net” wrote in message
news:xxxxx@ntdev:

> > With data of non-fixed size, wouldn’t the correct way be a loop to
> > find out the size and allocate the buffer on the first iteration, to
> > hopefully retrieve the data on the second iteration, and to
> > reallocate and retry in the unlikely event that the data’s size has
> > increased in between those previous calls on subsequent iterations?
>
> Absolutely. In fact, some MS APIs force you to use this approach as they don’t actually ever give you the right size, only a BUFFER_TOO_SMALL return code, and you need to “grow” your buffer in a loop until you have one big enough. IIRC, some of the volume management APIs work that way, for getting the volume label or something.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

> BULLSHIT, they give you the right size in the ResultLength value after

the first call which will return one of the buffer error codes. If you
are doing the loop you need to go back and take programming 101, and please tell
us the products you work on so we can avoid them like the plague they are.

Just to add to what Doron mentioned (which you may scoff at, but is a real issue if you’re working in kernel-space and there’s even the *remotest* chance that at the same time you make this call some other thread or a user will modify the contents of the key, replacing it with something larger), I would like to add that functions like DeviceIoControl do not even have a ResultLength value.

For example, when using IOCTL_DISK_GET_DRIVE_LAYOUT_EX… From MSDN: “If the output buffer is too small, the call fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and lpBytesReturned is zero.”

In this case, you need to grow the size of your buffer in a loop until you don’t get ERROR_INSUFFICIENT_BUFFER.

Of course, these aren’t concepts taught in Programming 101 and only gained after years of development on a very specific range of applications, whilst other people are pulling out their hair wondering why this line of code is failing at the most random of times.

You can find my programs at neosmart.net, feel free not to use them.

Ok, for the .001% case you have a valid point, but for what the OP was
asking it is still BULLSHIT. Yes there are dynamic cases but they are
extremely rare, and complicating the issue for the newbie just helps
them produce CRAP.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@NeoSmart.net” wrote in message
news:xxxxx@ntdev:

> > BULLSHIT, they give you the right size in the ResultLength value after
> > the first call which will return one of the buffer error codes. If you
> > are doing the loop you need to go back and take programming 101, and please tell
> > us the products you work on so we can avoid them like the plague they are.
>
> Just to add to what Doron mentioned (which you may scoff at, but is a real issue if you’re working in kernel-space and there’s even the remotest chance that at the same time you make this call some other thread or a user will modify the contents of the key, replacing it with something larger), I would like to add that functions like DeviceIoControl do not even have a ResultLength value.
>
> For example, when using IOCTL_DISK_GET_DRIVE_LAYOUT_EX… From MSDN: “If the output buffer is too small, the call fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and lpBytesReturned is zero.”
>
> In this case, you need to grow the size of your buffer in a loop until you don’t get ERROR_INSUFFICIENT_BUFFER.
>
> Of course, these aren’t concepts taught in Programming 101 and only gained after years of development on a very specific range of applications, whilst other people are pulling out their hair wondering why this line of code is failing at the most random of times.
>
> You can find my programs at neosmart.net, feel free not to use them.

When one expects a specific size, the straight-forward way is to hardcode
it and treat STATUS_BUFFER_TOO_SMALL like any other data corruption.
My point is that the two-call combo which was originally proposed (and is
widely used) is always formally incorrect as it leaves open the tiny
chance of a double failure. We do not argue about the probabilities of
other race conditions, do we?

On Fri, 12 Nov 2010 15:08:06 +0100, Don Burn wrote:
> Ok, for the .001% case you have a valid point, but for what the OP was
> asking it is still BULLSHIT. Yes there are dynamic cases but they are
> extremely rare, and complicating the issue for the newbie just helps
> them produce CRAP.
>
>
> Don Burn (MVP, Windows DKD)
> Windows Filesystem and Driver Consulting
> Website: http://www.windrvr.com
> Blog: http://msmvps.com/blogs/WinDrvr
>
>
>
>
> “xxxxx@NeoSmart.net” wrote in message
> news:xxxxx@ntdev:
>
>> > BULLSHIT, they give you the right size in the ResultLength value after
>> > the first call which will return one of the buffer error codes. If
>> you
>> > are doing the loop you need to go back and take programming 101, and
>> please tell
>> > us the products you work on so we can avoid them like the plague they
>> are.
>>
>> Just to add to what Doron mentioned (which you may scoff at, but is a
>> real issue if you’re working in kernel-space and there’s even the
>> remotest chance that at the same time you make this call some other
>> thread or a user will modify the contents of the key, replacing it with
>> something larger), I would like to add that functions like
>> DeviceIoControl do not even have a ResultLength value.
>>
>> For example, when using IOCTL_DISK_GET_DRIVE_LAYOUT_EX… From MSDN:
>> “If the output buffer is too small, the call fails, GetLastError
>> returns ERROR_INSUFFICIENT_BUFFER, and lpBytesReturned is zero.”
>>
>> In this case, you need to grow the size of your buffer in a loop until
>> you don’t get ERROR_INSUFFICIENT_BUFFER.
>>
>> Of course, these aren’t concepts taught in Programming 101 and only
>> gained after years of development on a very specific range of
>> applications, whilst other people are pulling out their hair wondering
>> why this line of code is failing at the most random of times.
>>
>> You can find my programs at neosmart.net, feel free not to use them.
>

Don, you seem to really like using that word :slight_smile:

The OP should have just googled STATUS_BUFFER_TOO_SMALL or ZwQueryValueKey. Both the MSDN and the OSR references (results #1 and #2 on Google) are very clear on the one-liner usage of ZwQueryValueKey, with a very succinct and to-the-point explanation of what a STATUS_BUFFER_TOO_SMALL return value means and what do about it. You’ll even note that in my first & second replies to the OP, I didn’t mention the loop.

But this is a mailing list for hard-core coding discussions, and Cay Bremer raised an important point and a good question, which was most-deserving of an explanation giving the loop answer. Even if it didn’t help the OP, it’s sure to help someone, someday.

>>you do actually need a loop in case between the time of the query for size and the alloc, the size of the value could change.

Another case is NtQuerySystemInformation, try SystemProcessInformation or similar and one can not really base it on returned size (process may get created between two calls),and hence the loop is required.

Your point was entirely valid and appropriate. It is negligibly more
difficult to handle this properly than to use the broken two-call
approach. I’ve no idea why Don feels the need to be so offensively rude
about it.

Cay Bremer wrote:

When one expects a specific size, the straight-forward way is to
hardcode it and treat STATUS_BUFFER_TOO_SMALL like any other data
corruption.
My point is that the two-call combo which was originally proposed (and
is widely used) is always formally incorrect as it leaves open the
tiny chance of a double failure. We do not argue about the probabilities
of other race conditions, do we?

On Fri, 12 Nov 2010 15:08:06 +0100, Don Burn wrote:
>> Ok, for the .001% case you have a valid point, but for what the OP was
>> asking it is still BULLSHIT. Yes there are dynamic cases but they are
>> extremely rare, and complicating the issue for the newbie just helps
>> them produce CRAP.
>>
>>
>> Don Burn (MVP, Windows DKD)
>> Windows Filesystem and Driver Consulting
>> Website: http://www.windrvr.com
>> Blog: http://msmvps.com/blogs/WinDrvr
>>
>>
>>
>>
>> “xxxxx@NeoSmart.net” wrote in
>> message news:xxxxx@ntdev:
>>
>>> > BULLSHIT, they give you the right size in the ResultLength value after
>>> > the first call which will return one of the buffer error codes.
>>> If you
>>> > are doing the loop you need to go back and take programming 101,
>>> and please tell
>>> > us the products you work on so we can avoid them like the plague
>>> they are.
>>>
>>> Just to add to what Doron mentioned (which you may scoff at, but is a
>>> real issue if you’re working in kernel-space and there’s even the
>>> remotest chance that at the same time you make this call some other
>>> thread or a user will modify the contents of the key, replacing it
>>> with something larger), I would like to add that functions like
>>> DeviceIoControl do not even have a ResultLength value.
>>>
>>> For example, when using IOCTL_DISK_GET_DRIVE_LAYOUT_EX… From
>>> MSDN: “If the output buffer is too small, the call fails,
>>> GetLastError returns ERROR_INSUFFICIENT_BUFFER, and lpBytesReturned
>>> is zero.”
>>>
>>> In this case, you need to grow the size of your buffer in a loop
>>> until you don’t get ERROR_INSUFFICIENT_BUFFER.
>>>
>>> Of course, these aren’t concepts taught in Programming 101 and only
>>> gained after years of development on a very specific range of
>>> applications, whilst other people are pulling out their hair
>>> wondering why this line of code is failing at the most random of times.
>>>
>>> You can find my programs at neosmart.net, feel free not to use them.
>>
>