Здравствуйте.
Пишу драйвер батареи: для APC smart на ком порту.
Драйвер легаси, но с пнп кодом: через devcon добавляю устройство, а дальше обычный пнп.
В AddDevice атачусь к тому что приходит, дальше открываю компорт через IoGetDeviceObjectPointer — но в стёк к нему не добавляюсь.
Порт открывается, IRP_MJ_DEVICE_CONTROL с IOCTL_SERIAL_* проходят вроде нормально — без ошибок.
А на IRP_MJ_WRITE ухожу в BSOD.
Пожалуйста помогите, уже неделю не могу осилить!
RtlInitUnicodeString(&ObjectName, L"\\DosDevices\\COM1");
Status = IoGetDeviceObjectPointer(&ObjectName, STANDARD_RIGHTS_ALL, &FileObject, &ComPdo);
...
pDeviceData->WriteBuffSize = OEM_SERIAL_BUFFSIZE;
pDeviceData->WriteBuff = ExAllocatePoolWithTag(NonPagedPool, pDeviceData->WriteBuffSize, DRIVER_TAG);
...
RtlCopyMemory(pDeviceData->WriteBuff, "Y", 1);//(*WriteBuff) = 'Y';
Status = SmBatt_SerialPortWrite(pDeviceData->ComPdo, pDeviceData->ComFileObject, pDeviceData->WriteBuff, 1);
...
NTSTATUS
IOSyncRequestCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(DeviceObject);
// If the lower driver didn't return STATUS_PENDING, we don't need to
// set the event because we won't be waiting on it.
// This optimization avoids grabbing the dispatcher lock and improves perf.
if (Irp->PendingReturned == TRUE)
KeSetEvent((PKEVENT)Context, 0, FALSE);
// We don't want IO to get our IRP and free it.
return(STATUS_MORE_PROCESSING_REQUIRED);
}
NTSTATUS
IOSyncRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
KEVENT Event;
DebugPrint("IOSyncRequest...");
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
IoSetCompletionRoutine(Irp, IOSyncRequestCompletionRoutine, (PVOID)&Event, TRUE, TRUE, TRUE);
// Call the device to do the read and wait for it to finish.
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING) { // Wait for the IRP
Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
if (Status == STATUS_SUCCESS)
Status = Irp->IoStatus.Status;
}
KeClearEvent(&Event);
DebugPrint("IOSyncRequest - DONE!!!");
return(Status);
}
NTSTATUS
SendDevIoControlReq(ULONG IoControlCode, BOOLEAN Internal, PDEVICE_OBJECT DeviceObject, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength, ULONG_PTR *pnBytesReturned)
{
NTSTATUS Status;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PAGED_CODE();
DebugPrint("SendDevIoControlReq...");
Irp = IoAllocateIrp((DeviceObject->StackSize + 1), FALSE);
if (Irp == NULL) {
DebugPrint("SendDevIoControlReq: Failed to allocate IRP");
return(STATUS_INSUFFICIENT_RESOURCES);
}
IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->MajorFunction = ((TRUE == Internal) ? IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL);
IrpSp->Parameters.DeviceIoControl.IoControlCode = IoControlCode;
IrpSp->Parameters.DeviceIoControl.InputBufferLength = InputBufferLength;
IrpSp->Parameters.DeviceIoControl.OutputBufferLength = OutputBufferLength;
Irp->UserBuffer = OutputBuffer;
Irp->AssociatedIrp.SystemBuffer = InputBuffer;
// Call the device to do the read and wait for it to finish.
Status = IOSyncRequest(DeviceObject, Irp);
IoFreeIrp(Irp);
DebugPrint("SendDevIoControlReq - DONE!!!");
if (pnBytesReturned)
*pnBytesReturned = Irp->IoStatus.Information;
return(Status);
}
NTSTATUS
SmBatt_SerialPortWrite(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, PVOID Buffer, ULONG NumberOfBytesToWrite)
{
NTSTATUS Status;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PAGED_CODE();
DebugPrint("SmBatt_SerialPortWrite...");
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE, DeviceObject, Buffer OPTIONAL, NumberOfBytesToWrite, NULL, NULL);
//Irp = IoAllocateIrp((DeviceObject->StackSize + 1), FALSE);
if (Irp == NULL) {
DebugPrint("SerialPortWrite: Failed to allocate IRP");
return(STATUS_INSUFFICIENT_RESOURCES);
}
/*IrpSp = IoGetNextIrpStackLocation(Irp);
IrpSp->MajorFunction = IRP_MJ_WRITE;
IrpSp->Parameters.Write.Length = NumberOfBytesToWrite;
IrpSp->FileObject = FileObject;
Irp->AssociatedIrp.SystemBuffer = Buffer;*/
// Call the device to do the read and wait for it to finish.
Status = IOSyncRequest(DeviceObject, Irp);
IoFreeIrp(Irp);
DebugPrint("SmBatt_SerialPortWrite - DONE!!!");
return(Status);
}