IoBuildAsynchronousFsdRequest with IRP_MJ_WRITE - c++

I developed a WDM filter driver on disk driver. I want to send an asynchronous request to write data on disk. The windows will crash when I delete the writeBuffer memory in WriteDataIRPCompletion function.
My question is: How can I safely free the writeBuffer memory without crashing?
This my send request code:
#pragma PAGEDCODE
NTSTATUS WriteToDeviceRoutine() {
PMYDRIVER_WRITE_CONTEXT context = (PMYDRIVER_WRITE_CONTEXT)ExAllocatePool(NonPagedPool,sizeof(PMYDRIVER_WRITE_CONTEXT));
context->writeBuffer = new(NonPagedPool) unsigned char[4096];
PIRP pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
pdx->LowerDeviceObject,
context->writeBuffer,(wroteRecordNodeCount<<SHIFT_BIT),
&startingOffset,NULL);
IoSetCompletionRoutine(pNewIrp,WriteDataIRPCompletion,context,TRUE,TRUE,TRUE);
IoCallDriver(pdx->LowerDeviceObject,pNewIrp);
}
This is my completion routine code:
#pragma LOCKEDCODE
NTSTATUS WriteDataIRPCompletion(IN PDEVICE_OBJECT DeviceObject,IN PIRP driverIrp,IN PVOID Context) {
PMDL mdl,nextMdl;
KdPrint((" WriteDataIRPCompletion \n"));
PMYDRIVER_WRITE_CONTEXT writeContext = (PMYDRIVER_WRITE_CONTEXT) Context;
if(driverIrp->MdlAddress!=NULL){
for(mdl=driverIrp->MdlAddress;mdl!=NULL;mdl = nextMdl) {
nextMdl = mdl->Next;
MmUnlockPages(mdl);
IoFreeMdl(mdl);
KdPrint(("mdl clear\n"));
}
driverIrp->MdlAddress = NULL;
}
delete [] writeContext->writeBuffer;
if(Context)
ExFreePool(Context);
KdPrint(("leave WriteDataIRPCompletion \n"));
return STATUS_CONTINUE_COMPLETION;
}

you error in next line
context = ExAllocatePool(NonPagedPool,sizeof(PMYDRIVER_WRITE_CONTEXT));
when must be
context = ExAllocatePool(NonPagedPool,sizeof(MYDRIVER_WRITE_CONTEXT));
not sizeof(PMYDRIVER_WRITE_CONTEXT) but sizeof(MYDRIVER_WRITE_CONTEXT) you allocate not structure but pointer to it.
this not produce error only if your MYDRIVER_WRITE_CONTEXT containing single field writeBuffer and no more data. otherwise you overwrite allocated memory (which is only sizeof(PVOID)) and this create bug
and about completion for IoBuildAsynchronousFsdRequest. unfortunately documentation not very good. here sated that
Before calling IoFreeIrp, an additional step is required to free the
buffer for an IRP built by IoBuildAsynchronousFsdRequest if the
following are all true:
The buffer was allocated from system memory pool.
but then all attention for
The Irp->MdlAddress field is non-NULL.
however we must check and for IRP_DEALLOCATE_BUFFER|IRP_BUFFERED_IO, without this we can leak Irp->AssociatedIrp.SystemBuffer. need next code
if (Irp->Flags & IRP_BUFFERED_IO)
{
if (Irp->Flags & IRP_INPUT_OPERATION)
{
if (!NT_ERROR(Irp->IoStatus.Status) && Irp->IoStatus.Information)
{
memcpy( Irp->UserBuffer, Irp->AssociatedIrp.SystemBuffer, Irp->IoStatus.Information );
}
}
if (Irp->Flags & IRP_DEALLOCATE_BUFFER)
{
ExFreePool(Irp->AssociatedIrp.SystemBuffer);
Irp->AssociatedIrp.SystemBuffer = 0;
}
Irp->Flags &= ~(IRP_DEALLOCATE_BUFFER|IRP_BUFFERED_IO);
}
and check for if (writeContext) after use writeContext->writeBuffer already senseless and nosense. really you need do check for context != NULL yet in WriteToDeviceRoutine()

