mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
b21019e3d1
CORE-13866
221 lines
5.7 KiB
C
221 lines
5.7 KiB
C
/*
|
|
* PROJECT: ReactOS Storport Driver
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Storport helper functions
|
|
* COPYRIGHT: Copyright 2017 Eric Kohl (eric.kohl@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
ForwardIrpAndWaitCompletion(
|
|
_In_ PDEVICE_OBJECT DeviceObject,
|
|
_In_ PIRP Irp,
|
|
_In_ PVOID Context)
|
|
{
|
|
if (Irp->PendingReturned)
|
|
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
|
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ForwardIrpAndWait(
|
|
_In_ PDEVICE_OBJECT LowerDevice,
|
|
_In_ PIRP Irp)
|
|
{
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
|
|
ASSERT(LowerDevice);
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
|
|
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
|
|
|
|
Status = IoCallDriver(LowerDevice, Irp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
|
|
if (NT_SUCCESS(Status))
|
|
Status = Irp->IoStatus.Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
ForwardIrpAndForget(
|
|
_In_ PDEVICE_OBJECT LowerDevice,
|
|
_In_ PIRP Irp)
|
|
{
|
|
ASSERT(LowerDevice);
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
return IoCallDriver(LowerDevice, Irp);
|
|
}
|
|
|
|
|
|
INTERFACE_TYPE
|
|
GetBusInterface(
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
GUID Guid;
|
|
ULONG Length;
|
|
NTSTATUS Status;
|
|
|
|
Status = IoGetDeviceProperty(DeviceObject,
|
|
DevicePropertyBusTypeGuid,
|
|
sizeof(Guid),
|
|
&Guid,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
return InterfaceTypeUndefined;
|
|
|
|
if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_PCMCIA, sizeof(GUID)) == sizeof(GUID))
|
|
return PCMCIABus;
|
|
else if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_PCI, sizeof(GUID)) == sizeof(GUID))
|
|
return PCIBus;
|
|
else if (RtlCompareMemory(&Guid, &GUID_BUS_TYPE_ISAPNP, sizeof(GUID)) == sizeof(GUID))
|
|
return PNPISABus;
|
|
|
|
return InterfaceTypeUndefined;
|
|
}
|
|
|
|
|
|
static
|
|
ULONG
|
|
GetResourceListSize(
|
|
PCM_RESOURCE_LIST ResourceList)
|
|
{
|
|
PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
|
|
INT i;
|
|
ULONG Size;
|
|
|
|
DPRINT1("GetResourceListSize(%p)\n", ResourceList);
|
|
|
|
Size = sizeof(CM_RESOURCE_LIST);
|
|
if (ResourceList->Count == 0)
|
|
{
|
|
DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
|
|
return Size;
|
|
}
|
|
|
|
DPRINT1("ResourceList->Count: %lu\n", ResourceList->Count);
|
|
|
|
Descriptor = &ResourceList->List[0];
|
|
for (i = 0; i < ResourceList->Count; i++)
|
|
{
|
|
/* Process resources in CM_FULL_RESOURCE_DESCRIPTOR block number ix. */
|
|
|
|
DPRINT1("PartialResourceList->Count: %lu\n", Descriptor->PartialResourceList.Count);
|
|
|
|
/* Add the size of the current full descriptor */
|
|
Size += sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
|
|
(Descriptor->PartialResourceList.Count - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|
|
|
/* Advance to next CM_FULL_RESOURCE_DESCRIPTOR block in memory. */
|
|
Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)(Descriptor->PartialResourceList.PartialDescriptors +
|
|
Descriptor->PartialResourceList.Count);
|
|
}
|
|
|
|
DPRINT1("Size: 0x%lx (%u)\n", Size, Size);
|
|
return Size;
|
|
}
|
|
|
|
|
|
PCM_RESOURCE_LIST
|
|
CopyResourceList(
|
|
POOL_TYPE PoolType,
|
|
PCM_RESOURCE_LIST Source)
|
|
{
|
|
PCM_RESOURCE_LIST Destination;
|
|
ULONG Size;
|
|
|
|
DPRINT1("CopyResourceList(%lu %p)\n",
|
|
PoolType, Source);
|
|
|
|
/* Get the size of the resource list */
|
|
Size = GetResourceListSize(Source);
|
|
|
|
/* Allocate a new buffer */
|
|
Destination = ExAllocatePoolWithTag(PoolType,
|
|
Size,
|
|
TAG_RESOURCE_LIST);
|
|
if (Destination == NULL)
|
|
return NULL;
|
|
|
|
/* Copy the resource list */
|
|
RtlCopyMemory(Destination,
|
|
Source,
|
|
Size);
|
|
|
|
return Destination;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
QueryBusInterface(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PGUID Guid,
|
|
USHORT Size,
|
|
USHORT Version,
|
|
PBUS_INTERFACE_STANDARD Interface,
|
|
PVOID InterfaceSpecificData)
|
|
{
|
|
KEVENT Event;
|
|
NTSTATUS Status;
|
|
PIRP Irp;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
PIO_STACK_LOCATION Stack;
|
|
|
|
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
|
|
|
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
|
|
DeviceObject,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
&Event,
|
|
&IoStatus);
|
|
if (Irp == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
Stack = IoGetNextIrpStackLocation(Irp);
|
|
|
|
Stack->MajorFunction = IRP_MJ_PNP;
|
|
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
|
Stack->Parameters.QueryInterface.InterfaceType = Guid;
|
|
Stack->Parameters.QueryInterface.Size = Size;
|
|
Stack->Parameters.QueryInterface.Version = Version;
|
|
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)Interface;
|
|
Stack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
|
|
|
|
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
|
|
|
Status = IoCallDriver(DeviceObject, Irp);
|
|
if (Status == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
|
|
|
Status=IoStatus.Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|