/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: PpPathPath.c Abstract: The file implements support for managing devices on the paging path. Author: Adrian J. Oney (AdriaO) February 3rd, 2001 Revision History: Originally taken from ChuckL's implementation in mm\modwrite.c. --*/ #include "pnpmgrp.h" #include "pipagepath.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, PpPagePathAssign) #pragma alloc_text(PAGE, PpPagePathRelease) #pragma alloc_text(PAGE, PiPagePathSetState) #endif NTSTATUS PpPagePathAssign( IN PFILE_OBJECT FileObject ) /*++ Routine Description: This routine informs driver stacks that they are now on the paging path. Drivers need to take appropriate actions when on the path, such as failing IRP_MN_QUERY_STOP and IRP_MN_QUERY_REMOVE, locking their code and clearing the DO_POWER_PAGABLE bit, etc. Arguments: FileObject - File object for the paging file itself. Return Value: NTSTATUS. --*/ { PAGED_CODE(); return PiPagePathSetState(FileObject, TRUE); } NTSTATUS PpPagePathRelease( IN PFILE_OBJECT FileObject ) /*++ Routine Description: This routine informs driver stacks that the passed in file is no longer a paging file. Each driver stack notified may still be on the paging path however if their hardware supports a different paging file on another drive. Arguments: FileObject - File object for the paging file itself. Return Value: NTSTATUS. --*/ { PAGED_CODE(); return PiPagePathSetState(FileObject, FALSE); } NTSTATUS PiPagePathSetState( IN PFILE_OBJECT FileObject, IN BOOLEAN InPath ) /*++ Routine Description: This routine notifies driver stacks when a paging file is shut down on their device, or if a paging file is being started up on their device. If a paging file is being started up, this request is also a query as the stack may not be able to support a pagefile. Arguments: FileObject - File object for the paging file itself. InPath - Whether the page file is being started or shut down. Return Value: NTSTATUS. --*/ { PIRP irp; NTSTATUS status; PDEVICE_OBJECT deviceObject; KEVENT event; PIO_STACK_LOCATION irpSp; IO_STATUS_BLOCK localIoStatus; PAGED_CODE(); // // Reference the file object here so that no special checks need be made // in I/O completion to determine whether or not to dereference the file // object. // ObReferenceObject(FileObject); // // Initialize the local event. // KeInitializeEvent(&event, NotificationEvent, FALSE); // // Get the address of the target device object. // deviceObject = IoGetRelatedDeviceObject(FileObject); // // Allocate and initialize the irp for this operation. // irp = IoAllocateIrp(deviceObject->StackSize, FALSE); if (irp == NULL) { // // Don't dereference the file object, our caller will take care of that. // return STATUS_NO_MEMORY; } irp->Tail.Overlay.OriginalFileObject = FileObject; irp->Tail.Overlay.Thread = PsGetCurrentThread(); irp->RequestorMode = KernelMode; // // Fill in the service independent parameters in the IRP. // irp->UserEvent = &event; irp->Flags = IRP_SYNCHRONOUS_API; irp->UserIosb = &localIoStatus; irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; // // Get a pointer to the stack location for the first driver. This will be // used to pass the original function codes and parameters. // irpSp = IoGetNextIrpStackLocation(irp); irpSp->MajorFunction = IRP_MJ_PNP; irpSp->MinorFunction = IRP_MN_DEVICE_USAGE_NOTIFICATION; irpSp->FileObject = FileObject; irp->IoStatus.Status = STATUS_NOT_SUPPORTED; irp->AssociatedIrp.SystemBuffer = NULL; // irp->Flags = 0; irpSp->Parameters.UsageNotification.InPath = InPath; irpSp->Parameters.UsageNotification.Type = DeviceUsageTypePaging; // // Insert the packet at the head of the IRP list for the thread. // IoQueueThreadIrp(irp); // // Acquire the engine lock to ensure no rebalances, removes, or power // operations are in progress during this notification. // PpDevNodeLockTree(PPL_TREEOP_ALLOW_READS); // // Now simply invoke the driver at its dispatch entry with the IRP. // status = IoCallDriver(deviceObject, irp); // // Wait for the local event and copy the final status information // back to the caller. // if (status == STATUS_PENDING) { (VOID) KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = localIoStatus.Status; } // // Unlock the tree. // PpDevNodeUnlockTree(PPL_TREEOP_ALLOW_READS); return status; }