windows-nt/Source/XPSP1/NT/drivers/storage/mpath/control/wmi.c
2020-09-26 16:20:57 +08:00

551 lines
16 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "mpath.h"
#include <wmistr.h>
#include <wmidata.h>
#include <stdio.h>
#ifdef USE_BINARY_MOF_QUERY
//
// MOF data can be reported by a device driver via a resource attached to
// the device drivers image file or in response to a query on the binary
// mof data guid. Here we define global variables containing the binary mof
// data to return in response to a binary mof guid query. Note that this
// data is defined to be in a PAGED data segment since it does not need to
// be in nonpaged memory. Note that instead of a single large mof file
// we could have broken it into multiple individual files. Each file would
// have its own binary mof data buffer and get reported via a different
// instance of the binary mof guid. By mixing and matching the different
// sets of binary mof data buffers a "dynamic" composite mof would be created.
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("PAGED")
#endif
#pragma message ("USE_BINARY defined ChuckP")
UCHAR MPathBinaryMofData[] =
{
#include "mpathwmi.x"
};
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif
#endif
WMIGUIDREGINFO MPathWmiGuidList[] = {
{
&MPath_Disk_Info_GUID,
1,
0
},
{
&MPath_Test_GUID,
1,
0
},
{
&MSWmi_MofData_GUID,
1,
#ifdef USE_BINARY_MOF_QUERY
0
#else
WMIREG_FLAG_REMOVE_GUID
#endif
}
};
#define DiskInformation 0
#define MPathTest 1
#define BinaryMofGuid 2
#define MPathGuidCount (sizeof(MPathWmiGuidList) / sizeof(WMIGUIDREGINFO))
//#define MPATH_GUID_PDISK_INFO 0
//#define MPATH_BINARY_MOF 1
//#define MPATH_GUID_FAILOVER_INFO 1
//#define MPATH_GUID_CONFIG_INFO 2
//#define MPATH_GUID_DSM_NAME 3
//#define MPATH_GUID_PATH_MAINTENACE 4
//
// Always update this for any guid additions.
// This indicates the dividing line between our and DSM
// guids.
//
//#define MPATH_MAX_GUID_INDEX MPATH_BINARY_MOF
//
NTSTATUS
MPathFdoWmi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(deviceExtension->TargetObject, Irp);
}
NTSTATUS
MPathQueryWmiRegInfo(
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;
*RegFlags = WMIREG_FLAG_INSTANCE_PDO;
*RegistryPath = &deviceExtension->RegistryPath;
*Pdo = deviceExtension->DeviceObject;
MPDebugPrint((0,
"MPathQueryWmiRegInfo: *Pdo (%x), DeviceObject (%x)\n",
*Pdo,
DeviceObject));
#ifndef USE_BINARY_MOF_QUERY
#pragma message ("BIN NOT - ChuckP")
//
// Return the name specified in the .rc file of the resource which
// contains the bianry mof data. By default WMI will look for this
// resource in the driver image (.sys) file, however if the value
// MofImagePath is specified in the driver's registry key
// then WMI will look for the resource in the file specified there.
RtlInitUnicodeString(MofResourceName, L"MofResourceName");
#endif
return STATUS_SUCCESS;
}
NTSTATUS
MPathQueryWmiDataBlock(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN ULONG InstanceIndex,
IN ULONG InstanceCount,
IN OUT PULONG InstanceLengthArray,
IN ULONG BufferAvail,
OUT PUCHAR Buffer
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PPSEUDO_DISK_EXTENSION diskExtension = &deviceExtension->PseudoDiskExtension;
NTSTATUS status;
ULONG i;
ULONG bytesReturned = 0;
if (TRUE) { //(GuidIndex <= MPATH_MAX_GUID_INDEX) {
//
// This is for the pdisk
// Ensure that this is a QUERY_SINGLE_INSTANCE, as these data blocks
// are defined as having only one instance.
//
if (InstanceIndex != 0 || InstanceCount != 1) {
status = STATUS_INVALID_DEVICE_REQUEST;
} else {
switch (GuidIndex) {
case MPathTest:
bytesReturned = sizeof(ULONG);
if (bytesReturned > BufferAvail) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
ULONG theValue = 0xaa55aa55;
RtlCopyMemory(Buffer,
&theValue,
sizeof(ULONG));
status = STATUS_SUCCESS;
}
break;
case DiskInformation: {
PMPath_Disk_Info diskInfo = (PMPath_Disk_Info)Buffer;
PSTORAGE_DEVICE_DESCRIPTOR storageDescriptor;
ULONG serialNumberLength;
ULONG totalStringLength;
PUCHAR serialNumber;
ANSI_STRING ansiSerialNumber;
UNICODE_STRING unicodeString;
bytesReturned = sizeof(MPath_Disk_Info);
//
// Determine the serial number length.
//
storageDescriptor =
diskExtension->DeviceDescriptors[0].StorageDescriptor;
serialNumber = (PUCHAR)storageDescriptor;
//
// Move serialNumber to the correct position in RawData.
//
(ULONG_PTR)serialNumber += storageDescriptor->SerialNumberOffset;
//
// Get it's length.
//
serialNumberLength = strlen(serialNumber);
totalStringLength = serialNumberLength * sizeof(WCHAR);
totalStringLength += sizeof(USHORT);
totalStringLength *= diskExtension->NumberPhysicalPaths;
bytesReturned += totalStringLength;
bytesReturned += (diskExtension->NumberPhysicalPaths - 1) *
sizeof(PHYSICAL_DISK_INFO);
if (bytesReturned > BufferAvail) {
status = STATUS_BUFFER_TOO_SMALL;
} else {
PWCHAR index;
PDEVICE_DESCRIPTOR deviceDescriptor;
PPHYSICAL_DISK_INFO deviceInfo = diskInfo->DeviceInfo;
diskInfo->NumberDrives = diskExtension->NumberPhysicalPaths;
diskInfo->IsLoadBalance = FALSE;
RtlInitAnsiString(&ansiSerialNumber, serialNumber);
RtlAnsiStringToUnicodeString(&unicodeString, &ansiSerialNumber, TRUE);
for (i = 0; i < diskExtension->NumberPhysicalPaths; i++) {
deviceDescriptor =
&diskExtension->DeviceDescriptors[i];
deviceInfo->BusType = 1;
deviceInfo->PortNumber =
deviceDescriptor->ScsiAddress->PortNumber;
deviceInfo->TargetId =
deviceDescriptor->ScsiAddress->TargetId;
deviceInfo->Lun =
deviceDescriptor->ScsiAddress->Lun;
deviceInfo->CorrespondingPathId =
(ULONG)deviceDescriptor->PhysicalPath->PhysicalPathId;
index = (PWCHAR)deviceInfo->VariableData;
*index++ = unicodeString.Length;
RtlCopyMemory(index,
unicodeString.Buffer,
unicodeString.Length);
(ULONG_PTR)deviceInfo +=
sizeof(PHYSICAL_DISK_INFO) + unicodeString.Length;
}
status = STATUS_SUCCESS;
}
break;
}
#ifdef USE_BINARY_MOF_QUERY
case BinaryMofGuid:
{
bytesReturned = sizeof(MPathBinaryMofData);
MPDebugPrint((0,
"MPathQueryDataBlock: BinaryMofGuid\n"));
DbgBreakPoint();
if (BufferAvail < bytesReturned)
{
status = STATUS_BUFFER_TOO_SMALL;
} else {
RtlCopyMemory(Buffer, MPathBinaryMofData, bytesReturned);
status = STATUS_SUCCESS;
}
break;
}
#endif
default:
status = STATUS_WMI_GUID_NOT_FOUND;
break;
}
}
} else {
//
// This is for the DSM
//
status = STATUS_WMI_GUID_NOT_FOUND;
}
MPDebugPrint((0,
"MpathQueryDataBlock: Buffer (%x) BytesReturned (%x). Status (%x)\n",
Buffer,
bytesReturned,
status));
//
// Indicate the data length.
//
*InstanceLengthArray = bytesReturned;
status = WmiCompleteRequest(DeviceObject,
Irp,
status,
bytesReturned,
IO_NO_INCREMENT);
return status;
}
NTSTATUS
MPathSetWmiDataBlock(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN ULONG InstanceIndex,
IN ULONG BufferSize,
IN PUCHAR Buffer
)
{
NTSTATUS status;
ULONG bytesReturned = 0;
if (FALSE) { // (GuidIndex <= MPATH_MAX_GUID_INDEX) {
status = STATUS_WMI_READ_ONLY;
} else {
//
// DSM Guid
// If there is a GUID match, call the dsm. It will have to call
// DsmCompleteWMIRequest to finish the request.
// DONOT complete it here, rather return the status from the DSM routine
// TODO
status = STATUS_WMI_GUID_NOT_FOUND;
}
status = WmiCompleteRequest(DeviceObject,
Irp,
status,
bytesReturned,
IO_NO_INCREMENT);
return status;
}
NTSTATUS
MPathSetWmiDataItem(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN ULONG InstanceIndex,
IN ULONG DataItemId,
IN ULONG BufferSize,
IN PUCHAR Buffer
)
{
NTSTATUS status;
ULONG bytesReturned = 0;
if (TRUE) { // (GuidIndex <= MPATH_MAX_GUID_INDEX) {
status = STATUS_WMI_READ_ONLY;
} else {
//
// DSM Guid
// TODO
status = STATUS_WMI_GUID_NOT_FOUND;
}
status = WmiCompleteRequest(DeviceObject,
Irp,
status,
bytesReturned,
IO_NO_INCREMENT);
return status;
}
NTSTATUS
MPathExecuteWmiMethod(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN ULONG InstanceIndex,
IN ULONG MethodId,
IN ULONG InBuffersize,
IN ULONG OutBufferSize,
IN OUT PUCHAR Buffer
)
{
NTSTATUS status;
ULONG bytesReturned = 0;
if (TRUE) { //(GuidIndex <= MPATH_MAX_GUID_INDEX ) {
switch (GuidIndex) {
//case MPATH_GUID_PATH_MAINTENACE: {
//
// Need to verify the parameters.
// TODO: Need data block that lists adapter
// (path) ids.
//
//status = MPathFailOver(id1, id2);
// status = STATUS_WMI_ITEMID_NOT_FOUND;
// }
// break;
default:
status = STATUS_WMI_ITEMID_NOT_FOUND;
break;
}
} else {
status = STATUS_WMI_ITEMID_NOT_FOUND;
}
status = WmiCompleteRequest(DeviceObject,
Irp,
status,
bytesReturned,
IO_NO_INCREMENT);
return status;
}
NTSTATUS
MPathWmiFunctionControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN ULONG GuidIndex,
IN WMIENABLEDISABLECONTROL Function,
IN BOOLEAN Enable
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PPSEUDO_DISK_EXTENSION diskExtension = &deviceExtension->PseudoDiskExtension;
NTSTATUS status;
//
// Handle the enabling/disabling of the datablocks/events
//
#if 0
if (GuidIndex == MPATH_GUID_FAILOVER_INFO) {
if (Enable) {
diskExtension->WmiEventsEnabled = TRUE;
} else {
diskExtension->WmiEventsEnabled = FALSE;
}
} else {
#endif
status = STATUS_WMI_GUID_NOT_FOUND;
//}
status = WmiCompleteRequest(DeviceObject,
Irp,
status,
0,
IO_NO_INCREMENT);
return status;
}
VOID
MPathSetupWmi(
IN PDEVICE_EXTENSION DeviceExtension
)
{
if (DeviceExtension->Type == DEV_MPATH_CONTROL) {
MPDebugPrint((0,
"MPathSetWmi: Control Object\n"));
DbgBreakPoint();
} else {
PPSEUDO_DISK_EXTENSION diskExtension = &DeviceExtension->PseudoDiskExtension;
diskExtension->WmiInfo.GuidCount = MPathGuidCount;
diskExtension->WmiInfo.GuidList = MPathWmiGuidList;
diskExtension->WmiInfo.QueryWmiRegInfo = MPathQueryWmiRegInfo;
diskExtension->WmiInfo.QueryWmiDataBlock = MPathQueryWmiDataBlock;
diskExtension->WmiInfo.SetWmiDataBlock = MPathSetWmiDataBlock;
diskExtension->WmiInfo.SetWmiDataItem = MPathSetWmiDataItem;
diskExtension->WmiInfo.ExecuteWmiMethod = MPathExecuteWmiMethod;
diskExtension->WmiInfo.WmiFunctionControl = MPathWmiFunctionControl;
}
}
NTSTATUS
MPathWmi(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
PUCHAR wmiBuffer = irpStack->Parameters.WMI.Buffer;
ULONG bufferSize = irpStack->Parameters.WMI.BufferSize;
ULONG savedLength = Irp->IoStatus.Information;
PPSEUDO_DISK_EXTENSION diskExtension;
SYSCTL_IRP_DISPOSITION disposition;
NTSTATUS status;
MPDebugPrint((0,
"MPathWmi: Irp (%x), MJ (%x), MN (%x)",
Irp,
irpStack->MajorFunction,
irpStack->MinorFunction));
diskExtension = &deviceExtension->PseudoDiskExtension;
status = WmiSystemControl(&diskExtension->WmiInfo,
DeviceObject,
Irp,
&disposition);
MPDebugPrint((0,
"Disposition is (%x). Status (%x)\n",
disposition,
status));
switch (disposition) {
case IrpProcessed:
//
// Already processed and the DpWmiXXX routines specified in WmiInfo will
// complete it.
//
break;
case IrpNotCompleted:
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IrpNotWmi:
case IrpForward:
default:
//
// Need to ensure this is the pseudodisk
//
if (deviceExtension->Type == DEV_MPATH_CONTROL) {
MPDebugPrint((0,
" for Control\n"));
//
// Call the 'control' (FDO) handler.
//
return MPathFdoWmi(DeviceObject, Irp);
} else {
//
// This is the PDO, so just complete it without touching anything.
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
break;
}
return status;
}