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.
1254 lines
27 KiB
1254 lines
27 KiB
/*++
|
|
|
|
Copyright (c) 1991 - 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
## ## ###### #### ## #### ##### #####
|
|
## ## ## ## ## ## # ## ## ## ##
|
|
## ## ## ## ## ## ## ## ## ##
|
|
## ## ## ## ## ## ## ## ## ##
|
|
## ## ## ## ## ## ##### #####
|
|
## ## ## ## ## ## ## # ## ##
|
|
#### ## #### ##### ## #### ## ##
|
|
|
|
Abstract:
|
|
|
|
Utility driver functions.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 23-Jan-2002
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Notes:
|
|
|
|
|
|
--*/
|
|
|
|
#include "internal.h"
|
|
#include <ntimage.h>
|
|
#include <stdarg.h>
|
|
|
|
#if DBG
|
|
ULONG WdDebugLevel;
|
|
#endif
|
|
|
|
ULONG OsMajorVersion;
|
|
ULONG OsMinorVersion;
|
|
|
|
|
|
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->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 );
|
|
}
|
|
|
|
|
|
VOID
|
|
WdDebugPrint(
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
va_list arg_ptr;
|
|
char buf[512];
|
|
char *s = buf;
|
|
|
|
|
|
|
|
#if DBG
|
|
if ((DebugLevel != 0xffffffff) && ((WdDebugLevel == 0) || ((WdDebugLevel & DebugLevel) == 0))) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
va_start( arg_ptr, DebugMessage );
|
|
strcpy( s, "WD: " );
|
|
s += strlen(s);
|
|
_vsnprintf( s, sizeof(buf)-1-strlen(s), DebugMessage, arg_ptr );
|
|
DbgPrint( buf );
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
VOID
|
|
GetOsVersion(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine gets the current OS version information
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
RTL_OSVERSIONINFOW VersionInformation;
|
|
|
|
VersionInformation.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
|
|
RtlGetVersion( &VersionInformation );
|
|
OsMajorVersion = VersionInformation.dwMajorVersion;
|
|
OsMinorVersion = VersionInformation.dwMinorVersion;
|
|
}
|
|
|
|
|
|
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 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];
|
|
|
|
|
|
NtHeaders = RtlpImageNtHeader( DriverObject->DriverStart );
|
|
if (NtHeaders) {
|
|
TimeStamp = NtHeaders->FileHeader.TimeDateStamp;
|
|
FormatTime( TimeStamp, buf );
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
WdSignalCompletion(
|
|
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, WdSignalCompletion, &event, TRUE, TRUE, TRUE );
|
|
IoCallDriver( TargetObject, Irp );
|
|
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
|
|
return Irp->IoStatus.Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
OpenParametersRegistryKey(
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN ULONG AccessMode,
|
|
OUT PHANDLE RegistryHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine opens the driver's paramaters
|
|
registry key for I/O.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - Full path to the root of the driver's
|
|
registry tree.
|
|
|
|
AccessMode - Specifies how the handle is to be opened (READ/WRITE/etc).
|
|
|
|
RegistryHandle - Output parameter that receives the registry handle.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
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( "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( "ZwOpenKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (serviceKey) {
|
|
ZwClose( serviceKey );
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
if (*RegistryHandle) {
|
|
ZwClose( *RegistryHandle );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
CreateParametersRegistryKey(
|
|
IN PUNICODE_STRING RegistryPath,
|
|
OUT PHANDLE parametersKey
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine creates the driver's paramaters
|
|
registry key for I/O.
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - Full path to the root of the driver's
|
|
registry tree.
|
|
|
|
RegistryHandle - Output parameter that receives the registry handle.
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
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( "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( "ZwCreateKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (serviceKey) {
|
|
ZwClose( serviceKey );
|
|
}
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
if (parametersKey) {
|
|
ZwClose( parametersKey );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ReadRegistryValue(
|
|
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 {
|
|
|
|
*KeyInformation = NULL;
|
|
|
|
status = OpenParametersRegistryKey(
|
|
RegistryPath,
|
|
KEY_READ,
|
|
¶metersKey
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( "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( "ZwQueryValueKey failed", status );
|
|
}
|
|
|
|
*KeyInformation = (PKEY_VALUE_FULL_INFORMATION) ExAllocatePool( NonPagedPool, keyValueLength );
|
|
if (*KeyInformation == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
ERROR_RETURN( "Failed to allocate pool for registry data", status );
|
|
}
|
|
|
|
status = ZwQueryValueKey(
|
|
parametersKey,
|
|
&unicodeString,
|
|
KeyValueFullInformation,
|
|
*KeyInformation,
|
|
keyValueLength,
|
|
&keyValueLength
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( "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 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(
|
|
RegistryPath,
|
|
KEY_READ | KEY_WRITE,
|
|
¶metersKey
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
status = CreateParametersRegistryKey(
|
|
RegistryPath,
|
|
¶metersKey
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( "CreateParametersRegistryKey failed", status );
|
|
}
|
|
}
|
|
|
|
RtlInitUnicodeString( &unicodeString, ValueName );
|
|
|
|
status = ZwSetValueKey(
|
|
parametersKey,
|
|
&unicodeString,
|
|
0,
|
|
RegistryType,
|
|
RegistryValue,
|
|
RegistryValueLength
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
ERROR_RETURN( "ZwQueryValueKey failed", status );
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
} __finally {
|
|
|
|
if (parametersKey) {
|
|
ZwClose( parametersKey );
|
|
}
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
WriteEventLogEntry (
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
IN ULONG ErrorCode,
|
|
IN PVOID InsertionStrings, OPTIONAL
|
|
IN ULONG StringCount, OPTIONAL
|
|
IN PVOID DumpData, OPTIONAL
|
|
IN ULONG DataSize OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Writes an entry into the system eventlog.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Pointer to a device extension object
|
|
|
|
ErrorCode - Eventlog errorcode as specified in eventmsg.mc
|
|
|
|
InsertionStrings - String to insert into the eventlog message
|
|
|
|
StringCount - Number of InsertionStrings
|
|
|
|
DumpData - Additional data to be include in the message
|
|
|
|
DataSize - Size of the DumpData
|
|
|
|
Return Value:
|
|
|
|
NT status code
|
|
|
|
--*/
|
|
|
|
{
|
|
#define ERROR_PACKET_SIZE sizeof(IO_ERROR_LOG_PACKET)
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
ULONG totalPacketSize;
|
|
ULONG i, stringSize = 0;
|
|
PWCHAR *strings, temp;
|
|
PIO_ERROR_LOG_PACKET logEntry;
|
|
UNICODE_STRING unicodeString;
|
|
|
|
|
|
__try {
|
|
|
|
//
|
|
// Calculate total string length, including NULL.
|
|
//
|
|
|
|
strings = (PWCHAR *) InsertionStrings;
|
|
|
|
for (i=0; i<StringCount; i++) {
|
|
RtlInitUnicodeString(&unicodeString, strings[i]);
|
|
stringSize += unicodeString.Length + sizeof(UNICODE_NULL);
|
|
}
|
|
|
|
//
|
|
// Calculate total packet size to allocate. The packet must be
|
|
// at least sizeof(IO_ERROR_LOG_PACKET) and not larger than
|
|
// ERROR_LOG_MAXIMUM_SIZE or the IoAllocateErrorLogEntry call will fail.
|
|
//
|
|
|
|
totalPacketSize = ERROR_PACKET_SIZE + DataSize + stringSize;
|
|
|
|
if (totalPacketSize >= ERROR_LOG_MAXIMUM_SIZE) {
|
|
ERROR_RETURN( "WriteEventLogEntry: Error Log Entry too large", STATUS_UNSUCCESSFUL );
|
|
}
|
|
|
|
//
|
|
// Allocate the error log packet
|
|
//
|
|
|
|
logEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceExtension->DeviceObject, (UCHAR)totalPacketSize );
|
|
if (!logEntry) {
|
|
ERROR_RETURN( "IoAllocateErrorLogEntry failed", STATUS_INSUFFICIENT_RESOURCES );
|
|
}
|
|
|
|
RtlZeroMemory( logEntry, totalPacketSize );
|
|
|
|
//
|
|
// Fill out the packet
|
|
//
|
|
|
|
//logEntry->MajorFunctionCode = 0;
|
|
//logEntry->RetryCount = 0;
|
|
//logEntry->UniqueErrorValue = 0;
|
|
//logEntry->FinalStatus = 0;
|
|
//logEntry->SequenceNumber = ErrorLogCount++;
|
|
//logEntry->IoControlCode = 0;
|
|
//logEntry->DeviceOffset.QuadPart = 0;
|
|
|
|
logEntry->DumpDataSize = (USHORT) DataSize;
|
|
logEntry->NumberOfStrings = (USHORT) StringCount;
|
|
logEntry->EventCategory = 0x1;
|
|
logEntry->ErrorCode = ErrorCode;
|
|
|
|
if (StringCount) {
|
|
logEntry->StringOffset = (USHORT) (ERROR_PACKET_SIZE + DataSize);
|
|
}
|
|
|
|
//
|
|
// Copy Dump Data
|
|
//
|
|
|
|
if (DataSize) {
|
|
RtlCopyMemory( (PVOID)logEntry->DumpData, DumpData, DataSize );
|
|
}
|
|
|
|
//
|
|
// Copy String Data
|
|
//
|
|
|
|
temp = (PWCHAR)((PUCHAR)logEntry + logEntry->StringOffset);
|
|
|
|
for (i=0; i<StringCount; i++) {
|
|
PWCHAR ptr = strings[i];
|
|
//
|
|
// This routine will copy the null terminator on the string
|
|
//
|
|
while ((*temp++ = *ptr++) != UNICODE_NULL);
|
|
}
|
|
|
|
//
|
|
// Submit error log packet
|
|
//
|
|
|
|
IoWriteErrorLogEntry(logEntry);
|
|
|
|
} __finally {
|
|
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
ULONG
|
|
ConvertTimeoutToMilliseconds(
|
|
IN ULONG Units,
|
|
IN ULONG NativeTimeout
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a time value that is represented in the native
|
|
format that is specified by the hardware watchdog timer's
|
|
ACPI table entry into a millisecond based value.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Pointer to a device extension object
|
|
|
|
NativeTimeout - Native timeout value
|
|
|
|
Return Value:
|
|
|
|
Converted value or zero.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Timeout = 0;
|
|
|
|
|
|
switch (Units) {
|
|
case 0:
|
|
//
|
|
// 1 seconds
|
|
//
|
|
Timeout = NativeTimeout * 1000;
|
|
break;
|
|
|
|
case 1:
|
|
//
|
|
// 100 miliseconds
|
|
//
|
|
Timeout = NativeTimeout / 100;
|
|
break;
|
|
|
|
case 2:
|
|
//
|
|
// 10 milliseconds
|
|
//
|
|
Timeout = NativeTimeout / 10;
|
|
break;
|
|
|
|
case 3:
|
|
//
|
|
// 1 miliseconds
|
|
//
|
|
Timeout = NativeTimeout;
|
|
break;
|
|
|
|
default:
|
|
Timeout = 0;
|
|
break;
|
|
}
|
|
|
|
return Timeout;
|
|
}
|
|
|
|
|
|
ULONG
|
|
ConvertTimeoutFromMilliseconds(
|
|
IN ULONG Units,
|
|
IN ULONG UserTimeout
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts a time value that is represented in milliseconds
|
|
to the native format that is specified by the hardware
|
|
watchdog timer's ACPI table entry.
|
|
|
|
Arguments:
|
|
|
|
DeviceExtension - Pointer to a device extension object
|
|
|
|
UserTimeout - Millisecond timeout value.
|
|
|
|
Return Value:
|
|
|
|
Converted value or zero.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Timeout = 0;
|
|
|
|
switch (Units) {
|
|
case 0:
|
|
//
|
|
// 1 seconds
|
|
//
|
|
Timeout = UserTimeout / 1000;
|
|
break;
|
|
|
|
case 1:
|
|
//
|
|
// 100 miliseconds
|
|
//
|
|
Timeout = UserTimeout * 100;
|
|
break;
|
|
|
|
case 2:
|
|
//
|
|
// 10 milliseconds
|
|
//
|
|
Timeout = UserTimeout * 10;
|
|
break;
|
|
|
|
case 3:
|
|
//
|
|
// 1 miliseconds
|
|
//
|
|
Timeout = UserTimeout;
|
|
break;
|
|
|
|
default:
|
|
Timeout = 0;
|
|
break;
|
|
}
|
|
|
|
return Timeout;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// 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";
|
|
default:
|
|
return "IOCTL_?????";
|
|
}
|
|
}
|
|
|
|
#endif
|