- Implement IoRegisterLastchanceShutdownNotification based on IoRegisterShutdownNotification

- Modify IoUnregisterShudownNotification to loop both lists now.
- Used the lock in IoShutdownREgisteredDevices when looping the list, and changed it to send IRP_MJ_SHUTDOWN to the attached DO. Also fixed a memory leak where the shutdown entry wasn't being freed, and optimized the function only to initialize the event once (And simply clear it each time).
- Moved IoSynchronousInvalidateDeviceRelations to PnP

svn path=/trunk/; revision=22743
This commit is contained in:
Alex Ionescu 2006-07-01 18:26:22 +00:00
parent f39240e913
commit 036139907e
3 changed files with 160 additions and 87 deletions

View file

@ -594,6 +594,7 @@ IoInitShutdownNotification(
); );
VOID VOID
NTAPI
IoShutdownRegisteredDevices( IoShutdownRegisteredDevices(
VOID VOID
); );

View file

@ -16,7 +16,7 @@
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
static ULONG IopDeviceObjectNumber = 0; ULONG IopDeviceObjectNumber = 0;
typedef struct _SHUTDOWN_ENTRY typedef struct _SHUTDOWN_ENTRY
{ {
@ -24,44 +24,61 @@ typedef struct _SHUTDOWN_ENTRY
PDEVICE_OBJECT DeviceObject; PDEVICE_OBJECT DeviceObject;
} SHUTDOWN_ENTRY, *PSHUTDOWN_ENTRY; } SHUTDOWN_ENTRY, *PSHUTDOWN_ENTRY;
LIST_ENTRY ShutdownListHead; LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead;
KSPIN_LOCK ShutdownListLock; KSPIN_LOCK ShutdownListLock;
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
VOID VOID
NTAPI
IoShutdownRegisteredDevices(VOID) IoShutdownRegisteredDevices(VOID)
{ {
PLIST_ENTRY ListEntry;
PDEVICE_OBJECT DeviceObject;
PSHUTDOWN_ENTRY ShutdownEntry; PSHUTDOWN_ENTRY ShutdownEntry;
IO_STATUS_BLOCK StatusBlock; IO_STATUS_BLOCK StatusBlock;
PIRP Irp; PIRP Irp;
KEVENT Event; KEVENT Event;
NTSTATUS Status; NTSTATUS Status;
LIST_FOR_EACH(ShutdownEntry, &ShutdownListHead, SHUTDOWN_ENTRY, ShutdownList) /* Initialize an event to wait on */
{ KeInitializeEvent(&Event, NotificationEvent, FALSE);
KeInitializeEvent (&Event,
NotificationEvent,
FALSE);
/* Get the first entry and start looping */
ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
&ShutdownListLock);
while (ListEntry)
{
/* Get the shutdown entry */
ShutdownEntry = CONTAINING_RECORD(ListEntry,
SHUTDOWN_ENTRY,
ShutdownList);
/* Get the attached device */
DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
/* Build the shutdown IRP and call the driver */
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
ShutdownEntry->DeviceObject, DeviceObject,
NULL, NULL,
0, 0,
NULL, NULL,
&Event, &Event,
&StatusBlock); &StatusBlock);
Status = IoCallDriver(DeviceObject, Irp);
Status = IoCallDriver (ShutdownEntry->DeviceObject,
Irp);
if (Status == STATUS_PENDING) if (Status == STATUS_PENDING)
{ {
KeWaitForSingleObject (&Event, /* Wait on the driver */
Executive, KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
KernelMode,
FALSE,
NULL);
} }
/* Free the shutdown entry and reset the event */
ExFreePool(ShutdownEntry);
KeClearEvent(&Event);
/* Go to the next entry */
ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
&ShutdownListLock);
} }
} }
@ -1097,41 +1114,125 @@ IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
} }
/* /*
* @unimplemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject) IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject)
{ {
UNIMPLEMENTED; PSHUTDOWN_ENTRY Entry;
return STATUS_NOT_IMPLEMENTED;
/* Allocate the shutdown entry */
Entry = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SHUTDOWN_ENTRY),
TAG_SHUTDOWN_ENTRY);
if (!Entry) return STATUS_INSUFFICIENT_RESOURCES;
/* Set the DO */
Entry->DeviceObject = DeviceObject;
/* Insert it into the list */
ExInterlockedInsertHeadList(&LastChanceShutdownListHead,
&Entry->ShutdownList,
&ShutdownListLock);
/* Set the shutdown registered flag */
DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
return STATUS_SUCCESS;
} }
/* /*
* @implemented * @implemented
*/ */
NTSTATUS NTSTATUS
STDCALL NTAPI
IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject) IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
{ {
PSHUTDOWN_ENTRY Entry; PSHUTDOWN_ENTRY Entry;
Entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_ENTRY), /* Allocate the shutdown entry */
Entry = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SHUTDOWN_ENTRY),
TAG_SHUTDOWN_ENTRY); TAG_SHUTDOWN_ENTRY);
if (Entry == NULL) if (!Entry) return STATUS_INSUFFICIENT_RESOURCES;
return STATUS_INSUFFICIENT_RESOURCES;
/* Set the DO */
Entry->DeviceObject = DeviceObject; Entry->DeviceObject = DeviceObject;
/* Insert it into the list */
ExInterlockedInsertHeadList(&ShutdownListHead, ExInterlockedInsertHeadList(&ShutdownListHead,
&Entry->ShutdownList, &Entry->ShutdownList,
&ShutdownListLock); &ShutdownListLock);
/* Set the shutdown registered flag */
DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED; DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/*
* @implemented
*/
VOID
NTAPI
IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
{
PSHUTDOWN_ENTRY ShutdownEntry;
PLIST_ENTRY NextEntry;
KIRQL OldIrql;
/* Acquire the shutdown lock and loop the shutdown list */
KeAcquireSpinLock(&ShutdownListLock, &OldIrql);
NextEntry = ShutdownListHead.Flink;
while (NextEntry != &ShutdownListHead)
{
/* Get the entry */
ShutdownEntry = CONTAINING_RECORD(NextEntry,
SHUTDOWN_ENTRY,
ShutdownList);
/* Get if the DO matches */
if (ShutdownEntry->DeviceObject == DeviceObject)
{
/* Remove it from the list */
RemoveEntryList(NextEntry);
NextEntry = NextEntry->Blink;
/* Free the entry */
ExFreePool(ShutdownEntry);
}
/* Go to the next entry */
NextEntry = NextEntry->Flink;
}
/* Now loop the last chance list */
NextEntry = LastChanceShutdownListHead.Flink;
while (NextEntry != &LastChanceShutdownListHead)
{
/* Get the entry */
ShutdownEntry = CONTAINING_RECORD(NextEntry,
SHUTDOWN_ENTRY,
ShutdownList);
/* Get if the DO matches */
if (ShutdownEntry->DeviceObject == DeviceObject)
{
/* Remove it from the list */
RemoveEntryList(NextEntry);
NextEntry = NextEntry->Blink;
/* Free the entry */
ExFreePool(ShutdownEntry);
}
/* Go to the next entry */
NextEntry = NextEntry->Flink;
}
/* Now remove the flag */
DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
}
/* /*
* @unimplemented * @unimplemented
*/ */
@ -1277,46 +1378,6 @@ IoStartPacket(PDEVICE_OBJECT DeviceObject,
{ {
IoReleaseCancelSpinLock(oldirql); IoReleaseCancelSpinLock(oldirql);
} }
}
/*
* @unimplemented
*/
VOID
STDCALL
IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_RELATION_TYPE Type)
{
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID
STDCALL
IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
{
PSHUTDOWN_ENTRY ShutdownEntry, tmp;
KIRQL oldlvl;
LIST_FOR_EACH_SAFE(ShutdownEntry, tmp, &ShutdownListHead, SHUTDOWN_ENTRY, ShutdownList)
{
if (ShutdownEntry->DeviceObject == DeviceObject)
{
DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
KeAcquireSpinLock(&ShutdownListLock,&oldlvl);
RemoveEntryList(&ShutdownEntry->ShutdownList);
KeReleaseSpinLock(&ShutdownListLock,oldlvl);
ExFreePool(ShutdownEntry);
return;
}
}
} }
/* EOF */ /* EOF */

View file

@ -81,6 +81,17 @@ IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject,
IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject), Type); IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject), Type);
} }
/*
* @unimplemented
*/
VOID
STDCALL
IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_RELATION_TYPE Type)
{
UNIMPLEMENTED;
}
/* /*
* @unimplemented * @unimplemented
*/ */