I'm not too familiar with the specifics of what you're working with, so here're a few details that caught my attention.
In WriteDataIRPCompletion function
PMYDRIVER_WRITE_CONTEXT writeContext = (PMYDRIVER_WRITE_CONTEXT) Context;
// ...
delete [] writeContext->writeBuffer;
if(Context)
ExFreePool(Context);
Notice that your writeContext originates from your Context argument. However, you seem to be deleting/freeing the allocated memory twice.
The ExFreePool function docs state:
Specifies the address of the block of pool memory being deallocated.
It looks like the delete [] writeContext->writeBuffer; line might be causing the problem and it just needs to be removed.
As it is right now, part of the memory that should be freed by the function has already been manually deleted by the time you invoke ExFreePool, but not set to NULL, which in turn causes ExFreePool to receive a now-invalid pointer (i.e. a non-null pointer pointing to de-allocated memory) in its Context argument, causing the crash.
In WriteToDeviceRoutine function
The documentation for ExFreePool explicitly states that it deallocates memory that has been allocated with other functions, such as ExAllocatePool and other friends.
However, your code is trying to allocate/deallocate the writeContext->writeBuffer directly using the new/delete operators respectively. It seems like you should be allocating your memory with ExAllocatePool and then deallocating with ExFreePool instead of trying to do things manually like that.
These functions may be organizing the memory in a specific way and if/when this pre-condition is not met in ExFreePool, it could end up in a crash.
On a separate note, it seems odd that you check if(Context) is null before invoking ExFreePool, but not above before you try to type-cast for your local writeContext variable and use it.
Maybe you should also check at that first point of use? If Context is always non-null, then the check might also be unnecessary prior to invoking ExFreePool.

Related

Pass an object to another thread with AfxBeginThread

My program has a callback function which is called to handle notifications that are received in the form of objects. Because we can handle hundreds a second, this callback function handles the events by spawning a separate thread to handle each one. This is the callback function:
void _OnEvent(LPCTSTR eventID, CNotification cNotificaton) {
if (_pActiveDoc) {
Param_Event* p = new Param_Event;
p->pDoc = _pActiveDoc;
p->lpszEventID = eventID;
p->cNotification = cNotification;
AfxBeginThread(ProcessEvent,p);
}
}
My query comes from the fact that is passed to the callback method is initially created on the stack, and is therefore (according to my understanding) limited to the scope of the calling method:
void CallingMethod(CString strEventID) {
CNotification cNotification;
// Fill in the details of the notification
_OnEvent(strEventID,cNotification);
}
CNotification has a full copy constructor, and since the Param_Event object is created on the heap, my belief was that this would allow the original CNotification object to fall out of scope safely, with the spawned thread working from its own "private" CNotification object that exists until the Param_Event object is deleted with delete. The fact is, however, that we are getting (rare but occasional) crashing, and I am wondering if perhaps my belief here is incorrect: is it possible that the spawned thread is still accessing the original object somehow? If this was the case, this would explain the crashing by the rare occurrence of the object both falling out of scope and being overwritten in memory, thus creating a memory access exception.
Could I be right? Is there anything actually wrong with the method I am using? Would it be safer create the notification object on the heap initially (this would mean changing a lot of our code), or building a new object on the heap to pass to the spawned thread?
For reference, here is my ProcessEvent() method:
Param_TelephoneEvent *p = (Param_TelephoneEvent*)lParam;
p->pDoc->OnTelephoneEvent(p->lpszEventID,p->cNotification);
delete p;
return 0;
All advice welcome. Thanks in advance!
Edit: Copy constructor:
CNotification& CNotification::operator=(const CNotification &rhs)
{
m_eamspeMostRecentEvent = rhs.m_eamspeMostRecentEvent;
m_eamtcsCallStatusAtEvent = rhs.m_eamtcsCallStatusAtEvent;
m_bInbound = rhs.m_bInbound;
strcpy(m_tcExtension , rhs.m_tcExtension);
strcpy(m_tcNumber, rhs.m_tcNumber);
strcpy(m_tcName,rhs.m_tcName);
strcpy(m_tcDDI,rhs.m_tcDDI);
strcpy(m_tcCallID,rhs.m_tcCallID);
strcpy(m_tcInterTelEvent,rhs.m_tcInterTelEvent);
m_dTimestamp = rhs.m_dTimestamp;
m_dStartTime = rhs.m_dStartTime;
m_nCallID = rhs.m_nCallID;
return *this;
}

