> Hi everyone hope you are all well.
Using osrmemdrv.cpp as my guide I’m unable to access the memory allocated
by the userland test program. The steps taken are as follows:
In the userland test program:
pAllocMem = ( long * ) malloc( BufSize );
strncpy ( (char *) pAllocMem, “METHOD_OUT_DIRECT”, 17 );
Note that this will fail disastrously if BufSize < 17. Note also that the
string in pAllocMem will not have a terminal NUL character.
DeviceIoControl using overlapped I/O to pass driver pAllocMem
check ERROR_IO_PENDING which it is
So what happens when it is completed? Who frees the buffer? Where is
your OVERLAPPED structure? Why are you using variables whose scope and
lifetime are indeterminate from the information presented?
In the driver:
using METHOD_OUT_DIRECT
pOutputBuffer = (MmGetSystemAddressForMdlSafe ( pIrp->MdlAddress, …
and save the pOutputBuffer into pAdapt->pMyBuffers
exit this DeviceIoControl by:
pAdapt->MypIrp = pIrp; // to be IoCompleteRequest’d in a diff
DeviceIoControl
Where is pAdapt declared? Note that it must not e a global variable. I
have no idea what that comment means.
NtStatus = STATUS_PENDING;
IoMarkIrpPending ( pIrp );
Many things missing here. What happens if another DeviceIoControl arrives
before this one finishes? Where do you enqueue it? What does your
dequeue routine do? What value to you return?
In another part of the driver:
if pAdapt->pMyBuffers not zero [ts initd value]
pnxtbuf = pAdapt->pMyBuffers;
This makes it look like you are using a global variable. As a beginner,
take this advice: as soon as you declarea global or static variable,
unless it has the const qualifier, you have made a serious coding error.
You may also ignore the people who jump in and say I’m wrong, that there
are valid uses for non-const global variables. They are experts. They
are also right. But as a beginner, you have no idea of the trouble you
are about to get into if you use a global variable. Those of us who are
experts know when to use them and how to use them, and more facts about
their use than you can imagine. Until you understand what is going on,
global variables are a path to total disaster. So the first thing you
have to do is remove them. That’s what device extensions, controller
extensions, and FILE_OBJECT extensions are for. And you should know the
implications for each one. For now, the device extension is the likeliest
place to put these values.
When putting upa code snippet, you MUST show the declarations of all
variables used, and, most importantly, WHERE they are declared. Scope and
extent matter. A lot.
// next will BSOD - when NOT MDL. METHOD_OUT_DIRECT and IOComplete early.
ach = *pnxtbuf;
I then DBGPRINT ach %X but it is not the value put there by the userland
program.
Yes, and so what? It doesn’t work, sure, but where does this appear?
Where is pnxtbuf declared? Where is it set (you show code about HOW it is
set, but don’t explain where that code is). It can’t be a global
variable, but even after you fix that mistake, we still need to know WHERE
that line of code is. And, given you are testing a variable for NULL,
where is that variable RESET to NULL?
You have not explained anything about the structure of your driver, and
there is no concept of an IRP being completed “early”. An IRP is
completed when your driver is done with it, and it is your responsibility
to see that all state relevant to that IRP is properly “reset”.
Furthermore, there should be no execution path that is possible after the
IRP has completed that requires any state set on behalf of that IRP.
You’re in your ISR, and there’s no IRP? Well, that’s your responsibility
to check for. If your ISR is using values associated with some IRP that
has already completed, that is a programming error. Fix it. And what are
you going to do with the data that just arrived? You’d better have an
answer for that (“throw it away” could be a valid answer, but if it isn’t,
you need to handle it). I could even ask, “Why is your device still
interrupt-enabled if there is no active IRP for it?” and you’d better have
a good answer that matches well with the “What do you do if you get an
interrupt and there is no active IRP.” question (they are linked).
Generally, you have a “current IRP” pointer which points to the most
recent IRP you have dequeued, and which is set to NULL right before you
complete the IRP. Testing *this* pointer is what keeps you from executing
code paths that would depend on having a valid IRP.
What I think I am seeing is a driver which contains a huge number of
design and coding errors. The major design error seems to be in enqueing
and dequeing IRPs, and maintaing state for the current active IRP, if any
(and “if any” is important!).
joe
What is this newbie doing wrong? Please help this misguided individual.
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/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer