// // Test.c - Code generated by wmimofck tool // // Finish code by doing all TODO: sections // #include #include #include #include #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); }