Programmatically deallocate memory in libstagrab

When and how do we free the memory when using libstatgrab. I didn't see any function call like sg_free that deallocates the memory object for storing the system statistics. For example:
sg_init(1);
sg_drop_privileges()
sg_load_stats *load_stat;
while(load_stat = sg_get_load_stats(NULL) != NULL) {
cout << load_stat->min1 << load_stat->min5 << load_stat->min15);
}
The above while loop keeps calling the sg_get_load_stats function to get the cpu load. Does it use internal buffer or create a new one every time it is called? If the later is true, shouldn't we free the object? Thanks.
The Documentation appears to state that sg_get_load_stats() has local scope and is handled by the libstatgrab library.
sg_get_load_stats_r(), which is presumably used to return the value of the stats out of the current scope, dynamically allocates and the resulting buffer needs to be cleaned up by the user.

global handler invokation

I have overloaded new function but unfortunetly never been able to execute global handler for requesting more memory access on my compiler. I also don't understand as per below code snippet if we invoke the
global handler for requesting more memory how it is gling to allocate to P.
I appreciate if anybody can through some light on this
void * Pool:: operator new ( size_t size ) throw( const char *)
{
int n=0;
while(1)
{
void *p = malloc (100000000L);
if(p==0)
{
new_handler ghd= set_new_handler(0);//deinstall curent handler
set_new_handler(ghd);// install global handler for more memory access
if(ghd)
(*ghd)();
else
throw "out of memory exception";
}
else
{
return p;
}
}
}
To have any effect, some other part of the program must have installed a global handler previously. That handler must also have some kind of memory to release when the handler is called (perhaps some buffers or cache that can be discarded).
The default new_handler is just a null pointer, so your code is very likely to end up throwing an exception.
Also, I would have thrown a bad_alloc exception to be consistent with other operator new overloads.
Here are two things to discuss, the first is using new_handler, the second is overloading operator new.
set_new_handler()
When you want use a new_handler, you have to register it. It is typically the first thing to do after entering main(). The handler should also be provided by you.
#include <iostream>
#include <new>
void noMemory() throw()
{
std::cout << "no memory" << std::endl;
exit(-1);
}
int main()
{
set_new_handler(noMemory);
// this will probably fail and noMemory() will be called
char *c = new char[100000000L];
std::cout << "end" << std::endl;
}
When no memory can be allocated, your registered handler will be called, and you have the chance to free up some memory. When the handler returns, operator new will give another try to allocate the amount of memory you requested.
operator new
The structure of the default operator new is something similar you presented. From the point of the new_handler the important part is the while(1) loop, since it is responsible for trying to get memory after called the new_handler.
There is two way out of this while(1) loop:
getting a valid pointer
throwing an exception
You have to have this in mind when you provide a new_handler, because if you can not do anything to free up memory you should deinstall the handler (or terminating or throwing an exception), otherwise you can stuck in an endless loop.
I guess omitting parameter size in your code is just for test purpose.
Also see Scott Meyers' Effective C++ Item 7 for details. As operator new must return a valid pointer even with parameter size = 0, the first thing to do in your operator new should be overwriting size to 1 in case of the user want to allocate 0 number of bytes. This trick is simple and fairly effective.

ExtAudioFileOpenURL leak

I am opening an audio file to read it and I get an abandoned malloc block from this caller each time.
In a loop I set data like this (which is marked as the memory usage in instruments as 99.7%) data = (short*)malloc(kSegmentSize*sizeof(short));
and free it like this free(data); at the end of each iteration.
Im not really sure what is happening here and would appreciate any help.
EDIT: KSegmentSize varies in the thousands, from minimum 6000 - max 50000 (speculative)
Instruments trace:
Not having the exact code:
Pretty sure you're having this problem b/c something between the malloc and free is throwing (and you're probably catching it already so you don't exit the loop). Depending on if this is happening in C (or objective-C) or C++ code, you have slightly different methods of resolution.
In C++, wrap the malloc/free in the RAII pattern so that when the stack is unwound the free is called.
class MyData {
public:
A(size_t numShorts) : dataPtr(0) { dataPtr = malloc(numShorts * sizeof(short)); }
~A() { free(dataPtr); }
operator short*() { return dataPtr; }
private:
short* dataPtr;
}
MyData data(numShorts);
// do your stuff, you can still use data as you were before due the 'operator short*'
// allow the dtor to be called when you go out of scope
In Objective-C you need to use a finally block:
void* myPtr = 0;
#try { myPtr = malloc(...); }
#catch {}
#finally { free(myPtr); }
Suggest that you start by simplifying, for example comment out (preferably using #if 0) all of the code except the malloc/free. Run the code and ensure no abandoned heap blocks. Then gradually re-introduce the remaining code and re-run until you hit the problem, then debug.
Sorry to answer my own question, but after commenting out code back up the stack trace the actual issue was to do with the file not be disposed.
Calling ExtAudioFileDispose(audioFile); solved this hidden bug. Instruments was not entirely clear and marked mallocs as the leak. To be fair the mallocs where from data that was within the file referenced by the ExtAudioOpenFile method, not disposing the file reference left a leak.

C++ function exits arbitrarily

I have a weird problem:
On my Win32 C++ App, I have a function where the function returns after a call to another function.
void f()
{
//SECTION 1//
if( interactFrame )
{
psFrame->getWindow()->deactivate();
interactFrame = activeFrame = 0;
logFile << "PS deactive" << endl;
}
//SECTION 2//
}
void Window::deactivate()
{
SetLayeredWindowAttributes( handle_, 0, 0, LWA_ALPHA );
SetFocus( applicationWindow_ );
}
After I call f(), the function goes through Section 1, branches into the if statement, completes line 1 (psFrame->...) and returns after that without evaluating the remaining two lines and the Section 2 out of the branch. I had this happen to me when for instance I was calling a method of a variable which was NULL, in this case psFrame, and it would instead of breaking, just return. However it is a legitimate variable, its contents and the pointer returned from getWindow() exists. In fact I can trace until the completion of deactivate() however my breakpoint at the next line is never hit.
In fact this is the same code that runs on one computer, and doesn't on my laptop. Both running Win 7.
What do you think could be the cause of this?
It sounds like something (quite possibly the deactivate, or something it calls) is making a mess of the stack (e.g., overwriting the end of a buffer) and messing up the return address. Much more than that would be a pretty wild guess though.
Given your description, it still sounds like you are getting null dereference errors. Guard your code a bit and see what happens like this:
if( interactFrame )
{
if (psFrame)
{
if (psFrame->getWindow())
{
psFrame->getWindow()->deactivate();
}
// else log("getWindow == null")
}
// else log("psFrame == null")
interactFrame = activeFrame = 0;
logFile << "PS deactive" << endl;
}
Beyond that we'd need to see more code.
UPDATE: OK - you posted more code, and that's pretty odd, unless something very strange is happening like getWindow() is overrunning your stack and trashing the return address. Check any local variables (especially strings and arrays) you have in getWindow().
GMan also has a good point - if psFrame is returning a pointer to a deleted window in getWindow, that could also be a culprit (and you might see different behaviors depending on if the memory has been re-allocated or not yet)
I guess the line
psFrame->getWindow()->deactivate();
simply generates an exception. And your function does not return at all - it terminates with exception. To confirm that set a breakpoint after the call to f() function (part of which is the code you've posted) and if this breakpoint doesn't hit either then it is likely an exception (possibly invalid memory access or simply C++ exception thrown).
Stack corruption is also possible and it will also likely lead to an exception (unless you accidentally overwrite return address with a valid address to executable memory).
Also note that if psFrame happen to be 0 (or other invalid pointer) then exception is guaranteed if getWindow() access any non-static member of its object in any way. And you would see exactly the behaviour you described. The same situation is when psFrame->getWindow() returns 0 (or another invalid pointer) and deactivate() accesses non-static member.
UPD:
You may also follow stack contents changes when debugging.