www.pudn.com > Microsoft Windows驱动程序模型设计 源代码.zip > Wmi.cpp


// WMI.CPP -- Windows Management Instrumentation handlers for wmiextra driver 
// Copyright (C) 1999 by Walter Oney 
// All rights reserved 
 
#include "stddcls.h" 
#include "driver.h" 
 
#include  
#include  
#include "guids.h" 
 
NTSTATUS QueryRegInfo(PDEVICE_OBJECT fdo, PULONG flags, PUNICODE_STRING instname, PUNICODE_STRING* regpath, PUNICODE_STRING resname, PDEVICE_OBJECT* pdo); 
NTSTATUS QueryDataBlock(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG instcount, PULONG instlength, ULONG bufsize, PUCHAR buffer); 
NTSTATUS SetDataBlock(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG bufsize, PUCHAR buffer); 
NTSTATUS SetDataItem(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG id, ULONG bufsize, PUCHAR buffer); 
NTSTATUS ExecuteMethod(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG id, ULONG cbInbuf, ULONG cbOutbuf, PUCHAR buffer); 
NTSTATUS FunctionControl(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, WMIENABLEDISABLECONTROL fcn, BOOLEAN enable); 
 
WMIGUIDREGINFO guidlist[] = { 
	{&GUID_WMIEXTRA_EVENT, 1, WMIREG_FLAG_EVENT_ONLY_GUID}, 
	{&GUID_WMIEXTRA_EXPENSIVE, 1, WMIREG_FLAG_EXPENSIVE}, 
	{&GUID_WMIEXTRA_METHOD, 1, 0}, 
	{&GUID_POWER_DEVICE_ENABLE, 1, 0}, 
	{&GUID_POWER_DEVICE_TIMEOUTS, 1, 0}, 
	{&GUID_POWER_DEVICE_WAKE_ENABLE, 1, 0}, 
	}; 
 
#define INDEX_WMIEXTRA_EVENT		0 
#define INDEX_WMIEXTRA_EXPENSIVE	1 
#define INDEX_WMIEXTRA_METHOD		2 
#define INDEX_POWER_ENABLE			3 
#define INDEX_POWER_TIMEOUTS		4 
#define INDEX_POWER_WAKE_ENABLE		5 
 
WMILIB_CONTEXT libinfo = { 
	arraysize(guidlist),		// GuidCount 
	guidlist,					// GuidList 
	QueryRegInfo, 
	QueryDataBlock, 
	SetDataBlock, 
	SetDataItem, 
	ExecuteMethod, 
	FunctionControl, 
	}; 
									   
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS DispatchWmi(IN PDEVICE_OBJECT fdo, IN PIRP Irp) 
	{							// DispatchWmi 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	NTSTATUS status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); 
	if (!NT_SUCCESS(status)) 
		return CompleteRequest(Irp, status, 0); 
 
#if DBG 
	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); 
	ULONG fcn = stack->MinorFunction; 
 
	static char* fcnname[] = { 
		"IRP_MN_QUERY_ALL_DATA", 
		"IRP_MN_QUERY_SINGLE_INSTANCE", 
		"IRP_MN_CHANGE_SINGLE_INSTANCE", 
		"IRP_MN_CHANGE_SINGLE_ITEM", 
		"IRP_MN_ENABLE_EVENTS", 
		"IRP_MN_DISABLE_EVENTS", 
		"IRP_MN_ENABLE_COLLECTION", 
		"IRP_MN_DISABLE_COLLECTION", 
		"IRP_MN_REGINFO", 
		"IRP_MN_EXECUTE_METHOD", 
		}; 
 
	KdPrint((DRIVERNAME " - WMI Request (%s)\n", fcnname[fcn])); 
#endif // DBG 
 
	// Delegate processing to the WMILIB helper library 
 
	SYSCTL_IRP_DISPOSITION disposition; 
	status = WmiSystemControl(&libinfo, fdo, Irp, &disposition); 
 
	switch (disposition) 
		{						// finish handling IRP 
 
	case IrpProcessed: 
		break; 
 
	case IrpNotCompleted: 
		IoCompleteRequest(Irp, IO_NO_INCREMENT); // WMILIB already filled in IoStatus fields 
		break; 
 
	default: 
	case IrpNotWmi: 
		ASSERT(FALSE); 
 
	case IrpForward: 
		IoSkipCurrentIrpStackLocation(Irp); 
		status = IoCallDriver(pdx->LowerDeviceObject, Irp); 
		break; 
		}						// finish handling IRP 
 
	IoReleaseRemoveLock(&pdx->RemoveLock, Irp); 
	return status; 
	}							// DispatchWmi 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
void WmiInitialize(PDEVICE_OBJECT fdo) 
	{							// WmiInitialize 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
 
	NTSTATUS status = IoWMIRegistrationControl(fdo, WMIREG_ACTION_REGISTER); 
	if (!NT_SUCCESS(status)) 
		KdPrint((DRIVERNAME " - IoWMIRegistrationControl failed - %X\n", status)); 
	}							// WmiInitialize 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
void WmiTerminate(PDEVICE_OBJECT fdo) 
	{							// WmiTerminate 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	IoWMIRegistrationControl(fdo, WMIREG_ACTION_DEREGISTER); 
	}							// WmiTerminate 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS QueryRegInfo(PDEVICE_OBJECT fdo, PULONG flags, PUNICODE_STRING instname,  
	PUNICODE_STRING* regpath, PUNICODE_STRING resname, PDEVICE_OBJECT* pdo) 
	{							// QueryRegInfo 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	*flags = WMIREG_FLAG_INSTANCE_BASENAME; 
	*regpath = &servkey; 
	RtlInitUnicodeString(resname, L"MofResource"); 
	static WCHAR basename[] = L"WMIEXTRA"; 
	instname->Buffer = (PWCHAR) ExAllocatePool(PagedPool, sizeof(basename)); 
	if (!instname->Buffer) 
		return STATUS_INSUFFICIENT_RESOURCES; 
	instname->MaximumLength = sizeof(basename); 
	instname->Length = sizeof(basename) - 2; 
	RtlCopyMemory(instname->Buffer, basename, sizeof(basename)); 
	return STATUS_SUCCESS; 
	}							// QueryRegInfo 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS QueryDataBlock(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex,  
	ULONG instindex, ULONG instcount, PULONG instlength, ULONG bufavail, PUCHAR buffer) 
	{							// QueryDataBlock 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	ULONG bufsize = 0; 
	NTSTATUS status = STATUS_SUCCESS; 
 
	switch (guidindex) 
		{						// provide indicated data 
 
	case INDEX_WMIEXTRA_EXPENSIVE: 
		{						// GUID_WMIEXTRA_EXPENSIVE 
		if (instindex != 0) 
			{ 
			status = STATUS_WMI_INSTANCE_NOT_FOUND; 
			break; 
			} 
 
		ASSERT(instcount == 1); 
		ASSERT(pdx->expenable); 
 
		bufsize = sizeof(ULONG); 
		if (!instlength || bufavail < bufsize) 
			status = STATUS_BUFFER_TOO_SMALL; 
		else 
			*(PULONG) buffer = 42; 
		break; 
		}						// GUID_WMIEXTRA_EXPENSIVE 
 
	// We will be called to deliver the value of the method object even though it 
	// doesn't really have a value 
 
	case INDEX_WMIEXTRA_EVENT: 
	case INDEX_WMIEXTRA_METHOD: 
		bufsize = 0; 
		break; 
 
	// Standard power controls: 
 
	case INDEX_POWER_ENABLE: 
		if (instindex != 0) 
			{ 
			status = STATUS_WMI_INSTANCE_NOT_FOUND; 
			break; 
			} 
		bufsize = sizeof(ULONG); 
		if (!instlength || bufavail < bufsize) 
			status = STATUS_BUFFER_TOO_SMALL; 
		else 
			*(PULONG) buffer = pdx->powerenable; 
		break; 
 
	case INDEX_POWER_WAKE_ENABLE: 
		if (instindex != 0) 
			{ 
			status = STATUS_WMI_INSTANCE_NOT_FOUND; 
			break; 
			} 
		bufsize = sizeof(ULONG); 
		if (!instlength || bufavail < bufsize) 
			status = STATUS_BUFFER_TOO_SMALL; 
		else 
			*(PULONG) buffer = pdx->wakeenable; 
		break; 
 
	default: 
		status = STATUS_WMI_GUID_NOT_FOUND; 
		}						// provide indicated data 
 
	return WmiCompleteRequest(fdo, Irp, status, bufsize, IO_NO_INCREMENT); 
	}							// QueryDataBlock 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS SetDataBlock(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG bufavail, PUCHAR buffer) 
	{							// SetDataBlock 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	NTSTATUS status; 
	ULONG info = 0; 
 
	switch (guidindex) 
		{						// select data block 
 
	case INDEX_POWER_ENABLE: 
		if (instindex != 0) 
			{ 
			status = STATUS_WMI_INSTANCE_NOT_FOUND; 
			break; 
			} 
		if (bufavail != sizeof(ULONG)) 
			{ 
			status = STATUS_INFO_LENGTH_MISMATCH; 
			break; 
			} 
		pdx->powerenable = (BOOLEAN) *(PULONG) buffer; 
		KdPrint((DRIVERNAME " - GUID_POWER_DEVICE_ENABLE = %c\n", pdx->powerenable)); 
		status = STATUS_SUCCESS; 
		info = sizeof(ULONG); 
		break; 
 
	case INDEX_POWER_WAKE_ENABLE: 
		if (instindex != 0) 
			{ 
			status = STATUS_WMI_INSTANCE_NOT_FOUND; 
			break; 
			} 
		if (bufavail != sizeof(ULONG)) 
			{ 
			status = STATUS_INFO_LENGTH_MISMATCH; 
			break; 
			} 
		pdx->wakeenable = (BOOLEAN) *(PULONG) buffer; 
		KdPrint((DRIVERNAME " - GUID_POWER_DEVICE_WAKE_ENABLE = %c\n", pdx->wakeenable)); 
		status = STATUS_SUCCESS; 
		info = sizeof(ULONG); 
		break; 
 
	default: 
		status = STATUS_WMI_GUID_NOT_FOUND; 
		break; 
		}						// select data block 
 
	return WmiCompleteRequest(fdo, Irp, status, info, IO_NO_INCREMENT); 
	}							// SetDataBlock 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS SetDataItem(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG id, ULONG bufavail, PUCHAR buffer) 
	{							// SetDataItem 
	return WmiCompleteRequest(fdo, Irp, STATUS_INVALID_DEVICE_REQUEST, 0, IO_NO_INCREMENT); 
	}							// SetDataItem 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS ExecuteMethod(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, ULONG instindex, ULONG id, ULONG cbInbuf, ULONG cbOutbuf, PUCHAR buffer) 
	{							// ExecuteMethod 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	NTSTATUS status = STATUS_SUCCESS; 
	ULONG bufused = 0; 
 
	switch (guidindex) 
		{						// process method call 
	case 2: 
		if (instindex != 0) 
			{ 
			status = STATUS_WMI_INSTANCE_NOT_FOUND; 
			break; 
			} 
 
		if (id != 1) 
			{ 
			status = STATUS_WMI_ITEMID_NOT_FOUND; 
			break; 
			} 
		 
		bufused = sizeof(ULONG); 
		if (cbOutbuf < bufused) 
			{ 
			status = STATUS_BUFFER_TOO_SMALL; 
			break; 
			} 
 
		(*(PULONG) buffer)++;	// return input value + 1 
		break; 
 
	default: 
		status = STATUS_WMI_GUID_NOT_FOUND; 
		break; 
		}						// process method call 
 
	return WmiCompleteRequest(fdo, Irp, status, bufused, IO_NO_INCREMENT); 
	}							// ExecuteMethod 
 
/////////////////////////////////////////////////////////////////////////////// 
 
#pragma PAGEDCODE 
 
NTSTATUS FunctionControl(PDEVICE_OBJECT fdo, PIRP Irp, ULONG guidindex, WMIENABLEDISABLECONTROL fcn, BOOLEAN enable) 
	{							// FunctionControl 
	PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; 
	NTSTATUS status = STATUS_SUCCESS; 
 
	switch (guidindex) 
		{						// process control operation 
	case 0: 
		if (fcn == WmiEventControl) 
			pdx->evenable = enable; 
		else 
			status = STATUS_WMI_NOT_SUPPORTED; 
		break; 
 
	case 1: 
		if (fcn == WmiDataBlockControl) 
			pdx->expenable = enable; 
		else 
			status = STATUS_WMI_NOT_SUPPORTED; 
		break; 
 
	default: 
		status = STATUS_WMI_GUID_NOT_FOUND; 
		break; 
		}						// process control operation 
 
	return WmiCompleteRequest(fdo, Irp, status, 0, IO_NO_INCREMENT); 
	}							// FunctionControl