📄 wdmstub.cpp
字号:
// WDMSTUB.CPP -- Stubs for missing Win2K WDM service functions
// Copyright (C) 1998 by Walter Oney
// All rights reserved
#include "stddcls.h"
#include "driver.h"
#include "NonStubs.h"
#define IFSMGR_SERVICES_ONLY
#include "ifsmgr.h"
CCHAR cKeNumberProcessors = 1;
BOOLEAN bKdDebuggerEnabled = 0;
BOOLEAN PrecisionErrata = FALSE;
DWORD features = 0;
// Pentium feature flags returned in EDX from CPUID with EAX == 1
#define FEATURE_FPU 0x00000001 // FPU on chip
#define FEATURE_RDTSC 0x00000010 // RDTSC instruction supported
#define FEATURE_MACHINE_CHECK 0x00000080 // machine check exception can occur
#define FEATURE_CMPXCHG8B 0x00000100 // CMPXCHG8B instruction supported
#define FEATURE_MMX 0x00800000 // MMX instructions supported
#define FEATURE_XMMI 0x02000000
#define BCS_WANSI 0 // ifs.h generates too many compile errors if we include it
extern "C" NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName(PUNICODE_STRING name, ULONG unknown1,
ULONG unknown2, ULONG unknown3, POBJECT_TYPE type,
KPROCESSOR_MODE mode, ULONG unknown4, PVOID *object);
extern "C" POBJECT_TYPE* IoDriverObjectType;
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
// Names of functions stubbed by this VxD. This isn't the array we actually pass
// to PELDR -- it's the array we use when we construct a list of functions
// that aren't already implemented by NTKERN. The names must be in resident storage
// because we don't copy them when we build the export table.
static char* names[] = {
"PoRegisterSystemState",
"PoSetSystemState",
"PoUnregisterSystemState",
"IoReportTargetDeviceChangeAsynchronous",
"ExSystemTimeToLocalTime",
"ExLocalTimeToSystemTime",
"IoCreateNotificationEvent",
"IoCreateSynchronizationEvent",
"IoAllocateWorkItem",
"IoFreeWorkItem",
"IoQueueWorkItem",
"PsGetVersion",
"RtlUshortByteSwap",
"RtlUlongByteSwap",
"RtlUlonglongByteSwap",
"RtlInt64ToUnicodeString",
"KeSetTargetProcessorDpc",
"KeNumberProcessors",
"KdDebuggerEnabled",
"IoReuseIrp",
"IoRaiseInformationalHardError",
"HalTranslateBusAddress",
"ExIsProcessorFeaturePresent",
"MmGetSystemRoutineAddress",
"ZwQueryInformationFile",
"ZwSetInformationFile",
"ZwQueryDefaultLocale",
"ExFreePoolWithTag",
"ZwLoadDriver",
"ZwUnloadDriver",
"SeSinglePrivilegeCheck",
"IoSetCompletionRoutineEx",
};
// As of SP-9, we're using C11 with the Xp options. String constants therefore end
// up in the referencing code segment, but we need to have *this* constant persist:
static char* ntoskrnl = "ntoskrnl.exe";
static char* remlocknames[] = {
"IoAcquireRemoveLockEx",
"IoReleaseRemoveLockEx",
"IoReleaseRemoveLockAndWaitEx",
"IoInitializeRemoveLockEx",
};
// The Win98 implementation of KeEnterCriticalRegion incorrectly raises the IRQL to
// APC_LEVEL, so we'll stub it no matter what
static char* critnames[] = {
"KeEnterCriticalRegion",
"KeLeaveCriticalRegion",
};
// Macros added in Xp DDK:
#undef RtlUshortByteSwap
#undef RtlUlongByteSwap
#undef RtlUlonglongByteSwap
USHORT
FASTCALL
RtlUshortByteSwap(
IN USHORT Source
);
ULONG
FASTCALL
RtlUlongByteSwap(
IN ULONG Source
);
ULONGLONG
FASTCALL
RtlUlonglongByteSwap(
IN ULONGLONG Source
);
NTSTATUS ZwLoadDriver(PUNICODE_STRING);
NTSTATUS ZwUnloadDriver(PUNICODE_STRING);
#pragma warning(disable:4273) // inconsistent dll linkage
// Addresses of stub functions (must line up with names array)
NTSTATUS ZwQueryDefaultLocale(BOOLEAN thread, LCID* plocale);
static PFN addresses[] = {
(PFN) PoRegisterSystemState,
(PFN) PoSetSystemState,
(PFN) PoUnregisterSystemState,
(PFN) IoReportTargetDeviceChangeAsynchronous,
(PFN) ExSystemTimeToLocalTime,
(PFN) ExLocalTimeToSystemTime,
(PFN) IoCreateNotificationEvent,
(PFN) IoCreateSynchronizationEvent,
(PFN) IoAllocateWorkItem,
(PFN) IoFreeWorkItem,
(PFN) IoQueueWorkItem,
(PFN) PsGetVersion,
(PFN) RtlUshortByteSwap,
(PFN) RtlUlongByteSwap,
(PFN) RtlUlonglongByteSwap,
(PFN) RtlInt64ToUnicodeString,
(PFN) KeSetTargetProcessorDpc,
(PFN) &cKeNumberProcessors,
(PFN) &bKdDebuggerEnabled,
(PFN) IoReuseIrp,
(PFN) IoRaiseInformationalHardError,
(PFN) HalTranslateBusAddress,
(PFN) ExIsProcessorFeaturePresent,
(PFN) MmGetSystemRoutineAddress,
(PFN) ZwQueryInformationFile,
(PFN) ZwSetInformationFile,
(PFN) ZwQueryDefaultLocale,
(PFN) ExFreePoolWithTag,
(PFN) ZwLoadDriver,
(PFN) ZwUnloadDriver,
(PFN) SeSinglePrivilegeCheck,
(PFN) IoSetCompletionRoutineEx,
};
static PFN remlockaddresses[] = {
(PFN) IoAcquireRemoveLockEx,
(PFN) IoReleaseRemoveLockEx,
(PFN) IoReleaseRemoveLockAndWaitEx,
(PFN) IoInitializeRemoveLockEx,
};
static PFN critaddresses[] = {
(PFN) KeEnterCriticalRegion,
(PFN) KeLeaveCriticalRegion,
};
__int64 GetZoneBias();
DWORD buildnum;
HPEEXPORTTABLE hExportTable = 0;
char** stubnames; // names of functions we stubbed
PFN* stubaddresses; // addresses of the stub functions
WORD* ordinals; // ordinal table to correlate the other two tables
LCID locale; // default locale
LCID GetSystemLocale();
DWORD atox(char* s);
NTSTATUS CompletionRoutineWrapper(PDEVICE_OBJECT fdo, PIRP Irp, PCOMPLETION_CONTEXT ctx);
///////////////////////////////////////////////////////////////////////////////
#pragma warning(disable:4035)
UINT __declspec(naked) __cdecl UniToBCS(PBYTE pBCSPath, WCHAR* pUniPath, UINT length, UINT maxLength, UINT charSet)
{
VxDJmp(UniToBCS)
}
#pragma warning(default:4035)
///////////////////////////////////////////////////////////////////////////////
#pragma INITCODE
#pragma warning(disable:4035)
BOOLEAN Test_Debug_Installed()
{
VMMCall(Test_Debug_Installed)
_asm setnz al
}
#pragma warning(default:4035)
extern "C" ULONG _fltused = 0;
// Flags in CR0:
#define CR0_PG 0x80000000 // paging
#define CR0_ET 0x00000010 // extension type (80387)
#define CR0_TS 0x00000008 // task switched
#define CR0_EM 0x00000004 // emulate math coprocessor
#define CR0_MP 0x00000002 // math present
#define CR0_PE 0x00000001 // protection enable
#define CR0_CD 0x40000000 // cache disable
#define CR0_NW 0x20000000 // not write-through
#define CR0_AM 0x00040000 // alignment mask
#define CR0_WP 0x00010000 // write protect
#define CR0_NE 0x00000020 // numeric error
BOOL CheckPrecisionErrata()
{ // CheckPrecisionErrata
static double Dividend = 4195835.0;
static double Divisor = 3145727.0;
BOOL result = FALSE;
_asm
{
pushfd ; save flags
cli
mov eax, cr0 ; make sure flags are the way we need them
mov ecx, eax
and eax, not (CR0_TS or CR0_MP or CR0_EM)
mov cr0, eax
fninit ; initialize coprocessor
fld Dividend ; perform division to show up precision errata
fdiv Divisor
fmul Divisor
fcomp Dividend
fstsw ax ; capture floating point status
sahf
jc noproblem
jz noproblem
mov result, 1
noproblem:
mov cr0, ecx ; restore CR0
popfd ; restore flags (including enable state)
}
return result;
} // CheckPrecisionErrata
BOOLEAN DefineStubs()
{ // DefineStubs
// Construct the name, ordinal, and address tables for functions we're going
// to stub. In various releases of Windows 98 and Millenium, some or all of
// these functions will be supported by the operating system, and we don't
// want to preempt the standard implementation.
stubnames = (char**) _HeapAllocate(sizeof(names) + sizeof(remlocknames), HEAPZEROINIT); // largest we might ever need
if (!stubnames)
return FALSE;
stubaddresses = (PFN*) _HeapAllocate(sizeof(addresses) + sizeof(remlockaddresses) + sizeof(critaddresses), HEAPZEROINIT);
if (!stubaddresses)
{
_HeapFree(stubnames, 0);
return FALSE;
}
ordinals = (WORD*) _HeapAllocate((arraysize(names) + arraysize(remlocknames) + arraysize(critnames)) * sizeof(WORD), HEAPZEROINIT);
if (!ordinals)
{
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
return FALSE;
}
int i, istub;
for (i = 0, istub = 0; i < arraysize(names); ++i)
{ // for each possible stub
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, names[i], NULL) == 0)
{ // stub this function
KdPrint((DRIVERNAME " - Stubbing %s\n", names[i]));
stubnames[istub] = names[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = addresses[i];
++istub;
} // stub this function
else
KdPrint((DRIVERNAME " - %s already implemented - not stubbing it\n", names[i]));
} // for each possible stub
// We have a special problem with the remove lock functions, in that Win98SE leaves out
// just IoRemoveLockAndWaitEx. We'll stub all of them if we find this function missing.
if (_PELDR_GetProcAddress((HPEMODULE) ntoskrnl, "IoReleaseRemoveLockAndWaitEx", NULL) == 0)
{ // stub remove lock functions
KdPrint((DRIVERNAME " - Stubbing all remove lock functions\n"));
for (i = 0; i < arraysize(remlocknames); ++i)
{ // for each remove lock function
stubnames[istub] = remlocknames[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = remlockaddresses[i];
++istub;
} // for each remove lock function
} // stub remove lock functions
else
KdPrint((DRIVERNAME " - Not stubbing remove lock functions\n"));
// Always replace the critical region functions to avoid having the IRQL raised
for (i = 0; i < arraysize(critnames); ++i)
{ // for each critical region function
KdPrint((DRIVERNAME " - Stubbing %s\n", critnames[i]));
stubnames[istub] = critnames[i];
ordinals[istub] = (WORD) istub;
stubaddresses[istub] = critaddresses[i];
++istub;
} // for each critical region function
// Create an export table to provide for these functions
if (_PELDR_AddExportTable(&hExportTable, ntoskrnl, istub,
istub, 0, (PVOID*) stubnames, ordinals, stubaddresses, NULL) != 0)
{ // can't define exports
KdPrint((DRIVERNAME " -- Unable to define export table\n"));
_HeapFree(ordinals, 0);
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
return FALSE;
} // can't define exports
// See if debugger running
bKdDebuggerEnabled = Test_Debug_Installed();
// Get build number from HKLM\Software\Microsoft\Windows\CurrentVersion[VersionNumber]
VMMHKEY hkey;
if (_RegOpenKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_SETUP, &hkey) == 0)
{ // get value
char value[64];
DWORD size = sizeof(value);
if (_RegQueryValueEx(hkey, "VersionNumber", NULL, NULL, (PBYTE) value, &size) == 0)
{ // parse value
char* p = value;
atoi(p); // major version number
if (*p == '.')
++p;
atoi(p); // minor version number
if (*p == '.')
++p;
buildnum = atoi(p); // build number
} // parse value
_RegCloseKey(hkey);
} // get value
// Determine CPU feature flags
DWORD machineinfo;
#undef Get_Machine_Info
VMMCall(Get_Machine_Info)
_asm mov machineinfo, ebx ; capture machine type flags
if (machineinfo & GMIF_CPUID)
{ // cpuid supported
_asm mov eax, 1 ; EAX = 1 => request for feature flags
_asm cpuid
_asm mov features, edx ; save feature flags
} // cpuid supported
if (features & FEATURE_FPU)
PrecisionErrata = (BOOLEAN) CheckPrecisionErrata();
// Determine the default locale for ZwQueryDefaultLocale
locale = GetSystemLocale();
return TRUE;
} // DefineStubs
///////////////////////////////////////////////////////////////////////////////
#pragma PAGEDCODE
VOID UndefineStubs()
{ // UndefineStubs
_PELDR_RemoveExportTable(hExportTable, NULL);
_HeapFree(ordinals, 0);
_HeapFree(stubaddresses, 0);
_HeapFree(stubnames, 0);
} // UndefineStubs
///////////////////////////////////////////////////////////////////////////////
#pragma LOCKEDCODE
PVOID PoRegisterSystemState(PVOID hstate, ULONG flags)
{ // PoRegisterSystemState
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
return NULL;
} // PoRegisterSystemState
VOID PoSetSystemState(ULONG flags)
{ // PoSetSystemState
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
} // PoSetSystemState
VOID PoUnregisterSystemState(PVOID hstate)
{ // PoUnregisterSystemState
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
} // PoUnregisterSystemState
NTSTATUS IoReportTargetDeviceChangeAsynchronous(PDEVICE_OBJECT pdo, PVOID NfyStruct, PDEVICE_CHANGE_COMPLETE_CALLBACK Callback, PVOID Context)
{ // IoReportTargetDeviceChangeAsynchronous
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
return STATUS_NOT_IMPLEMENTED;
} // IoReportTargetDeviceChangeAsynchronous
VOID ExSystemTimeToLocalTime(PLARGE_INTEGER systime, PLARGE_INTEGER localtime)
{ // ExSystemTimeToLocalTime
localtime->QuadPart = systime->QuadPart - GetZoneBias();
} // ExSystemTimeToLocalTime
VOID ExLocalTimeToSystemTime(PLARGE_INTEGER localtime, PLARGE_INTEGER systime)
{ // ExLocalTimeToSystemTime
systime->QuadPart = localtime->QuadPart + GetZoneBias();
} // ExLocalTimeToSystemTime
PKEVENT IoCreateNotificationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle)
{ // IoCreateNotificationEvent
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
return NULL;
} // IoCreateNotificationEvent
PKEVENT IoCreateSynchronizationEvent(PUNICODE_STRING EventName, PHANDLE EventHandle)
{ // IoCreateSynchronizationEvent
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
return NULL;
} // IoCreateSynchronizationEvent
PIO_WORKITEM IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
{ // IoAllocateWorkItem
return AllocateWorkItem(DeviceObject);
} // IoAllocateWorkItem
VOID IoFreeWorkItem(PIO_WORKITEM item)
{ // IoFreeWorkItem
FreeWorkItem(item);
} // IoFreeWorkItem
VOID IoQueueWorkItem(PIO_WORKITEM item, PIO_WORKITEM_ROUTINE Routine, WORK_QUEUE_TYPE QueueType, PVOID Context)
{ // IoQueueWorkItem
QueueWorkItem(item, Routine, QueueType, Context);
} // IoQueueWorkItem
BOOLEAN PsGetVersion(PULONG MajorVersion, PULONG MinorVersion, PULONG BuildNumber, PUNICODE_STRING spnum)
{ // PsGetVersion
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -