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

📄 pnpmon.cpp

📁 Windows WDM 设备驱动程序开发指南光盘 保护随书的源代码
💻 CPP
字号:
// PNPMON.CPP -- VxD version of PNPMON.SYS for Win98
// Copyright (C) 1999 by Walter Oney
// All rights reserved

#include "stdvxd.h"
#include "..\sys\ioctls.h"

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

#pragma warning(disable:4035)

BOOL _VWIN32_SetWin32Event(PVOID hEvent)
	{
	_asm mov eax, hEvent
	VMMCall(_VWIN32_SetWin32Event)
	}

#pragma warning(default:4035)

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

typedef struct _REG_RECORD {
	GUID Guid;
	PVOID NotificationEntry;
	PVOID Event;
	} REG_RECORD, *PREG_RECORD;

typedef struct _EVENT_RECORD {
	GETEVENT_PARAMS params;
	} EVENT_RECORD, *PEVENT_RECORD;

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

DWORD Register(PREGISTER_PARAMS p);
DWORD Deregister(PUNREGISTER_PARAMS p);
VOID DeregisterAll();
NTSTATUS OnPnpNotify(PDEVICE_INTERFACE_CHANGE_NOTIFICATION p, PREG_RECORD reg);
DWORD GetEvent(PGETEVENT_PARAMS p);

VMMLIST RegRecordList = NULL;
VMMLIST EventList = NULL;

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

SYSCTL BOOL OnSysDynamicDeviceInit()
	{							// OnSysDynamicDeviceInit
	RegRecordList = List_Create(0, sizeof(REG_RECORD));
	EventList = List_Create(LF_ASYNC, sizeof(EVENT_RECORD));
	return TRUE;
	}							// OnSysDynamicDeviceInit

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

SYSCTL BOOL OnSysDynamicDeviceExit()
	{							// OnSysDynamicDeviceExit
	DeregisterAll();
	List_Destroy(EventList);
	List_Destroy(RegRecordList);
	return TRUE;
	}							// OnSysDynamicDeviceExit

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

SYSCTL DWORD OnW32DeviceIoControl(PDIOCPARAMETERS p)
	{							// OnW32DeviceIoControl
	DWORD status = 0;
	DWORD info = 0;

	DWORD cbin = p->cbInBuffer;
	DWORD cbout = p->cbOutBuffer;
	DWORD code = p->dwIoControlCode;

	switch (code)
		{						// process control operation
	case DIOC_OPEN:
	case DIOC_CLOSEHANDLE:
		break;

	case IOCTL_REGISTER:
		if (cbin < sizeof(REGISTER_PARAMS))
			{
			status = ERROR_INVALID_PARAMETER;
			break;
			}
		status = Register((PREGISTER_PARAMS) p->lpvInBuffer);
		break;

	case IOCTL_DEREGISTER:
		if (cbin < sizeof(UNREGISTER_PARAMS))
			{
			status = ERROR_INVALID_PARAMETER;
			break;
			}
		status = Deregister((PUNREGISTER_PARAMS) p->lpvInBuffer);
		break;

	case IOCTL_GETEVENT:
		if (cbout < sizeof(GETEVENT_PARAMS))
			{
			status = ERROR_INVALID_PARAMETER;
			break;
			}
		status = GetEvent((PGETEVENT_PARAMS) p->lpvOutBuffer);
		break;

	default:
		ASSERT(FALSE);
		status = ERROR_INVALID_FUNCTION;
		}						// process control operation

	if (p->lpcbBytesReturned)
		*(PDWORD) p->lpcbBytesReturned = info;
	return status;
	}							// OnW32DeviceIoControl

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

DWORD Register(PREGISTER_PARAMS p)
	{							// Register
	PREG_RECORD reg = (PREG_RECORD) List_Allocate(RegRecordList);
	if (!reg)
		return ERROR_NOT_ENOUGH_MEMORY;
	memset(reg, 0, sizeof(REG_RECORD));

	reg->Event = VWIN32OpenVxDHandle((ULONG) p->hevent, OPENVXD_TYPE_EVENT);
	reg->Guid = p->guid;

	NTSTATUS status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
		PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
		&p->guid, NULL, (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) OnPnpNotify, reg, &reg->NotificationEntry);

	if (!NT_SUCCESS(status))
		{
		Debug_Printf("PNPMON - IoRegisterPlugPlayNotification failed - %X\n", status);
		List_Deallocate(RegRecordList, reg);
		return ERROR_CRC;
		}

	List_Attach_Tail(RegRecordList, reg);
	return 0;
	}							// Register

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

DWORD Deregister(PUNREGISTER_PARAMS p)
	{							// Deregister
	DWORD status = 0;
	PREG_RECORD reg;

	for (reg = (PREG_RECORD) List_Get_First(RegRecordList); reg; )
		{						// for each list element
		PREG_RECORD next = (PREG_RECORD) List_Get_Next(RegRecordList, reg);
		if (memcmp(&reg->Guid, &p->guid, sizeof(GUID)) == 0)
			{					// found a registration record
			List_Remove(RegRecordList, reg);
			IoUnregisterPlugPlayNotification(reg->NotificationEntry);
			List_Deallocate(RegRecordList, reg);
			}					// found a registration record
		reg = next;
		}						// for each list element
	return status;
	}							// Deregister

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

VOID DeregisterAll()
	{							// DeregisterAll
	PREG_RECORD reg;
	while ((reg = (PREG_RECORD) List_Remove_First(RegRecordList)))
		{						// deregister all notifications
		IoUnregisterPlugPlayNotification(reg->NotificationEntry);
		List_Deallocate(RegRecordList, reg);
		}						// deregister all notifications
	}							// DeregisterAll

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

VOID __declspec(naked) __cdecl EventProc()
	{							// EventProc
	_asm mov eax, edx
	VMMCall(_VWIN32_SetWin32Event)
	_asm ret
	}							// EventProc

NTSTATUS OnPnpNotify(PDEVICE_INTERFACE_CHANGE_NOTIFICATION p, PREG_RECORD reg)
	{							// OnPnpNotify

	_asm pushfd
	_asm cli
	PEVENT_RECORD evrec = (PEVENT_RECORD) List_Allocate(EventList);
	_asm popfd

	memset(evrec, 0, sizeof(EVENT_RECORD));

	evrec->params.guid = p->InterfaceClassGuid;
	evrec->params.event = p->Event;
	memcpy(evrec->params.linkname, p->SymbolicLinkName->Buffer, p->SymbolicLinkName->Length);
	evrec->params.linkname[p->SymbolicLinkName->Length/2] = 0;

	_asm pushfd
	_asm cli
	List_Attach_Tail(EventList, evrec);
	_asm popfd

	HVM hvmSystem = Get_Sys_VM_Handle();	
	if (Get_Cur_VM_Handle() == hvmSystem)
		_VWIN32_SetWin32Event(reg->Event);
	else
		Call_Restricted_Event(0, hvmSystem, 0, (ULONG) reg->Event, (VMM_EVENT_HANDLER) EventProc, 0);

	return STATUS_SUCCESS;
	}							// OnPnpNotify

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

#pragma VxD_LOCKED_CODE_SEG

DWORD GetEvent(PGETEVENT_PARAMS p)
	{							// GetEvent
	PEVENT_RECORD evrec;
	_asm pushfd
	_asm cli
	evrec = (PEVENT_RECORD) List_Remove_First(EventList);
	_asm popfd

	if (!evrec)
		return ERROR_NO_MORE_ITEMS;

	*p = evrec->params;
	
	_asm pushfd
	_asm cli
	List_Deallocate(EventList, evrec);
	_asm popfd

	return 0;
	}							// GetEvent

⌨️ 快捷键说明

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