[NTOSKRNL]

Hackplement IoWMIOpenBlock and IoWMIQueryAllData. Just enough to query the SMBIOS tables.

svn path=/trunk/; revision=66822
This commit is contained in:
Timo Kreuzer 2015-03-19 21:31:20 +00:00
parent 02b663f961
commit 0ca08e8f25
6 changed files with 427 additions and 61 deletions

View file

@ -270,6 +270,7 @@ list(APPEND SOURCE
${REACTOS_SOURCE_DIR}/ntoskrnl/se/token.c
${REACTOS_SOURCE_DIR}/ntoskrnl/vf/driver.c
${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/guidobj.c
${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/smbios.c
${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/wmi.c
${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/wmidrv.c)

View file

@ -167,22 +167,13 @@ WmipGUIDFromString(
static
NTSTATUS
WmipCreateGuidObject(
_In_ PUNICODE_STRING GuidString,
_In_ const GUID *Guid,
_Out_ PWMIP_GUID_OBJECT *OutGuidObject)
{
OBJECT_ATTRIBUTES ObjectAttributes;
GUID Guid;
PWMIP_GUID_OBJECT GuidObject;
NTSTATUS Status;
/* Convert the string into a GUID structure */
Status = WmipGUIDFromString(GuidString, &Guid);
if (!NT_SUCCESS(Status))
{
DPRINT1("WMI: Invalid uuid format for guid '%wZ'\n", GuidString);
return Status;
}
/* Initialize object attributes for an unnamed object */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
@ -207,7 +198,7 @@ WmipCreateGuidObject(
}
RtlZeroMemory(GuidObject, sizeof(*GuidObject));
GuidObject->Guid = Guid;
GuidObject->Guid = *Guid;
*OutGuidObject = GuidObject;
@ -217,37 +208,22 @@ WmipCreateGuidObject(
NTSTATUS
NTAPI
WmipOpenGuidObject(
POBJECT_ATTRIBUTES ObjectAttributes,
ACCESS_MASK DesiredAccess,
KPROCESSOR_MODE AccessMode,
PHANDLE OutGuidObjectHandle,
PVOID *OutGuidObject)
_In_ LPCGUID Guid,
_In_ ACCESS_MASK DesiredAccess,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PHANDLE OutGuidObjectHandle,
_Outptr_ PVOID *OutGuidObject)
{
static UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\WmiGuid\\");
UNICODE_STRING GuidString;
ULONG HandleAttributes;
PWMIP_GUID_OBJECT GuidObject;
ULONG HandleAttributes;
NTSTATUS Status;
PAGED_CODE();
/* Check if we have the expected prefix */
if (!RtlPrefixUnicodeString(&Prefix, ObjectAttributes->ObjectName, FALSE))
{
DPRINT1("WMI: Invalid prefix for guid object '%wZ'\n",
ObjectAttributes->ObjectName);
return STATUS_INVALID_PARAMETER;
}
/* Extract the GUID string */
GuidString = *ObjectAttributes->ObjectName;
GuidString.Buffer += Prefix.Length / sizeof(WCHAR);
GuidString.Length -= Prefix.Length;
/* Create the GUID object */
Status = WmipCreateGuidObject(&GuidString, &GuidObject);
Status = WmipCreateGuidObject(Guid, &GuidObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create GUID object: 0x%lx\n", Status);
*OutGuidObject = NULL;
return Status;
}
@ -266,6 +242,7 @@ WmipOpenGuidObject(
{
DPRINT1("ObOpenObjectByPointer failed: 0x%lx\n", Status);
ObfDereferenceObject(GuidObject);
GuidObject = NULL;
}
*OutGuidObject = GuidObject;
@ -273,3 +250,46 @@ WmipOpenGuidObject(
return Status;
}
NTSTATUS
NTAPI
WmipOpenGuidObjectByName(
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ ACCESS_MASK DesiredAccess,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PHANDLE OutGuidObjectHandle,
_Outptr_ PVOID *OutGuidObject)
{
static UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\WmiGuid\\");
UNICODE_STRING GuidString;
NTSTATUS Status;
GUID Guid;
PAGED_CODE();
/* Check if we have the expected prefix */
if (!RtlPrefixUnicodeString(&Prefix, ObjectAttributes->ObjectName, FALSE))
{
DPRINT1("WMI: Invalid prefix for guid object '%wZ'\n",
ObjectAttributes->ObjectName);
return STATUS_INVALID_PARAMETER;
}
/* Extract the GUID string */
GuidString = *ObjectAttributes->ObjectName;
GuidString.Buffer += Prefix.Length / sizeof(WCHAR);
GuidString.Length -= Prefix.Length;
/* Convert the string into a GUID structure */
Status = WmipGUIDFromString(&GuidString, &Guid);
if (!NT_SUCCESS(Status))
{
DPRINT1("WMI: Invalid uuid format for guid '%wZ'\n", GuidString);
return Status;
}
return WmipOpenGuidObject(&Guid,
DesiredAccess,
AccessMode,
OutGuidObjectHandle,
OutGuidObject);
}

View file

@ -0,0 +1,279 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/io/wmi.c
* PURPOSE: I/O Windows Management Instrumentation (WMI) Support
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#include <wmiguid.h>
#include <wmidata.h>
#include <wmistr.h>
#include "wmip.h"
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
typedef struct _SMBIOS21_ENTRY_POINT
{
CHAR AnchorString[4];
UCHAR Checksum;
UCHAR Length;
UCHAR MajorVersion;
UCHAR MinorVersion;
USHORT MaxStructureSize;
UCHAR EntryPointRevision;
CHAR FormattedArea[5];
CHAR AnchorString2[5];
UCHAR Checksum2;
USHORT TableLength;
ULONG TableAddress;
USHORT NumberOfStructures;
UCHAR BCDRevision;
} SMBIOS21_ENTRY_POINT, *PSMBIOS21_ENTRY_POINT;
typedef struct _SMBIOS30_ENTRY_POINT
{
CHAR AnchorString[5];
UCHAR Checksum;
UCHAR Length;
UCHAR MajorVersion;
UCHAR MinorVersion;
UCHAR Docref;
UCHAR Revision;
UCHAR Reserved;
ULONG TableMaxSize;
ULONG64 TableAddress;
} SMBIOS30_ENTRY_POINT, *PSMBIOS30_ENTRY_POINT;
static
BOOLEAN
GetEntryPointData(
_In_ const UCHAR *EntryPointAddress,
_Out_ PULONG64 TableAddress,
_Out_ PULONG TableSize,
_Out_ PMSSmBios_RawSMBiosTables BiosTablesHeader)
{
PSMBIOS21_ENTRY_POINT EntryPoint21;
PSMBIOS30_ENTRY_POINT EntryPoint30;
UCHAR Checksum;
ULONG i;
/* Check for SMBIOS 2.1 entry point */
EntryPoint21 = (PSMBIOS21_ENTRY_POINT)EntryPointAddress;
if (RtlEqualMemory(EntryPoint21->AnchorString, "_SM_", 4))
{
if (EntryPoint21->Length > 32)
return FALSE;
/* Calculate the checksum */
Checksum = 0;
for (i = 0; i < EntryPoint21->Length; i++)
{
Checksum += EntryPointAddress[i];
}
if (Checksum != 0)
return FALSE;
*TableAddress = EntryPoint21->TableAddress;
*TableSize = EntryPoint21->TableLength;
BiosTablesHeader->Used20CallingMethod = 0;
BiosTablesHeader->SmbiosMajorVersion = EntryPoint21->MajorVersion;
BiosTablesHeader->SmbiosMinorVersion = EntryPoint21->MinorVersion;
BiosTablesHeader->DmiRevision = 2;
BiosTablesHeader->Size = EntryPoint21->TableLength;
return TRUE;
}
/* Check for SMBIOS 3.0 entry point */
EntryPoint30 = (PSMBIOS30_ENTRY_POINT)EntryPointAddress;
if (RtlEqualMemory(EntryPoint30->AnchorString, "_SM3_", 5))
{
if (EntryPoint30->Length > 32)
return FALSE;
/* Calculate the checksum */
Checksum = 0;
for (i = 0; i < EntryPoint30->Length; i++)
{
Checksum += EntryPointAddress[i];
}
if (Checksum != 0)
return FALSE;
*TableAddress = EntryPoint30->TableAddress;
*TableSize = EntryPoint30->TableMaxSize;
BiosTablesHeader->Used20CallingMethod = 0;
BiosTablesHeader->SmbiosMajorVersion = EntryPoint30->MajorVersion;
BiosTablesHeader->SmbiosMinorVersion = EntryPoint30->MinorVersion;
BiosTablesHeader->DmiRevision = 3;
BiosTablesHeader->Size = EntryPoint30->TableMaxSize;
return TRUE;
}
return FALSE;
}
_At_(*OutTableData, __drv_allocatesMem(Mem))
NTSTATUS
NTAPI
WmipGetRawSMBiosTableData(
_Outptr_opt_result_buffer_(*OutDataSize) PVOID *OutTableData,
_Out_ PULONG OutDataSize)
{
static const SIZE_T SearchSize = 0x10000;
static const ULONG HeaderSize = FIELD_OFFSET(MSSmBios_RawSMBiosTables, SMBiosData);
PHYSICAL_ADDRESS PhysicalAddress;
PUCHAR EntryPointMapping;
MSSmBios_RawSMBiosTables BiosTablesHeader;
PVOID BiosTables, TableMapping;
ULONG Offset, TableSize;
ULONG64 TableAddress = 0;
/* This is where the range for the entry point starts */
PhysicalAddress.QuadPart = 0xF0000;
/* Map the range into the system address space */
EntryPointMapping = MmMapIoSpace(PhysicalAddress, SearchSize, MmCached);
if (EntryPointMapping == NULL)
{
DPRINT1("Failed to map range for SMBIOS entry point\n");
return STATUS_UNSUCCESSFUL;
}
/* Loop the table memory in 16 byte steps */
for (Offset = 0; Offset <= (0x10000 - 32); Offset += 16)
{
/* Check if we have an entry point here and get it's data */
if (GetEntryPointData(EntryPointMapping + Offset,
&TableAddress,
&TableSize,
&BiosTablesHeader))
{
break;
}
}
/* Unmap the entry point */
MmUnmapIoSpace(EntryPointMapping, SearchSize);
/* Did we find anything */
if (TableAddress == 0)
{
DPRINT1("Could not find the SMBIOS entry point\n");
return STATUS_NOT_FOUND;
}
/* Check if the caller asked for the buffer */
if (OutTableData != NULL)
{
/* Allocate a buffer for the result */
BiosTables = ExAllocatePoolWithTag(PagedPool,
HeaderSize + TableSize,
'BTMS');
if (BiosTables == NULL)
{
DPRINT1("Failed to allocate %lu bytes for the SMBIOS table\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Copy the header */
RtlCopyMemory(BiosTables, &BiosTablesHeader, HeaderSize);
/* This is where the table is */
PhysicalAddress.QuadPart = TableAddress;
/* Map the table into the system address space */
TableMapping = MmMapIoSpace(PhysicalAddress, TableSize, MmCached);
if (TableMapping == NULL)
{
return STATUS_UNSUCCESSFUL;
}
/* Copy the table */
RtlCopyMemory((PUCHAR)BiosTables + HeaderSize, TableMapping, TableSize);
/* Unmap the table */
MmUnmapIoSpace(TableMapping, TableSize);
*OutTableData = BiosTables;
}
*OutDataSize = HeaderSize + TableSize;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
WmipQueryRawSMBiosTables(
_Inout_ ULONG *InOutBufferSize,
_Out_opt_ PVOID OutBuffer)
{
NTSTATUS Status;
PVOID TableData = NULL;
ULONG TableSize, ResultSize;
PWNODE_ALL_DATA AllData;
/* Get the table data */
Status = WmipGetRawSMBiosTableData(OutBuffer ? &TableData : NULL, &TableSize);
if (!NT_SUCCESS(Status))
{
DPRINT1("WmipGetRawSMBiosTableData failed: 0x08lx\n", Status);
return Status;
}
ResultSize = sizeof(WNODE_ALL_DATA) + TableSize;
/* Check if the caller provided a buffer */
if ((OutBuffer != NULL) && (*InOutBufferSize != 0))
{
/* Check if the buffer is large enough */
if (*InOutBufferSize < ResultSize)
{
DPRINT1("Buffer too small. Got %lu, need %lu\n",
*InOutBufferSize, ResultSize);
return STATUS_BUFFER_TOO_SMALL;
}
/// FIXME: most of this is fubar
AllData = OutBuffer;
AllData->WnodeHeader.BufferSize = ResultSize;
AllData->WnodeHeader.ProviderId = 0;
AllData->WnodeHeader.Version = 0;
AllData->WnodeHeader.Linkage = 0; // last entry
//AllData->WnodeHeader.CountLost;
AllData->WnodeHeader.KernelHandle = NULL;
//AllData->WnodeHeader.TimeStamp;
AllData->WnodeHeader.Guid = MSSmBios_RawSMBiosTables_GUID;
AllData->WnodeHeader.ClientContext;
AllData->WnodeHeader.Flags = WNODE_FLAG_FIXED_INSTANCE_SIZE;
AllData->DataBlockOffset = sizeof(WNODE_ALL_DATA);
AllData->InstanceCount = 1;
AllData->OffsetInstanceNameOffsets;
AllData->FixedInstanceSize = TableSize;
RtlCopyMemory(AllData + 1, TableData, TableSize);
}
/* Set the size */
*InOutBufferSize = ResultSize;
/* Free the table buffer */
if (TableData != NULL)
{
ExFreePoolWithTag(TableData, 'BTMS');
}
return STATUS_SUCCESS;
}

View file

@ -9,6 +9,11 @@
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define INITGUID
#include <wmiguid.h>
#include <wmidata.h>
#include <wmistr.h>
#include "wmip.h"
#define NDEBUG
@ -106,12 +111,28 @@ IoWMIWriteEvent(IN PVOID WnodeEventItem)
*/
NTSTATUS
NTAPI
IoWMIOpenBlock(IN LPCGUID DataBlockGuid,
IN ULONG DesiredAccess,
OUT PVOID *DataBlockObject)
IoWMIOpenBlock(
_In_ LPCGUID DataBlockGuid,
_In_ ULONG DesiredAccess,
_Out_ PVOID *DataBlockObject)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
HANDLE GuidObjectHandle;
NTSTATUS Status;
/* Open the GIOD object */
Status = WmipOpenGuidObject(DataBlockGuid,
DesiredAccess,
KernelMode,
&GuidObjectHandle,
DataBlockObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("WmipOpenGuidObject failed: 0x%lx\n", Status);
return Status;
}
return STATUS_SUCCESS;
}
/*
@ -119,12 +140,39 @@ IoWMIOpenBlock(IN LPCGUID DataBlockGuid,
*/
NTSTATUS
NTAPI
IoWMIQueryAllData(IN PVOID DataBlockObject,
IN OUT ULONG *InOutBufferSize,
OUT PVOID OutBuffer)
IoWMIQueryAllData(
IN PVOID DataBlockObject,
IN OUT ULONG *InOutBufferSize,
OUT PVOID OutBuffer)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
PWMIP_GUID_OBJECT GuidObject;
NTSTATUS Status;
Status = ObReferenceObjectByPointer(DataBlockObject,
WMIGUID_QUERY,
WmipGuidObjectType,
KernelMode);
if (!NT_SUCCESS(Status))
{
return Status;
}
GuidObject = DataBlockObject;
/* Huge HACK! */
if (IsEqualGUID(&GuidObject->Guid, &MSSmBios_RawSMBiosTables_GUID))
{
Status = WmipQueryRawSMBiosTables(InOutBufferSize, OutBuffer);
}
else
{
Status = STATUS_NOT_SUPPORTED;
}
ObDereferenceObject(DataBlockObject);
return Status;
}
/*

View file

@ -210,14 +210,14 @@ WmipRegisterGuids(
}
/* Open a new GUID object */
Status = WmipOpenGuidObject(&LocalObjectAttributes,
SPECIFIC_RIGHTS_ALL,
PreviousMode,
&GuidObjectHandle,
&GuidObject);
Status = WmipOpenGuidObjectByName(&LocalObjectAttributes,
SPECIFIC_RIGHTS_ALL,
PreviousMode,
&GuidObjectHandle,
&GuidObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("WmipOpenGuidObject failed: 0x%lx\n", Status);
DPRINT1("WmipOpenGuidObjectByName failed: 0x%lx\n", Status);
return Status;
}
@ -409,14 +409,14 @@ WmipOpenGuidForEvents(
}
/* Open a new GUID object */
Status = WmipOpenGuidObject(&LocalObjectAttributes,
OpenGuidForEvents->DesiredAccess,
PreviousMode,
&GuidObjectHandle,
&GuidObject);
Status = WmipOpenGuidObjectByName(&LocalObjectAttributes,
OpenGuidForEvents->DesiredAccess,
PreviousMode,
&GuidObjectHandle,
&GuidObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("WmipOpenGuidObject failed: 0x%lx\n", Status);
DPRINT1("WmipOpenGuidObjectByName failed: 0x%lx\n", Status);
return Status;
}

View file

@ -1,6 +1,8 @@
#pragma once
extern POBJECT_TYPE WmipGuidObjectType;
#define GUID_STRING_LENGTH 36
typedef struct _WMIP_IRP_CONTEXT
@ -32,8 +34,24 @@ WmipInitializeGuidObjectType(
NTSTATUS
NTAPI
WmipOpenGuidObject(
POBJECT_ATTRIBUTES ObjectAttributes,
ACCESS_MASK DesiredAccess,
KPROCESSOR_MODE AccessMode,
PHANDLE OutGuidObjectHandle,
PVOID *OutGuidObject);
_In_ LPCGUID Guid,
_In_ ACCESS_MASK DesiredAccess,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PHANDLE OutGuidObjectHandle,
_Outptr_ PVOID *OutGuidObject);
NTSTATUS
NTAPI
WmipOpenGuidObjectByName(
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_ ACCESS_MASK DesiredAccess,
_In_ KPROCESSOR_MODE AccessMode,
_Out_ PHANDLE OutGuidObjectHandle,
_Outptr_ PVOID *OutGuidObject);
NTSTATUS
NTAPI
WmipQueryRawSMBiosTables(
_Inout_ ULONG *InOutBufferSize,
_Out_opt_ PVOID OutBuffer);