mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 23:15:39 +00:00
- 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:
parent
f39240e913
commit
036139907e
3 changed files with 160 additions and 87 deletions
|
@ -594,6 +594,7 @@ IoInitShutdownNotification(
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
NTAPI
|
||||||
IoShutdownRegisteredDevices(
|
IoShutdownRegisteredDevices(
|
||||||
VOID
|
VOID
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,52 +16,69 @@
|
||||||
|
|
||||||
/* GLOBALS ********************************************************************/
|
/* GLOBALS ********************************************************************/
|
||||||
|
|
||||||
static ULONG IopDeviceObjectNumber = 0;
|
ULONG IopDeviceObjectNumber = 0;
|
||||||
|
|
||||||
typedef struct _SHUTDOWN_ENTRY
|
typedef struct _SHUTDOWN_ENTRY
|
||||||
{
|
{
|
||||||
LIST_ENTRY ShutdownList;
|
LIST_ENTRY ShutdownList;
|
||||||
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)
|
||||||
{
|
{
|
||||||
PSHUTDOWN_ENTRY ShutdownEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
IO_STATUS_BLOCK StatusBlock;
|
PDEVICE_OBJECT DeviceObject;
|
||||||
PIRP Irp;
|
PSHUTDOWN_ENTRY ShutdownEntry;
|
||||||
KEVENT Event;
|
IO_STATUS_BLOCK StatusBlock;
|
||||||
NTSTATUS Status;
|
PIRP Irp;
|
||||||
|
KEVENT Event;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
LIST_FOR_EACH(ShutdownEntry, &ShutdownListHead, SHUTDOWN_ENTRY, ShutdownList)
|
/* Initialize an event to wait on */
|
||||||
{
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||||
KeInitializeEvent (&Event,
|
|
||||||
NotificationEvent,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
Irp = IoBuildSynchronousFsdRequest (IRP_MJ_SHUTDOWN,
|
/* Get the first entry and start looping */
|
||||||
ShutdownEntry->DeviceObject,
|
ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
|
||||||
NULL,
|
&ShutdownListLock);
|
||||||
0,
|
while (ListEntry)
|
||||||
NULL,
|
{
|
||||||
&Event,
|
/* Get the shutdown entry */
|
||||||
&StatusBlock);
|
ShutdownEntry = CONTAINING_RECORD(ListEntry,
|
||||||
|
SHUTDOWN_ENTRY,
|
||||||
|
ShutdownList);
|
||||||
|
|
||||||
Status = IoCallDriver (ShutdownEntry->DeviceObject,
|
/* Get the attached device */
|
||||||
Irp);
|
DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
|
||||||
if (Status == STATUS_PENDING)
|
|
||||||
{
|
/* Build the shutdown IRP and call the driver */
|
||||||
KeWaitForSingleObject (&Event,
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
|
||||||
Executive,
|
DeviceObject,
|
||||||
KernelMode,
|
NULL,
|
||||||
FALSE,
|
0,
|
||||||
NULL);
|
NULL,
|
||||||
}
|
&Event,
|
||||||
|
&StatusBlock);
|
||||||
|
Status = IoCallDriver(DeviceObject, Irp);
|
||||||
|
if (Status == STATUS_PENDING)
|
||||||
|
{
|
||||||
|
/* Wait on the driver */
|
||||||
|
KeWaitForSingleObject(&Event, Executive, 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,39 +1114,123 @@ 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 */
|
||||||
TAG_SHUTDOWN_ENTRY);
|
Entry = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
if (Entry == NULL)
|
sizeof(SHUTDOWN_ENTRY),
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
TAG_SHUTDOWN_ENTRY);
|
||||||
|
if (!Entry) return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
Entry->DeviceObject = DeviceObject;
|
/* Set the DO */
|
||||||
|
Entry->DeviceObject = DeviceObject;
|
||||||
|
|
||||||
ExInterlockedInsertHeadList(&ShutdownListHead,
|
/* Insert it into the list */
|
||||||
&Entry->ShutdownList,
|
ExInterlockedInsertHeadList(&ShutdownListHead,
|
||||||
&ShutdownListLock);
|
&Entry->ShutdownList,
|
||||||
|
&ShutdownListLock);
|
||||||
|
|
||||||
DeviceObject->Flags |= DO_SHUTDOWN_REGISTERED;
|
/* Set the shutdown registered flag */
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue