IoGetDevicePropertyData() bug checks with 0xF7

PVOID pDevicePropertyData = NULL;
DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
ULONG bufferLength = 0;

status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
pDevicePropertydataType
);
If the buffer is small as per the manual it should return BUFFER_TOO_SMALL and returnedLength should have the expected length and I am supposed to call it again. Instead of that it bug checks:

Bug Check 0xF7: DRIVER_OVERRAN_STACK_BUFFER

  • This indicates that a driver has overrun a stack-based buffer.
    I could never get a usage example of the IoGetDevicePropertyData() anywhere. Is this call broken?

Output of !analyze -v please

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Monday, April 2, 2012 9:29 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] IoGetDevicePropertyData() bug checks with 0xF7

PVOID pDevicePropertyData = NULL;
DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
ULONG bufferLength = 0;

status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
pDevicePropertydataType
);
If the buffer is small as per the manual it should return BUFFER_TOO_SMALL and returnedLength should have the expected length and I am supposed to call it again. Instead of that it bug checks:

Bug Check 0xF7: DRIVER_OVERRAN_STACK_BUFFER

  • This indicates that a driver has overrun a stack-based buffer.
    I could never get a usage example of the IoGetDevicePropertyData() anywhere. Is this call broken?

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

Very sorry I realized my mistake. I was at a higher IRQL when I should have been at <=APC_LEVEL. Please ignore my question. I shall try running the same call at lower IRQL and if it still fails will get back on this forum. Doran thanks for the quick response.

27: kd> !irql
Debugger saved IRQL for processor 0x1b – 2 (DISPATCH_LEVEL)

If you’re in the bugcheck stack, !irql is not correct.

You are right Alex but now indeed I am IRQL PASSIVE_LEVEL I checked, so IRQL is not the reason. Here is my dump:

Use !analyze -v to get detailed debugging information.

BugCheck F7, {fffff98002d9a4b0, f8800125f5af, ffff077ffeda0a50, 0}

Probably caused by : Florin64.sys ( Florin64!__GSHandlerCheck+13 )

Followup: MachineOwner

