You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1148 lines
28 KiB
1148 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1991 - 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
## ## ###### #### ## #### ##### #####
|
|
## ## ## ## ## ## # ## ## ## ##
|
|
## ## ## ## ## ## ## ## ## ##
|
|
## ## ## ## ## ## ## ## ## ##
|
|
## ## ## ## ## ## ##### #####
|
|
## ## ## ## ## ## ## # ## ##
|
|
#### ## #### ##### ## #### ## ##
|
|
|
|
Abstract:
|
|
|
|
Utility driver functions.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 1-Oct-2001
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
|
|
#include "internal.h"
|
|
#include <ntimage.h>
|
|
#include <stdarg.h>
|
|
|
|
#if DBG
|
|
ULONG SaPortDebugLevel[5];
|
|
#endif
|
|
|
|
|
|
|
|
NTSTATUS
|
|
CompleteRequest(
|
|
PIRP Irp,
|
|
NTSTATUS Status,
|
|
ULONG_PTR Information
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine completes as outstanding I/O request.
|
|
|
|
Arguments:
|
|
|
|
Irp - Pointer to an IRP structure that describes the requested I/O operation.
|
|
Status - NT status value
|
|
Information - Informational, request specific data
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
KIRQL CancelIrql;
|
|
|
|
|
|
if (IrpSp && (IrpSp->MajorFunction == IRP_MJ_READ || IrpSp->MajorFunction == IRP_MJ_WRITE)) {
|
|
IoAcquireCancelSpinLock( &CancelIrql );
|
|
IoSetCancelRoutine( Irp, NULL );
|
|
IoReleaseCancelSpinLock( CancelIrql );
|
|
}
|
|
|
|
Irp->IoStatus.Information = Information;
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest( Irp, IO_NO_INCREMENT );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ForwardRequest(
|
|
IN PIRP Irp,
|
|
IN PDEVICE_OBJECT TargetObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine forwards the IRP to another driver.
|
|
|
|
Arguments:
|
|
|
|
Irp - Pointer to an IRP structure that describes the requested I/O operation.
|
|
TargetObject - Target device object to receive the request packet
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
IoSkipCurrentIrpStackLocation( Irp );
|
|
return IoCallDriver( TargetObject, Irp );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CallMiniPortDriverReadWrite(
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN BOOLEAN WriteIo,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length,
|
|
IN ULONG Offset
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine creates an IRP for a read/write I/O and
|
|
then passes the IRP to the driver. This call is
|
|
synchronous, control returns only when the driver has
|
|
completed the IRP.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Port driver device extension pointer
|
|
WriteIo - TRUE for a write, FALSE for a read
|
|
Buffer - Pointer to the I/O buffer
|
|
Length - Length in bytes of the I/O buffer
|
|
Offset - Starting offset of the I/O
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PIRP Irp;
|
|
KEVENT Event;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
LARGE_INTEGER StartingOffset;
|
|
|
|
|
|
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
|
|
|
StartingOffset.QuadPart = Offset;
|
|
|
|
Irp = IoBuildSynchronousFsdRequest(
|
|
WriteIo ? IRP_MJ_WRITE : IRP_MJ_READ,
|
|
DeviceObject,
|
|
Buffer,
|
|
Length,
|
|
&StartingOffset,
|
|
&Event,
|
|
&IoStatus
|
|
);
|
|
if (!Irp) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "IoBuildSynchronousFsdRequest failed", STATUS_INSUFFICIENT_RESOURCES );
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
MARK_IRP_INTERNAL( Irp );
|
|
|
|
Status = IoCallDriver( DeviceObject, Irp );
|
|
if (Status == STATUS_PENDING) {
|
|
KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "Miniport I/O request failed", Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CallMiniPortDriverDeviceControl(
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN ULONG IoControlCode,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength,
|
|
OUT PVOID OutputBuffer,
|
|
IN ULONG OutputBufferLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine creates an IRP for a device control I/O and
|
|
then passes the IRP to the driver. This call is
|
|
synchronous, control returns only when the driver has
|
|
completed the IRP.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Port driver device extension pointer
|
|
IoControlCode - Device I/O control code
|
|
InputBuffer - Input buffer pointer
|
|
InputBufferLength - Length in bytes of the input buffer
|
|
OutputBuffer - Output buffer pointer
|
|
OutputBufferLength - Length in bytes of output buffer
|
|
|
|
Return Value:
|
|
|
|
NT status code.
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS Status;
|
|
PIRP Irp;
|
|
KEVENT Event;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
|
|
KeInitializeEvent( &Event, NotificationEvent, FALSE );
|
|
|
|
Irp = IoBuildDeviceIoControlRequest(
|
|
IoControlCode,
|
|
DeviceObject,
|
|
InputBuffer,
|
|
InputBufferLength,
|
|
OutputBuffer,
|
|
OutputBufferLength,
|
|
FALSE,
|
|
&Event,
|
|
&IoStatus
|
|
);
|
|
if (!Irp) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "IoBuildDeviceIoControlRequest failed", STATUS_INSUFFICIENT_RESOURCES );
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
MARK_IRP_INTERNAL( Irp );
|
|
|
|
Status = IoCallDriver( DeviceObject, Irp );
|
|
if (Status == STATUS_PENDING) {
|
|
KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL );
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
REPORT_ERROR( DeviceExtension->DeviceType, "Miniport device control request failed", Status );
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
SaPortDebugPrint(
|
|
IN ULONG DeviceType,
|
|
IN ULONG DebugLevel,
|
|
IN PSTR DebugMessage,
|
|
IN ...
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine prints a formatted string to the debugger.
|
|
|
|
Arguments:
|
|
|
|
DebugLevel - Debug level that controls when a message is printed
|
|
DebugMessage - String that is printed
|
|
... - Arguments that are used by the DebugMessage
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
static char *DeviceName[] = {"SAPORT", "DISPLAY","KEYPAD","NVRAM","WATCHDOG"};
|
|
va_list arg_ptr;
|
|
char buf[512];
|
|
char *s = buf;
|
|
|
|
|
|
|
|
#if DBG
|
|
if ((SaPortDebugLevel[DeviceType] == 0) || ((SaPortDebugLevel[DeviceType] & DebugLevel) == 0)) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
va_start( arg_ptr, DebugMessage );
|
|
sprintf( s, "%s: ", DeviceName[DeviceType] );
|
|
s += strlen(s);
|
|
_vsnprintf( s, sizeof(buf)-strlen(s), DebugMessage, arg_ptr );
|
|
DbgPrint( buf );
|
|
}
|
|
|
|
|
|
VOID
|
|
GetOsVersion(
|
|
VOID
|
|
)
|
|
{
|
|
#if (WINVER >= 0x0501)
|
|
RTL_OSVERSIONINFOW VersionInformation;
|
|
|
|
VersionInformation.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
|
|
RtlGetVersion( &VersionInformation );
|
|
OsMajorVersion = VersionInformation.dwMajorVersion;
|
|
OsMinorVersion = VersionInformation.dwMinorVersion;
|
|
#else
|
|
OsMajorVersion = 0;
|
|
OsMinorVersion = 0;
|
|
//PsGetVersion( &OsMajorVersion, &OsMinorVersion, NULL, NULL );
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
#if DBG
|
|
|
|
VOID
|
|
FormatTime(
|
|
ULONG TimeStamp,
|
|
PSTR TimeBuf
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine formats a timestamp word into a string.
|
|
|
|
Arguments:
|
|
|
|
TimeStamp - Timestamp word
|
|
TimeBuf - Buffer to place the resulting string
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
static char mnames[] = { "JanFebMarAprMayJunJulAugSepOctNovDec" };
|
|
LARGE_INTEGER MyTime;
|
|
TIME_FIELDS TimeFields;
|
|
|
|
|
|
RtlSecondsSince1970ToTime( TimeStamp, &MyTime );
|
|
ExSystemTimeToLocalTime( &MyTime, &MyTime );
|
|
RtlTimeToTimeFields( &MyTime, &TimeFields );
|
|
|
|
strncpy( TimeBuf, &mnames[(TimeFields.Month - 1) * 3], 3 );
|
|
sprintf(
|
|
&TimeBuf[3],
|
|
" %02d, %04d @ %02d:%02d:%02d",
|
|
TimeFields.Day,
|
|
TimeFields.Year,
|
|
TimeFields.Hour,
|
|
TimeFields.Minute,
|
|
TimeFields.Second
|
|
);
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintDriverVersion(
|
|
IN ULONG DeviceType,
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine locates the NT image headers from the
|
|
base of a loaded driver.
|
|
|
|
Arguments:
|
|
|
|
DeviceType - Miniport device type (see saio.h for the enumeration)
|
|
DriverObject - Pointer to the DRIVER_OBJECT structure
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
|
ULONG TimeStamp;
|
|
CHAR buf[32];
|
|
PSTR DriverId;
|
|
|
|
|
|
NtHeaders = RtlpImageNtHeader( DriverObject->DriverStart );
|
|
if (NtHeaders) {
|
|
TimeStamp = NtHeaders->FileHeader.TimeDateStamp;
|
|
FormatTime( TimeStamp, buf );
|
|
DebugPrint(( DeviceType, SAPORT_DEBUG_INFO_LEVEL, "***********************************************\n" ));
|
|
switch (DeviceType) {
|
|
case 0:
|
|
DriverId = "Server Appliance Port";
|
|
break;
|
|
|
|
case SA_DEVICE_DISPLAY:
|
|
DriverId = "Local Display";
|
|
break;
|
|
|
|
case SA_DEVICE_KEYPAD:
|
|
DriverId = "Keypad";
|
|
break;
|
|
|
|
case SA_DEVICE_NVRAM:
|
|
DriverId = "NVRAM";
|
|
break;
|
|
|
|
case SA_DEVICE_WATCHDOG:
|
|
DriverId = "Watchdog Timer";
|
|
break;
|
|
|
|
default:
|
|
DriverId = "Unknown";
|
|
break;
|
|
}
|
|
DebugPrint(( DeviceType, SAPORT_DEBUG_INFO_LEVEL, "%s Driver Built: %s\n", DriverId, buf ));
|
|
if (RunningOnWin2k) {
|
|
DebugPrint(( DeviceType, SAPORT_DEBUG_INFO_LEVEL, "Running on Windows 2000\n" ));
|
|
} else if (RunningOnWinXp) {
|
|
DebugPrint(( DeviceType, SAPORT_DEBUG_INFO_LEVEL, "Running on Windows XP\n" ));
|
|
} else {
|
|
DebugPrint(( DeviceType, SAPORT_DEBUG_INFO_LEVEL, "Running on *UNKNOWN*\n" ));
|
|
}
|
|
DebugPrint(( DeviceType, SAPORT_DEBUG_INFO_LEVEL, "***********************************************\n" ));
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
SaSignalCompletion(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Event
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to signal the completion of an
|
|
I/O request and is used ONLY by CallLowerDriverAndWait.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the miniport's device object
|
|
Irp - I/O request packet
|
|
Event - Event to be signaled when the I/O is completed
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
KeSetEvent( (PKEVENT)Event, IO_NO_INCREMENT, FALSE );
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CallLowerDriverAndWait(
|
|
IN PIRP Irp,
|
|
IN PDEVICE_OBJECT TargetObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine calls a lower driver and waits for the I/O to complete.
|
|
|
|
Arguments:
|
|
|
|
Irp - I/O request packet
|
|
TargetObject - Pointer to the target device object
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
KEVENT event;
|
|
|
|
KeInitializeEvent( &event, NotificationEvent, FALSE );
|
|
IoCopyCurrentIrpStackLocationToNext( Irp );
|
|
IoSetCompletionRoutine( Irp, SaSignalCompletion, &event, TRUE, TRUE, TRUE );
|
|
IoCallDriver( TargetObject, Irp );
|
|
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
OpenParametersRegistryKey(
|
|
IN PSAPORT_DRIVER_EXTENSION DriverExtension,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN ULONG AccessMode,
|
|
OUT PHANDLE RegistryHandle
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
UNICODE_STRING unicodeString;
|
|
HANDLE serviceKey = NULL;
|
|
|
|
|
|
__try {
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
RegistryPath,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
status = ZwOpenKey(
|
|
&serviceKey,
|
|
AccessMode,
|
|
&objectAttributes
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwOpenKey failed", status );
|
|
}
|
|
|
|
RtlInitUnicodeString( &unicodeString, L"Parameters" );
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&unicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
serviceKey,
|
|
NULL
|
|
);
|
|
|
|
status = ZwOpenKey(
|
|
RegistryHandle,
|
|
AccessMode,
|
|
&objectAttributes
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwOpenKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (serviceKey) {
|
|
ZwClose( serviceKey );
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
if (*RegistryHandle) {
|
|
ZwClose( *RegistryHandle );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CreateParametersRegistryKey(
|
|
IN PSAPORT_DRIVER_EXTENSION DriverExtension,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
OUT PHANDLE parametersKey
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
UNICODE_STRING unicodeString;
|
|
HANDLE serviceKey = NULL;
|
|
ULONG Disposition;
|
|
|
|
|
|
__try {
|
|
|
|
parametersKey = NULL;
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
RegistryPath,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
status = ZwOpenKey(
|
|
&serviceKey,
|
|
KEY_READ | KEY_WRITE,
|
|
&objectAttributes
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwOpenKey failed", status );
|
|
}
|
|
|
|
RtlInitUnicodeString( &unicodeString, L"Parameters" );
|
|
|
|
InitializeObjectAttributes(
|
|
&objectAttributes,
|
|
&unicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
serviceKey,
|
|
NULL
|
|
);
|
|
|
|
status = ZwCreateKey(
|
|
parametersKey,
|
|
KEY_READ | KEY_WRITE,
|
|
&objectAttributes,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
&Disposition
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwCreateKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (serviceKey) {
|
|
ZwClose( serviceKey );
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
if (parametersKey) {
|
|
ZwClose( parametersKey );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ReadRegistryValue(
|
|
IN PSAPORT_DRIVER_EXTENSION DriverExtension,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PWSTR ValueName,
|
|
OUT PKEY_VALUE_FULL_INFORMATION *KeyInformation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads a registry arbitrary value from the
|
|
device's parameter registry data. The necessary memory
|
|
is allocated by this function and must be freed by the caller.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - String containing the path to the driver's registry data
|
|
ValueName - Value name in the registry
|
|
KeyInformation - Pointer to a PKEY_VALUE_FULL_INFORMATION pointer that is allocated by this function
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
UNICODE_STRING unicodeString;
|
|
HANDLE parametersKey = NULL;
|
|
ULONG keyValueLength;
|
|
|
|
|
|
__try {
|
|
|
|
status = OpenParametersRegistryKey(
|
|
DriverExtension,
|
|
RegistryPath,
|
|
KEY_READ,
|
|
¶metersKey
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "OpenParametersRegistryKey failed", status );
|
|
}
|
|
|
|
RtlInitUnicodeString( &unicodeString, ValueName );
|
|
|
|
status = ZwQueryValueKey(
|
|
parametersKey,
|
|
&unicodeString,
|
|
KeyValueFullInformation,
|
|
NULL,
|
|
0,
|
|
&keyValueLength
|
|
);
|
|
if (status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwQueryValueKey failed", status );
|
|
}
|
|
|
|
*KeyInformation = (PKEY_VALUE_FULL_INFORMATION) ExAllocatePool( NonPagedPool, keyValueLength );
|
|
if (*KeyInformation == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "Failed to allocate pool for registry data", status );
|
|
}
|
|
|
|
status = ZwQueryValueKey(
|
|
parametersKey,
|
|
&unicodeString,
|
|
KeyValueFullInformation,
|
|
*KeyInformation,
|
|
keyValueLength,
|
|
&keyValueLength
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwQueryValueKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (parametersKey) {
|
|
ZwClose( parametersKey );
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
if (*KeyInformation) {
|
|
ExFreePool( *KeyInformation );
|
|
}
|
|
*KeyInformation = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
WriteRegistryValue(
|
|
IN PSAPORT_DRIVER_EXTENSION DriverExtension,
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PWSTR ValueName,
|
|
IN ULONG RegistryType,
|
|
IN PVOID RegistryValue,
|
|
IN ULONG RegistryValueLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads a registry arbitrary value from the
|
|
device's parameter registry data. The necessary memory
|
|
is allocated by this function and must be freed by the caller.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - String containing the path to the driver's registry data
|
|
ValueName - Value name in the registry
|
|
KeyInformation - Pointer to a PKEY_VALUE_FULL_INFORMATION pointer that is allocated by this function
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
NTSTATUS status;
|
|
UNICODE_STRING unicodeString;
|
|
HANDLE parametersKey = NULL;
|
|
|
|
|
|
__try {
|
|
|
|
status = OpenParametersRegistryKey(
|
|
DriverExtension,
|
|
RegistryPath,
|
|
KEY_READ | KEY_WRITE,
|
|
¶metersKey
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
status = CreateParametersRegistryKey(
|
|
DriverExtension,
|
|
RegistryPath,
|
|
¶metersKey
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "CreateParametersRegistryKey failed", status );
|
|
}
|
|
}
|
|
|
|
RtlInitUnicodeString( &unicodeString, ValueName );
|
|
|
|
status = ZwSetValueKey(
|
|
parametersKey,
|
|
&unicodeString,
|
|
0,
|
|
RegistryType,
|
|
RegistryValue,
|
|
RegistryValueLength
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( DriverExtension->InitData.DeviceType, "ZwQueryValueKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (parametersKey) {
|
|
ZwClose( parametersKey );
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// debugging stuff
|
|
//------------------------------------------------------------------------
|
|
|
|
|
|
#if DBG
|
|
|
|
PCHAR
|
|
PnPMinorFunctionString(
|
|
UCHAR MinorFunction
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates a minor function code into a string.
|
|
|
|
Arguments:
|
|
|
|
MinorFunction - Minor function code
|
|
|
|
Return Value:
|
|
|
|
Pointer to a string representation of the MinorFunction code.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (MinorFunction) {
|
|
case IRP_MN_START_DEVICE:
|
|
return "IRP_MN_START_DEVICE";
|
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
|
return "IRP_MN_QUERY_REMOVE_DEVICE";
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
return "IRP_MN_REMOVE_DEVICE";
|
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
|
return "IRP_MN_CANCEL_REMOVE_DEVICE";
|
|
case IRP_MN_STOP_DEVICE:
|
|
return "IRP_MN_STOP_DEVICE";
|
|
case IRP_MN_QUERY_STOP_DEVICE:
|
|
return "IRP_MN_QUERY_STOP_DEVICE";
|
|
case IRP_MN_CANCEL_STOP_DEVICE:
|
|
return "IRP_MN_CANCEL_STOP_DEVICE";
|
|
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
|
return "IRP_MN_QUERY_DEVICE_RELATIONS";
|
|
case IRP_MN_QUERY_INTERFACE:
|
|
return "IRP_MN_QUERY_INTERFACE";
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
return "IRP_MN_QUERY_CAPABILITIES";
|
|
case IRP_MN_QUERY_RESOURCES:
|
|
return "IRP_MN_QUERY_RESOURCES";
|
|
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
|
return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
|
|
case IRP_MN_QUERY_DEVICE_TEXT:
|
|
return "IRP_MN_QUERY_DEVICE_TEXT";
|
|
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
|
return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
|
|
case IRP_MN_READ_CONFIG:
|
|
return "IRP_MN_READ_CONFIG";
|
|
case IRP_MN_WRITE_CONFIG:
|
|
return "IRP_MN_WRITE_CONFIG";
|
|
case IRP_MN_EJECT:
|
|
return "IRP_MN_EJECT";
|
|
case IRP_MN_SET_LOCK:
|
|
return "IRP_MN_SET_LOCK";
|
|
case IRP_MN_QUERY_ID:
|
|
return "IRP_MN_QUERY_ID";
|
|
case IRP_MN_QUERY_PNP_DEVICE_STATE:
|
|
return "IRP_MN_QUERY_PNP_DEVICE_STATE";
|
|
case IRP_MN_QUERY_BUS_INFORMATION:
|
|
return "IRP_MN_QUERY_BUS_INFORMATION";
|
|
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
|
return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
|
|
case IRP_MN_SURPRISE_REMOVAL:
|
|
return "IRP_MN_SURPRISE_REMOVAL";
|
|
case IRP_MN_QUERY_LEGACY_BUS_INFORMATION:
|
|
return "IRP_MN_QUERY_LEGACY_BUS_INFORMATION";
|
|
default:
|
|
return "IRP_MN_?????";
|
|
}
|
|
}
|
|
|
|
PCHAR
|
|
PowerMinorFunctionString(
|
|
UCHAR MinorFunction
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates a minor power function code into a string.
|
|
|
|
Arguments:
|
|
|
|
MinorFunction - Minor function code
|
|
|
|
Return Value:
|
|
|
|
Pointer to a string representation of the MinorFunction code.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (MinorFunction) {
|
|
case IRP_MN_WAIT_WAKE:
|
|
return "IRP_MN_WAIT_WAKE";
|
|
case IRP_MN_POWER_SEQUENCE:
|
|
return "IRP_MN_POWER_SEQUENCE";
|
|
case IRP_MN_SET_POWER:
|
|
return "IRP_MN_SET_POWER";
|
|
case IRP_MN_QUERY_POWER:
|
|
return "IRP_MN_QUERY_POWER";
|
|
default:
|
|
return "IRP_MN_?????";
|
|
}
|
|
}
|
|
|
|
PCHAR
|
|
PowerDeviceStateString(
|
|
DEVICE_POWER_STATE State
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates a power state code into a string.
|
|
|
|
Arguments:
|
|
|
|
State - State code
|
|
|
|
Return Value:
|
|
|
|
Pointer to a string representation of the state code.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (State) {
|
|
case PowerDeviceUnspecified:
|
|
return "PowerDeviceUnspecified";
|
|
case PowerDeviceD0:
|
|
return "PowerDeviceD0";
|
|
case PowerDeviceD1:
|
|
return "PowerDeviceD1";
|
|
case PowerDeviceD2:
|
|
return "PowerDeviceD2";
|
|
case PowerDeviceD3:
|
|
return "PowerDeviceD3";
|
|
case PowerDeviceMaximum:
|
|
return "PowerDeviceMaximum";
|
|
default:
|
|
return "PowerDevice?????";
|
|
}
|
|
}
|
|
|
|
PCHAR
|
|
PowerSystemStateString(
|
|
SYSTEM_POWER_STATE State
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates a power system state code into a string.
|
|
|
|
Arguments:
|
|
|
|
State - State code
|
|
|
|
Return Value:
|
|
|
|
Pointer to a string representation of the state code.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (State) {
|
|
case PowerSystemUnspecified:
|
|
return "PowerSystemUnspecified";
|
|
case PowerSystemWorking:
|
|
return "PowerSystemWorking";
|
|
case PowerSystemSleeping1:
|
|
return "PowerSystemSleeping1";
|
|
case PowerSystemSleeping2:
|
|
return "PowerSystemSleeping2";
|
|
case PowerSystemSleeping3:
|
|
return "PowerSystemSleeping3";
|
|
case PowerSystemHibernate:
|
|
return "PowerSystemHibernate";
|
|
case PowerSystemShutdown:
|
|
return "PowerSystemShutdown";
|
|
case PowerSystemMaximum:
|
|
return "PowerSystemMaximum";
|
|
default:
|
|
return "PowerSystem?????";
|
|
}
|
|
}
|
|
|
|
PCHAR
|
|
IoctlString(
|
|
ULONG IoControlCode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates an IOCTL code into a string.
|
|
|
|
Arguments:
|
|
|
|
IoControlCode - I/O control code
|
|
|
|
Return Value:
|
|
|
|
Pointer to a string representation of the I/O control code.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (IoControlCode) {
|
|
case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME:
|
|
return "IOCTL_MOUNTDEV_QUERY_DEVICE_NAME";
|
|
case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID:
|
|
return "IOCTL_MOUNTDEV_QUERY_UNIQUE_ID";
|
|
case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME:
|
|
return "IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME";
|
|
case IOCTL_STORAGE_GET_MEDIA_TYPES:
|
|
return "IOCTL_STORAGE_GET_MEDIA_TYPES";
|
|
case IOCTL_DISK_GET_MEDIA_TYPES:
|
|
return "IOCTL_DISK_GET_MEDIA_TYPES";
|
|
case IOCTL_DISK_CHECK_VERIFY:
|
|
return "IOCTL_DISK_CHECK_VERIFY";
|
|
case IOCTL_DISK_GET_DRIVE_GEOMETRY:
|
|
return "IOCTL_DISK_GET_DRIVE_GEOMETRY";
|
|
case IOCTL_DISK_IS_WRITABLE:
|
|
return "IOCTL_DISK_IS_WRITABLE";
|
|
case IOCTL_DISK_VERIFY:
|
|
return "IOCTL_DISK_VERIFY";
|
|
case IOCTL_DISK_GET_DRIVE_LAYOUT:
|
|
return "IOCTL_DISK_GET_DRIVE_LAYOUT";
|
|
case IOCTL_DISK_GET_PARTITION_INFO:
|
|
return "IOCTL_DISK_GET_PARTITION_INFO";
|
|
case IOCTL_DISK_GET_PARTITION_INFO_EX:
|
|
return "IOCTL_DISK_GET_PARTITION_INFO_EX";
|
|
case IOCTL_DISK_GET_LENGTH_INFO:
|
|
return "IOCTL_DISK_GET_LENGTH_INFO";
|
|
case IOCTL_DISK_MEDIA_REMOVAL:
|
|
return "IOCTL_DISK_MEDIA_REMOVAL";
|
|
case IOCTL_SA_GET_VERSION:
|
|
return "IOCTL_SA_GET_VERSION";
|
|
case IOCTL_SA_GET_CAPABILITIES:
|
|
return "IOCTL_SA_GET_CAPABILITIES";
|
|
case IOCTL_SAWD_DISABLE:
|
|
return "IOCTL_SAWD_DISABLE";
|
|
case IOCTL_SAWD_QUERY_EXPIRE_BEHAVIOR:
|
|
return "IOCTL_SAWD_QUERY_EXPIRE_BEHAVIOR";
|
|
case IOCTL_SAWD_SET_EXPIRE_BEHAVIOR:
|
|
return "IOCTL_SAWD_SET_EXPIRE_BEHAVIOR";
|
|
case IOCTL_SAWD_PING:
|
|
return "IOCTL_SAWD_PING";
|
|
case IOCTL_SAWD_QUERY_TIMER:
|
|
return "IOCTL_SAWD_QUERY_TIMER";
|
|
case IOCTL_SAWD_SET_TIMER:
|
|
return "IOCTL_SAWD_SET_TIMER";
|
|
case IOCTL_NVRAM_WRITE_BOOT_COUNTER:
|
|
return "IOCTL_NVRAM_WRITE_BOOT_COUNTER";
|
|
case IOCTL_NVRAM_READ_BOOT_COUNTER:
|
|
return "IOCTL_NVRAM_READ_BOOT_COUNTER";
|
|
case IOCTL_SADISPLAY_LOCK:
|
|
return "IOCTL_SADISPLAY_LOCK";
|
|
case IOCTL_SADISPLAY_UNLOCK:
|
|
return "IOCTL_SADISPLAY_UNLOCK";
|
|
case IOCTL_SADISPLAY_BUSY_MESSAGE:
|
|
return "IOCTL_SADISPLAY_BUSY_MESSAGE";
|
|
case IOCTL_SADISPLAY_SHUTDOWN_MESSAGE:
|
|
return "IOCTL_SADISPLAY_SHUTDOWN_MESSAGE";
|
|
case IOCTL_SADISPLAY_CHANGE_LANGUAGE:
|
|
return "IOCTL_SADISPLAY_CHANGE_LANGUAGE";
|
|
default:
|
|
return "IOCTL_?????";
|
|
}
|
|
}
|
|
|
|
#endif
|