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

📄 wdmcheck.cpp

📁 一本在讲述USB驱动程式的书 及其范例原码
💻 CPP
字号:
// wdmcheck.c -- Implementation of WDMCHECK.VXD
// Copyright (C) 2000 by Walter Oney
// All rights reserved

#include "stdvxd.h"
#include "wdmcheck.h"
#include "ioctls.h"
#include "version.h"

VOID GetStubInfo();
VOID DeleteStubInfo();
BOOL StringOkay(char* s, DWORD len);
DWORD IsExportDefined(char* module, char* fcn);

#define IOCTL_INTERNAL_WDMSTUB_GET_VERSION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)

///////////////////////////////////////////////////////////////////////////////
// Overrides for library new and delete operators.

void* __cdecl ::operator new(unsigned int size)
	{							// operator new
	return _HeapAllocate(size, 0);
	}							// operator new

void __cdecl ::operator delete(void* p)
	{							// operator delete
	if (p)
		_HeapFree(p, 0);
	}							// operator delete

///////////////////////////////////////////////////////////////////////////////
// Global data areas:

#pragma VxD_PAGEABLE_DATA_SEG	// data which can be paged

CStubVersion* CStubVersion::Anchor = NULL;

///////////////////////////////////////////////////////////////////////////////

WCHAR* wcscpy(WCHAR* target, WCHAR* source)
	{							// wcscpy
	WCHAR* result = target;
	WCHAR ch;
	do	{
		ch = *source++;
		*target++ = ch;
		}
	while (ch);

	return result;
	}							// wcscpy

int wcslen(WCHAR* s)
	{							// wcslen
	int len = 0;
	while (*s++)
		++len;
	return len;
	}							// wcslen

WCHAR* wcscat(WCHAR* target, WCHAR* source)
	{							// wcscat
	WCHAR* result = target;
	wcscpy(target + wcslen(target), source);
	return result;
	}							// wcscat

#pragma warning(disable:4035)

int  __declspec(naked) __cdecl _lstrcmpi(const char* left, const char* right)
	{							// _lstrcmpi
	VMMJmp(_lstrcmpi)
	}							// _lstrcmpi

Device_Location_List* VMM_GetVxDLocationList(DWORD& nvxds, DWORD& tabsize)
	{							// VMM_GetVxDLocationList
	VMMCall(VMM_GetVxDLocationList)
	_asm
		{
		jz		error
		push	eax
		mov		eax, nvxds
		mov		[eax], edx		; EDX = count of VxDs
		mov		eax, tabsize
		mov		[eax], ecx		; ECX = size of table
		pop		eax
	error:
		}
	}							// VMM_GetVxDLocationList

#pragma warning(default:4035)

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// System control message handlers
///////////////////////////////////////////////////////////////////////////////

#pragma VxD_INIT_CODE_SEG

SYSCTL BOOL __cdecl OnSysDynamicDeviceInit(void)
	{							// OnSysDynamicDeviceInit
	GetStubInfo();
	return TRUE;
	}							// OnSysDynamicDeviceInit

///////////////////////////////////////////////////////////////////////////////

#pragma VxD_PAGEABLE_CODE_SEG

SYSCTL BOOL __cdecl OnSysDynamicDeviceExit(void)
	{							// OnSysDynamicDeviceExit
	DeleteStubInfo();
	return TRUE;
	}							// OnSysDynamicDeviceExit

///////////////////////////////////////////////////////////////////////////////

#pragma VxD_PAGEABLE_CODE_SEG

SYSCTL DWORD __cdecl OnW32DeviceIoControl(PDIOCPARAMETERS p)
	{							// OnW32DeviceIoControl
	switch (p->dwIoControlCode)
		{						// process IOCTL operation

	case DIOC_OPEN:
	case DIOC_CLOSEHANDLE:
		return 0;

	case IOCTL_GET_VERSION:
		if (p->cbOutBuffer < sizeof(DWORD))
			return ERROR_INVALID_PARAMETER;
		*(PDWORD) p->lpvOutBuffer = (VERMAJOR << 16) | VERMINOR;
		if (p->lpcbBytesReturned)
			*(PDWORD) p->lpcbBytesReturned = sizeof(DWORD);
		return 0;

	case IOCTL_EXPORT_DEFINED:
		{						// IOCTL_EXPORT_DEFINE
		if (p->cbInBuffer < sizeof(EXPORT_DEFINED_PARMS))
			return ERROR_INVALID_PARAMETER;
		if (p->cbOutBuffer < sizeof(DWORD))
			return ERROR_INVALID_PARAMETER;

		PEXPORT_DEFINED_PARMS parms = (PEXPORT_DEFINED_PARMS) p->lpvInBuffer;

		if (!StringOkay(parms->modname, parms->modlen))
			return ERROR_INVALID_PARAMETER;
		if (HIWORD(parms->fcn))
			{					// function name is a string
			if (!StringOkay(parms->fcn, parms->fcnlen))
				return ERROR_INVALID_PARAMETER;
			}					// function name is a string

		*(PDWORD) p->lpvOutBuffer = IsExportDefined(parms->modname, parms->fcn);
		if (p->lpcbBytesReturned)
			*(PDWORD) p->lpcbBytesReturned = sizeof(DWORD);
		return 0;
		}						// IOCTL_EXPORT_DEFINED

	default:
		return ERROR_INVALID_FUNCTION;
		}						// process IOCTL operation
	}							// OnW32DeviceIoControl

///////////////////////////////////////////////////////////////////////////////

VOID GetStubInfo()
	{							// GetStubInfo

	// Look for a VxD version of WDMSTUB

	PVMMDDB ddb = Get_DDB(0, "WDMSTUB ");
	if (ddb)
		new CStubVersion(ddb);

	// Look for WDMSTUB.SYS and OEM clones thereof

	for (ULONG index = 0; index < 100; ++index)
		{						// for each possible driver index
		WCHAR namebuf[32];
		UNICODE_STRING devname;

		// Note: _snwprintf not exported in wdmvxd.clb

		wcscpy(namebuf, L"\\Device\\WDMSTUB");
		char indexbuf[3];
		WCHAR windexbuf[3];
		_Sprintf(indexbuf, "%d", index);
		windexbuf[0] = indexbuf[0];
		windexbuf[1] = indexbuf[1];
		windexbuf[2] = indexbuf[2];
		wcscat(namebuf, windexbuf);
		RtlInitUnicodeString(&devname, namebuf);

		PFILE_OBJECT fop;
		PDEVICE_OBJECT clone;
		NTSTATUS status = IoGetDeviceObjectPointer(&devname, FILE_READ_DATA, &fop, &clone);

		if (NT_SUCCESS(status))
			{					// found another version
			new CStubVersion(clone);
			ObDereferenceObject(fop);
			}					// found another version
		}						// for each possible driver index

	if (!CStubVersion::Anchor)
		return;					// no WDMSTUB versions loaded, so just return

	// Run through the list of all loaded drivers (which is presumably much longer
	// than the list of WDMSTUBs) to determine the addresses of the sections in
	// these drivers. We have to run VXDLDR's and VMM's lists of drivers to get all
	// of this info

	for (DeviceInfo* dip = VXDLDR_GetDeviceList(); dip; dip = dip->DI_Next)
		{						// for each device
		char drvname[256];
		_Sprintf(drvname, "\\Driver\\%s.sys", dip->DI_ModuleName);
		for (CStubVersion* stub = CStubVersion::Anchor; stub; stub = stub->m_next)
			{					// for each WDMSTUB
			if (stub->m_ddb == dip->DI_DDB
				|| stub->m_name &&_lstrcmpi(stub->m_name, drvname) == 0)
				stub->GetSectionInfo(dip);
			}					// for each WDMSTUB
		}						// for each device

	DWORD nvxds;
	DWORD size;

	Device_Location_List* loclist = VMM_GetVxDLocationList(nvxds, size);
	for (DWORD ivxd = 0; ivxd < nvxds; ++ivxd)
		{						// for each VxD
		for (CStubVersion* stub = CStubVersion::Anchor; stub; stub = stub->m_next)
			{					// for each WDMSTUB
			if (stub->m_ddb == (PVMMDDB) loclist->DLL_DDB)
				stub->GetSectionInfo(loclist);
			}					// for each WDMSTUB
		loclist = (Device_Location_List*) (loclist->DLL_ObjLocation + loclist->DLL_NumObjects);
		}						// for each VxD
	}							// GetStubInfo

///////////////////////////////////////////////////////////////////////////////

VOID DeleteStubInfo()
	{							// DeleteStubInfo
	while (CStubVersion::Anchor)
		delete CStubVersion::Anchor;
	}							// DeleteStubInfo

