diff options
Diffstat (limited to 'simemi/simemifdo.c')
| -rw-r--r-- | simemi/simemifdo.c | 888 |
1 files changed, 888 insertions, 0 deletions
diff --git a/simemi/simemifdo.c b/simemi/simemifdo.c new file mode 100644 index 00000000..87f5698f --- /dev/null +++ b/simemi/simemifdo.c @@ -0,0 +1,888 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + simemifdo.c + +Abstract: + + This module contains the implementation of the routines related to the + simemi virtual bus device. + +--*/ + +#include "simemi.h" +#include <limits.h> +#include <ntintsafe.h> + +NTSTATUS +SimEmiFdoCreateChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request + ); + +NTSTATUS +SimEmiFdoDeleteChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request + ); + +PSIM_EMI_BUS_PDO_DATA +SimEmiFdoFindChildDevice ( + _In_ WDFDEVICE Device, + _In_ ULONG ChildDeviceHandle + ); + +EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_CLEANUP SimEmiPdoIdentificationCleanup; +EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_COMPARE SimEmiPdoIdentificationCompare; +EVT_WDF_CHILD_LIST_IDENTIFICATION_DESCRIPTION_DUPLICATE SimEmiPdoIdentificationDuplicate; + +NTSTATUS +SimEmiFdoQueryChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request, + _Out_ PULONG OutputBufferSizeOut + ); + +NTSTATUS +SimEmiFdoUpdateChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request + ); + +#pragma alloc_text(PAGE, SimEmiFdoControl) +#pragma alloc_text(PAGE, SimEmiFdoCreateChildDevice) +#pragma alloc_text(PAGE, SimEmiFdoDeleteChildDevice) +#pragma alloc_text(PAGE, SimEmiFdoCreateDevice) +#pragma alloc_text(PAGE, SimEmiFdoFindChildDevice) +#pragma alloc_text(PAGE, SimEmiFdoQueryChildDevice) +#pragma alloc_text(PAGE, SimEmiFdoUpdateChildDevice) + +VOID +SimEmiFdoControl ( + _In_ WDFQUEUE Queue, + _In_ WDFREQUEST Request, + _In_ size_t OutputBufferLength, + _In_ size_t InputBufferLength, + _In_ ULONG IoControlCode + ) + +/*++ + +Routine Description: + + This routine handles device control requests for the EMI Bus. + +Arguments: + + Queue - Supplies a reference to the WDF queue that this request originates. + + Request - Supplies a reference to the WDF request that was sent. + + OutputBufferLength - Supplies the length of the output buffer in bytes. + + InputBufferLength - Supplies the length of the input buffer in bytes. + + IoControlCode - Supplies the IOCTL for the request. + +Return Value: + + None. + +--*/ + +{ + + WDFDEVICE Device; + PSIM_EMI_BUS_FDO_DATA FdoData; + ULONG OutputLength; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(InputBufferLength); + + Device = WdfIoQueueGetDevice(Queue); + FdoData = SimEmiGetFdoData(Device); + ExAcquireFastMutex(&FdoData->BusMutex); + OutputLength = 0; + switch (IoControlCode) { + case IOCTL_EMI_BUS_CREATE_DEVICE: + Status = SimEmiFdoCreateChildDevice(Device, Request); + break; + + case IOCTL_EMI_BUS_DELETE_DEVICE: + Status = SimEmiFdoDeleteChildDevice(Device, Request); + break; + + case IOCTL_EMI_BUS_QUERY_DEVICE_INFO: + Status = SimEmiFdoQueryChildDevice(Device, Request, &OutputLength); + break; + + case IOCTL_EMI_BUS_SET_DEVICE_RATE: + Status = SimEmiFdoUpdateChildDevice(Device, Request); + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + WdfRequestCompleteWithInformation(Request, Status, OutputLength); + ExReleaseFastMutex(&FdoData->BusMutex); + return; +} + +NTSTATUS +SimEmiFdoCreateChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request + ) + +/*++ + +Routine Description: + + This routine handles an IOCTL_EMI_BUS_CREATE_DEVICE request. + +Arguments: + + Device - Supplies a reference to the BUS FDO device. + + Request - Supplies a reference to the WDF Request. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + USHORT ChannelCount; + USHORT ChannelIndex; + PSIM_EMI_BUS_CHANNEL_INFO ChannelInfo; + ULONG ChannelInfoSize; + ULONG EntrySize; + SIM_EMI_BUS_PDO_IDENTIFICATION_INFO Identification; + PSIM_EMI_BUS_CREATE_DEVICE_INPUT_BUFFER InputBuffer; + size_t InputBufferLength; + ULONG RemainingBufferSize; + NTSTATUS Status; + + RtlZeroMemory(&Identification, + sizeof(SIM_EMI_BUS_PDO_IDENTIFICATION_INFO)); + + Status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(SIM_EMI_BUS_CREATE_DEVICE_INPUT_BUFFER), + (PVOID*)&InputBuffer, + &InputBufferLength); + + if (!NT_SUCCESS(Status)) { + goto FdoCreateChildDeviceEnd; + } + + ChannelCount = InputBuffer->ChannelCount; + if (InputBuffer->EmiVersion == EMI_VERSION_V1) { + if (ChannelCount != 1) { + Status = STATUS_INVALID_PARAMETER; + goto FdoCreateChildDeviceEnd; + } + + } else if (InputBuffer->EmiVersion == EMI_VERSION_V2) { + if (ChannelCount == 0) { + Status = STATUS_INVALID_PARAMETER; + goto FdoCreateChildDeviceEnd; + } + + } else { + Status = STATUS_INVALID_PARAMETER; + goto FdoCreateChildDeviceEnd; + } + + if (InputBufferLength > ULONG_MAX) { + Status = STATUS_BUFFER_OVERFLOW; + goto FdoCreateChildDeviceEnd; + } + + ChannelInfo = &InputBuffer->ChannelInfo[0]; + ChannelInfoSize = 0; + RemainingBufferSize = (ULONG)InputBufferLength; + RemainingBufferSize -= FIELD_OFFSET(SIM_EMI_BUS_CREATE_DEVICE_INPUT_BUFFER, + ChannelInfo); + + for (ChannelIndex = 0; ChannelIndex < ChannelCount; ++ChannelIndex) { + EntrySize = SIM_EMI_BUS_CHANNEL_INFO_SIZE(ChannelInfo->ChannelNameSize); + if (EntrySize > RemainingBufferSize) { + Status = STATUS_INVALID_PARAMETER; + goto FdoCreateChildDeviceEnd; + } + + RemainingBufferSize -= EntrySize; + ChannelInfoSize += EntrySize; + ChannelInfo = SIM_EMI_BUS_CHANNEL_INFO_NEXT_CHANNEL_INFO(ChannelInfo); + } + + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( + &Identification.Header, + sizeof(SIM_EMI_BUS_PDO_IDENTIFICATION_INFO)); + + //#pragma warning( suppress : 4996 ) + Identification.ChannelInfo = ExAllocatePool2(POOL_FLAG_NON_PAGED, + ChannelInfoSize, + SIM_EMI_TAG); + + if (Identification.ChannelInfo == NULL) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto FdoCreateChildDeviceEnd; + } + + // + // Initialize description and add the device. + // + + Identification.EmiVersion = InputBuffer->EmiVersion; + Identification.ChildDeviceHandle = InputBuffer->ChildDeviceHandle; + Identification.ChannelCount = InputBuffer->ChannelCount; + Identification.ChannelInfoSize = ChannelInfoSize; + RtlCopyMemory(&Identification.ChannelInfo[0], + &InputBuffer->ChannelInfo[0], + ChannelInfoSize); + + Status = WdfChildListAddOrUpdateChildDescriptionAsPresent( + WdfFdoGetDefaultChildList(Device), + &Identification.Header, + NULL); + + if (!NT_SUCCESS(Status)) { + goto FdoCreateChildDeviceEnd; + } + + Status = STATUS_SUCCESS; + +FdoCreateChildDeviceEnd: + if (Identification.ChannelInfo != NULL) { + ExFreePoolWithTag(Identification.ChannelInfo, SIM_EMI_TAG); + } + + return Status; +} + +NTSTATUS +SimEmiFdoDeleteChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request + ) + +/*++ + +Routine Description: + + This routine handles an IOCTL_EMI_BUS_DELETE_DEVICE request. + +Arguments: + + Device - Supplies a reference to the BUS FDO device. + + Request - Supplies a reference to the WDF Request. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + WDFCHILDLIST ChildList; + SIM_EMI_BUS_PDO_IDENTIFICATION_INFO Identification; + PSIM_EMI_BUS_DELETE_DEVICE_INPUT_BUFFER InputBuffer; + NTSTATUS Status; + + ChildList = WdfFdoGetDefaultChildList(Device); + Status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(SIM_EMI_BUS_DELETE_DEVICE_INPUT_BUFFER), + (PVOID*)&InputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + goto FdoDeleteChildDeviceEnd; + } + + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( + &Identification.Header, + sizeof(SIM_EMI_BUS_PDO_IDENTIFICATION_INFO)); + + Identification.ChildDeviceHandle = InputBuffer->ChildDeviceHandle; + Status = WdfChildListUpdateChildDescriptionAsMissing( + ChildList, + &Identification.Header); + + if (Status == STATUS_NO_SUCH_DEVICE) { + Status = STATUS_INVALID_PARAMETER; + } + +FdoDeleteChildDeviceEnd: + return Status; +} + +NTSTATUS +SimEmiFdoCreateDevice ( + _In_ WDFDRIVER Driver, + _In_ PWDFDEVICE_INIT DeviceInit + ) + +/*++ + +Routine Description: + + This routine creates and initializes the bus FDO device. + +Arguments: + + Driver - Supplies a reference to the WDFDRIVER for this device. + + DeviceInit - Supplies a pointer to the WDFDEVICE_INIT instance for this + device. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + WDF_CHILD_LIST_CONFIG ChildListConfig; + WDFDEVICE DeviceHandle; + PSIM_EMI_BUS_FDO_DATA FdoData; + WDF_OBJECT_ATTRIBUTES FdoDeviceAttributes; + WDFQUEUE Queue; + WDF_IO_QUEUE_CONFIG QueueConfig; + NTSTATUS Status; + + DECLARE_CONST_UNICODE_STRING(DeviceName, SIM_EMI_DEVICE_PATH); + DECLARE_CONST_UNICODE_STRING(DeviceAlias, SIM_EMI_DEVICE_ALIAS_PATH); + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + KdPrint(("Initializing SimEmi PDO.\n")); + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&FdoDeviceAttributes, + SIM_EMI_BUS_FDO_DATA); + + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); + WdfDeviceInitSetExclusive(DeviceInit, TRUE); + WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); + + // + // Initialize child list. + // + + WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, + sizeof(SIM_EMI_BUS_PDO_IDENTIFICATION_INFO), + &SimEmiPdoCreateDevice); + + ChildListConfig.EvtChildListIdentificationDescriptionCleanup = + &SimEmiPdoIdentificationCleanup; + + ChildListConfig.EvtChildListIdentificationDescriptionCompare = + &SimEmiPdoIdentificationCompare; + + ChildListConfig.EvtChildListIdentificationDescriptionDuplicate = + &SimEmiPdoIdentificationDuplicate; + + WdfFdoInitSetDefaultChildListConfig(DeviceInit, + &ChildListConfig, + WDF_NO_OBJECT_ATTRIBUTES); + + Status = WdfDeviceInitAssignName(DeviceInit, &DeviceName); + if (!NT_SUCCESS(Status)) { + KdPrint(("WdfDeviceInitAssignName failed with status code 0x%08X.\n", + Status)); + + goto FdoCreateDeviceEnd; + } + + Status = WdfDeviceCreate(&DeviceInit, &FdoDeviceAttributes, &DeviceHandle); + if (!NT_SUCCESS(Status)) { + KdPrint(("WdfDeviceCreate failed with status code 0x%08X.\n", Status)); + goto FdoCreateDeviceEnd; + } + + FdoData = SimEmiGetFdoData(DeviceHandle); + RtlZeroMemory(FdoData, sizeof(SIM_EMI_BUS_FDO_DATA)); + InitializeListHead(&FdoData->ChildDevices); + ExInitializeFastMutex(&FdoData->BusMutex); + + // + // Setup symbolic links for UM. + // + + Status = WdfDeviceCreateSymbolicLink(DeviceHandle, &DeviceAlias); + if (!NT_SUCCESS(Status)) { + KdPrint(("WdfDeviceCreateSymbolicLink failed with status code :0x%08X.\n", + Status)); + + goto FdoCreateDeviceEnd; + } + + + + // + // Initialize IO Queue. + // + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, + WdfIoQueueDispatchSequential); + + QueueConfig.EvtIoDeviceControl = &SimEmiFdoControl; + Status = WdfIoQueueCreate(DeviceHandle, + &QueueConfig, + WDF_NO_OBJECT_ATTRIBUTES, + &Queue); + + if (!NT_SUCCESS(Status)) { + KdPrint(("WdfIoQueueCreate failed with status code 0x%08X.\n", Status)); + goto FdoCreateDeviceEnd; + } + + Status = WdfDeviceCreateDeviceInterface(DeviceHandle, + &GUID_DEVICE_SIM_EMI_BUS, + NULL); + + if (!NT_SUCCESS(Status)) { + KdPrint(("WdfDeviceCreateDeviceInterface failed with status code 0x%08X.\n", + Status)); + + goto FdoCreateDeviceEnd; + } + + Status = STATUS_SUCCESS; + +FdoCreateDeviceEnd: + return Status; +} + +PSIM_EMI_BUS_PDO_DATA +SimEmiFdoFindChildDevice ( + _In_ WDFDEVICE Device, + _In_ ULONG ChildDeviceHandle + ) + +/*++ + +Routine Description: + + This routine locates the PDO data for the child device with the provided + device handle. + +Arguments: + + Device - Supplies a reference to the WDFDEVICE of the bus FDO. + + ChildDeviceHandle - Supplies the device handle of the child device to + locate. + +Return Value: + + Returns a pointer to the PDO data for the child device with the provided + device handle or NULL if no child exists with the provided device handle. + +--*/ + +{ + + PSIM_EMI_BUS_PDO_DATA ChildData; + PLIST_ENTRY ListEntry; + PSIM_EMI_BUS_FDO_DATA FdoData; + + FdoData = SimEmiGetFdoData(Device); + ChildData = NULL; + for (ListEntry = FdoData->ChildDevices.Flink; + ListEntry != &FdoData->ChildDevices; + ListEntry = ListEntry->Flink) { + + ChildData = CONTAINING_RECORD(ListEntry, + SIM_EMI_BUS_PDO_DATA, + Link); + + if (ChildData->ChildDeviceHandle == ChildDeviceHandle) { + break; + } + + ChildData = NULL; + } + + return ChildData; +} + +NTSTATUS +SimEmiFdoQueryChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request, + _Out_ PULONG OutputBufferSizeOut + ) + +/*++ + +Routine Description: + + This routine handles an IOCTL_EMI_BUS_QUERY_DEVICE_INFO request. + +Arguments: + + Device - Supplies a reference to the BUS FDO device. + + Request - Supplies a reference to the WDF Request. + + OutputBufferSizeOut - Supplies a pointer in which to place the size of the + output data written. + +Return Value: + + NTSTATUS. + +--*/ +{ + + USHORT ChannelCount; + PSIM_EMI_CHANNEL_DATA ChannelData; + PSIM_EMI_BUS_CHANNEL_INFO ChannelInfo; + PSIM_EMI_BUS_PDO_DATA ChildData; + ULONG EntrySize; + PSIM_EMI_BUS_QUERY_DEVICE_INFO_INPUT_BUFFER InputBuffer; + PSIM_EMI_BUS_QUERY_DEVICE_INFO_OUTPUT_BUFFER OutputBuffer; + ULONG OutputBufferSize; + NTSTATUS Status; + + Status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(SIM_EMI_BUS_QUERY_DEVICE_INFO_INPUT_BUFFER), + (PVOID*)&InputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + goto FdoQueryChildDeviceEnd; + } + + ChildData = SimEmiFdoFindChildDevice(Device, + InputBuffer->ChildDeviceHandle); + + if (ChildData == NULL) { + Status = STATUS_NOT_FOUND; + goto FdoQueryChildDeviceEnd; + } + + OutputBufferSize = FIELD_OFFSET(SIM_EMI_BUS_QUERY_DEVICE_INFO_OUTPUT_BUFFER, + ChannelInfo); + + ChannelCount = ChildData->ChannelCount; + ChannelData = &ChildData->ChannelData[0]; + while (ChannelCount != 0) { + EntrySize = + SIM_EMI_BUS_CHANNEL_INFO_SIZE(ChannelData->Info.ChannelNameSize); + + Status = RtlULongAdd(OutputBufferSize, EntrySize, &OutputBufferSize); + if (!NT_SUCCESS(Status)) { + goto FdoQueryChildDeviceEnd; + } + + ChannelData = SIM_EMI_CHANNEL_DATA_NEXT_CHANNEL_DATA(ChannelData); + ChannelCount -= 1; + } + + *OutputBufferSizeOut = OutputBufferSize; + Status = WdfRequestRetrieveOutputBuffer(Request, + OutputBufferSize, + (PVOID*)&OutputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + goto FdoQueryChildDeviceEnd; + } + + OutputBuffer->EmiVersion = ChildData->EmiVersion; + OutputBuffer->ChannelCount = ChildData->ChannelCount; + ChannelCount = ChildData->ChannelCount; + ChannelData = &ChildData->ChannelData[0]; + ChannelInfo = &OutputBuffer->ChannelInfo[0]; + while (ChannelCount != 0) { + EntrySize = + SIM_EMI_BUS_CHANNEL_INFO_SIZE(ChannelData->Info.ChannelNameSize); + + RtlCopyMemory(ChannelInfo, &ChannelData->Info, EntrySize); + ChannelData = SIM_EMI_CHANNEL_DATA_NEXT_CHANNEL_DATA(ChannelData); + ChannelInfo = SIM_EMI_BUS_CHANNEL_INFO_NEXT_CHANNEL_INFO(ChannelInfo); + ChannelCount -= 1; + } + + Status = STATUS_SUCCESS; + +FdoQueryChildDeviceEnd: + return Status; +} + +NTSTATUS +SimEmiFdoUpdateChildDevice ( + _In_ WDFDEVICE Device, + _In_ WDFREQUEST Request + ) + +/*++ + +Routine Description: + + This routine handles an IOCTL_EMI_BUS_SET_DEVICE_RATE request. + +Arguments: + + Device - Supplies a reference to the BUS FDO device. + + Request - Supplies a reference to the WDF Request. + +Return Value: + + NTSTATUS. + +--*/ +{ + + PULONG64 AbsoluteEnergyRates; + USHORT ChannelCount; + PSIM_EMI_CHANNEL_DATA ChannelData; + PSIM_EMI_BUS_PDO_DATA ChildData; + PSIM_EMI_BUS_SET_DEVICE_RATE_INPUT_BUFFER InputBuffer; + ULONG InputBufferSize; + NTSTATUS Status; + + Status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(SIM_EMI_BUS_SET_DEVICE_RATE_INPUT_BUFFER), + (PVOID*)&InputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + goto FdoUpdateChildDeviceEnd; + } + + ChildData = SimEmiFdoFindChildDevice(Device, + InputBuffer->ChildDeviceHandle); + + if (ChildData == NULL) { + Status = STATUS_INVALID_PARAMETER; + goto FdoUpdateChildDeviceEnd; + } + + if ((ChildData->EmiVersion != InputBuffer->EmiVersion) || + (ChildData->ChannelCount != InputBuffer->ChannelCount)) { + + Status = STATUS_INVALID_PARAMETER; + goto FdoUpdateChildDeviceEnd; + } + + ChannelCount = ChildData->ChannelCount; + Status = RtlULongMult(sizeof(ULONG64), ChannelCount, &InputBufferSize); + if (!NT_SUCCESS(Status)) { + goto FdoUpdateChildDeviceEnd; + } + + InputBufferSize += FIELD_OFFSET(SIM_EMI_BUS_SET_DEVICE_RATE_INPUT_BUFFER, + AbsoluteEnergyRates); + + Status = WdfRequestRetrieveInputBuffer(Request, + InputBufferSize, + (PVOID*)&InputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + goto FdoUpdateChildDeviceEnd; + } + + AbsoluteEnergyRates = &InputBuffer->AbsoluteEnergyRates[0]; + ChannelData = &ChildData->ChannelData[0]; + while (ChannelCount != 0) { + ChannelData->Info.AbsoluteEnergyRate = *AbsoluteEnergyRates; + AbsoluteEnergyRates += 1; + ChannelData = SIM_EMI_CHANNEL_DATA_NEXT_CHANNEL_DATA(ChannelData); + ChannelCount -= 1; + } + + Status = STATUS_SUCCESS; + +FdoUpdateChildDeviceEnd: + return Status; +} + +VOID +SimEmiPdoIdentificationCleanup ( + _In_ WDFCHILDLIST ChildList, + _Inout_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription + ) + +/*++ + +Routine Description: + + This routine cleans up the resources owned by a bus PDO description + instance. + +Arguments: + + ChildList - Supplies a reference to the WDFCHILDLIST this description is + being added to. + + IdentificationDescription - Supplies a pointer to the identification info + instance to clean up. + +Return Value: + + None. + +--*/ + +{ + + PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO Description; + + UNREFERENCED_PARAMETER(ChildList); + + Description = + (PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO)IdentificationDescription; + + if (Description->ChannelInfo != NULL) { + ExFreePoolWithTag(Description->ChannelInfo, SIM_EMI_TAG); + } + + return; +} + +BOOLEAN +SimEmiPdoIdentificationCompare ( + _In_ WDFCHILDLIST ChildList, + _In_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER FirstIdentificationDescription, + _In_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SecondIdentificationDescription + ) + +/*++ + +Routine Description: + + This routine compares two SIM_EMI_BUS_PDO_IDENTIFICATION_INFOs for + equality. + +Arguments: + + ChildList - Supplies a reference to the WDFCHILDLIST this description is + being added to. + + FirstIdentificationDescription - Supplies a pointer to a PDO identification + info instance. + + SecondIdentificationDescription - Supplies a pointer to a PDO + identification instance. + +Return Value: + + Returns TRUE if FirstIdentificationInfo == SecondIdentificationInfo, FALSE + otherwise. + +--*/ + +{ + + PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO Description1; + PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO Description2; + BOOLEAN Result; + + UNREFERENCED_PARAMETER(ChildList); + + Description1 = + (PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO)FirstIdentificationDescription; + + Description2 = + (PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO)SecondIdentificationDescription; + + Result = FALSE; + if (Description1->ChildDeviceHandle == Description2->ChildDeviceHandle) { + Result = TRUE; + } + + return Result; +} + +NTSTATUS +SimEmiPdoIdentificationDuplicate ( + _In_ WDFCHILDLIST ChildList, + _In_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SourceIdentificationDescription, + _Out_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER DestinationIdentificationDescription + ) + +/*++ + +Routine Description: + + This routine duplicates a SIM_EMI_BUS_PDO_IDENTIFICATION_INFO instance. + +Arguments: + + ChildList - Supplies a reference to the WDFCHILDLIST this description is + being added to. + + SourceIdentificationDescription - Supplies a pointer to the identification + info instance to duplicate. + + DestinationIdentificationDescription - Supplies a pointer to the location + to place the copied identification info. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + ULONG ChannelInfoSize; + PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO DestinationDescription; + PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO SourceDescription; + NTSTATUS Status; + + UNREFERENCED_PARAMETER(ChildList); + + DestinationDescription = + (PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO)DestinationIdentificationDescription; + + SourceDescription = + (PSIM_EMI_BUS_PDO_IDENTIFICATION_INFO)SourceIdentificationDescription; + + ChannelInfoSize = SourceDescription->ChannelInfoSize; + //#pragma warning( suppress : 4996 ) + DestinationDescription->ChannelInfo = ExAllocatePool2(POOL_FLAG_NON_PAGED, + ChannelInfoSize, + SIM_EMI_TAG); + + if (DestinationDescription->ChannelInfo == NULL) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto PdoIdentificationDuplicateEnd; + } + + DestinationDescription->EmiVersion = SourceDescription->EmiVersion; + DestinationDescription->ChildDeviceHandle = + SourceDescription->ChildDeviceHandle; + + DestinationDescription->ChannelCount = SourceDescription->ChannelCount; + DestinationDescription->ChannelInfoSize = ChannelInfoSize; + RtlCopyMemory(&DestinationDescription->ChannelInfo[0], + &SourceDescription->ChannelInfo[0], + ChannelInfoSize); + + Status = STATUS_SUCCESS; + +PdoIdentificationDuplicateEnd: + return Status; +}
\ No newline at end of file |
