1591 lines
53 KiB
C
1591 lines
53 KiB
C
|
//
|
||
|
// Test.c - Code generated by wmimofck tool
|
||
|
//
|
||
|
// Finish code by doing all TODO: sections
|
||
|
//
|
||
|
|
||
|
#include <wdm.h>
|
||
|
#include <wmistr.h>
|
||
|
#include <wmiguid.h>
|
||
|
#include <wmilib.h>
|
||
|
|
||
|
#include "filter.h"
|
||
|
|
||
|
//
|
||
|
// Include data header for classes
|
||
|
#include "hbadata.h"
|
||
|
|
||
|
|
||
|
|
||
|
#define NUMBEROFPORTS 8
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// TODO: Place the contents in this device extension into the driver's
|
||
|
// actual device extension. It is only defined here to supply
|
||
|
// a device extension so that this file can be compiled on its own
|
||
|
//
|
||
|
#ifdef MAKE_THIS_COMPILE
|
||
|
typedef struct DEVICE_EXTENSION
|
||
|
{
|
||
|
WMILIB_CONTEXT WmiLib;
|
||
|
PDEVICE_OBJECT physicalDevObj;
|
||
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||
|
#endif
|
||
|
|
||
|
NTSTATUS
|
||
|
TestFunctionControl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp,
|
||
|
IN ULONG GuidIndex,
|
||
|
IN WMIENABLEDISABLECONTROL Function,
|
||
|
IN BOOLEAN Enable
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
TestExecuteWmiMethod(
|
||
|
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
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
TestSetWmiDataBlock(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp,
|
||
|
IN ULONG GuidIndex,
|
||
|
IN ULONG InstanceIndex,
|
||
|
IN ULONG BufferSize,
|
||
|
IN PUCHAR Buffer
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
TestQueryWmiDataBlock(
|
||
|
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
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
TestQueryWmiRegInfo(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
OUT ULONG *RegFlags,
|
||
|
OUT PUNICODE_STRING InstanceName,
|
||
|
OUT PUNICODE_STRING *RegistryPath,
|
||
|
OUT PUNICODE_STRING MofResourceName,
|
||
|
OUT PDEVICE_OBJECT *Pdo
|
||
|
);
|
||
|
|
||
|
#ifdef ALLOC_PRAGMA
|
||
|
#pragma alloc_text(PAGE,TestQueryWmiRegInfo)
|
||
|
#pragma alloc_text(PAGE,TestQueryWmiDataBlock)
|
||
|
#pragma alloc_text(PAGE,TestSetWmiDataBlock)
|
||
|
#pragma alloc_text(PAGE,TestExecuteWmiMethod)
|
||
|
#pragma alloc_text(PAGE,TestFunctionControl)
|
||
|
#pragma alloc_text(PAGE,TestInitializeWmilibContext)
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// TODO: Decide if your MOF is going to be part of your driver as a resource
|
||
|
// attached to it. If this is done then all MOF in the resource will be
|
||
|
// added to the schema. If this is the case be sure that
|
||
|
// USE_BINARY_MOF_RESOURCE is defined. MOF can also be reported at
|
||
|
// runtime via a query to the driver. This can be useful if you want
|
||
|
// the MOF reported to the schema to be dynamic. If MOF is reported via
|
||
|
// a query then USE_BINARY_MOF_QUERY should be defined.
|
||
|
|
||
|
#define USE_BINARY_MOF_RESOURCE
|
||
|
|
||
|
#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
|
||
|
|
||
|
UCHAR TestBinaryMofData[] =
|
||
|
{
|
||
|
#include "test.x"
|
||
|
};
|
||
|
#ifdef ALLOC_DATA_PRAGMA
|
||
|
#pragma data_seg()
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Define symbolic names for the guid indexes
|
||
|
#define MSFC_FibrePortHBAStatisticsGuidIndex 0
|
||
|
#define MSFC_FibrePortHBAAttributesGuidIndex 1
|
||
|
#define MSFC_FibrePortHBAMethodsGuidIndex 2
|
||
|
#define MSFC_FCAdapterHBAAttributesGuidIndex 3
|
||
|
#define MSFC_HBAFC3MgmtInfoGuidIndex 4
|
||
|
#define MSFC_HBAPortMethodsGuidIndex 5
|
||
|
#define MSFC_HBAFc3MgmtMethodsGuidIndex 6
|
||
|
#define MSFC_HBAFCPInfoGuidIndex 7
|
||
|
#ifdef USE_BINARY_MOF_QUERY
|
||
|
#define BinaryMofGuidIndex 8
|
||
|
#endif
|
||
|
//
|
||
|
// List of guids supported
|
||
|
|
||
|
GUID MSFC_FibrePortHBAStatisticsGUID = MSFC_FibrePortHBAStatisticsGuid;
|
||
|
GUID MSFC_FibrePortHBAAttributesGUID = MSFC_FibrePortHBAAttributesGuid;
|
||
|
GUID MSFC_FibrePortHBAMethodsGUID = MSFC_FibrePortHBAMethodsGuid;
|
||
|
GUID MSFC_FCAdapterHBAAttributesGUID = MSFC_FCAdapterHBAAttributesGuid;
|
||
|
GUID MSFC_HBAFC3MgmtInfoGUID = MSFC_HBAFC3MgmtInfoGuid;
|
||
|
GUID MSFC_HBAPortMethodsGUID = MSFC_HBAPortMethodsGuid;
|
||
|
GUID MSFC_HBAFc3MgmtMethodsGUID = MSFC_HBAFc3MgmtMethodsGuid;
|
||
|
GUID MSFC_HBAFCPInfoGUID = MSFC_HBAFCPInfoGuid;
|
||
|
#ifdef USE_BINARY_MOF_QUERY
|
||
|
GUID TestBinaryMofGUID = BINARY_MOF_GUID;
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// TODO: Make sure the instance count and flags are set properly for each
|
||
|
// guid
|
||
|
WMIGUIDREGINFO TestGuidList[] =
|
||
|
{
|
||
|
{
|
||
|
&MSFC_FibrePortHBAStatisticsGUID, // Guid
|
||
|
NUMBEROFPORTS, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_FibrePortHBAAttributesGUID, // Guid
|
||
|
NUMBEROFPORTS, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_FibrePortHBAMethodsGUID, // Guid
|
||
|
NUMBEROFPORTS, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_FCAdapterHBAAttributesGUID, // Guid
|
||
|
1, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_HBAFC3MgmtInfoGUID, // Guid
|
||
|
1, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_HBAPortMethodsGUID, // Guid
|
||
|
1, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_HBAFc3MgmtMethodsGUID, // Guid
|
||
|
1, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
{
|
||
|
&MSFC_HBAFCPInfoGUID, // Guid
|
||
|
1, // # of instances in each device
|
||
|
0 // Flags
|
||
|
},
|
||
|
#ifdef USE_BINARY_MOF_QUERY
|
||
|
{
|
||
|
&TestBinaryMofGUID,
|
||
|
1,
|
||
|
0
|
||
|
}
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
#define TestGuidCount (sizeof(TestGuidList) / sizeof(WMIGUIDREGINFO))
|
||
|
|
||
|
//
|
||
|
// We need to hang onto the registry path passed to our driver entry so that
|
||
|
// we can return it in the QueryWmiRegInfo callback. Be sure to store a copy
|
||
|
// of it into TestRegistryPath in the DriverEntry routine
|
||
|
//
|
||
|
extern UNICODE_STRING FilterRegistryPath;
|
||
|
|
||
|
NTSTATUS TestSystemControl(
|
||
|
PDEVICE_OBJECT DeviceObject,
|
||
|
PIRP Irp
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Dispatch routine for System Control IRPs (MajorFunction == IRP_MJ_SYSTEM_CONTROL)
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject
|
||
|
Irp
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NT status code
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PWMILIB_CONTEXT wmilibContext;
|
||
|
NTSTATUS status;
|
||
|
SYSCTL_IRP_DISPOSITION disposition;
|
||
|
PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
|
||
|
|
||
|
//
|
||
|
// TODO: Point at the WMILIB context within the device extension
|
||
|
wmilibContext = &devExt->WmiLib;
|
||
|
|
||
|
//
|
||
|
// Call Wmilib helper function to crack the irp. If this is a wmi irp
|
||
|
// that is targetted for this device then WmiSystemControl will callback
|
||
|
// at the appropriate callback routine.
|
||
|
//
|
||
|
status = WmiSystemControl(wmilibContext,
|
||
|
DeviceObject,
|
||
|
Irp,
|
||
|
&disposition);
|
||
|
|
||
|
switch(disposition)
|
||
|
{
|
||
|
case IrpProcessed:
|
||
|
{
|
||
|
//
|
||
|
// This irp has been processed and may be completed or pending.
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IrpNotCompleted:
|
||
|
{
|
||
|
//
|
||
|
// This irp has not been completed, but has been fully processed.
|
||
|
// we will complete it now.
|
||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case IrpForward:
|
||
|
case IrpNotWmi:
|
||
|
default:
|
||
|
{
|
||
|
//
|
||
|
// This irp is either not a WMI irp or is a WMI irp targetted
|
||
|
// at a device lower in the stack.
|
||
|
|
||
|
// TODO: Forward IRP down the device stack to the next device
|
||
|
// Or if this is a PDO then just complete the irp without
|
||
|
// touching it.
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return(status);
|
||
|
}
|
||
|
NTSTATUS
|
||
|
TestQueryWmiRegInfo(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
OUT ULONG *RegFlags,
|
||
|
OUT PUNICODE_STRING InstanceName,
|
||
|
OUT PUNICODE_STRING *RegistryPath,
|
||
|
OUT PUNICODE_STRING MofResourceName,
|
||
|
OUT PDEVICE_OBJECT *Pdo
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is a callback into the driver to retrieve the list of
|
||
|
guids or data blocks that the driver wants to register with WMI. This
|
||
|
routine may not pend or block. Driver should NOT call
|
||
|
WmiCompleteRequest.
|
||
|
|
||
|
gArguments:
|
||
|
|
||
|
DeviceObject is the device whose registration info is being queried
|
||
|
|
||
|
*RegFlags returns with a set of flags that describe the guids being
|
||
|
registered for this device. If the device wants enable and disable
|
||
|
collection callbacks before receiving queries for the registered
|
||
|
guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
|
||
|
returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
|
||
|
the instance name is determined from the PDO associated with the
|
||
|
device object. Note that the PDO must have an associated devnode. If
|
||
|
WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
|
||
|
name for the device.
|
||
|
|
||
|
InstanceName returns with the instance name for the guids if
|
||
|
WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
|
||
|
caller will call ExFreePool with the buffer returned.
|
||
|
|
||
|
*RegistryPath returns with the registry path of the driver. The caller
|
||
|
does NOT free this buffer.
|
||
|
|
||
|
*MofResourceName returns with the name of the MOF resource attached to
|
||
|
the binary file. If the driver does not have a mof resource attached
|
||
|
then this can be returned as NULL. The caller does NOT free this
|
||
|
buffer.
|
||
|
|
||
|
*Pdo returns with the device object for the PDO associated with this
|
||
|
device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
|
||
|
*RegFlags.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
status
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
struct DEVICE_EXTENSION * devExt = DeviceObject->DeviceExtension;
|
||
|
|
||
|
//
|
||
|
// Return the registry path for this driver. This is required so WMI
|
||
|
// can find your driver image and can attribute any eventlog messages to
|
||
|
// your driver.
|
||
|
*RegistryPath = &FilterRegistryPath;
|
||
|
|
||
|
#ifndef USE_BINARY_MOF_RESOURCE
|
||
|
//
|
||
|
// 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
|
||
|
|
||
|
*RegFlags = WMIREG_FLAG_INSTANCE_PDO;
|
||
|
*Pdo = devExt->physicalDevObj;
|
||
|
|
||
|
return(STATUS_SUCCESS);
|
||
|
}
|
||
|
|
||
|
#define CopyString(field, string, length) \
|
||
|
{ \
|
||
|
PWCHAR p = field; \
|
||
|
*p++ = length*sizeof(WCHAR); \
|
||
|
wcsncpy(p, string, length); \
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
TestQueryWmiDataBlock(
|
||
|
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
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is a callback into the driver to query for the contents of
|
||
|
all instances of a data block. If the driver can satisfy the query within
|
||
|
the callback it should call WmiCompleteRequest to complete the irp before
|
||
|
returning to the caller. Or the driver can return STATUS_PENDING if the
|
||
|
irp cannot be completed immediately and must then call WmiCompleteRequest
|
||
|
once the query is satisfied.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject is the device whose data block is being queried
|
||
|
|
||
|
Irp is the Irp that makes this request
|
||
|
|
||
|
GuidIndex is the index into the list of guids provided when the
|
||
|
device registered
|
||
|
|
||
|
InstanceCount is the number of instnaces expected to be returned for
|
||
|
the data block.
|
||
|
|
||
|
InstanceLengthArray is a pointer to an array of ULONG that returns the
|
||
|
lengths of each instance of the data block. If this is NULL then
|
||
|
there was not enough space in the output buffer to fufill the request
|
||
|
so the irp should be completed with the buffer needed.
|
||
|
|
||
|
BufferAvail on entry has the maximum size available to write the data
|
||
|
blocks.
|
||
|
|
||
|
Buffer on return is filled with the returned data blocks. Note that each
|
||
|
instance of the data block must be aligned on a 8 byte boundry.
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
status
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
||
|
struct DEVICE_EXTENSION * devExt = DeviceObject->DeviceExtension;
|
||
|
ULONG SizeNeeded;
|
||
|
ULONG i, LastIndex, InstanceSize;
|
||
|
|
||
|
switch(GuidIndex)
|
||
|
{
|
||
|
case MSFC_FibrePortHBAStatisticsGuidIndex:
|
||
|
{
|
||
|
PMSFC_FibrePortHBAStatistics PortStats;
|
||
|
|
||
|
//
|
||
|
// First thing to do is verify if there is enough room in
|
||
|
// the output buffer to return all data requested
|
||
|
//
|
||
|
InstanceSize = (sizeof(MSFC_FibrePortHBAStatistics)+7)&~7;
|
||
|
SizeNeeded = InstanceCount * InstanceSize;
|
||
|
|
||
|
if (BufferAvail >= SizeNeeded)
|
||
|
{
|
||
|
//
|
||
|
// Yes, loop over all instances for the data block and
|
||
|
// fill in the values for them
|
||
|
//
|
||
|
LastIndex = InstanceIndex + InstanceCount;
|
||
|
for (i = InstanceIndex; i < LastIndex; i++)
|
||
|
{
|
||
|
PortStats = (PMSFC_FibrePortHBAStatistics)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: Initialize values in PortStats for the port
|
||
|
//
|
||
|
memset(Buffer, (CHAR)i, InstanceSize);
|
||
|
|
||
|
//
|
||
|
// Establish a unique value for the port
|
||
|
//
|
||
|
PortStats->UniquePortId = ((ULONGLONG)DeviceObject) + i;
|
||
|
|
||
|
Buffer += InstanceSize;
|
||
|
*InstanceLengthArray++ = sizeof(MSFC_FibrePortHBAStatistics);
|
||
|
}
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_FibrePortHBAAttributesGuidIndex:
|
||
|
{
|
||
|
PMSFC_FibrePortHBAAttributes PortAttributes;
|
||
|
|
||
|
//
|
||
|
// First thing to do is verify if there is enough room in
|
||
|
// the output buffer to return all data requested
|
||
|
//
|
||
|
InstanceSize = (sizeof(MSFC_FibrePortHBAAttributes)+7)&~7;
|
||
|
SizeNeeded = InstanceCount * InstanceSize;
|
||
|
|
||
|
if (BufferAvail >= SizeNeeded)
|
||
|
{
|
||
|
//
|
||
|
// Yes, loop over all instances for the data block and
|
||
|
// fill in the values for them
|
||
|
//
|
||
|
LastIndex = InstanceIndex + InstanceCount;
|
||
|
for (i = InstanceIndex; i < LastIndex; i++)
|
||
|
{
|
||
|
PortAttributes = (PMSFC_FibrePortHBAAttributes)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: initialize port attribute values properly
|
||
|
//
|
||
|
memset(Buffer, (CHAR)i, InstanceSize);
|
||
|
|
||
|
#define PORTNAME L"FibrePortName"
|
||
|
CopyString(PortAttributes->Attributes.PortSymbolicName,
|
||
|
PORTNAME,
|
||
|
256);
|
||
|
|
||
|
#define OSDEVICENAME L"OsDeviceName"
|
||
|
CopyString(PortAttributes->Attributes.OSDeviceName,
|
||
|
OSDEVICENAME,
|
||
|
256);
|
||
|
|
||
|
//
|
||
|
// Establish a unique value for the port
|
||
|
//
|
||
|
PortAttributes->UniquePortId = ((ULONGLONG)DeviceObject) + i;
|
||
|
|
||
|
Buffer += InstanceSize;
|
||
|
*InstanceLengthArray++ = sizeof(MSFC_FibrePortHBAAttributes);
|
||
|
}
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_FCAdapterHBAAttributesGuidIndex:
|
||
|
{
|
||
|
PMSFC_FCAdapterHBAAttributes AdapterAttributes;
|
||
|
|
||
|
//
|
||
|
// First thing to do is verify if there is enough room in
|
||
|
// the output buffer to return all data requested
|
||
|
//
|
||
|
SizeNeeded = (sizeof(MSFC_FCAdapterHBAAttributes));
|
||
|
|
||
|
if (BufferAvail >= SizeNeeded)
|
||
|
{
|
||
|
//
|
||
|
// We know there is always only 1 instance for this
|
||
|
// guid
|
||
|
//
|
||
|
AdapterAttributes = (PMSFC_FCAdapterHBAAttributes)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: initialize adapter attribute values properly
|
||
|
//
|
||
|
memset(Buffer, (CHAR)7, SizeNeeded);
|
||
|
AdapterAttributes->NumberOfPorts = 8;
|
||
|
|
||
|
#define MANUFACTURER L"FibreAdapter Manufacturer"
|
||
|
CopyString(AdapterAttributes->Manufacturer,
|
||
|
MANUFACTURER,
|
||
|
64);
|
||
|
|
||
|
#define SERIALNUMBER L"FibreAdapter SerialNumber"
|
||
|
CopyString(AdapterAttributes->SerialNumber,
|
||
|
SERIALNUMBER,
|
||
|
64);
|
||
|
|
||
|
#define MODEL L"FibreAdapter Model"
|
||
|
CopyString(AdapterAttributes->Model,
|
||
|
MODEL,
|
||
|
256);
|
||
|
|
||
|
#define MODELDESCRIPTION L"FibreAdapter ModelDescription"
|
||
|
CopyString(AdapterAttributes->ModelDescription,
|
||
|
MODELDESCRIPTION,
|
||
|
256);
|
||
|
|
||
|
#define NODESYMBOLICNAME L"FibreAdapter NodeSymbolicName"
|
||
|
CopyString(AdapterAttributes->NodeSymbolicName,
|
||
|
NODESYMBOLICNAME,
|
||
|
256);
|
||
|
|
||
|
#define HARDWAREVERSION L"FibreAdapter HardwareVersion"
|
||
|
CopyString(AdapterAttributes->HardwareVersion,
|
||
|
HARDWAREVERSION,
|
||
|
256);
|
||
|
|
||
|
#define DRIVERVERSION L"FibreAdapter DriverVersion"
|
||
|
CopyString(AdapterAttributes->DriverVersion,
|
||
|
DRIVERVERSION,
|
||
|
256);
|
||
|
|
||
|
#define OPTIONROMVERSION L"FibreAdapter OptionROMVersion"
|
||
|
CopyString(AdapterAttributes->OptionROMVersion,
|
||
|
OPTIONROMVERSION,
|
||
|
256);
|
||
|
|
||
|
#define FIRMWAREVERSION L"FibreAdapter FirmwareVersion"
|
||
|
CopyString(AdapterAttributes->FirmwareVersion,
|
||
|
FIRMWAREVERSION,
|
||
|
256);
|
||
|
|
||
|
#define DRIVERNAME L"FibreAdapter DriverName"
|
||
|
CopyString(AdapterAttributes->DriverName,
|
||
|
DRIVERNAME,
|
||
|
256);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Establish a unique value for the Adapter
|
||
|
//
|
||
|
AdapterAttributes->UniqueAdapterId = ((ULONGLONG)DeviceObject);
|
||
|
|
||
|
*InstanceLengthArray = sizeof(MSFC_FCAdapterHBAAttributes);
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFC3MgmtInfoGuidIndex:
|
||
|
{
|
||
|
PMSFC_HBAFC3MgmtInfo Fc3MgmtInfo;
|
||
|
|
||
|
//
|
||
|
// First thing to do is verify if there is enough room in
|
||
|
// the output buffer to return all data requested
|
||
|
//
|
||
|
SizeNeeded = sizeof(MSFC_HBAFC3MgmtInfo);
|
||
|
|
||
|
if (BufferAvail >= SizeNeeded)
|
||
|
{
|
||
|
//
|
||
|
// We know there is always only 1 instance for this
|
||
|
// guid
|
||
|
//
|
||
|
Fc3MgmtInfo = (PMSFC_HBAFC3MgmtInfo)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: initialize adapter fc3 values properly
|
||
|
//
|
||
|
memset(Buffer, (CHAR)4, SizeNeeded);
|
||
|
|
||
|
*InstanceLengthArray = sizeof(MSFC_HBAFC3MgmtInfo);
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFCPInfoGuidIndex:
|
||
|
case MSFC_HBAFc3MgmtMethodsGuidIndex:
|
||
|
case MSFC_FibrePortHBAMethodsGuidIndex:
|
||
|
case MSFC_HBAPortMethodsGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// Methods don't return data per se, but must respond to
|
||
|
// queries with an empty data block. We know that all of
|
||
|
// these method guids only have one instance
|
||
|
//
|
||
|
SizeNeeded = sizeof(ULONG);
|
||
|
|
||
|
if (BufferAvail >= SizeNeeded)
|
||
|
{
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef USE_BINARY_MOF_QUERY
|
||
|
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
|
||
|
//
|
||
|
SizeNeeded = sizeof(TestBinaryMofData);
|
||
|
|
||
|
if (BufferAvail < SizeNeeded)
|
||
|
{
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
} else {
|
||
|
RtlCopyMemory(Buffer, TestBinaryMofData, SizeNeeded);
|
||
|
*InstanceLengthArray = SizeNeeded;
|
||
|
status = STATUS_SUCCESS;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Complete the irp. If there was not enough room in the output buffer
|
||
|
// then status is STATUS_BUFFER_TOO_SMALL and sizeNeeded has the size
|
||
|
// needed to return all of the data. If there was enough room then
|
||
|
// status is STATUS_SUCCESS and sizeNeeded is the actual number of bytes
|
||
|
// being returned.
|
||
|
status = WmiCompleteRequest(
|
||
|
DeviceObject,
|
||
|
Irp,
|
||
|
status,
|
||
|
SizeNeeded,
|
||
|
IO_NO_INCREMENT);
|
||
|
|
||
|
return(status);
|
||
|
}
|
||
|
NTSTATUS
|
||
|
TestExecuteWmiMethod(
|
||
|
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:
|
||
|
|
||
|
This routine is a callback into the driver to execute a method. If
|
||
|
the driver can complete the method within the callback it should
|
||
|
call WmiCompleteRequest to complete the irp before returning to the
|
||
|
caller. Or the driver can return STATUS_PENDING if the irp cannot be
|
||
|
completed immediately and must then call WmiCompleteRequest once the
|
||
|
data is changed.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject is the device whose method is being executed
|
||
|
|
||
|
Irp is the Irp that makes this request
|
||
|
|
||
|
GuidIndex is the index into the list of guids provided when the
|
||
|
device registered
|
||
|
|
||
|
MethodId has the id of the method being called
|
||
|
|
||
|
InBufferSize has the size of the data block passed in as the input to
|
||
|
the method.
|
||
|
|
||
|
OutBufferSize on entry has the maximum size available to write the
|
||
|
returned data block.
|
||
|
|
||
|
Buffer is filled with the input buffer on entry and returns with
|
||
|
the output data block
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
status
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG sizeNeeded = 0;
|
||
|
NTSTATUS status;
|
||
|
ULONG i;
|
||
|
|
||
|
switch(GuidIndex)
|
||
|
{
|
||
|
case MSFC_FibrePortHBAMethodsGuidIndex:
|
||
|
{
|
||
|
switch(MethodId)
|
||
|
{
|
||
|
//
|
||
|
// void ResetStatistics();
|
||
|
//
|
||
|
case ResetStatistics:
|
||
|
{
|
||
|
//
|
||
|
// No input or output buffers expected so no
|
||
|
// validation needed. InstanceIndex has the Port
|
||
|
// Index
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// TODO: Do what is needed to reset port
|
||
|
// statistics. The index to the port is the
|
||
|
// InstanceIndex parameter
|
||
|
//
|
||
|
sizeNeeded = 0;
|
||
|
status = STATUS_SUCCESS;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_ITEMID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAPortMethodsGuidIndex:
|
||
|
{
|
||
|
switch(MethodId)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// void GetDiscoveredPortAttributes(
|
||
|
// [in
|
||
|
// ] uint32 PortIndex,
|
||
|
//
|
||
|
// [in] uint32 DiscoveredPortIndex,
|
||
|
//
|
||
|
// [out,
|
||
|
// HBAType("HBA_PORTATTRIBUTES")
|
||
|
// ] MSFC_HBAPortAttributesResults PortAttributes);
|
||
|
//
|
||
|
case GetDiscoveredPortAttributes:
|
||
|
{
|
||
|
//
|
||
|
// Validate that the input buffer is the correct
|
||
|
// size and the output buffer is large enough
|
||
|
//
|
||
|
if (InBufferSize >= sizeof(GetDiscoveredPortAttributes_IN))
|
||
|
{
|
||
|
sizeNeeded = sizeof(GetDiscoveredPortAttributes_OUT);
|
||
|
if (OutBufferSize >= sizeNeeded)
|
||
|
{
|
||
|
PGetDiscoveredPortAttributes_IN In;
|
||
|
PGetDiscoveredPortAttributes_OUT Out;
|
||
|
|
||
|
In = (PGetDiscoveredPortAttributes_IN)Buffer;
|
||
|
Out = (PGetDiscoveredPortAttributes_OUT)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: Examine In->PortIndex and
|
||
|
// In->DiscoveredPortIndex and
|
||
|
// validate that they are correct.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// TODO: Fill Out->PortAttributes with
|
||
|
// correct values.
|
||
|
//
|
||
|
memset(&Out->PortAttributes,
|
||
|
3,
|
||
|
sizeof(MSFC_HBAPortAttributesResults));
|
||
|
|
||
|
CopyString(Out->PortAttributes.PortSymbolicName,
|
||
|
PORTNAME,
|
||
|
256);
|
||
|
|
||
|
CopyString(Out->PortAttributes.OSDeviceName,
|
||
|
OSDEVICENAME,
|
||
|
256);
|
||
|
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
} else {
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case GetPortAttributesByWWN:
|
||
|
{
|
||
|
//
|
||
|
// Validate that the input buffer is the correct
|
||
|
// size and the output buffer is large enough
|
||
|
//
|
||
|
if (InBufferSize >= sizeof(GetPortAttributesByWWN_IN))
|
||
|
{
|
||
|
sizeNeeded = sizeof(GetPortAttributesByWWN_OUT);
|
||
|
if (OutBufferSize >= sizeNeeded)
|
||
|
{
|
||
|
PGetPortAttributesByWWN_IN In;
|
||
|
PGetPortAttributesByWWN_OUT Out;
|
||
|
|
||
|
In = (PGetPortAttributesByWWN_IN)Buffer;
|
||
|
Out = (PGetPortAttributesByWWN_OUT)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: Examine In->wwn to // In->DiscoveredPortIndex and
|
||
|
// validate that it is correct.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// TODO: Fill Out->PortAttributes with
|
||
|
// correct values.
|
||
|
//
|
||
|
memset(&Out->PortAttributes,
|
||
|
3,
|
||
|
sizeof(MSFC_HBAPortAttributesResults));
|
||
|
|
||
|
CopyString(Out->PortAttributes.PortSymbolicName,
|
||
|
PORTNAME,
|
||
|
256);
|
||
|
|
||
|
CopyString(Out->PortAttributes.OSDeviceName,
|
||
|
OSDEVICENAME,
|
||
|
256);
|
||
|
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
} else {
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_ITEMID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFc3MgmtMethodsGuidIndex:
|
||
|
{
|
||
|
switch(MethodId)
|
||
|
{
|
||
|
case SendCTPassThru:
|
||
|
{
|
||
|
PSendCTPassThru_IN In;
|
||
|
PSendCTPassThru_OUT Out;
|
||
|
ULONG RequestCount, ResponseCount;
|
||
|
ULONG InSizeNeeded;
|
||
|
|
||
|
//
|
||
|
// Validate that the input buffer is the correct
|
||
|
// size and the output buffer is large enough
|
||
|
//
|
||
|
if (InBufferSize >= sizeof(ULONG))
|
||
|
{
|
||
|
In = (PSendCTPassThru_IN)Buffer;
|
||
|
|
||
|
RequestCount = In->RequestBufferCount;
|
||
|
InSizeNeeded = sizeof(SendCTPassThru_IN) - 1 + RequestCount;
|
||
|
if (InBufferSize >= InSizeNeeded)
|
||
|
{
|
||
|
#define RESPONSE_BUFFER_SIZE 0x1000
|
||
|
ResponseCount = RESPONSE_BUFFER_SIZE;
|
||
|
sizeNeeded = sizeof(SendCTPassThru_OUT) - 1 + ResponseCount;
|
||
|
|
||
|
if (OutBufferSize >= sizeNeeded)
|
||
|
{
|
||
|
Out = (PSendCTPassThru_OUT)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: Do the CT Pass thru
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// TODO: Fill the output buffer with
|
||
|
// results
|
||
|
//
|
||
|
Out->ResponseBufferCount = ResponseCount;
|
||
|
memset(Out->ResponseBuffer,
|
||
|
7,
|
||
|
ResponseCount);
|
||
|
|
||
|
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
} else {
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
} else {
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case SendRNID:
|
||
|
{
|
||
|
PSendRNID_IN In;
|
||
|
PSendRNID_OUT Out;
|
||
|
ULONG ResponseCount;
|
||
|
ULONG InSizeNeeded;
|
||
|
|
||
|
//
|
||
|
// Validate that the input buffer is the correct
|
||
|
// size and the output buffer is large enough
|
||
|
//
|
||
|
if (InBufferSize >= sizeof(SendRNID_IN))
|
||
|
{
|
||
|
|
||
|
ResponseCount = RESPONSE_BUFFER_SIZE;
|
||
|
sizeNeeded = sizeof(SendRNID_OUT) - 1 + ResponseCount;
|
||
|
|
||
|
if (OutBufferSize >= sizeNeeded)
|
||
|
{
|
||
|
In = (PSendRNID_IN)Buffer;
|
||
|
Out = (PSendRNID_OUT)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: Do the SendRNID
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// TODO: Fill the output buffer with
|
||
|
// results
|
||
|
//
|
||
|
Out->ResponseBufferCount = ResponseCount;
|
||
|
memset(Out->ResponseBuffer,
|
||
|
7,
|
||
|
ResponseCount);
|
||
|
|
||
|
|
||
|
status = STATUS_SUCCESS;
|
||
|
} else {
|
||
|
status = STATUS_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
} else {
|
||
|
status = STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_ITEMID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFCPInfoGuidIndex:
|
||
|
{
|
||
|
switch(MethodId)
|
||
|
{
|
||
|
case GetFcpTargetMapping:
|
||
|
{
|
||
|
PGetFcpTargetMapping_OUT Out;
|
||
|
|
||
|
//
|
||
|
// TODO: Change this code to return the correct
|
||
|
// number of mappings and the correct
|
||
|
// mappings
|
||
|
//
|
||
|
#define FCPTargetMappingCount 0x20
|
||
|
sizeNeeded = sizeof(GetFcpTargetMapping_OUT) -
|
||
|
sizeof(HBAFCPScsiEntry) +
|
||
|
FCPTargetMappingCount * sizeof(HBAFCPScsiEntry);
|
||
|
if (OutBufferSize > sizeNeeded)
|
||
|
{
|
||
|
Out = (PGetFcpTargetMapping_OUT)Buffer;
|
||
|
Out->EntryCount = FCPTargetMappingCount;
|
||
|
for (i = 0; i < FCPTargetMappingCount; i++)
|
||
|
{
|
||
|
memset(&Out->Entry[i],
|
||
|
3,
|
||
|
sizeof(HBAFCPScsiEntry));
|
||
|
|
||
|
CopyString(Out->Entry[i].ScsiId.OSDeviceName,
|
||
|
OSDEVICENAME,
|
||
|
256);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case GetFcpPersistentBinding:
|
||
|
{
|
||
|
PGetFcpPersistentBinding_OUT Out;
|
||
|
|
||
|
//
|
||
|
// TODO: Change this code to return the correct
|
||
|
// number of mappings and the correct
|
||
|
// mappings
|
||
|
//
|
||
|
#define FCPPersistentBindingCount 0x20
|
||
|
sizeNeeded = sizeof(GetFcpPersistentBinding_OUT) -
|
||
|
sizeof(HBAFCPBindingEntry) +
|
||
|
FCPPersistentBindingCount * sizeof(HBAFCPBindingEntry);
|
||
|
if (OutBufferSize > sizeNeeded)
|
||
|
{
|
||
|
Out = (PGetFcpPersistentBinding_OUT)Buffer;
|
||
|
Out->EntryCount = FCPPersistentBindingCount;
|
||
|
for (i = 0; i < FCPPersistentBindingCount; i++)
|
||
|
{
|
||
|
memset(&Out->Entry[i],
|
||
|
3,
|
||
|
sizeof(HBAFCPBindingEntry));
|
||
|
|
||
|
CopyString(Out->Entry[i].ScsiId.OSDeviceName,
|
||
|
OSDEVICENAME,
|
||
|
256);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_ITEMID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status = WmiCompleteRequest(
|
||
|
DeviceObject,
|
||
|
Irp,
|
||
|
status,
|
||
|
sizeNeeded,
|
||
|
IO_NO_INCREMENT);
|
||
|
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
TestSetWmiDataBlock(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp,
|
||
|
IN ULONG GuidIndex,
|
||
|
IN ULONG InstanceIndex,
|
||
|
IN ULONG BufferSize,
|
||
|
IN PUCHAR Buffer
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is a callback into the driver to change the contents of
|
||
|
a data block. If the driver can change the data block within
|
||
|
the callback it should call WmiCompleteRequest to complete the irp before
|
||
|
returning to the caller. Or the driver can return STATUS_PENDING if the
|
||
|
irp cannot be completed immediately and must then call WmiCompleteRequest
|
||
|
once the data is changed.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject is the device whose data block is being queried
|
||
|
|
||
|
Irp is the Irp that makes this request
|
||
|
|
||
|
GuidIndex is the index into the list of guids provided when the
|
||
|
device registered
|
||
|
|
||
|
BufferSize has the size of the data block passed
|
||
|
|
||
|
Buffer has the new values for the data block
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
status
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ULONG sizeNeeded = 0;
|
||
|
NTSTATUS status;
|
||
|
|
||
|
switch(GuidIndex)
|
||
|
{
|
||
|
case MSFC_HBAFC3MgmtInfoGuidIndex:
|
||
|
{
|
||
|
PMSFC_HBAFC3MgmtInfo FC3MgmtInfo;
|
||
|
|
||
|
if (BufferSize >= sizeof(MSFC_HBAFC3MgmtInfo))
|
||
|
{
|
||
|
FC3MgmtInfo = (PMSFC_HBAFC3MgmtInfo)Buffer;
|
||
|
|
||
|
//
|
||
|
// TODO: Extract informtion from FC3MgmtInfo and
|
||
|
// process it appropriately
|
||
|
//
|
||
|
status = STATUS_SUCCESS;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFCPInfoGuidIndex:
|
||
|
case MSFC_HBAFc3MgmtMethodsGuidIndex:
|
||
|
case MSFC_FibrePortHBAMethodsGuidIndex:
|
||
|
case MSFC_HBAPortMethodsGuidIndex:
|
||
|
case MSFC_FibrePortHBAAttributesGuidIndex:
|
||
|
case MSFC_FCAdapterHBAAttributesGuidIndex:
|
||
|
case MSFC_FibrePortHBAStatisticsGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// These are read only
|
||
|
//
|
||
|
status = STATUS_WMI_READ_ONLY;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status = WmiCompleteRequest(
|
||
|
DeviceObject,
|
||
|
Irp,
|
||
|
status,
|
||
|
0,
|
||
|
IO_NO_INCREMENT);
|
||
|
|
||
|
return(status);
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
TestFunctionControl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp,
|
||
|
IN ULONG GuidIndex,
|
||
|
IN WMIENABLEDISABLECONTROL Function,
|
||
|
IN BOOLEAN Enable
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is a callback into the driver to enabled or disable event
|
||
|
generation or data block collection. A device should only expect a
|
||
|
single enable when the first event or data consumer enables events or
|
||
|
data collection and a single disable when the last event or data
|
||
|
consumer disables events or data collection. Data blocks will only
|
||
|
receive collection enable/disable if they were registered as requiring
|
||
|
it. If the driver can complete enabling/disabling within the callback it
|
||
|
should call WmiCompleteRequest to complete the irp before returning to
|
||
|
the caller. Or the driver can return STATUS_PENDING if the irp cannot be
|
||
|
completed immediately and must then call WmiCompleteRequest once the
|
||
|
data is changed.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject is the device object
|
||
|
|
||
|
GuidIndex is the index into the list of guids provided when the
|
||
|
device registered
|
||
|
|
||
|
Function specifies which functionality is being enabled or disabled
|
||
|
|
||
|
Enable is TRUE then the function is being enabled else disabled
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
status
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
NTSTATUS status;
|
||
|
|
||
|
switch(GuidIndex)
|
||
|
{
|
||
|
case MSFC_FibrePortHBAStatisticsGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_FibrePortHBAAttributesGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_FibrePortHBAMethodsGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_FCAdapterHBAAttributesGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFC3MgmtInfoGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAPortMethodsGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFc3MgmtMethodsGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MSFC_HBAFCPInfoGuidIndex:
|
||
|
{
|
||
|
//
|
||
|
// TODO: Delete this entire case if data block does not have the
|
||
|
// WMIREG_FLAG_EXPENSIVE flag set
|
||
|
//
|
||
|
if (Enable)
|
||
|
{
|
||
|
//
|
||
|
// TODO: Datablock collection is being enabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// first data consumer opens this data block. If
|
||
|
// anything needs to be done to allow data to be
|
||
|
// collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
} else {
|
||
|
//
|
||
|
// TODO: Datablock collection is being disabled. If this
|
||
|
// data block has been marked as expensive in the
|
||
|
// guid list then this code will be called when the
|
||
|
// last data consumer closes this data block. If
|
||
|
// anything needs to be done to cleanup after data has
|
||
|
// been collected for this data block then it should be
|
||
|
// done here
|
||
|
//
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
default:
|
||
|
{
|
||
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
status = WmiCompleteRequest(
|
||
|
DeviceObject,
|
||
|
Irp,
|
||
|
STATUS_SUCCESS,
|
||
|
0,
|
||
|
IO_NO_INCREMENT);
|
||
|
return(status);
|
||
|
}
|
||
|
NTSTATUS
|
||
|
TestInitializeWmilibContext(
|
||
|
IN PWMILIB_CONTEXT WmilibContext
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine will initialize the wmilib context structure with the
|
||
|
guid list and the pointers to the wmilib callback functions. This routine
|
||
|
should be called before calling IoWmiRegistrationControl to register
|
||
|
your device object.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
WmilibContext is pointer to the wmilib context.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
status
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
RtlZeroMemory(WmilibContext, sizeof(WMILIB_CONTEXT));
|
||
|
|
||
|
WmilibContext->GuidCount = TestGuidCount;
|
||
|
WmilibContext->GuidList = TestGuidList;
|
||
|
|
||
|
WmilibContext->QueryWmiRegInfo = TestQueryWmiRegInfo;
|
||
|
WmilibContext->QueryWmiDataBlock = TestQueryWmiDataBlock;
|
||
|
WmilibContext->ExecuteWmiMethod = TestExecuteWmiMethod;
|
||
|
WmilibContext->WmiFunctionControl = TestFunctionControl;
|
||
|
WmilibContext->SetWmiDataBlock = TestSetWmiDataBlock;
|
||
|
|
||
|
return(STATUS_SUCCESS);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|