///////////////////////////////////////////////////////////////////////////////
// Verify that a string pointer is valid and that null terminator is within
// the specified length

#pragma VxD_PAGEABLE_CODE_SEG

BOOL StringOkay(char* s, DWORD len)
	{							// StringOkay
	if (!_Assert_Range(s, len, 0, 0, 0))
		return FALSE;			// pointer is invalid in some way

	while (len--)
		if (!*s++)
			return TRUE;

	return FALSE;				// exhausted length before finding NUL
	}							// StringOkay

///////////////////////////////////////////////////////////////////////////////

#pragma VxD_PAGEABLE_CODE_SEG

DWORD IsExportDefined(char* module, char* fcn)
	{							// IsExportDefined
	DWORD addr = (DWORD) _PELDR_GetProcAddress((HPEMODULE) module, fcn, NULL);
	if (!addr)
		return WDMCHECK_NOT_DEFINED;

	// This symbol is defined. See if the definition is inside WDMSTUB

	for (CStubVersion* stub = CStubVersion::Anchor; stub; stub = stub->m_next)
		{						// for each stub
		if (!stub->m_sections)
			continue;			// we never found this guy's sections
		for (ULONG i = 0; i < stub->m_nsections; ++i)
			if (addr >= stub->m_sections[i].startaddr && addr < stub->m_sections[i].endaddr)
				return WDMCHECK_STUB_DEFINED;
		}						// for each stub

	// The symbol must be exported by the regular kernel

	return 0;
	}							// IsExportDefined

///////////////////////////////////////////////////////////////////////////////

CStubVersion::CStubVersion(PVMMDDB ddb)
	{							// CStubVersion::CStubVersion
	Initialize();
	m_ddb = ddb;
	}							// CStubVersion::CStubVersion

CStubVersion::CStubVersion(PDEVICE_OBJECT DeviceObject)
	{							// CStubVersion::CStubVersion
	Initialize();
	PDRIVER_OBJECT DriverObject = DeviceObject->DriverObject;
	ANSI_STRING as = {0};
	RtlUnicodeStringToAnsiString(&as, &DriverObject->DriverName, TRUE);
	m_name = as.Buffer;
	}							// CStubVersion::CStubVersion

CStubVersion::~CStubVersion()
	{							// CStubVersion::~CStubVersion
	if (m_next)
		m_next->m_prev = m_prev;
	if (m_prev)
		m_prev->m_next = m_next;
	else
		Anchor = m_next;
		
	if (m_name)
		_HeapFree(m_name, 0);
	if (m_nsections)
		delete [] m_sections;
	}							// CStubVersion::~CStubVersion

void CStubVersion::GetSectionInfo(DeviceInfo* dip)
	{							// CStubVersion::GetSectionInfo
	m_nsections = dip->DI_ObjCount;
	m_sections = new SECTION_INFO[m_nsections];
	for (ULONG i = 0; i < m_nsections; ++i)
		{						// for each section
		m_sections[i].startaddr = dip->DI_ObjInfo[i].OI_LinearAddress;
		m_sections[i].endaddr = dip->DI_ObjInfo[i].OI_LinearAddress + dip->DI_ObjInfo[i].OI_Size;
		}						// for each section
	}							// CStubVersion::GetSectionInfo

void CStubVersion::GetSectionInfo(Device_Location_List* dll)
	{							// CStubVersion::GetSectionInfo
	m_nsections = dll->DLL_NumObjects;
	m_sections = new SECTION_INFO[m_nsections];
	for (ULONG i = 0; i < m_nsections; ++i)
		{						// for each section
		m_sections[i].startaddr = dll->DLL_ObjLocation[i].OL_LinearAddr;
		m_sections[i].endaddr = dll->DLL_ObjLocation[i].OL_LinearAddr + dll->DLL_ObjLocation[i].OL_Size;
		}						// for each section
	}							// CStubVersion::GetSectionInfo

void CStubVersion::Initialize()
	{							// CStubVersion::Initialize
	m_next = Anchor;
	m_prev = NULL;
	if (Anchor)
		Anchor->m_prev = this;
	Anchor = this;

	m_ddb = NULL;
	m_name = NULL;
	m_nsections = 0;
	m_sections = NULL;
	}							// CStubVersion::Initialize

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -