|
|
/*++
Copyright (c) 1999-2001 Microsoft Corporation
Module Name:
pnpmem.c
Abstract:
This module implements the Plug and Play Memory driver entry points.
Author:
Dave Richards (daveri) 16-Aug-1999
Environment:
Kernel mode only.
Revision History:
--*/
#include "pnpmem.h"
#include <initguid.h>
#include <poclass.h>
#define PM_DEBUG_BUFFER_SIZE 512
#define rgzMemoryManagement L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
#define rgzMemoryRemovable L"Memory Removable"
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ); NTSTATUS PmAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT Pdo );
NTSTATUS PmPnpDispatch( IN PDEVICE_OBJECT Fdo, IN PIRP Irp );
VOID PmUnload( IN PDRIVER_OBJECT DriverObject );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, PmAddDevice)
#pragma alloc_text(PAGE, PmUnload)
#endif
ULONG DbgMask = 0xFFFFFFFF; BOOLEAN MemoryRemovalSupported;
#if DBG
VOID PmDebugPrint( ULONG DebugPrintLevel, PCCHAR DebugMessage, ... ) /*++
Routine Description:
Arguments:
DebugPrintLevel - The bit mask that when anded with the debuglevel, must equal itself DebugMessage - The string to feed through vsprintf
Return Value:
None
--*/ { va_list ap; UCHAR debugBuffer[PM_DEBUG_BUFFER_SIZE];
//
// Get the variable arguments
//
va_start( ap, DebugMessage );
//
// Call the kernel function to print the message
//
_vsnprintf( debugBuffer, PM_DEBUG_BUFFER_SIZE, DebugMessage, ap );
if (DebugPrintLevel & DbgMask) { DbgPrint("%s", debugBuffer); }
//
// We are done with the varargs
//
va_end( ap ); } #endif
NTSTATUS PmAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject )
/*++
Routine Description:
This function creates a functional device object and attaches it to the physical device object (device stack).
Arguments:
DriverObject - The driver object.
Pdo - The physical device object.
Return Value:
NTSTATUS
--*/
{ PDEVICE_OBJECT functionalDeviceObject; PDEVICE_OBJECT attachedDeviceObject; PPM_DEVICE_EXTENSION deviceExtension; NTSTATUS status;
PAGED_CODE();
//
// Create the FDO.
//
status = IoCreateDevice( DriverObject, sizeof (PM_DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN | FILE_DEVICE_SECURE_OPEN, 0, FALSE, &functionalDeviceObject );
if (!NT_SUCCESS(status)) { return status; }
//
// Attach the FDO (indirectly) to the PDO.
//
deviceExtension = functionalDeviceObject->DeviceExtension;
deviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack( functionalDeviceObject, PhysicalDeviceObject );
if (deviceExtension->AttachedDevice == NULL) { IoDeleteDevice(functionalDeviceObject); return STATUS_NO_SUCH_DEVICE; }
IoInitializeRemoveLock(&deviceExtension->RemoveLock, 0, 1, 20);
functionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
return status; }
NTSTATUS PmControlDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PPM_DEVICE_EXTENSION deviceExtension;
deviceExtension = DeviceObject->DeviceExtension; IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(deviceExtension->AttachedDevice, Irp); }
VOID PmPowerCallback( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction, IN POWER_STATE PowerState, IN PVOID Context, IN PIO_STATUS_BLOCK IoStatus ) { PPM_DEVICE_EXTENSION deviceExtension; PIRP Irp; NTSTATUS status;
Irp = Context; deviceExtension = DeviceObject->DeviceExtension;
Irp->IoStatus.Status = IoStatus->Status; PoStartNextPowerIrp(Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); }
NTSTATUS PmPowerCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID NotUsed ) /*++
Routine Description:
The completion routine for Power
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Not used - context pointer
Return Value:
NT status code
--*/ { PIO_STACK_LOCATION irpStack; PPM_DEVICE_EXTENSION deviceExtension; NTSTATUS status;
irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = DeviceObject->DeviceExtension;
if (irpStack->Parameters.Power.Type == SystemPowerState) { SYSTEM_POWER_STATE system = irpStack->Parameters.Power.State.SystemState; POWER_STATE power;
if (NT_SUCCESS(Irp->IoStatus.Status)) {
power.DeviceState = deviceExtension->DeviceStateMapping[system];
status = PoRequestPowerIrp(DeviceObject, irpStack->MinorFunction, power, PmPowerCallback, Irp, NULL); if (NT_SUCCESS(status)) { return STATUS_MORE_PROCESSING_REQUIRED; } else { Irp->IoStatus.Status = status; } } PoStartNextPowerIrp(Irp); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); return STATUS_SUCCESS; } else { if (NT_SUCCESS(Irp->IoStatus.Status)) { PoSetPowerState(DeviceObject, DevicePowerState, irpStack->Parameters.Power.State); deviceExtension->PowerState = irpStack->Parameters.Power.State.DeviceState; } PoStartNextPowerIrp(Irp); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); return STATUS_SUCCESS; } } NTSTATUS PmPowerDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PPM_DEVICE_EXTENSION deviceExtension; PIO_STACK_LOCATION irpStack; NTSTATUS status;
irpStack = IoGetCurrentIrpStackLocation(Irp); deviceExtension = DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, (PVOID) Irp); if (status == STATUS_DELETE_PENDING) { Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE; PoStartNextPowerIrp(Irp); IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_NO_SUCH_DEVICE; }
if (irpStack->Parameters.Power.Type == SystemPowerState) { switch (irpStack->MinorFunction) { case IRP_MN_QUERY_POWER: case IRP_MN_SET_POWER: IoMarkIrpPending(Irp); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, PmPowerCompletion, NULL, //Context
TRUE, //InvokeOnSuccess
TRUE, //InvokeOnError
TRUE //InvokeOnCancel
); (VOID) PoCallDriver(deviceExtension->AttachedDevice, Irp); return STATUS_PENDING; default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); status = PoCallDriver(deviceExtension->AttachedDevice, Irp); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); return status; } } else { switch (irpStack->MinorFunction) { case IRP_MN_SET_POWER:
if (irpStack->Parameters.Power.State.DeviceState <= deviceExtension->PowerState) {
//
// Powering up device
//
IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, PmPowerCompletion, NULL, //Context
TRUE, //InvokeOnSuccess
TRUE, //InvokeOnError
TRUE //InvokeOnCancel
); (VOID) PoCallDriver(deviceExtension->AttachedDevice, Irp); return STATUS_PENDING;
} else {
//
// Powering down device
//
PoSetPowerState(DeviceObject, DevicePowerState, irpStack->Parameters.Power.State); deviceExtension->PowerState = irpStack->Parameters.Power.State.DeviceState; //
// Fall through ...
//
} case IRP_MN_QUERY_POWER: //
// Fall through as the bus driver will mark this
// STATUS_SUCCESS and complete it, if it gets that far.
//
default: PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); break; } status = PoCallDriver(deviceExtension->AttachedDevice, Irp); IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); return status; } }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
/*++
Routine Description:
This function initializes the driver object.
Arguments:
DriverObject - The driver object.
RegistryPath - The registry path for the device.
Return Value:
STATUS_SUCCESS
--*/
{ OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING unicodeString; PKEY_VALUE_PARTIAL_INFORMATION valueInfo; HANDLE hMemoryManagement; NTSTATUS status; PAGED_CODE();
RtlInitUnicodeString (&unicodeString, rgzMemoryManagement); InitializeObjectAttributes (&objectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE, NULL, // handle
NULL); status = ZwOpenKey(&hMemoryManagement, KEY_READ, &objectAttributes); if (NT_SUCCESS(status)) { status = PmGetRegistryValue(hMemoryManagement, rgzMemoryRemovable, &valueInfo); if (NT_SUCCESS(status)) { if ((valueInfo->Type == REG_DWORD) && (valueInfo->DataLength >= sizeof(ULONG))) { MemoryRemovalSupported = (BOOLEAN) *((PULONG)valueInfo->Data); } ExFreePool(valueInfo); } ZwClose(hMemoryManagement); }
DriverObject->MajorFunction[IRP_MJ_PNP] = PmPnpDispatch; DriverObject->MajorFunction[IRP_MJ_POWER] = PmPowerDispatch; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PmControlDispatch; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PmControlDispatch; DriverObject->DriverExtension->AddDevice = PmAddDevice;
return STATUS_SUCCESS; }
VOID PmUnload( IN PDRIVER_OBJECT DriverObject ) /*++
Routine Description: This is called to reverse any operations performed in DriverEntry before a driver is unloaded. Arguments:
DriverObject - The system owned driver object for PNPMEM --*/ { PAGED_CODE(); return; }
|