nt!RtlpBreakWithStatusInstruction:
fffff800`01688490 cc int 3
31: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

DRIVER_OVERRAN_STACK_BUFFER (f7)
A driver has overrun a stack-based buffer. This overrun could potentially
allow a malicious user to gain control of this machine.
DESCRIPTION
A driver overran a stack-based buffer (or local variable) in a way that would
have overwritten the function’s return address and jumped back to an arbitrary
address when the function returned. This is the classic “buffer overrun”
hacking attack and the system has been brought down to prevent a malicious user
from gaining complete control of it.
Do a kb to get a stack backtrace – the last routine on the stack before the
buffer overrun handlers and bugcheck call is the one that overran its local
variable(s).
Arguments:
Arg1: fffff98002d9a4b0, Actual security check cookie from the stack
Arg2: 0000f8800125f5af, Expected security check cookie
Arg3: ffff077ffeda0a50, Complement of the expected security check cookie
Arg4: 0000000000000000, zero

Debugging Details:

GSFAILURE_FUNCTION: Florin64!__GSHandlerCheck

GSFAILURE_MISSING_ESTABLISHER_FRAME: TRUE

GSFAILURE_MODULE_COOKIE: 0000f8800125f5af Florin64!__security_cookie [fffff8800125f100]

GSFAILURE_FRAME_COOKIE: ffffffffffffffff

SECURITY_COOKIE: Expected 0000f8800125f5af found fffff98002d9a4b0

GSFAILURE_ANALYSIS_TEXT: !gs output:
Establisher Frame not found: suspect corruption
Corruption occurred in Florin64!__GSHandlerCheck or one of its callers

Analyzing __report_gsfailure frame (5)…
LEA usage: Function @0xFFFFF8800125C7C8-0xFFFFF8800125C7DB is NOT using LEA
Module canary at 0xFFFFF8800125F100 (Florin64!__security_cookie): 0xF8800125F5AF
Complement at 0xFFFFF8800125F108: 0xFFFF077FFEDA0A50 (matches OK)
Couldn’t find Canary! Function is likely not using GS or dont know how to find the canary

Stack buffer overrun analysis completed successfully.

BUGCHECK_STR: STACK_BUFFER_OVERRUN

DEFAULT_BUCKET_ID: STACK_BUFFER_OVERRUN

PROCESS_NAME: System

CURRENT_IRQL: 2

STACK_TEXT:
fffff88002d98ad8 fffff80001777d92 : fffff98002d9a4b0 fffffa8302118680 0000000000000065 fffff800016cc178 : nt!RtlpBreakWithStatusInstruction
fffff88002d98ae0 fffff80001778b7e : ffff077f00000003 0000000000000000 fffff800016cc9d0 00000000000000f7 : nt!KiBugCheckDebugBreak+0x12
fffff88002d98b40 fffff80001690744 : fffff8a0000dc948 ffffffffffffffff 0000000000001000 fffff80001c03f02 : nt!KeBugCheck2+0x71e
fffff88002d99210 fffff8800125c72e : 00000000000000f7 fffff98002d9a4b0 0000f8800125f5af ffff077ffeda0a50 : nt!KeBugCheckEx+0x104
fffff88002d99250 fffff8800125c7db : fffff88002d99728 fffff88002d99720 fffff88002d99a00 fffff800016bc2a0 : Florin64!__report_gsfailure+0x26 [d:\5359\minkernel\tools\gs_support\kmode\gs_report.c @ 46]
fffff88002d99290 fffff800016bbf6d : fffff800018a6aa0 fffff800017d43fc fffff80001610000 fffff88002d9a1a8 : Florin64!__GSHandlerCheck+0x13 [d:\5359\minkernel\crts\crtw32\misc\amd64\gshandler.c @ 93]
fffff88002d992c0 fffff800016bad45 : fffff8800125e4c0 fffff88002d99338 fffff88002d9a1a8 fffff88001256000 : nt!RtlpExecuteHandlerForException+0xd
fffff88002d992f0 fffff800016cbdc1 : fffff88002d9a1a8 fffff88002d99a00 fffff88000000000 0000000000000000 : nt!RtlDispatchException+0x415
fffff88002d999d0 fffff8000168fcc2 : fffff88002d9a1a8 0000000000000000 fffff88002d9a250 fffff88002d9a530 : nt!KiDispatchException+0x135
fffff88002d9a070 fffff8000168e83a : 0000000000000001 0000000000000000 fffff8a001695600 0000000000000000 : nt!KiExceptionDispatch+0xc2
fffff88002d9a250 fffff800019c830a : fffffa8302973a10 fffff88002d9a530 0000000000000000 0000000000000000 : nt!KiPageFault+0x23a
fffff88002d9a3e0 fffff800018fee42 : fffffa8302973a10 0000000000000002 0000000000000000 fffffa8302973a10 : nt! ?? ::NNGAKEGL::string'+0x1cc5f fffff88002d9a460 fffff88001261622 : 0000000000000001 fffffa8302973a10 fffff8800125e2a4 fffff8800125e2a4 : nt!IoGetDevicePropertyData+0x7a fffff88002d9a4b0 ed00000000800103 : 0100000000000000 0000030200000000 0000000b0000000b 00000000ffffffff : Florin64!FlorinAddDevice+0x612 [d:\work\pcie\florin\3.0\sys\florin.c @ 525] fffff88002d9a5a0 0100000000000000 : 0000030200000000 0000000b0000000b 00000000ffffffff fffff88001261010 : 0xed00000000800103
fffff88002d9a5a8 0000030200000000 : 0000000b0000000b 00000000ffffffff fffff88001261010 fffffa8302973740 : 0x100000000000000 fffff88002d9a5b0 0000000b0000000b : 00000000ffffffff fffff88001261010 fffffa8302973740 fffff88001261010 : 0x30200000000
fffff88002d9a5b8 00000000ffffffff : fffff88001261010 fffffa8302973740 fffff88001261010 fffff80001a713f5 : 0xb0000000b fffff88002d9a5c0 fffff8800126100f : fffffa8302973740 fffff88001261010 fffff80001a713f5 0000000000000001 : 0xffffffff fffff88002d9a5c8 fffffa8302973740 : fffff88001261010 fffff80001a713f5 0000000000000001 fffffa830304ed80 : Florin64!__PchSym_ <perf> (Florin64+0xb00f)<br>fffff88002d9a5d0 fffff8800126100f : fffff80001a713f5 0000000000000001 fffffa830304ed80 0000000000000002 : 0xfffffa8302973740
fffff88002d9a5d8 fffff80001a713f5 : 0000000000000001 fffffa830304ed80 0000000000000002 fffffa8302973740 : Florin64!_PchSym (Florin64+0xb00f)
fffff88002d9a5e0 fffff80001a78921 : fffffa8302973740 fffffa8302973740 0000000000000000 0000000000000000 : nt!PnpCallAddDevice+0xd5
fffff88002d9a660 fffff80001a79eb2 : fffffa8302153850 fffffa8302973740 0000000000000002 fffffa83021670f0 : nt!PipCallDriverAddDevice+0x661
fffff88002d9a810 fffff80001a7a34c : fffff80001889d00 0000000000000000 0000000000000000 0000000000000000 : nt!PipProcessDevNodeTree+0x2b2
fffff88002d9aa80 fffff80001789b72 : 0000000100000003 0000000000000000 0000000032706e50 0000000000000000 : nt!PiProcessStartSystemDevices+0x7c
fffff88002d9aad0 fffff8000169aa21 : fffff80001789870 fffff80001986f01 fffffa8302118600 0000000000000000 : nt!PnpDeviceActionWorker+0x302
fffff88002d9ab70 fffff8000192dcce : 0f12000a424b4e4c fffffa8302118680 0000000000000080 fffffa830204db30 : nt!ExpWorkerThread+0x111
fffff88002d9ac00 fffff80001681fe6 : fffff88002440180 fffffa8302118680 fffff8800244b6c0 010a001cffff0c04 : nt!PspSystemThreadStartup+0x5a
fffff88002d9ac40 0000000000000000 : fffff88002d9b000 fffff88002d95000 fffff88002d9a3f0 0000000000000000 : nt!KxStartSystemThread+0x16

STACK_COMMAND: kb

FOLLOWUP_IP:
Florin64!__GSHandlerCheck+13 [d:\5359\minkernel\crts\crtw32\misc\amd64\gshandler.c @ 93]
fffff880`0125c7db b801000000 mov eax,1

FAULTING_SOURCE_CODE:
No source found for ‘d:\5359\minkernel\crts\crtw32\misc\amd64\gshandler.c’

SYMBOL_STACK_INDEX: 5

SYMBOL_NAME: Florin64! GSHandlerCheck+13

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: Florin64

IMAGE_NAME: Florin64.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 4f79df0d

FAILURE_BUCKET_ID: X64_STACK_BUFFER_OVERRUN_MISMATCH_GSCOOKIE_Florin64!
GSHandlerCheck+13

BUCKET_ID: X64_STACK_BUFFER_OVERRUN_MISMATCH_GSCOOKIE_Florin64!__GSHandlerCheck+13

Followup: MachineOwner
---------

xxxxx@gmail.com wrote:

PVOID pDevicePropertyData = NULL;
DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
ULONG bufferLength = 0;

status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
pDevicePropertydataType
);

The very last parameter is not supposed to be a PDEVPROPTYPE passed by
value. It’s supposed to be a DEVPROPTYPE passed by address, which the
function will fill in:

DEVPROPTYPE DevicePropertydataType;

&DevicePropertydataType
);


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

:frowning: No luck. Same bug check Tim

PVOID pDevicePropertyData = NULL;
DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
ULONG bufferLength = 0;
DEVPROPTYPE devicePropertydataType;

status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
&devicePropertydataType
);

