⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wdmstub.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -