> OK. Heres failing code:
NTSTATUS
MyVolFltEvtDeviceAdd(In WDFDRIVER Driver, Inout PWDFDEVICE_INIT
DeviceInit)
/*++
Routine Description:EvtDeviceAdd is called by the framework in response to AddDevice
call from the PnP manager. We create and initialize a device object to
represent a new instance of the device.Arguments:
Driver - Handle to a framework driver object created in DriverEntry
DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure.
Return Value:
NTSTATUS
–*/
{
NTSTATUS status;PAGED_CODE();
UNREFERENCED_PARAMETER(Driver);
//PDEVICE_OBJECT Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
DECLARE_UNICODE_STRING_SIZE(name, 256);
I am sort of curious how you determined that 256 is a valid value here.
In app space, it is 261 characters, and there is a manifest constant that
is used to get this value, MAX_PATH. I presume there is a similar
constant defined in ntddk.h, and that’s what you should use here.
ULONG retLen;
status = WdfFdoInitQueryProperty(DeviceInit, DevicePropertyClassGuid,
sizeof(name_buffer), name.Buffer, &retLen);
I don’t know the spec for this, but in app space it is a common error to
use sizeof() on a Unicode string but the APIs want character count, not
byte count. In the kernel, string counts in UNICODE_STRINGs are in bytes,
but be sure you double-check this. And it would probably make sense that
you store the result in the name.Length field. But what is name_buffer?
I don’t see it declared anywhere, and the UNICODE_STRING would not have a
meaningful sizeof(). The value is likely to be name.MaxLength or whatever
the field is (I can’t check it right now, and I’m trusting a very rusty
memory that has not had to look at a UNICODE_STRING in several years. I
note that retLen is not declared anywhere, either. It should be a local
variable. You can’t post code that has undefined variables; we don’t know
where they are declared, or even their types.
I’m sure you understand its running on passive IRQL:
1: kd> !irql
Debugger saved IRQL for processor 0x1 – 0 (LOW_LEVEL)FAULTING_SOURCE_FILE: c:\program files (x86)\windows
kits\8.1\include\wdf\kmdf\1.11\wdffdo.hFAULTING_SOURCE_LINE_NUMBER: 202
FAULTING_SOURCE_CODE:
198: PULONG ResultLength
199: )
200: {
201: return ((PFN_WDFFDOINITQUERYPROPERTY)
WdfFunctions[WdfFdoInitQueryPropertyTableIndex])(WdfDriverGlobals,
DeviceInit, DeviceProperty, BufferLength, PropertyBuffer,
ResultLength);
While it is nice that C and C++ let you compose long and complex
expressions like this, you will find it a LOT easier to debug if you break
this into about four lines of code. It becomes easier to debug. Even in
C, you can make this more readable by declaring any variables you need in
a local scope, e.g.,
{
SOMETYPE st;
ANOTHERVAR v;
st = …some computation…;
v = …some computation based on st…;
return v;
}
In C++, you don’t need to declare the variables until they are used, but I
often use this technique to give very limited scope to temporary variables
I might need.
There are many things that can go wrong here; WdfFunctions at that index
may have an invalid address or have been damaged by some bad pointer work.
But it looks like you made one of the silliest possible errors. You read
the documentation of the function, and it said “PULONG ResultLength”. So
you assumed you had to have a variable of type PULONG that you would pass
in, which means you have no idea how C works. So you declared a variable
of type PULONG. Did you initialize it? If you did not initialize it, it
holds garbage. If your luck is good, the value that is in this
uninitialized variable will cause a BSOD; if your luck is bad, it will be
a pointer to something important and that something important will be
clobbered.
The correct way, which you would know if you understood C/C++, would be
ULONG ResultLength;
…(WdfDriverGlobals, …, &ResultLength)
I suggest reading about pointers in C, and fully understand what a pointer
is, and does, and how they are created. &ResultLength creates a PULONG
referencing the ULONG ResultLength. This is beginner’s C knowledge.
Learn the language you are programming in. The specification of a type of
an argument to a function DOES NOT MEAN YOU NEED A VARIABLE OF THAT TYPE.
It means you need an /expression/ of that type. So, for example, if
ResultLength is a ULONG, the expression &ResultLength is a PULONG. And
that satisfies the requirement of the function prototype. You simply
passed an uninitialized variable in; if you had set your warning level to
4, I think it would have caught this, and certainly if you used the
/ANALYZE option which runs The Program Formerly Known As Prefast, that
would definitely have caught it. So you need to understand how to
properly use the tool chain that creates a driver. /W3 is simply
inadequate for most serious programming.
> 202: }
PAGE_FAULT_IN_NONPAGED_AREA (50)
Yep, you have been lucky. You got a BSOD instead of clobbering something
important.
You need a good remedial course in the C language.
joe
Invalid system memory was referenced. This cannot be protected by
try-except,
it must be protected by a Probe. Typically the address is just plain bad
or it
is pointing at freed memory.
Arguments:
Arg1: ffffe00020464c10, memory referenced.Arg1 is DeviceInit.
Is this a debugger side-effect? Since it doesn’t happen when there is no
debugger attached or when I just don’t step over at that point.
NTDEV is sponsored by OSR
Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
OSR is HIRING!! See http://www.osr.com/careers
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminarsTo unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer