1698 lines
45 KiB
C
1698 lines
45 KiB
C
#include <wdm.h>
|
||
#include <wmistr.h>
|
||
#include <wmiguid.h>
|
||
#include <wmilib.h>
|
||
#include "mpio.h"
|
||
#include "wmi.h"
|
||
#include "pdowmi.h"
|
||
#include <stdio.h>
|
||
|
||
#define USE_BINARY_MOF_QUERY
|
||
UCHAR MPIOBinaryMofData[] =
|
||
{
|
||
#include "wmi.x"
|
||
};
|
||
|
||
UCHAR PdoBinaryMofData[] =
|
||
{
|
||
#include "pdowmi.x"
|
||
};
|
||
//
|
||
// Guid Index Symbolic Names.
|
||
//
|
||
#define MPIO_DISK_INFOGuidIndex 0
|
||
#define MPIO_PATH_INFORMATIONGuidIndex 1
|
||
#define MPIO_CONTROLLER_CONFIGURATIONGuidIndex 2
|
||
#define MPIO_EventEntryGuidIndex 3
|
||
#define MPIO_WmiBinaryMofGuidIndex 4
|
||
|
||
//
|
||
// Guid Index for Pdos
|
||
//
|
||
#define MPIO_GET_DESCRIPTORGuidIndex 0
|
||
#define BinaryMofGuidIndex 1
|
||
//
|
||
// List of supported Guids.
|
||
//
|
||
GUID MPIO_DISK_INFOGUID = MPIO_DISK_INFOGuid;
|
||
GUID MPIO_PATH_INFORMATIONGUID = MPIO_PATH_INFORMATIONGuid;
|
||
GUID MPIO_CONTROLLER_CONFIGURATIONGUID = MPIO_CONTROLLER_CONFIGURATIONGuid;
|
||
GUID MPIO_EventEntryGUID = MPIO_EventEntryGuid;
|
||
GUID MPIOWmiBinaryMofGUID = BINARY_MOF_GUID;
|
||
|
||
WMIGUIDREGINFO MPIOWmiGuidList[] =
|
||
{
|
||
{
|
||
&MPIO_DISK_INFOGUID,
|
||
1,
|
||
0
|
||
},
|
||
{
|
||
&MPIO_PATH_INFORMATIONGUID,
|
||
1,
|
||
0
|
||
},
|
||
{
|
||
&MPIO_CONTROLLER_CONFIGURATIONGUID,
|
||
1,
|
||
0
|
||
},
|
||
{
|
||
&MPIO_EventEntryGUID,
|
||
1,
|
||
0
|
||
},
|
||
{
|
||
&MPIOWmiBinaryMofGUID,
|
||
1,
|
||
0
|
||
}
|
||
};
|
||
|
||
#define MPIO_GUID_COUNT (sizeof(MPIOWmiGuidList) / sizeof(WMIGUIDREGINFO))
|
||
|
||
|
||
GUID MPIO_GET_DESCRIPTORGUID = MPIO_GET_DESCRIPTORGuid;
|
||
GUID PdowmiBinaryMofGUID = BINARY_MOF_GUID;
|
||
WMIGUIDREGINFO PdowmiGuidList[] =
|
||
{
|
||
{
|
||
&MPIO_GET_DESCRIPTORGUID,
|
||
1,
|
||
0
|
||
},
|
||
{
|
||
&PdowmiBinaryMofGUID,
|
||
1,
|
||
0
|
||
}
|
||
};
|
||
|
||
#define PdowmiGuidCount (sizeof(PdowmiGuidList) / sizeof(WMIGUIDREGINFO))
|
||
|
||
|
||
NTSTATUS
|
||
MPIOQueryRegInfo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
OUT PULONG RegFlags,
|
||
OUT PUNICODE_STRING InstanceName,
|
||
OUT PUNICODE_STRING *RegistryPath,
|
||
OUT PUNICODE_STRING MofResourceName,
|
||
OUT PDEVICE_OBJECT *Pdo
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
UNICODE_STRING nameString;
|
||
ANSI_STRING ansiString;
|
||
UCHAR instanceName[] = "Multi-Path Disk";
|
||
|
||
//
|
||
// Return a pointer to the reg. path. Wmi needs this for some reason.
|
||
//
|
||
*RegistryPath = &deviceExtension->RegistryPath;
|
||
|
||
|
||
if (FALSE) { //deviceExtension->Type == MPIO_MPDISK) {
|
||
|
||
RtlInitAnsiString(&ansiString, instanceName);
|
||
RtlAnsiStringToUnicodeString(InstanceName, &ansiString, TRUE);
|
||
|
||
*RegFlags = WMIREG_FLAG_INSTANCE_BASENAME;
|
||
|
||
} else {
|
||
//
|
||
// Indicate that instance names should be auto-generated.
|
||
//
|
||
*RegFlags = WMIREG_FLAG_INSTANCE_PDO;
|
||
|
||
//
|
||
// Set the PDO.
|
||
//
|
||
*Pdo = deviceExtension->Pdo;
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
ULONG
|
||
MPIOGetDriveInfoSize(
|
||
IN PDEVICE_OBJECT DeviceObject
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PDSM_ENTRY dsm = &diskExtension->DsmInfo;
|
||
ULONG length;
|
||
WCHAR buffer[64];
|
||
PUCHAR serialNumber;
|
||
ULONG serialNumberLength;
|
||
|
||
|
||
//
|
||
// Determine name length.
|
||
// \Device\MPIODisk(N)
|
||
//
|
||
swprintf(buffer, L"MPIO Disk%0d", diskExtension->DeviceOrdinal);
|
||
length = wcslen(buffer) + 1;
|
||
length *= sizeof(WCHAR);
|
||
|
||
//
|
||
// Add in a USHORT to account for the 'Length' field.
|
||
//
|
||
length += sizeof(USHORT);
|
||
|
||
//
|
||
// Add a ULONG size. (NumberPaths)
|
||
//
|
||
length += sizeof(ULONG);
|
||
|
||
//
|
||
// Determine SN size.
|
||
//
|
||
serialNumber = (PUCHAR)diskExtension->DeviceDescriptor;
|
||
(ULONG_PTR)serialNumber += diskExtension->DeviceDescriptor->SerialNumberOffset;
|
||
serialNumberLength = strlen(serialNumber) + 1;
|
||
|
||
//
|
||
// Length of the buffer.
|
||
//
|
||
length += (serialNumberLength * sizeof(WCHAR));
|
||
|
||
//
|
||
// Length of the 'length' field.
|
||
//
|
||
length += sizeof(USHORT);
|
||
|
||
//
|
||
// Get the DSM Name.
|
||
//
|
||
length += dsm->DisplayName.Length;
|
||
length += sizeof(USHORT);
|
||
length += sizeof(UNICODE_NULL);
|
||
|
||
if (length & 3) {
|
||
|
||
length += sizeof(ULONG);
|
||
length &= ~(sizeof(ULONG) - 1);
|
||
}
|
||
return length;
|
||
}
|
||
|
||
|
||
ULONG
|
||
MPIOBuildDriveInfo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN OUT PWCHAR Buffer
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PDSM_ENTRY dsm = &diskExtension->DsmInfo;
|
||
PREAL_DEV_INFO targetInfo;
|
||
WCHAR nameBuffer[64];
|
||
PWCHAR buffer;
|
||
PUCHAR serialNumber;
|
||
ANSI_STRING ansiSerialNumber;
|
||
UNICODE_STRING unicodeString;
|
||
ULONG i;
|
||
ULONG stringLength;
|
||
ULONG totalLength;
|
||
BOOLEAN freeBuffer = FALSE;
|
||
|
||
buffer = Buffer;
|
||
*((PULONG)buffer) = diskExtension->DsmIdList.Count;
|
||
|
||
totalLength = sizeof(ULONG);
|
||
(PUCHAR)buffer += sizeof(ULONG);
|
||
|
||
//
|
||
// Build the string locally.
|
||
//
|
||
swprintf(nameBuffer, L"MPIO Disk%0d", diskExtension->DeviceOrdinal);
|
||
|
||
//
|
||
// Get the number of characters + 1 (for the terminating NULL).
|
||
//
|
||
stringLength = wcslen(nameBuffer) + 1;
|
||
|
||
//
|
||
// Convert length to WCHAR sized.
|
||
//
|
||
stringLength *= sizeof(WCHAR);
|
||
|
||
//
|
||
// The WMI strings are sort-of unicode strings. They have a length, but not
|
||
// maximum length.
|
||
// Indicate the Length.
|
||
//
|
||
*((PUSHORT)buffer) = (USHORT)stringLength;
|
||
(PUCHAR)buffer += sizeof(USHORT);
|
||
|
||
MPDebugPrint((0,
|
||
"Buffer (%x) Length (%x)\n", buffer, stringLength));
|
||
|
||
//
|
||
// Copy the string.
|
||
//
|
||
RtlCopyMemory(buffer,
|
||
nameBuffer,
|
||
stringLength);
|
||
|
||
//
|
||
// Return the length of the string (plus NULL term.) + the USHORT length field.
|
||
//
|
||
totalLength += stringLength + sizeof(USHORT);
|
||
|
||
//
|
||
// Build the serial Number.
|
||
//
|
||
(PUCHAR)buffer += stringLength;
|
||
|
||
if (diskExtension->DeviceDescriptor->SerialNumberOffset == (ULONG)-1) {
|
||
*((PUSHORT)Buffer) = 0;
|
||
unicodeString.Length = sizeof(USHORT);
|
||
|
||
//
|
||
// No buffer to free.
|
||
//
|
||
freeBuffer = FALSE;
|
||
|
||
} else {
|
||
|
||
serialNumber = (PUCHAR)diskExtension->DeviceDescriptor;
|
||
(ULONG_PTR)serialNumber += diskExtension->DeviceDescriptor->SerialNumberOffset;
|
||
RtlInitAnsiString(&ansiSerialNumber, serialNumber);
|
||
RtlAnsiStringToUnicodeString(&unicodeString, &ansiSerialNumber, TRUE);
|
||
|
||
//
|
||
// Set the serial Number Length, and move the pointer
|
||
// to the string location.
|
||
//
|
||
*((PUSHORT)buffer) = unicodeString.Length + sizeof(UNICODE_NULL);
|
||
(PUCHAR)buffer += sizeof(USHORT);
|
||
MPDebugPrint((0,
|
||
"Buffer (%x) Length (%x)\n", buffer, unicodeString.Length));
|
||
|
||
//
|
||
// Copy the serialNumber.
|
||
//
|
||
RtlCopyMemory(buffer,
|
||
unicodeString.Buffer,
|
||
unicodeString.Length);
|
||
|
||
totalLength += unicodeString.Length + sizeof(USHORT);
|
||
totalLength += sizeof(UNICODE_NULL);
|
||
|
||
//
|
||
// Indicate that the unicode buffer was actually allocated.
|
||
//
|
||
freeBuffer = TRUE;
|
||
}
|
||
|
||
//
|
||
// Push the buffer to the next string location.
|
||
//
|
||
// CHUCKP - just added the sizeof(UNICOE_NULL)...
|
||
//
|
||
(PUCHAR)buffer += unicodeString.Length;
|
||
(PUCHAR)buffer += sizeof(UNICODE_NULL);
|
||
|
||
//
|
||
// Free up the Unicode string, as it's no longer needed.
|
||
//
|
||
if (freeBuffer) {
|
||
RtlFreeUnicodeString(&unicodeString);
|
||
}
|
||
|
||
MPDebugPrint((0,
|
||
"Buffer (%x) Length (%x)\n", buffer, dsm->DisplayName.Length));
|
||
//
|
||
// Set the size of the DSM's name.
|
||
//
|
||
*((PUSHORT)buffer) = dsm->DisplayName.Length + sizeof(UNICODE_NULL);
|
||
(PUCHAR)buffer += sizeof(USHORT);
|
||
|
||
RtlCopyMemory(buffer,
|
||
dsm->DisplayName.Buffer,
|
||
dsm->DisplayName.Length);
|
||
|
||
//
|
||
// Need to account for a NULL at the end of this.
|
||
//
|
||
totalLength += sizeof(UNICODE_NULL);
|
||
|
||
//
|
||
// update the returned length for the Length field and
|
||
// the string itself.
|
||
//
|
||
totalLength += dsm->DisplayName.Length + sizeof(USHORT);
|
||
return totalLength;
|
||
}
|
||
|
||
|
||
MPIOGetPathInfoSize(
|
||
IN PDEVICE_OBJECT DeviceObject
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
PLIST_ENTRY entry;
|
||
PID_ENTRY id;
|
||
ULONG dataLength;
|
||
ULONG stringLength;
|
||
ULONG i;
|
||
|
||
dataLength = sizeof(ULONG);
|
||
entry = controlExtension->IdList.Flink;
|
||
for (i = 0; i < controlExtension->NumberPaths; i++) {
|
||
|
||
if (dataLength & 7) {
|
||
dataLength += sizeof(LONGLONG);
|
||
dataLength &= ~(sizeof(LONGLONG) - 1);
|
||
}
|
||
dataLength += sizeof(LONGLONG);
|
||
dataLength += sizeof(UCHAR) * 4;
|
||
|
||
id = CONTAINING_RECORD(entry, ID_ENTRY, ListEntry);
|
||
stringLength = id->AdapterName.Length + sizeof(USHORT);
|
||
if (stringLength & 3) {
|
||
stringLength += sizeof(ULONG);
|
||
stringLength &= ~(sizeof(ULONG) -1);
|
||
}
|
||
dataLength += stringLength;
|
||
|
||
}
|
||
return dataLength;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOBuildPathInfo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PUCHAR Buffer
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
ULONG dataLength;
|
||
PLIST_ENTRY entry;
|
||
PID_ENTRY id;
|
||
ULONG i;
|
||
USHORT stringLength;
|
||
PUCHAR buffer = Buffer;
|
||
|
||
*((PULONG)buffer) = controlExtension->NumberPaths;
|
||
buffer += sizeof(ULONG);
|
||
|
||
entry = controlExtension->IdList.Flink;
|
||
for (i = 0; i < controlExtension->NumberPaths; i++) {
|
||
|
||
if ((ULONG_PTR)buffer & 7) {
|
||
(ULONG_PTR)buffer += sizeof(LONGLONG);
|
||
(ULONG_PTR)buffer &= ~(sizeof(LONGLONG) - 1);
|
||
}
|
||
|
||
id = CONTAINING_RECORD(entry, ID_ENTRY, ListEntry);
|
||
if (id->UIDValid == FALSE) {
|
||
|
||
id->UID = MPIOCreateUID(DeviceObject,
|
||
id->PathID);
|
||
}
|
||
|
||
*((PLONGLONG)buffer) = id->UID;
|
||
|
||
//
|
||
// Need the adapter location.
|
||
// The Bus Number.
|
||
//
|
||
(ULONG_PTR)buffer += sizeof(LONGLONG);
|
||
*buffer = id->Address.Bus;
|
||
|
||
//
|
||
// The device.
|
||
//
|
||
(ULONG_PTR)buffer += 1;
|
||
*buffer = id->Address.Device;
|
||
|
||
//
|
||
// The function.
|
||
//
|
||
(ULONG_PTR)buffer += 1;
|
||
*buffer = id->Address.Function;
|
||
|
||
//
|
||
// Zero the padding byte.
|
||
//
|
||
(ULONG_PTR)buffer += 1;
|
||
*buffer = 0;
|
||
(ULONG_PTR)buffer += 1;
|
||
|
||
//
|
||
// Need the adapter friendly name...
|
||
//
|
||
stringLength = id->AdapterName.Length;
|
||
*((PUSHORT)buffer) = stringLength;
|
||
(ULONG_PTR)buffer += sizeof(USHORT);
|
||
RtlCopyMemory(buffer,
|
||
id->AdapterName.Buffer,
|
||
id->AdapterName.Length);
|
||
(ULONG_PTR)buffer += stringLength;
|
||
|
||
//
|
||
// Get the next path struct.
|
||
//
|
||
entry = entry->Flink;
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
ULONG
|
||
MPIOGetControllerInfoSize(
|
||
IN PDEVICE_OBJECT DeviceObject
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
PLIST_ENTRY entry;
|
||
PCONTROLLER_ENTRY controller;
|
||
ULONG dataLength;
|
||
ULONG stringLength;
|
||
ULONG i;
|
||
|
||
dataLength = sizeof(ULONG);
|
||
entry = controlExtension->ControllerList.Flink;
|
||
for (i = 0; i < controlExtension->NumberControllers; i++) {
|
||
|
||
//
|
||
// ControllerId.
|
||
//
|
||
if (dataLength & 7) {
|
||
dataLength += sizeof(LONGLONG);
|
||
dataLength &= ~(sizeof(LONGLONG) - 1);
|
||
}
|
||
dataLength += sizeof(LONGLONG);
|
||
|
||
//
|
||
// ControllerSate.
|
||
//
|
||
dataLength += sizeof(ULONG);
|
||
|
||
controller = CONTAINING_RECORD(entry, CONTROLLER_ENTRY, ListEntry);
|
||
stringLength = controller->Dsm->DisplayName.Length + sizeof(USHORT);
|
||
if (stringLength & 3) {
|
||
stringLength += sizeof(ULONG);
|
||
stringLength &= ~(sizeof(ULONG) -1);
|
||
}
|
||
dataLength += stringLength;
|
||
entry = entry->Flink;
|
||
|
||
}
|
||
return dataLength;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOGetControllerInfo(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PUCHAR Buffer
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
ULONG dataLength;
|
||
PLIST_ENTRY entry;
|
||
PCONTROLLER_ENTRY controller;
|
||
ULONG i;
|
||
USHORT stringLength;
|
||
PUCHAR buffer = Buffer;
|
||
|
||
*((PULONG)buffer) = controlExtension->NumberControllers;
|
||
buffer += sizeof(ULONG);
|
||
|
||
entry = controlExtension->ControllerList.Flink;
|
||
for (i = 0; i < controlExtension->NumberControllers; i++) {
|
||
|
||
if ((ULONG_PTR)buffer & 7) {
|
||
(ULONG_PTR)buffer += sizeof(LONGLONG);
|
||
(ULONG_PTR)buffer &= ~(sizeof(LONGLONG) - 1);
|
||
}
|
||
|
||
controller = CONTAINING_RECORD(entry, CONTROLLER_ENTRY, ListEntry);
|
||
*((PLONGLONG)buffer) = controller->ControllerInfo->ControllerIdentifier;
|
||
|
||
(ULONG_PTR)buffer += sizeof(LONGLONG);
|
||
*((PULONG)buffer) = controller->ControllerInfo->State;
|
||
|
||
(ULONG_PTR)buffer += sizeof(ULONG);
|
||
|
||
//
|
||
// Build the dsm name.
|
||
//
|
||
stringLength = controller->Dsm->DisplayName.Length;
|
||
*((PUSHORT)buffer) = stringLength;
|
||
(ULONG_PTR)buffer += sizeof(USHORT);
|
||
RtlCopyMemory(buffer,
|
||
controller->Dsm->DisplayName.Buffer,
|
||
controller->Dsm->DisplayName.Length);
|
||
(ULONG_PTR)buffer += stringLength;
|
||
|
||
//
|
||
// Get the next path struct.
|
||
//
|
||
entry = entry->Flink;
|
||
}
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOQueryDataBlock(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN ULONG GuidIndex,
|
||
IN ULONG InstanceIndex,
|
||
IN ULONG InstanceCount,
|
||
IN OUT PULONG InstanceLengthArray,
|
||
IN ULONG BufferAvailable,
|
||
OUT PUCHAR Buffer
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
NTSTATUS status;
|
||
ULONG dataLength;
|
||
ULONG i;
|
||
PDISK_ENTRY diskEntry;
|
||
|
||
switch (GuidIndex) {
|
||
case MPIO_DISK_INFOGuidIndex: {
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
PMPIO_DISK_INFO diskInfo;
|
||
LARGE_INTEGER systemTime;
|
||
ULONG stringLength;
|
||
ULONG driveInfoLength;
|
||
ULONG length2;
|
||
|
||
//
|
||
// Check data length to ensure buffer is large enough.
|
||
//
|
||
dataLength = sizeof(ULONG);
|
||
|
||
//
|
||
// Add the length to handle the DRIVE_INFO structs for each
|
||
// MPDisk.
|
||
//
|
||
for (i = 0; i < controlExtension->NumberDevices; i++) {
|
||
diskEntry = MPIOGetDiskEntry(DeviceObject, i);
|
||
driveInfoLength = MPIOGetDriveInfoSize(diskEntry->PdoObject);
|
||
MPDebugPrint((0,
|
||
"QueryDataBlock: DriveInfoLength (%x)\n",
|
||
driveInfoLength));
|
||
dataLength += driveInfoLength;
|
||
}
|
||
|
||
MPDebugPrint((0,
|
||
"MPIOQueryDataBlock: Length is (%x)\n", dataLength));
|
||
|
||
if (dataLength > BufferAvailable) {
|
||
|
||
//
|
||
// It's not. Report the size needed back to WMI.
|
||
//
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
|
||
PWCHAR buffer;
|
||
ULONG length;
|
||
|
||
RtlZeroMemory(Buffer, dataLength);
|
||
//
|
||
// Indicate the number of PDO's we've created.
|
||
//
|
||
diskInfo = (PMPIO_DISK_INFO)Buffer;
|
||
diskInfo->NumberDrives = controlExtension->NumberDevices;
|
||
buffer = (PWCHAR)diskInfo->DriveInfo;
|
||
for (i = 0; i < controlExtension->NumberDevices; i++) {
|
||
diskEntry = MPIOGetDiskEntry(DeviceObject, i);
|
||
|
||
length = MPIOBuildDriveInfo(diskEntry->PdoObject,
|
||
buffer);
|
||
MPDebugPrint((0,
|
||
"BuildDriveInfo Length (%x) buffer (%x)\n", length, buffer));
|
||
(PUCHAR)buffer += length;
|
||
if ((ULONG_PTR)buffer & 3) {
|
||
(ULONG_PTR)buffer += sizeof(ULONG);
|
||
(ULONG_PTR)buffer &= ~(sizeof(ULONG) - 1);
|
||
}
|
||
MPDebugPrint((0,
|
||
"After fixup buffer (%x)\n",buffer));
|
||
|
||
}
|
||
|
||
*InstanceLengthArray = dataLength;
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
break;
|
||
}
|
||
case MPIO_PATH_INFORMATIONGuidIndex: {
|
||
dataLength = MPIOGetPathInfoSize(DeviceObject);
|
||
if (dataLength > BufferAvailable) {
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
status = MPIOBuildPathInfo(DeviceObject,
|
||
Buffer);
|
||
*InstanceLengthArray = dataLength;
|
||
}
|
||
break;
|
||
}
|
||
case MPIO_CONTROLLER_CONFIGURATIONGuidIndex: {
|
||
|
||
//
|
||
// Determine the buffer size needed.
|
||
//
|
||
dataLength = MPIOGetControllerInfoSize(DeviceObject);
|
||
|
||
if (dataLength > BufferAvailable) {
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
|
||
status = MPIOGetControllerInfo(DeviceObject,
|
||
Buffer);
|
||
*InstanceLengthArray = dataLength;
|
||
}
|
||
|
||
break;
|
||
}
|
||
case MPIO_EventEntryGuidIndex:
|
||
|
||
//
|
||
// This is an event. Set zero info and
|
||
// return.
|
||
//
|
||
*InstanceLengthArray = 0;
|
||
status = STATUS_SUCCESS;
|
||
break;
|
||
|
||
case MPIO_WmiBinaryMofGuidIndex:
|
||
|
||
//
|
||
// Need to copy over the mof data.
|
||
//
|
||
dataLength = sizeof(MPIOBinaryMofData);
|
||
|
||
//
|
||
// Ensure that the buffer is large enough.
|
||
//
|
||
if (dataLength > BufferAvailable) {
|
||
|
||
//
|
||
// dataLength is passed back to the WmiLib
|
||
// so it can adjust.
|
||
//
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
||
} else {
|
||
|
||
RtlCopyMemory(Buffer, MPIOBinaryMofData, dataLength);
|
||
*InstanceLengthArray = dataLength;
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
break;
|
||
default:
|
||
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Complete the request.
|
||
//
|
||
status = WmiCompleteRequest(DeviceObject,
|
||
Irp,
|
||
status,
|
||
dataLength,
|
||
IO_NO_INCREMENT);
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOWmiControl(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN ULONG GuidIndex,
|
||
IN WMIENABLEDISABLECONTROL Function,
|
||
IN BOOLEAN Enable
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
NTSTATUS status;
|
||
|
||
switch (GuidIndex) {
|
||
case MPIO_EventEntryGuidIndex:
|
||
if (Enable) {
|
||
|
||
//
|
||
// Indicate that it's OK to fire the Log event.
|
||
//
|
||
deviceExtension->FireLogEvent = TRUE;
|
||
} else {
|
||
|
||
//
|
||
// Turn off firing the logger.
|
||
//
|
||
deviceExtension->FireLogEvent = FALSE;
|
||
}
|
||
MPDebugPrint((0,
|
||
"MPIOWmiControl: Turning the Logger (%s) on (%x)\n",
|
||
Enable ? "ON" : "OFF",
|
||
DeviceObject));
|
||
|
||
break;
|
||
|
||
default:
|
||
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
break;
|
||
}
|
||
|
||
status = WmiCompleteRequest(DeviceObject,
|
||
Irp,
|
||
status,
|
||
0,
|
||
IO_NO_INCREMENT);
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// PDO Call-Backs.
|
||
//
|
||
|
||
|
||
ULONG
|
||
MPIOGetDescriptorSize(
|
||
IN PDEVICE_OBJECT DeviceObject
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PREAL_DEV_INFO targetInfo = diskExtension->TargetInfo;
|
||
ULONG dataLength = 0;
|
||
NTSTATUS status;
|
||
ULONG i;
|
||
ULONG stringLength;
|
||
ULONG bytesRequired;
|
||
|
||
//
|
||
// NumberPdos
|
||
//
|
||
dataLength = sizeof(ULONG);
|
||
|
||
if (diskExtension->HasName == FALSE) {
|
||
|
||
//
|
||
// Get the name of the first PortPdo - being as it's
|
||
// the same device, the name remains the same for all.
|
||
//
|
||
status = IoGetDeviceProperty(targetInfo->PortPdo,
|
||
DevicePropertyFriendlyName,
|
||
diskExtension->PdoName.MaximumLength,
|
||
diskExtension->PdoName.Buffer,
|
||
&bytesRequired);
|
||
|
||
if (status == STATUS_SUCCESS) {
|
||
|
||
MPDebugPrint((0,
|
||
"GetDescriptor: size of name is (%x)\n",
|
||
bytesRequired));
|
||
//
|
||
// The buffer is NULL terminated. Reduce it.
|
||
//
|
||
bytesRequired -= sizeof(UNICODE_NULL);
|
||
|
||
stringLength = sizeof(USHORT);
|
||
stringLength += bytesRequired;
|
||
|
||
diskExtension->HasName = TRUE;
|
||
|
||
//
|
||
// Align the buffer size.
|
||
//
|
||
if (stringLength & 3) {
|
||
|
||
MPDebugPrint((0,
|
||
"GetDescriptor: Need to align (%x\n",
|
||
stringLength));
|
||
|
||
stringLength += sizeof(ULONG);
|
||
stringLength &= ~(sizeof(ULONG) -1);
|
||
}
|
||
|
||
MPDebugPrint((0,
|
||
"GetDescriptor: size of name is now (%x). StrLeng (%x)\n",
|
||
bytesRequired,
|
||
stringLength));
|
||
|
||
diskExtension->PdoName.Length = (USHORT)bytesRequired;
|
||
|
||
} else {
|
||
MPDebugPrint((0,
|
||
"MPIOGetDescriptor: Buffer not large enough (%lu)\n",
|
||
bytesRequired));
|
||
}
|
||
} else {
|
||
stringLength = sizeof(USHORT);
|
||
stringLength += diskExtension->PdoName.Length;
|
||
|
||
if (stringLength & 3) {
|
||
stringLength += sizeof(ULONG);
|
||
stringLength &= ~(sizeof(ULONG) -1);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Length of the string + the size field.
|
||
//
|
||
dataLength += stringLength;
|
||
|
||
for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
|
||
|
||
//
|
||
// Length of the scsi address.
|
||
//
|
||
dataLength += sizeof(SCSI_ADDR);
|
||
|
||
//
|
||
// Path Identifier.
|
||
//
|
||
dataLength += sizeof(LONGLONG);
|
||
|
||
//
|
||
// Controller ID.
|
||
//
|
||
dataLength += sizeof(ULONGLONG);
|
||
if (dataLength & 7) {
|
||
dataLength += sizeof(LONGLONG);
|
||
dataLength &= ~(sizeof(LONGLONG) - 1);
|
||
}
|
||
|
||
//
|
||
// Get the next targetInfo.
|
||
//
|
||
targetInfo++;
|
||
}
|
||
|
||
MPDebugPrint((0,
|
||
"GetDescriptor: Total Length (%x)\n",
|
||
dataLength));
|
||
|
||
return dataLength;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOBuildDescriptor(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PUCHAR Buffer
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PREAL_DEV_INFO targetInfo = diskExtension->TargetInfo;
|
||
PMPIO_GET_DESCRIPTOR descriptor = (PMPIO_GET_DESCRIPTOR)Buffer;
|
||
NTSTATUS status;
|
||
PUCHAR buffer;
|
||
ULONG i;
|
||
PSCSI_ADDR scsiAddress;
|
||
|
||
descriptor->NumberPdos = diskExtension->DsmIdList.Count;
|
||
buffer = Buffer;
|
||
buffer += sizeof(ULONG);
|
||
|
||
//
|
||
// Set the string length.
|
||
//
|
||
*((PUSHORT)buffer) = diskExtension->PdoName.Length;
|
||
buffer += sizeof(USHORT);
|
||
|
||
//
|
||
// Copy it over.
|
||
//
|
||
RtlCopyMemory(buffer,
|
||
diskExtension->PdoName.Buffer,
|
||
diskExtension->PdoName.Length);
|
||
|
||
//
|
||
// Push it to the end of the string.
|
||
//
|
||
buffer += diskExtension->PdoName.Length;
|
||
|
||
//
|
||
// ULONG align.
|
||
//
|
||
if ((ULONG_PTR)buffer & 3) {
|
||
|
||
(ULONG_PTR)buffer += sizeof(ULONG);
|
||
(ULONG_PTR)buffer &= ~(sizeof(ULONG) - 1);
|
||
}
|
||
|
||
for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
|
||
|
||
scsiAddress = (PSCSI_ADDR)buffer;
|
||
|
||
scsiAddress->PortNumber = targetInfo->ScsiAddress.PortNumber;
|
||
scsiAddress->ScsiPathId = targetInfo->ScsiAddress.PathId;
|
||
scsiAddress->TargetId = targetInfo->ScsiAddress.TargetId;
|
||
scsiAddress->Lun = targetInfo->ScsiAddress.Lun;
|
||
|
||
buffer += sizeof(SCSI_ADDR);
|
||
|
||
if (targetInfo->PathUIDValue == FALSE) {
|
||
targetInfo->Identifier = MPIOCreateUID(diskExtension->ControlObject,
|
||
targetInfo->PathId);
|
||
ASSERT(targetInfo->Identifier != 0);
|
||
targetInfo->PathUIDValue = TRUE;
|
||
}
|
||
|
||
//
|
||
// Align the buffer
|
||
//
|
||
if ((ULONG_PTR)buffer & 7) {
|
||
(ULONG_PTR)buffer += sizeof(LONGLONG);
|
||
(ULONG_PTR)buffer &= ~(sizeof(LONGLONG) - 1);
|
||
}
|
||
*((PLONGLONG)buffer) = targetInfo->Identifier;
|
||
buffer += sizeof(LONGLONG);
|
||
|
||
//
|
||
// Get the controllerID.
|
||
//
|
||
*((PULONGLONG)buffer) = targetInfo->ControllerId;
|
||
buffer += sizeof(ULONGLONG);
|
||
|
||
//
|
||
// Handle the next device.
|
||
//
|
||
targetInfo++;
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
MPIOPdoQueryDataBlock(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN ULONG GuidIndex,
|
||
IN ULONG InstanceIndex,
|
||
IN ULONG InstanceCount,
|
||
IN OUT PULONG InstanceLengthArray,
|
||
IN ULONG BufferAvailable,
|
||
OUT PUCHAR Buffer
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PDSM_ENTRY dsm = &diskExtension->DsmInfo;
|
||
NTSTATUS status;
|
||
ULONG dataLength;
|
||
|
||
switch(GuidIndex) {
|
||
case MPIO_GET_DESCRIPTORGuidIndex: {
|
||
|
||
dataLength = MPIOGetDescriptorSize(DeviceObject);
|
||
|
||
if (dataLength > BufferAvailable) {
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
RtlZeroMemory(Buffer, dataLength);
|
||
status = MPIOBuildDescriptor(DeviceObject,
|
||
Buffer);
|
||
*InstanceLengthArray = dataLength;
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
break;
|
||
}
|
||
|
||
case BinaryMofGuidIndex: {
|
||
//
|
||
// TODO: If the driver supports reporting MOF dynamically,
|
||
// change this code to handle multiple instances of the
|
||
// binary mof guid and return only those instances that
|
||
// should be reported to the schema
|
||
//
|
||
dataLength = sizeof(PdoBinaryMofData);
|
||
|
||
if (BufferAvailable < dataLength)
|
||
{
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
} else {
|
||
RtlCopyMemory(Buffer, PdoBinaryMofData, dataLength);
|
||
*InstanceLengthArray = dataLength;
|
||
status = STATUS_SUCCESS;
|
||
}
|
||
break;
|
||
}
|
||
|
||
default: {
|
||
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Complete the request.
|
||
//
|
||
status = WmiCompleteRequest(DeviceObject,
|
||
Irp,
|
||
status,
|
||
dataLength,
|
||
IO_NO_INCREMENT);
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOGetDiskDescriptorSize(
|
||
IN PDEVICE_OBJECT DeviceObject
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
ULONG dataLength;
|
||
NTSTATUS status;
|
||
ULONG i;
|
||
|
||
//
|
||
// Length is ULONG (NumberDisks) + sizeof(MPDISK_DESCRIPTOR)
|
||
//
|
||
dataLength = sizeof(ULONG);
|
||
|
||
//
|
||
// For the string length field.
|
||
//
|
||
dataLength += sizeof(USHORT);
|
||
|
||
//
|
||
// Length of the product/vendor/rev string
|
||
// (8 + 16+ 4 + 2 (spaces between vendor/product/rev) + 1 (trailing NULL)) * sizeof(WCHAR)
|
||
//
|
||
dataLength += 0x3C;
|
||
|
||
//
|
||
// Ensure that the start of each array entry is ULONG aligned.
|
||
//
|
||
dataLength += sizeof(ULONG);
|
||
dataLength &= ~(sizeof(ULONG) - 1);
|
||
|
||
for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
|
||
|
||
//
|
||
// SCSI_ADDR (almost like SCSI_ADDRESS, but without the length field)
|
||
//
|
||
dataLength += sizeof(SCSI_ADDR);
|
||
|
||
|
||
}
|
||
return dataLength;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOGetDiskDescriptor(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG BufferLength
|
||
)
|
||
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PUCHAR buffer = Buffer;
|
||
PREAL_DEV_INFO targetInfo;
|
||
PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
|
||
PUCHAR inquiryField;
|
||
PUCHAR index;
|
||
UCHAR inquiryData[32];
|
||
ANSI_STRING ansiInquiry;
|
||
UNICODE_STRING unicodeString;
|
||
PSCSI_ADDR scsiAddress;
|
||
ULONG i;
|
||
NTSTATUS status;
|
||
|
||
RtlZeroMemory(Buffer, BufferLength);
|
||
|
||
*((PULONG)buffer) = diskExtension->DsmIdList.Count;
|
||
targetInfo = diskExtension->TargetInfo;
|
||
|
||
//
|
||
// Set the number of drives underlying this mpdisk.
|
||
//
|
||
(ULONG_PTR)buffer += sizeof(ULONG);
|
||
|
||
|
||
//
|
||
// Preload the inquiry buffer with spaces and a null-terminator.
|
||
//
|
||
for (i = 0; i < 32; i++) {
|
||
inquiryData[i] = ' ';
|
||
}
|
||
inquiryData[30] = '\0';
|
||
inquiryData[31] = '\0';
|
||
|
||
//
|
||
// Merge the ascii inquiry data into one long string.
|
||
//
|
||
deviceDescriptor = diskExtension->DeviceDescriptor;
|
||
inquiryField = (PUCHAR)deviceDescriptor;
|
||
(ULONG_PTR)inquiryField += deviceDescriptor->VendorIdOffset;
|
||
index = inquiryData;
|
||
|
||
//
|
||
// Copy the vendorId.
|
||
//
|
||
RtlCopyMemory(index, inquiryField, 8);
|
||
|
||
//
|
||
// Account for vendorId + a space.
|
||
//
|
||
index += 9;
|
||
|
||
inquiryField = (PUCHAR)deviceDescriptor;
|
||
(ULONG_PTR)inquiryField += deviceDescriptor->ProductIdOffset;
|
||
|
||
//
|
||
// Copy ProductId.
|
||
//
|
||
RtlCopyMemory(index, inquiryField, 16);
|
||
|
||
//
|
||
// Account for product + space.
|
||
//
|
||
index += 17;
|
||
|
||
inquiryField = (PUCHAR)deviceDescriptor;
|
||
(ULONG_PTR)inquiryField += deviceDescriptor->ProductRevisionOffset;
|
||
RtlCopyMemory(index, inquiryField, 4);
|
||
|
||
//
|
||
// Convert to WCHAR.
|
||
//
|
||
RtlInitAnsiString(&ansiInquiry, inquiryData);
|
||
RtlAnsiStringToUnicodeString(&unicodeString, &ansiInquiry, TRUE);
|
||
|
||
//
|
||
// Build the name string. First is the length.
|
||
//
|
||
// BUGBUG: Note the hack of +2
|
||
//
|
||
*((PUSHORT)buffer) = unicodeString.Length + 2;
|
||
(ULONG_PTR)buffer += sizeof(USHORT);
|
||
|
||
//
|
||
// Copy the serialNumber.
|
||
//
|
||
RtlCopyMemory(buffer,
|
||
unicodeString.Buffer,
|
||
unicodeString.Length);
|
||
|
||
//
|
||
// Advance the pointer past the inquiry string.
|
||
//
|
||
(ULONG_PTR)buffer += unicodeString.Length;
|
||
|
||
RtlFreeUnicodeString(&unicodeString);
|
||
|
||
//
|
||
// ULONG align it.
|
||
//
|
||
(ULONG_PTR)buffer += sizeof(ULONG);
|
||
(ULONG_PTR)buffer &= ~(sizeof(ULONG) - 1);
|
||
|
||
for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
|
||
scsiAddress = (PSCSI_ADDR)buffer;
|
||
|
||
scsiAddress->PortNumber = targetInfo->ScsiAddress.PortNumber;
|
||
scsiAddress->ScsiPathId = targetInfo->ScsiAddress.PathId;
|
||
scsiAddress->TargetId = targetInfo->ScsiAddress.TargetId;
|
||
scsiAddress->Lun = targetInfo->ScsiAddress.Lun;
|
||
targetInfo++;
|
||
|
||
(ULONG_PTR)buffer += sizeof(SCSI_ADDR);
|
||
#if 0
|
||
|
||
//
|
||
// Fake the WWN.
|
||
// TODO get the real stuff.
|
||
//
|
||
*((PLONGLONG)buffer) = 0;
|
||
|
||
(ULONG_PTR)buffer += sizeof(LONGLONG);
|
||
#endif
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOExecuteMethod(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN ULONG GuidIndex,
|
||
IN ULONG InstanceIndex,
|
||
IN ULONG MethodId,
|
||
IN ULONG InBufferSize,
|
||
IN ULONG OutBufferSize,
|
||
IN PUCHAR Buffer
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Arguments:
|
||
'aReturn Value:
|
||
|
||
status
|
||
|
||
--*/
|
||
{
|
||
ULONG dataLength = 0;
|
||
ULONG ordinal;
|
||
PDISK_ENTRY diskEntry;
|
||
NTSTATUS status;
|
||
|
||
switch(GuidIndex) {
|
||
#if 0
|
||
case MPIO_GET_DESCRIPTORSGuidIndex: {
|
||
switch(MethodId) {
|
||
case MPIOGetMPIODiskDescriptor: {
|
||
//
|
||
// Check the input buffer size.
|
||
//
|
||
if (InBufferSize != sizeof(ULONG)) {
|
||
status = STATUS_INVALID_PARAMETER;
|
||
dataLength = 0;
|
||
break;
|
||
|
||
}
|
||
|
||
//
|
||
// The input buffer is the ordinal of the device in which
|
||
// the caller has interest.
|
||
//
|
||
ordinal = *((PULONG)Buffer);
|
||
|
||
//
|
||
// Ensure that ordinal is with-in range.
|
||
// TODO
|
||
diskEntry = MPIOGetDiskEntry(DeviceObject,
|
||
ordinal);
|
||
//
|
||
// Get the size of the return info.
|
||
//
|
||
dataLength = MPIOGetDiskDescriptorSize(diskEntry->PdoObject);
|
||
|
||
if (dataLength > OutBufferSize) {
|
||
|
||
status = STATUS_BUFFER_TOO_SMALL;
|
||
break;
|
||
}
|
||
|
||
//
|
||
//
|
||
status = MPIOGetDiskDescriptor(diskEntry->PdoObject,
|
||
Buffer,
|
||
OutBufferSize);
|
||
|
||
|
||
|
||
break;
|
||
}
|
||
|
||
default: {
|
||
status = STATUS_WMI_ITEMID_NOT_FOUND;
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
#endif
|
||
default: {
|
||
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
}
|
||
}
|
||
|
||
status = WmiCompleteRequest(DeviceObject,
|
||
Irp,
|
||
status,
|
||
dataLength,
|
||
IO_NO_INCREMENT);
|
||
|
||
return(status);
|
||
}
|
||
|
||
NTSTATUS
|
||
MPIOPdoWmiControl(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN ULONG GuidIndex,
|
||
IN WMIENABLEDISABLECONTROL Function,
|
||
IN BOOLEAN Enable
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
NTSTATUS status;
|
||
|
||
switch (GuidIndex) {
|
||
case MPIO_EventEntryGuidIndex:
|
||
if (Enable) {
|
||
|
||
//
|
||
// Indicate that it's OK to fire the Log event.
|
||
//
|
||
deviceExtension->FireLogEvent = TRUE;
|
||
} else {
|
||
|
||
//
|
||
// Turn off firing the logger.
|
||
//
|
||
deviceExtension->FireLogEvent = FALSE;
|
||
}
|
||
MPDebugPrint((0,
|
||
"MPIOWmiControl: Turning the Logger (%s) on (%x)\n",
|
||
Enable ? "ON" : "OFF",
|
||
DeviceObject));
|
||
|
||
break;
|
||
|
||
default:
|
||
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
break;
|
||
}
|
||
|
||
status = WmiCompleteRequest(DeviceObject,
|
||
Irp,
|
||
status,
|
||
0,
|
||
IO_NO_INCREMENT);
|
||
return status;
|
||
}
|
||
|
||
|
||
VOID
|
||
MPIOSetupWmi(
|
||
IN PDEVICE_OBJECT DeviceObject
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension;
|
||
PWMILIB_CONTEXT wmiLibContext = &deviceExtension->WmiLib;
|
||
NTSTATUS status;
|
||
PDSM_ENTRY dsm;
|
||
PDSM_WMILIB_CONTEXT wmiContext;
|
||
ULONG guids;
|
||
ULONG guidListSize;
|
||
PUCHAR index;
|
||
|
||
//
|
||
// This simply jams in all the fields of the wmilib context for
|
||
// use by WmiSystemControl.
|
||
//
|
||
|
||
if (deviceExtension->Type == MPIO_MPDISK) {
|
||
|
||
//
|
||
// TODO: Revisit piggybacking off of the PDO. It may be
|
||
// better to use the FDO.
|
||
//
|
||
diskExtension = deviceExtension->TypeExtension;
|
||
dsm = &diskExtension->DsmInfo;
|
||
|
||
//
|
||
// Get the DSM's Wmi Info and append it to ours.
|
||
//
|
||
//wmiContext = &dsm->WmiContext;
|
||
|
||
//
|
||
// Currently, there are no PDO associated GUIDs. As soon as they are in place
|
||
// this needs to be updated accordingly.
|
||
//
|
||
#if 0
|
||
guids = wmiContext->GuidCount + MPIO_PDO_GUID_COUNT;
|
||
guidListSize = sizeof(MPIOPdoGuidList) + sizeof(wmiContext->GuidList);
|
||
guidListSize = sizeof(wmiContext->GuidList);
|
||
deviceExtension->WmiLib.GuidList = ExAllocatePool(NonPagedPool,guidListSize);
|
||
RtlZeroMemory(deviceExtension->WmiLib.GuidList, guidListSize);
|
||
|
||
//
|
||
// Copy over the pdo's list.
|
||
//
|
||
index = (PUCHAR)deviceExtension->WmiLib.GuidList;
|
||
RtlCopyMemory(index,
|
||
MPIOPdoGuidList,
|
||
sizeof(MPIOPdoGuidList));
|
||
index += sizeof(MPIOPdoGuidList);
|
||
|
||
wmiLibContext->GuidCount = guids;
|
||
|
||
//
|
||
// copy over the DSM's.
|
||
//
|
||
RtlCopyMemory(index,
|
||
wmiContext->GuidList,
|
||
sizeof(wmiContext->GuidList));
|
||
|
||
#endif
|
||
wmiLibContext->GuidCount = PdowmiGuidCount;
|
||
wmiLibContext->GuidList = PdowmiGuidList;
|
||
wmiLibContext->QueryWmiRegInfo = MPIOQueryRegInfo;
|
||
wmiLibContext->QueryWmiDataBlock = MPIOPdoQueryDataBlock;
|
||
//wmiLibContext->SetWmiDataBlock = MPIOPdoSetDataBlock;
|
||
//wmiLibContext->SetWmiDataItem = MPIOPdoSetDataItem;
|
||
//wmiLibContext->ExecuteWmiMethod = MPIOPdoExecuteMethod;
|
||
//wmiLibContext->WmiFunctionControl = MPIOPdoWmiControl;
|
||
|
||
} else {
|
||
|
||
wmiLibContext->GuidCount = MPIO_GUID_COUNT;
|
||
wmiLibContext->GuidList = MPIOWmiGuidList;
|
||
wmiLibContext->QueryWmiRegInfo = MPIOQueryRegInfo;
|
||
wmiLibContext->QueryWmiDataBlock = MPIOQueryDataBlock;
|
||
//wmiLibContext->SetWmiDataBlock = MPIOSetDataBlock;
|
||
//wmiLibContext->SetWmiDataItem = MPIOSetDataItem;
|
||
wmiLibContext->ExecuteWmiMethod = MPIOExecuteMethod;
|
||
wmiLibContext->WmiFunctionControl = MPIOWmiControl;
|
||
|
||
}
|
||
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOPdoWmi(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
{
|
||
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||
SYSCTL_IRP_DISPOSITION disposition;
|
||
NTSTATUS status;
|
||
|
||
//
|
||
// Using the WMI Library, so call it with the request.
|
||
// This will call the appropriate DpWmi function.
|
||
//
|
||
status = WmiSystemControl(&deviceExtension->WmiLib,
|
||
DeviceObject,
|
||
Irp,
|
||
&disposition);
|
||
|
||
switch (disposition) {
|
||
case IrpProcessed:
|
||
|
||
//
|
||
// Already handled by one of the DpWmi call-backs.
|
||
//
|
||
break;
|
||
case IrpNotCompleted:
|
||
|
||
//
|
||
// Probably an error, or the IRP_MN_REGINFO
|
||
//
|
||
MPDebugPrint((0,
|
||
"MPIOrPdoWmi: Irp (%x) Mn (%x) Status (%x)\n",
|
||
Irp,
|
||
irpStack->MinorFunction,
|
||
status));
|
||
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
break;
|
||
case IrpNotWmi:
|
||
case IrpForward:
|
||
default:
|
||
//
|
||
// Forward this irp.
|
||
//
|
||
status = MPIOForwardRequest(DeviceObject, Irp);
|
||
break;
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOFdoWmi(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
)
|
||
{
|
||
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||
PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
|
||
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||
SYSCTL_IRP_DISPOSITION disposition;
|
||
NTSTATUS status;
|
||
|
||
//
|
||
// Using the WMI Library, so call it with the request.
|
||
// This will call the appropriate DpWmi function.
|
||
//
|
||
status = WmiSystemControl(&deviceExtension->WmiLib,
|
||
DeviceObject,
|
||
Irp,
|
||
&disposition);
|
||
|
||
switch (disposition) {
|
||
case IrpProcessed:
|
||
|
||
//
|
||
// Already handled by one of the DpWmi call-backs.
|
||
//
|
||
break;
|
||
case IrpNotCompleted:
|
||
|
||
//
|
||
// Probably an error, or the IRP_MN_REGINFO
|
||
//
|
||
MPDebugPrint((0,
|
||
"MPIOFdoWmi: Irp (%x) Mn (%x) Status (%x)\n",
|
||
Irp,
|
||
irpStack->MinorFunction,
|
||
status));
|
||
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
break;
|
||
case IrpNotWmi:
|
||
case IrpForward:
|
||
default:
|
||
//
|
||
// Forward this irp.
|
||
//
|
||
status = MPIOForwardRequest(DeviceObject, Irp);
|
||
break;
|
||
}
|
||
|
||
return status;
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
MPIOFireEvent(
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PWCHAR ComponentName,
|
||
IN PWCHAR EventDescription,
|
||
IN ULONG Severity
|
||
)
|
||
{
|
||
PMPIO_EventEntry eventEntry;
|
||
ULONG dataLength;
|
||
PWCHAR nameString;
|
||
LARGE_INTEGER systemTime;
|
||
NTSTATUS status;
|
||
USHORT componentLength;
|
||
USHORT eventLength;
|
||
PUCHAR index;
|
||
|
||
//
|
||
// Determine the total allocation length based on the
|
||
// structure and string lengths.
|
||
//
|
||
componentLength = wcslen(ComponentName) * sizeof(WCHAR);
|
||
componentLength += sizeof(UNICODE_NULL);
|
||
eventLength = wcslen(EventDescription) * sizeof(WCHAR);
|
||
eventLength += sizeof(UNICODE_NULL);
|
||
|
||
if ((componentLength > MPIO_STRING_LENGTH) ||
|
||
(eventLength > MPIO_STRING_LENGTH)) {
|
||
return STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
dataLength = sizeof(MPIO_EventEntry);
|
||
|
||
//
|
||
// Allocate the EventData.
|
||
//
|
||
eventEntry = ExAllocatePool(NonPagedPool, dataLength);
|
||
if (eventEntry == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlZeroMemory(eventEntry, dataLength);
|
||
|
||
|
||
//
|
||
// Set the severity of the event.
|
||
//
|
||
eventEntry->Severity = Severity;
|
||
KeQuerySystemTime(&systemTime);
|
||
eventEntry->TimeStamp = systemTime.QuadPart;
|
||
|
||
//
|
||
// Copy the Component Name.
|
||
//
|
||
nameString = eventEntry->Component;
|
||
*((PUSHORT)nameString) = componentLength;
|
||
nameString++;
|
||
wcscpy(nameString, ComponentName);
|
||
|
||
MPDebugPrint((0,
|
||
"NameString (%x). Length (%d)\n",
|
||
nameString,
|
||
componentLength));
|
||
|
||
//
|
||
// Copy over the Object name.
|
||
//
|
||
nameString = eventEntry->EventDescription;
|
||
*((PUSHORT)nameString) = eventLength;
|
||
nameString++;
|
||
wcscpy(nameString, EventDescription);
|
||
|
||
//
|
||
// Send the event.
|
||
//
|
||
status = WmiFireEvent(DeviceObject,
|
||
&MPIO_EventEntryGUID,
|
||
0,
|
||
dataLength,
|
||
eventEntry);
|
||
if (status != STATUS_SUCCESS) {
|
||
MPDebugPrint((0,
|
||
"MPIOFireEvent: Status (%x)\n",
|
||
status));
|
||
|
||
//
|
||
// TODO: Queue these for when we get the Enable request.
|
||
//
|
||
ExFreePool(eventEntry);
|
||
|
||
}
|
||
return status;
|
||
}
|