xxxxx@gmail.com wrote:

:frowning: No luck. Same bug check Tim

Your code will have two calls to IoGetDevicePropertyData – one to fetch
the length, one to fetch the property after you allocate the buffer.
Are you quite sure this is the call that is failing?

If so, then you’ll have to trace into this and figure out where it’s
going awry.


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

Given the check gs error, you are passing in a pointer to local, but telling the API that this pointer is larger than its size on the stack. the API then writes into the pointer to the local and beyond it, trashing the gs cookie, thus causing the bugcheck. Look at the parameters you pass and the sizes you say they are. Also, run prefast/oacr against the code, it might tell you what you are doing wrong.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, April 02, 2012 1:31 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] IoGetDevicePropertyData() bug checks with 0xF7

xxxxx@gmail.com wrote:

:frowning: No luck. Same bug check Tim

Your code will have two calls to IoGetDevicePropertyData – one to fetch the length, one to fetch the property after you allocate the buffer.
Are you quite sure this is the call that is failing?

If so, then you’ll have to trace into this and figure out where it’s going awry.


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


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

Make pDevicePropertyData point to a small buffer, instead of NULL.

Your stack frame is probably previously corrupted by another call. You can find that out by finding bugcheck arg1 on the stack, and checking which local variable it follows (see the locals’ addresses in Windbg locals window).

When the bugcheck happens, the fault handler is going through the chain of exception handlers. In that course, it’s validating stack frames. Your stack frame is corrupted.

Folks,

Thanks to all for the ideas and way to debug. If not for this issue I will find these tips good for other issues I am going to run. However I am happy to say this simple innocuous call solved my problem.

status = IoGetDeviceNumaNode(FdoData->UnderlyingPDO, &nodeNumber);

A colleague suggested this and it just worked without any compunction. I moved my device around and for sure the nodeNumber changed and was always the physically nearest to my device. I learnt a lot through this series of emails. Thanks again. This case me be deemed as closed.

Now, does anybody know ahow to allocate a common buffer on the specific node, to avoid DMA having to travel far?

Wow! You asked my question Alex. That was my ultimate idea. My hope was to use
PVOID MmAllocateContiguousMemorySpecifyCacheNode(
__in SIZE_T NumberOfBytes,
__in PHYSICAL_ADDRESS LowestAcceptableAddress,
__in PHYSICAL_ADDRESS HighestAcceptableAddress,
__in_opt PHYSICAL_ADDRESS BoundaryAddressMultiple,
__in MEMORY_CACHING_TYPE CacheType,
__in NODE_REQUIREMENT PreferredNode
);
Would this work?

> :frowning: No luck. Same bug check Tim

PVOID pDevicePropertyData = NULL;
DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
ULONG bufferLength = 0;
DEVPROPTYPE devicePropertydataType;

status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
&devicePropertydataType
);
****
Note that you are calling it with a buffer length of 0 and a NULL pointer.
I did not see in the MSDN where this is a valid combination. Presumably
it should be expected to return the correct value in &returnLength, but
the docs are silent on this. And if you want to pass in 0,NULL, then the
correct thing to do is pass in the values 0, NULL; you don’t need to use
variables to hold these values!
****


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

xxxxx@flounder.com wrote:

> :frowning: No luck. Same bug check Tim
> …
> PVOID pDevicePropertyData = NULL;
> DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
> ULONG bufferLength = 0;
> DEVPROPTYPE devicePropertydataType;
>
>
> status = IoGetDevicePropertyData(
> FdoData->UnderlyingPDO, // PhysicalDeviceObject
> &propertyKey,
> LOCALE_NEUTRAL,
> 0,
> bufferLength,
> pDevicePropertyData,
> &returnedLength,
> &devicePropertydataType
> );
Note that you are calling it with a buffer length of 0 and a NULL pointer.
I did not see in the MSDN where this is a valid combination. Presumably
it should be expected to return the correct value in &returnLength, but
the docs are silent on this. And if you want to pass in 0,NULL, then the
correct thing to do is pass in the values 0, NULL; you don’t need to use
variables to hold these values!

Of course, Joe knows that there is absolutely no difference between
those. The function will see two zeros. It doesn’t care whether they
are constants or variables passed by value.

We’re not seeing all of the code here. I would not be surprised if this
were in “while” loop, where the first iteration passes these zeros, and
when the call completes, it shoves numbers in those variables and loops
again.


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

Finally I got it to working. Thanks to all of you for contributing to the success. Here is the working code. I have given both the method:
Method 1 to get the nearest Node to a given device:
DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
ULONG bufferLength = 100; // Hopefully big enough size
PVOID pDevicePropertyData;
DEVPROPTYPE devicePropertydataType;
ULONG returnedLength;

pDevicePropertyData = ExAllocatePoolWithTag(NonPagedPool, bufferLength, FLORIN_TAG);
if (pDevicePropertyData == NULL) {
DbgPrintEx(DID, TRACE, “First ExAllocatePoolWithTag failed\n”);
return(status);
}

status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
&devicePropertydataType
);

if (status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL) {
DbgPrintEx(DID, TRACE, “First IoGetDevicePropertyData failed\n”);
return(status);
}
if (status == STATUS_BUFFER_TOO_SMALL) {
ExFreePoolWithTag(pDevicePropertyData, FLORIN_TAG);
bufferLength = returnedLength;
pDevicePropertyData = ExAllocatePoolWithTag(NonPagedPool, bufferLength, FLORIN_TAG);
if (pDevicePropertyData == NULL) {
DbgPrintEx(DID, TRACE, “Second ExAllocatePoolWithTag failed\n”);
return(status);
}
status = IoGetDevicePropertyData(
FdoData->UnderlyingPDO, // PhysicalDeviceObject
&propertyKey,
LOCALE_NEUTRAL,
0,
bufferLength,
pDevicePropertyData,
&returnedLength,
&devicePropertydataType
);
if (status != STATUS_SUCCESS) {
DbgPrintEx(DID, TRACE, “Second IoGetDevicePropertyData failed\n”);
return(status);
}
}

Method 2 to get the nearest Node to a given device:
// This one puny line replaces the whole above circus :slight_smile:
USHORT nodeNumber;
status = IoGetDeviceNumaNode(FdoData->UnderlyingPDO, &nodeNumber);

Whew! I am done. Just for curiosity when I dump pDevicePropertyData:

0: kd> dd 0xfffffa83032230b0 fffffa83032230b0 00000001 00000000 008001b0 fffff880 –> 1 is the node number
fffffa83032230c0 00044042 00000000 00380036 00000000 fffffa83032230d0 092492e0 fffff8a0 00000000 00000000
fffffa83032230e0 00000000 00000000 00000000 00000000 fffffa83032230f0 00060001 00000000 032230f8 fffffa83
fffffa8303223100 032230f8 fffffa83 00060000 00000000 fffffa8303223110 03223110 fffffa83 03223110 fffffa83
fffffa83`03223120 040a0008 ee657645 00000000 00000000

Question is to what structure do I typecast pDevicePropertyData when the key is DEVPKEY_Device_Numa_Node? I tried to get this out of MSDN but it would not yield it. A URL or a header file which has all the typedef would be much appreciated.

Make sure to free the buffers on failure exits. So far there are two points where you forget to do that.

Good point. Thanks Alex, will do but as a I said i am not using method 1. I will be using method 2. If some one can answer my last question that would be nice. I feel all I have to typecast it to a ULONG but cant seem to justify it …

I find that quite often people feel *compelled* to create variables to
hold constant values, because the parameters say DWORD so they have to
have a DWORD variable. Uusually, this variable is declared at the head of
the function, and serves no purpose other than to hold the 0 value.

If this code fragment is incomplete, the OP should do a better job of
posting code fragments! Given what I see here, which is all I can believe
exists, the use of variables seems entirely gratuitous.

However, I read the docs and nowhere do they say the pointer is allowed to
be NULL.
joe

xxxxx@flounder.com wrote:
>> :frowning: No luck. Same bug check Tim
>> …
>> PVOID pDevicePropertyData = NULL;
>> DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
>> ULONG bufferLength = 0;
>> DEVPROPTYPE devicePropertydataType;
>>
>>
>> status = IoGetDevicePropertyData(
>> FdoData->UnderlyingPDO, // PhysicalDeviceObject
>> &propertyKey,
>> LOCALE_NEUTRAL,
>> 0,
>> bufferLength,
>> pDevicePropertyData,
>> &returnedLength,
>> &devicePropertydataType
>> );
> Note that you are calling it with a buffer length of 0 and a NULL
> pointer.
> I did not see in the MSDN where this is a valid combination. Presumably
> it should be expected to return the correct value in &returnLength, but
> the docs are silent on this. And if you want to pass in 0,NULL, then
> the
> correct thing to do is pass in the values 0, NULL; you don’t need to use
> variables to hold these values!

Of course, Joe knows that there is absolutely no difference between
those. The function will see two zeros. It doesn’t care whether they
are constants or variables passed by value.

We’re not seeing all of the code here. I would not be surprised if this
were in “while” loop, where the first iteration passes these zeros, and
when the call completes, it shoves numbers in those variables and loops
again.


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


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

>However, I read the docs and nowhere do they say the pointer is allowed to

be NULL.

The WDK docs can be incomplete or misleading. It’s in cases like this that
it would be exceptionally helpful to have a clear example of how to call the
API. I’m always amazed whenever I have to call a Win32 API and there’s a
nice, clean example of how to use the API in a useful way.

However, as a standard pattern with NT APIs, if the API returns
STATUS_BUFFER_TOO_SMALL it’s typically fine to pass a length of zero and a
NULL buffer pointer to retrieve the size to allocate (what else would you
pass?). Note that this is distinct from APIs that return
STATUS_BUFFER_OVERFLOW, which usually requires that you pass in some fixed
length buffer to determine the actual buffer length that you need to
allocate. In this particular case, a well placed breakpoint during boot will
show that the in box drivers call this API with a length of zero and a NULL
pointer to retrieve the size required.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

wrote in message news:xxxxx@ntdev…

I find that quite often people feel *compelled* to create variables to
hold constant values, because the parameters say DWORD so they have to
have a DWORD variable. Uusually, this variable is declared at the head of
the function, and serves no purpose other than to hold the 0 value.

If this code fragment is incomplete, the OP should do a better job of
posting code fragments! Given what I see here, which is all I can believe
exists, the use of variables seems entirely gratuitous.

However, I read the docs and nowhere do they say the pointer is allowed to
be NULL.
joe

xxxxx@flounder.com wrote:
>> :frowning: No luck. Same bug check Tim
>> …
>> PVOID pDevicePropertyData = NULL;
>> DEVPROPKEY propertyKey = DEVPKEY_Device_Numa_Node;
>> ULONG bufferLength = 0;
>> DEVPROPTYPE devicePropertydataType;
>>
>>
>> status = IoGetDevicePropertyData(
>> FdoData->UnderlyingPDO, // PhysicalDeviceObject
>> &propertyKey,
>> LOCALE_NEUTRAL,
>> 0,
>> bufferLength,
>> pDevicePropertyData,
>> &returnedLength,
>> &devicePropertydataType
>> );
> Note that you are calling it with a buffer length of 0 and a NULL
> pointer.
> I did not see in the MSDN where this is a valid combination. Presumably
> it should be expected to return the correct value in &returnLength, but
> the docs are silent on this. And if you want to pass in 0,NULL, then
> the
> correct thing to do is pass in the values 0, NULL; you don’t need to use
> variables to hold these values!

Of course, Joe knows that there is absolutely no difference between
those. The function will see two zeros. It doesn’t care whether they
are constants or variables passed by value.

We’re not seeing all of the code here. I would not be surprised if this
were in “while” loop, where the first iteration passes these zeros, and
when the call completes, it shoves numbers in those variables and loops
again.


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


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