HI All
I have a question about MS sample code BulkUsb.
In the follow piece of code, it seems the "irpContext" be ExFreePool two
times in certain situation.
Please See my Comments.
It 's helpful for me if you can correct me.
thanks
thanks
VOID
IdleNotificationCallback(
IN PDEVICE_EXTENSION DeviceExtension
)
/*++
Routine Description:
"A pointer to a callback function in your driver is passed down the stack
with
this IOCTL, and it is this callback function that is called by USBHUB
when it
safe for your device to power down."
"When the callback in your driver is called, all you really need to do is to
to first ensure that a WaitWake Irp has been submitted for your device, if
remote wake is possible for your device and then request a SetD2 (or
DeviceWake)"
Arguments:
DeviceExtension - pointer to device extension
Return Value:
NT status value
--*/
{
NTSTATUS ntStatus;
POWER_STATE powerState;
KEVENT irpCompletionEvent;
PIRP_COMPLETION_CONTEXT irpContext;
BulkUsb_DbgPrint(3, ("IdleNotificationCallback - begins\n"));
//
// Dont idle, if the device was just disconnected or being stopped
// i.e. return for the following DeviceState(s)
// NotStarted, Stopped, PendingStop, PendingRemove, SurpriseRemoved,
Removed
//
if(DeviceExtension->DeviceState != Working) {
return;
}
//
// If there is not already a WW IRP pending, submit one now
//
if(DeviceExtension->WaitWakeEnable) {
IssueWaitWake(DeviceExtension);
}
//
// power down the device
//
irpContext = (PIRP_COMPLETION_CONTEXT)
ExAllocatePool(NonPagedPool,
sizeof(IRP_COMPLETION_CONTEXT));
if(!irpContext) {
BulkUsb_DbgPrint(1, ("Failed to alloc memory for irpContext\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else {
//
// increment the count. In the HoldIoRequestWorkerRoutine, the
// count is decremented twice (one for the system Irp and the
// other for the device Irp. An increment here compensates for
// the sytem irp..The decrement corresponding to this increment
// is in the completion function
//
BulkUsb_DbgPrint(3, ("IdleNotificationCallback::"));
BulkUsb_IoIncrement(DeviceExtension);
powerState.DeviceState = DeviceExtension->PowerDownLevel;
KeInitializeEvent(&irpCompletionEvent, NotificationEvent, FALSE);
irpContext->DeviceExtension = DeviceExtension;
irpContext->Event = &irpCompletionEvent;
ntStatus = PoRequestPowerIrp(
DeviceExtension->PhysicalDeviceObject,
IRP_MN_SET_POWER,
powerState,
(PREQUEST_POWER_COMPLETE) PoIrpCompletionFunc,
irpContext,
NULL);
if(STATUS_PENDING == ntStatus) {
BulkUsb_DbgPrint(3, ("IdleNotificationCallback::"
"waiting for the power irp to complete\n"));
KeWaitForSingleObject(&irpCompletionEvent,
Executive,
KernelMode,
FALSE,
NULL);
}
}
////////// My Comment
////if ntStatus is a Error code from "PoRequestPowerIrp" ,then
////ExFreePool(irpContext) will be called by one time.
////
if(!NT_SUCCESS(ntStatus)) {
if(irpContext) {
ExFreePool(irpContext);
}
}
BulkUsb_DbgPrint(3, ("IdleNotificationCallback - ends\n"));
}
VOID
PoIrpCompletionFunc(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR MinorFunction,
IN POWER_STATE PowerState,
IN PVOID Context,
IN PIO_STATUS_BLOCK IoStatus
)
/*++
Routine Description:
Completion routine for power irp PoRequested in
IdleNotificationCallback.
Arguments:
DeviceObject - pointer to device object
MinorFunciton - minor function for the irp.
PowerState - irp power state
Context - context passed to the completion function
IoStatus - status block.
Return Value:
None
--*/
{
PIRP_COMPLETION_CONTEXT irpContext;
UNREFERENCED_PARAMETER( DeviceObject );
UNREFERENCED_PARAMETER( MinorFunction );
UNREFERENCED_PARAMETER( PowerState );
UNREFERENCED_PARAMETER( IoStatus );
//
// initialize variables
//
irpContext = NULL;
if(Context) {
irpContext = (PIRP_COMPLETION_CONTEXT) Context;
}
//
// all we do is set the event and decrement the count
//
///////////My Comments
///// This completeFunction will Free the irpContext the Second time.
///// ????????. is It correct ?????
if(irpContext) {
KeSetEvent(irpContext->Event, 0, FALSE);
BulkUsb_DbgPrint(3, ("PoIrpCompletionFunc::"));
BulkUsb_IoDecrement(irpContext->DeviceExtension);
ExFreePool(irpContext);
}
return;
}