reactos/drivers/parallel/parport/fdo.c
Joachim Henze b098b6e6cb [0.4.8][PARPORT] Fix I/O port length check, [REACTOS] Logging & formatting, e.g. CORE-14388 CORE-19105
Ports back a real fix:
0.4.15-dev-1173-g ba09834c5e [PARPORT] Fix I/O port length check

Ports back logging and formatting:
0.4.15-dev-6794-g 4eace8d762 [IPHLPAPI] Silence obsolete FIXME in GetAdaptersAddresses (#5834) CORE-14388
0.4.15-dev-6438-g b12ab486d8 [MUP] Mute DPRINT1's that slow down shared folder accesses (#5545) CORE-19105

And mutes some other loggings as well for stuff, that I either never want to port back, e.g. the IMM-implementations,
or which is not really helpful in the older branches:
fixme:(win32ss/user/user32/misc/imm.c:446) WINNLSEnableIME is UNIMPLEMENTED!
fixme:(../dll/win32/iphlpapi/address.c:290) GetAdaptersAddresses - Semi Stub: Family 2, Flags 0x0000002e, Reserved 00000000, pAdapterAddress 00000000, pOutBufLen 0143EBD4.

when browsing the startmenu:
fixme:(dll/win32/comctl32/toolbar.c:394) [00080086] TBSTYLE_REGISTERDROP not implemented
fixme:(dll/win32/comctl32/toolbar.c:5636) [00080086] response 2045774661 not handled to NM_CUSTOMDRAW (CDDS_PREERASE)
fixme:(dll/win32/comctl32/toolbar.c:5673) [00080086] response 3225142 not handled to NM_CUSTOMDRAW (CDDS_POSTERASE)
fixme:(dll/win32/comctl32/toolbar.c:5636) [000200BA] response 9 not handled to NM_CUSTOMDRAW (CDDS_PREERASE)
fixme:(dll/win32/comctl32/toolbar.c:5636) [00080086] response 2288892 not handled to NM_CUSTOMDRAW (CDDS_PREERASE)
fixme:(dll/win32/comctl32/toolbar.c:5673) [00080086] response 3291448 not handled to NM_CUSTOMDRAW (CDDS_POSTERASE)

and a bigger block regarding the parallel port during booting:
(drivers/parallel/parport/parport.c:127) Parport DriverEntry
(drivers/parallel/parport/fdo.c:391) AddDevice(B0B50548 B0FED980)
(drivers/parallel/parport/fdo.c:25) AddDeviceInternal()
(drivers/parallel/parport/fdo.c:513) FdoPnp()
(drivers/parallel/parport/fdo.c:582) IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS
(drivers/parallel/parport/fdo.c:513) FdoPnp()
(drivers/parallel/parport/fdo.c:546) IRP_MJ_PNP / IRP_MN_START_DEVICE
(drivers/parallel/parport/misc.c:42) Calling lower device B0FED980
(drivers/parallel/parport/fdo.c:116) FdoStartDevice ()
(drivers/parallel/parport/fdo.c:160) Port: BaseAddress 0x378  Length 8
(drivers/parallel/parport/fdo.c:160) Port: BaseAddress 0x778  Length 8
(drivers/parallel/parport/fdo.c:174) Interrupt: Level 20  Vector 55
(drivers/parallel/parport/fdo.c:195) New LPT port: Base 0x378
(drivers/parallel/parport/fdo.c:513) FdoPnp()
(drivers/parallel/parport/fdo.c:586) Unknown minor function 0x9
(drivers/parallel/parport/fdo.c:513) FdoPnp()
(drivers/parallel/parport/fdo.c:586) Unknown minor function 0x14
(drivers/parallel/parport/fdo.c:513) FdoPnp()
(drivers/parallel/parport/fdo.c:564) IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations
(drivers/parallel/parport/fdo.c:351) FdoQueryBusRelations()
(drivers/parallel/parport/fdo.c:233) FdoCreateRawParallelPdo()
(drivers/parallel/parport/fdo.c:378) Done
(drivers/parallel/parport/pdo.c:165) PdoPnp()
2023-11-05 13:55:26 +01:00

564 lines
16 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: Parallel Port Function Driver
* PURPOSE: FDO functions
*/
#include "parport.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
AddDeviceInternal(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo,
IN PULONG pLptPortNumber OPTIONAL,
OUT PDEVICE_OBJECT* pFdo OPTIONAL)
{
PFDO_DEVICE_EXTENSION DeviceExtension = NULL;
PDEVICE_OBJECT Fdo = NULL;
WCHAR DeviceNameBuffer[32];
UNICODE_STRING DeviceName;
NTSTATUS Status;
ASSERT(DriverObject);
ASSERT(Pdo);
/* Create new device object */
swprintf(DeviceNameBuffer,
L"\\Device\\ParallelPort%lu",
IoGetConfigurationInformation()->ParallelCount);
RtlInitUnicodeString(&DeviceName,
DeviceNameBuffer);
Status = IoCreateDevice(DriverObject,
sizeof(FDO_DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_PARALLEL_PORT,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateDevice() failed (Status 0x%08lx)\n", Status);
Fdo = NULL;
goto done;
}
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension,
sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->Common.IsFDO = TRUE;
DeviceExtension->Common.PnpState = dsStopped;
DeviceExtension->PortNumber = IoGetConfigurationInformation()->ParallelCount++;
DeviceExtension->Pdo = Pdo;
Status = IoAttachDeviceToDeviceStackSafe(Fdo,
Pdo,
&DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoAttachDeviceToDeviceStackSafe() failed (Status 0x%08lx)\n", Status);
goto done;
}
if (DeviceExtension->LowerDevice->Flags & DO_POWER_PAGABLE)
Fdo->Flags |= DO_POWER_PAGABLE;
if (DeviceExtension->LowerDevice->Flags & DO_BUFFERED_IO)
Fdo->Flags |= DO_BUFFERED_IO;
if (DeviceExtension->LowerDevice->Flags & DO_DIRECT_IO)
Fdo->Flags |= DO_DIRECT_IO;
/* Choose default strategy */
if ((Fdo->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) == 0)
Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
if (pFdo)
{
*pFdo = Fdo;
}
return STATUS_SUCCESS;
done:
if (Fdo)
{
IoDeleteDevice(Fdo);
}
return Status;
}
NTSTATUS
NTAPI
FdoStartDevice(IN PDEVICE_OBJECT DeviceObject,
IN PCM_RESOURCE_LIST ResourceList,
IN PCM_RESOURCE_LIST ResourceListTranslated)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
ULONG i;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
ASSERT(DeviceExtension->Common.IsFDO == TRUE);
if (!ResourceList)
{
DPRINT1("No allocated resources sent to driver\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
if (ResourceList->Count != 1)
{
DPRINT1("Wrong number of allocated resources sent to driver\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
if ((ResourceList->List[0].PartialResourceList.Version != 1) ||
(ResourceList->List[0].PartialResourceList.Revision != 1) ||
(ResourceListTranslated->List[0].PartialResourceList.Version != 1) ||
(ResourceListTranslated->List[0].PartialResourceList.Revision != 1))
{
DPRINT1("Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
ResourceList->List[0].PartialResourceList.Version,
ResourceList->List[0].PartialResourceList.Revision,
ResourceListTranslated->List[0].PartialResourceList.Version,
ResourceListTranslated->List[0].PartialResourceList.Revision);
return STATUS_REVISION_MISMATCH;
}
DeviceExtension->BaseAddress = 0;
for (i = 0; i < ResourceList->List[0].PartialResourceList.Count; i++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[i];
switch (PartialDescriptor->Type)
{
case CmResourceTypePort:
if (DeviceExtension->BaseAddress == 0)
{
if (PartialDescriptor->u.Port.Length < 3)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart;
}
break;
case CmResourceTypeInterrupt:
break;
default:
break;
}
}
if (!DeviceExtension->BaseAddress)
return STATUS_INSUFFICIENT_RESOURCES;
#if 0
if (!Dirql)
return STATUS_INSUFFICIENT_RESOURCES;
#endif
DeviceExtension->Common.PnpState = dsStarted;
/* We don't really care if the call succeeded or not... */
return STATUS_SUCCESS;
}
static
NTSTATUS
FdoCreateRawParallelPdo(
IN PDEVICE_OBJECT DeviceObject)
{
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PPDO_DEVICE_EXTENSION PdoDeviceExtension = NULL;
PDEVICE_OBJECT Pdo = NULL;
WCHAR DeviceNameBuffer[32];
WCHAR LinkNameBuffer[32];
WCHAR LptPortBuffer[32];
UNICODE_STRING DeviceName;
UNICODE_STRING LinkName;
UNICODE_STRING LptPort;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE KeyHandle;
NTSTATUS Status;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Create new device object */
swprintf(DeviceNameBuffer,
L"\\Device\\Parallel%lu",
FdoDeviceExtension->PortNumber);
RtlInitUnicodeString(&DeviceName,
DeviceNameBuffer);
Status = IoCreateDevice(DeviceObject->DriverObject,
sizeof(PDO_DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_CONTROLLER,
0,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateDevice() failed with status 0x%08x\n", Status);
goto done;
}
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
Pdo->Flags |= DO_POWER_PAGABLE;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
PdoDeviceExtension->Common.IsFDO = FALSE;
PdoDeviceExtension->Common.PnpState = dsStopped;
Pdo->StackSize = DeviceObject->StackSize + 1;
FdoDeviceExtension->AttachedRawPdo = Pdo;
PdoDeviceExtension->AttachedFdo = DeviceObject;
PdoDeviceExtension->PortNumber = FdoDeviceExtension->PortNumber;
PdoDeviceExtension->LptPort = PdoDeviceExtension->PortNumber + 1;
/* Create link \DosDevices\LPTX -> \Device\ParallelY */
swprintf(LinkNameBuffer, L"\\DosDevices\\LPT%lu", PdoDeviceExtension->LptPort);
RtlInitUnicodeString(&LinkName, LinkNameBuffer);
Status = IoCreateSymbolicLink(&LinkName,
&DeviceName);
if (!NT_SUCCESS(Status))
{
DPRINT1("IoCreateSymbolicLink() failed with status 0x%08x\n", Status);
goto done;
}
swprintf(LptPortBuffer, L"LPT%lu", PdoDeviceExtension->LptPort);
RtlInitUnicodeString(&LptPort, LptPortBuffer);
/* Write an entry value under HKLM\HARDWARE\DeviceMap\PARALLEL PORTS. */
/* This step is not mandatory, so do not exit in case of error. */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\HARDWARE\\DeviceMap\\PARALLEL PORTS");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_SET_VALUE,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
if (NT_SUCCESS(Status))
{
/* Key = \Device\Parallelx, Value = LPTx */
ZwSetValueKey(KeyHandle,
&DeviceName,
0,
REG_SZ,
LptPortBuffer,
LptPort.Length + sizeof(WCHAR));
ZwClose(KeyHandle);
}
Pdo->Flags |= DO_BUFFERED_IO;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
done:
if (!NT_SUCCESS(Status))
{
if (Pdo)
{
ASSERT(PdoDeviceExtension);
IoDeleteDevice(Pdo);
}
}
return Status;
}
static
NTSTATUS
FdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
ULONG Size;
ULONG i;
ULONG PdoCount = 0;
NTSTATUS Status;
UNREFERENCED_PARAMETER(IrpSp);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->Common.IsFDO);
/* TODO: Enumerate parallel devices and create their PDOs */
Status = FdoCreateRawParallelPdo(DeviceObject);
if (!NT_SUCCESS(Status))
return Status;
PdoCount++;
/* Allocate a buffer for the device relations */
Size = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PdoCount - 1);
DeviceRelations = ExAllocatePoolWithTag(PagedPool, Size, PARPORT_TAG);
if (DeviceRelations == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
/* Fill the buffer */
i = 0;
ObReferenceObject(DeviceExtension->AttachedRawPdo);
DeviceRelations->Objects[i] = DeviceExtension->AttachedRawPdo;
DeviceRelations->Count = 1;
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return STATUS_SUCCESS;
}
/* PUBLIC FUNCTIONS *********************************************************/
NTSTATUS
NTAPI
AddDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
/* Serial.sys is a legacy driver. AddDevice is called once
* with a NULL Pdo just after the driver initialization.
* Detect this case and return success.
*/
if (Pdo == NULL)
return STATUS_SUCCESS;
/* We have here a PDO not null. It represents a real serial
* port. So call the internal AddDevice function.
*/
return AddDeviceInternal(DriverObject, Pdo, NULL, NULL);
}
NTSTATUS
NTAPI
FdoCreate(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("FdoCreate()\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
{
DPRINT1("Not a directory\n");
Status = STATUS_NOT_A_DIRECTORY;
goto done;
}
DPRINT("Open parallel port %lu: successful\n", DeviceExtension->PortNumber);
DeviceExtension->OpenCount++;
done:
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
NTAPI
FdoClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PFDO_DEVICE_EXTENSION pDeviceExtension;
DPRINT("FdoClose()\n");
pDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
pDeviceExtension->OpenCount--;
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FdoCleanup(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("FdoCleanup()\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FdoRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("FdoRead()\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
NTSTATUS
NTAPI
FdoWrite(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("FdoWrite()\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_NOT_SUPPORTED;
}
NTSTATUS
NTAPI
FdoPnp(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
/* FIXME: do all these minor functions
IRP_MN_QUERY_REMOVE_DEVICE 0x1
IRP_MN_REMOVE_DEVICE 0x2
{
TRACE_(SERIAL, "IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
IoAcquireRemoveLock
IoReleaseRemoveLockAndWait
pass request to DeviceExtension-LowerDriver
disable interface
IoDeleteDevice(Fdo) and/or IoDetachDevice
break;
}
IRP_MN_CANCEL_REMOVE_DEVICE 0x3
IRP_MN_STOP_DEVICE 0x4
IRP_MN_QUERY_STOP_DEVICE 0x5
IRP_MN_CANCEL_STOP_DEVICE 0x6
IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) 0x7
IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
IRP_MN_QUERY_INTERFACE (optional) 0x8
IRP_MN_QUERY_CAPABILITIES (optional) 0x9
IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional) 0xd
IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
IRP_MN_SURPRISE_REMOVAL 0x17
*/
case IRP_MN_START_DEVICE: /* 0x0 */
ASSERT(((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Common.PnpState == dsStopped);
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
{
Status = FdoStartDevice(DeviceObject,
Stack->Parameters.StartDevice.AllocatedResources,
Stack->Parameters.StartDevice.AllocatedResourcesTranslated);
}
break;
case IRP_MN_QUERY_DEVICE_RELATIONS: /* (optional) 0x7 */
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
Status = FdoQueryBusRelations(DeviceObject, Irp, Stack);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
case RemovalRelations:
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations\n");
return ForwardIrpAndForget(DeviceObject, Irp);
default:
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
return ForwardIrpAndForget(DeviceObject, Irp);
}
break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* (optional) 0xd */
return ForwardIrpAndForget(DeviceObject, Irp);
default:
return ForwardIrpAndForget(DeviceObject, Irp);
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
NTAPI
FdoPower(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice;
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(LowerDevice, Irp);
}
/* EOF */