www.pudn.com > Microsoft Windows驱动程序模型设计 源代码.zip > AltWmi.cpp
// Windows Management Instrumentation handlers for wmi42 driver // Copyright (C) 1999 by Walter Oney // All rights reserved #include "stddcls.h" #include "driver.h" #include#include #include "guids.h" NTSTATUS DefaultWmiHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp); NTSTATUS HandleQueryAllData(IN PDEVICE_OBJECT fdo, IN PIRP Irp); NTSTATUS HandleQueryInstance(IN PDEVICE_OBJECT fdo, IN PIRP Irp); NTSTATUS HandleWmiReginfo(IN PDEVICE_OBJECT fdo, IN PIRP Irp); class CRegInfo { // class CRegInfo public: CRegInfo(PUCHAR base, ULONG size); void NewInfo(PCWSTR drivername, PCWSTR resname, ULONG size); void NewDataBlock(const GUID* guid, PDEVICE_OBJECT pdo); ULONG Data(PCWSTR s); ULONG Data(PVOID p); PUCHAR m_base; // base address of buffer ULONG m_size; // size of structure ULONG m_info; // where next info field goes (increases) ULONG m_data; // where next data field goes (decreases) PWMIREGINFO m_current; // current WMIREGINFO header ULONG m_cursize; // size of current WMIREGINFO (incl all data) }; // class CRegInfo /////////////////////////////////////////////////////////////////////////////// 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); PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ASSERT(stack->MajorFunction == IRP_MJ_SYSTEM_CONTROL); static NTSTATUS (*fcntab[])(IN PDEVICE_OBJECT fdo, IN PIRP Irp) = { HandleQueryAllData, // IRP_MN_QUERY_ALL_DATA HandleQueryInstance, // IRP_MN_QUERY_SINGLE_INSTANCE DefaultWmiHandler, // IRP_MN_CHANGE_SINGLE_INSTANCE DefaultWmiHandler, // IRP_MN_CHANGE_SINGLE_ITEM DefaultWmiHandler, // IRP_MN_ENABLE_EVENTS DefaultWmiHandler, // IRP_MN_DISABLE_EVENTS DefaultWmiHandler, // IRP_MN_ENABLE_COLLECTION DefaultWmiHandler, // IRP_MN_DISABLE_COLLECTION HandleWmiReginfo, // IRP_MN_REGINFO DefaultWmiHandler, // IRP_MN_EXECUTE_METHOD }; ULONG fcn = stack->MinorFunction; #if DBG 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 // If the provider id in the IRP doesn't match ours, pass the request along. (Device // drivers use the address of their device objects as provider IDs). Also pass // the IRP along if we don't know how to handle this minor function because it // was defined in a later DDK than we built with. if (fcn >= arraysize(fcntab) || fdo != (PDEVICE_OBJECT) stack->Parameters.WMI.ProviderId) { // unknown function status = DefaultWmiHandler(fdo, Irp); // some function we don't know about IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } // unknown function status = (*fcntab[fcn])(fdo, Irp); IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return status; } // DispatchWmi /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// NTSTATUS DefaultWmiHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { // DefaultWmiHandler IoSkipCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; return IoCallDriver(pdx->LowerDeviceObject, Irp); } // DefaultWmiHandler /////////////////////////////////////////////////////////////////////////////// NTSTATUS HandleQueryAllData(PDEVICE_OBJECT fdo, PIRP Irp) { // HandleQueryAllData PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; ASSERT(stack->MajorFunction == IRP_MJ_SYSTEM_CONTROL); ASSERT(stack->MinorFunction == IRP_MN_QUERY_ALL_DATA); ULONG bufsize = stack->Parameters.WMI.BufferSize; PWNODE_ALL_DATA buffer = (PWNODE_ALL_DATA) stack->Parameters.WMI.Buffer; // See if we're being asked about a data block we understand if (*(LPGUID) stack->Parameters.WMI.DataPath != GUID_WMI42_SCHEMA) return CompleteRequest(Irp, STATUS_WMI_GUID_NOT_FOUND, 0); ASSERT(buffer->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES); // Verify that the output buffer is large enough to hold the data we're going // to return ULONG need = FIELD_OFFSET(WNODE_ALL_DATA, OffsetInstanceNameOffsets); // size of basic structure need += sizeof(ULONG); // size of FixedInstanceSize member need = (need + 7) & ~7; // round up to quadword boundary ULONG dataoffset = need; // this is where data will begin need += sizeof(ULONG); // size of all the data blocks put together if (bufsize < need) return CompleteRequest(Irp, STATUS_BUFFER_TOO_SMALL, need); // Fill in the data buffer with the value of a single instance of a fixed-size // data block buffer->WnodeHeader.BufferSize = need; buffer->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE; buffer->DataBlockOffset = dataoffset; buffer->InstanceCount = 1; buffer->OffsetInstanceNameOffsets = 0; // no instance names buffer->FixedInstanceSize = sizeof(ULONG); *(PULONG) ((PUCHAR) buffer + dataoffset) = 42; // our data value return CompleteRequest(Irp, STATUS_SUCCESS, need); } // HandleQueryAllData /////////////////////////////////////////////////////////////////////////////// NTSTATUS HandleQueryInstance(PDEVICE_OBJECT fdo, PIRP Irp) { // HandleQueryInstance PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; ASSERT(stack->MajorFunction == IRP_MJ_SYSTEM_CONTROL); ASSERT(stack->MinorFunction == IRP_MN_QUERY_SINGLE_INSTANCE); ULONG bufsize = stack->Parameters.WMI.BufferSize; PWNODE_SINGLE_INSTANCE buffer = (PWNODE_SINGLE_INSTANCE) stack->Parameters.WMI.Buffer; // See if we're being asked about a data block we understand if (*(LPGUID) stack->Parameters.WMI.DataPath != GUID_WMI42_SCHEMA) return CompleteRequest(Irp, STATUS_WMI_GUID_NOT_FOUND, 0); ASSERT(buffer->WnodeHeader.Flags & WNODE_FLAG_STATIC_INSTANCE_NAMES); if (buffer->InstanceIndex != 0) return CompleteRequest(Irp, STATUS_WMI_INSTANCE_NOT_FOUND, 0); // Verify that the output buffer is large enough to hold the data we're going // to return ULONG need = buffer->DataBlockOffset + sizeof(ULONG); if (bufsize < need) return CompleteRequest(Irp, STATUS_BUFFER_TOO_SMALL, need); // Fill in the data block buffer->WnodeHeader.BufferSize = need; buffer->OffsetInstanceName = 0; // no instance name buffer->SizeDataBlock = sizeof(ULONG); *(PULONG) ((PUCHAR) buffer + buffer->DataBlockOffset) = pdx->TheAnswer; // our data value return CompleteRequest(Irp, STATUS_SUCCESS, need); } // HandleQueryInstance /////////////////////////////////////////////////////////////////////////////// NTSTATUS HandleWmiReginfo(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { // HandleWmiReginfo PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; ASSERT(stack->MajorFunction == IRP_MJ_SYSTEM_CONTROL); ASSERT(stack->MinorFunction == IRP_MN_REGINFO); ULONG bufsize = stack->Parameters.WMI.BufferSize; PUCHAR buffer = (PUCHAR) stack->Parameters.WMI.Buffer; if ((ULONG) stack->Parameters.WMI.DataPath != WMIREGISTER) return CompleteRequest(Irp, STATUS_SUCCESS, 0); // Calculate the size needed for our registration info ULONG need = sizeof(WMIREGINFO); // base size of structure static WCHAR resname[] = L"MofResource"; // name of schema need += sizeof(resname) + sizeof(WCHAR); // name plus count need += servkey.Length + sizeof(WCHAR); // ditto need += sizeof(WMIREGGUID); // guid info // Make sure enough buffer space was provided. if (bufsize < need) { // buffer too small ASSERT(bufsize >= sizeof(ULONG)); // must be at least this big! *(PULONG) buffer = need; return CompleteRequest(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG)); } // buffer too small // Build the registration information structure CRegInfo r(buffer, need); r.NewInfo(servkey.Buffer, resname, need); r.NewDataBlock(&GUID_WMI42_SCHEMA, pdx->Pdo); return CompleteRequest(Irp, STATUS_SUCCESS, need); } // HandleWmiReginfo /////////////////////////////////////////////////////////////////////////////// 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 /////////////////////////////////////////////////////////////////////////////// void WmiTerminate(PDEVICE_OBJECT fdo) { // WmiTerminate PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; IoWMIRegistrationControl(fdo, WMIREG_ACTION_DEREGISTER); } // WmiTerminate /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// CRegInfo::CRegInfo(PUCHAR base, ULONG size) { // CRegInfo::CRegInfo m_base = base; m_size = size; m_info = 0; m_data = 0; m_current = NULL; } // CRegInfo::CRegInfo /////////////////////////////////////////////////////////////////////////////// void CRegInfo::NewInfo(PCWSTR drivername, PCWSTR resname, ULONG size) { // CRegInfo::NewInfo if (m_current) { // we follow another info structure m_info = ((PUCHAR) m_current - m_base) + m_cursize; m_current->NextWmiRegInfo = m_info; } // we follow another info structure ASSERT(m_info + size <= m_size); m_data = m_info + m_size; // where data for this info structure will go PWMIREGINFO p = (PWMIREGINFO) (m_base + m_info); p->BufferSize = size; p->NextWmiRegInfo = 0; p->RegistryPath = Data(drivername); p->MofResourceName = Data(resname); p->GuidCount = 0; m_info += sizeof(WMIREGINFO); m_current = p; m_cursize = size; } // CRegInfo::NewInfo /////////////////////////////////////////////////////////////////////////////// void CRegInfo::NewDataBlock(const GUID* guid, PDEVICE_OBJECT pdo) { // CRegInfo::NewDataBlock ASSERT(m_info + sizeof(WMIREGGUID) < m_data); ASSERT(m_current); PWMIREGGUID p = &m_current->WmiRegGuid[m_current->GuidCount++]; m_info += sizeof(WMIREGGUID); p->Guid = *guid; p->Flags = WMIREG_FLAG_INSTANCE_PDO; p->InstanceCount = 1; p->Pdo = (ULONG_PTR) pdo; } // CRegInfo::NewDataBlock /////////////////////////////////////////////////////////////////////////////// ULONG CRegInfo::Data(PCWSTR s) { // CRegInfo::Data ULONG len = wcslen(s); ASSERT(m_info + (len + 1) * sizeof(WCHAR) <= m_data); m_data -= (len + 1) * sizeof(WCHAR); PWSTR t = (PWSTR) (m_base + m_data); *t++ = (USHORT) (len + 1) * sizeof(WCHAR); // length is in bytes, includes the count RtlCopyBytes(t, s, len * sizeof(WCHAR)); return m_data; } // CRegInfo::Data ULONG CRegInfo::Data(PVOID p) { // CRegInfo::Data ULONG len = sizeof(p); ASSERT(m_info + len <= m_data); m_data -= len; *(PVOID*) (m_base + m_data) = p; return m_data; } // CRegInfo::Data