Пытаюсь написать фильтр для ком порта, присоеденился к стеку, пытаюсь перехватывать IRP. При изменении режима питания - все нормально, IRP монторятся, но когда пытаюсь открыть ком-порт, CreateFile возвращает ERROR_ACCESS_DENIED. Подскажите, пожалуйста, как мне пристроится в стек ком-порта не в "монопольном" режиме? Вот исходник фильтра: Код (Text): #include "ComFltr.h" #pragma PAGEDCODE NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING UnicodeString) { NTSTATUS Status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx; PDEVICE_OBJECT FiDO; PDEVICE_OBJECT fdo; PDEVICE_OBJECT LowObject; PFILE_OBJECT fLowObject; UNICODE_STRING sLowObject; int i; #ifdef DBG DbgPrint(DRIVERNAME ": Enter to DriverEntry, DriverObject: %x; UnicodeString: %ws \n", DriverObject, UnicodeString); #endif for (i = 0; i < ARRAYSIZE(DriverObject->MajorFunction); ++i) DriverObject->MajorFunction[i] = DispatchAny; DriverObject->DriverUnload = DriverUnload; DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower; DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_PARALLEL_PORT, 0, FALSE, &FiDO); if (!NT_SUCCESS(Status)) { DbgPrint(DRIVERNAME ": IoCreateDevice failed with status %x\n", Status); return Status; } RtlInitUnicodeString(&sLowObject, L"\\Device\\Serial1"); Status = IoGetDeviceObjectPointer(&sLowObject, FILE_ALL_ACCESS, &fLowObject, &LowObject); if (!NT_SUCCESS(Status)) { DbgPrint(DRIVERNAME ": IoGetDeviceObjectPointer failed with status %x\n", Status); return Status; } pdx = (PDEVICE_EXTENSION) FiDO->DeviceExtension; do { IoInitializeRemoveLock(&pdx->RemoveLock, 0, 0, 0); pdx->DeviceObject = FiDO; pdx->PDO = LowObject; fdo = IoAttachDeviceToDeviceStack(FiDO, LowObject); if (!fdo) { DbgPrint(DRIVERNAME ": IoAttachDeviceToDeviceStack failed \n"); Status = STATUS_DEVICE_REMOVED; break; } pdx->LowerDeviceObject = fdo; FiDO->Flags |= fdo->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE); FiDO->Flags &= ~DO_DEVICE_INITIALIZING; }while(FALSE); if (!NT_SUCCESS(Status)) { if (pdx->LowerDeviceObject) IoDetachDevice(pdx->LowerDeviceObject); IoDeleteDevice(FiDO); } #ifdef DBG DbgPrint(DRIVERNAME ": DriverEntry completed with status %x\n", Status); #endif return Status; } void DriverUnload(PDRIVER_OBJECT FiDO) { PDEVICE_EXTENSION pdx = FiDO->DriverExtension; #ifdef DBG DbgPrint(DRIVERNAME ": Entering to DriverUnload with FiDO %x", FiDO); #endif ObDereferenceObject(pdx->LowerDeviceObject); } #pragma LOCKEDCODE NTSTATUS CompleteRequest(PIRP Irp, NTSTATUS Status, ULONG_PTR Info) { Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Info; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; } #pragma LOCKEDCODE NTSTATUS DispatchAny(PDEVICE_OBJECT FiDO, PIRP Irp) { PDEVICE_EXTENSION pdx = FiDO->DeviceExtension; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); NTSTATUS Status; #if DBG static char* irpname[] = { "IRP_MJ_CREATE", "IRP_MJ_CREATE_NAMED_PIPE", "IRP_MJ_CLOSE", "IRP_MJ_READ", "IRP_MJ_WRITE", "IRP_MJ_QUERY_INFORMATION", "IRP_MJ_SET_INFORMATION", "IRP_MJ_QUERY_EA", "IRP_MJ_SET_EA", "IRP_MJ_FLUSH_BUFFERS", "IRP_MJ_QUERY_VOLUME_INFORMATION", "IRP_MJ_SET_VOLUME_INFORMATION", "IRP_MJ_DIRECTORY_CONTROL", "IRP_MJ_FILE_SYSTEM_CONTROL", "IRP_MJ_DEVICE_CONTROL", "IRP_MJ_INTERNAL_DEVICE_CONTROL", "IRP_MJ_SHUTDOWN", "IRP_MJ_LOCK_CONTROL", "IRP_MJ_CLEANUP", "IRP_MJ_CREATE_MAILSLOT", "IRP_MJ_QUERY_SECURITY", "IRP_MJ_SET_SECURITY", "IRP_MJ_POWER", "IRP_MJ_SYSTEM_CONTROL", "IRP_MJ_DEVICE_CHANGE", "IRP_MJ_QUERY_QUOTA", "IRP_MJ_SET_QUOTA", "IRP_MJ_PNP", }; UCHAR Type = stack->MajorFunction; DbgPrint(DRIVERNAME ": Entering to DispatchAny (FiDO = %x; Irp = %x)\n", FiDO, Irp); if (Type >= ARRAYSIZE(irpname)) DbgPrint(DRIVERNAME ": Unknown IRP major type %x\n", Type); else DbgPrint(DRIVERNAME ": - %s name\n", irpname[Type]); #endif Status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(Status)) return CompleteRequest(Irp, Status, 0); IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLock(&pdx->RemoveLock, Irp); #ifdef DBG DbgPrint(DRIVERNAME ": DispatchAny completed with Status %x\n", Status); #endif return Status; } NTSTATUS DispatchPower(PDEVICE_OBJECT FiDO, PIRP Irp) { NTSTATUS Status; PDEVICE_EXTENSION pdx; #ifdef DBG PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG fcn = stack->MinorFunction; static char* fcnname[] = { "IRP_MN_WAIT_WAKE", "IRP_MN_POWER_SEQUENCE", "IRP_MN_SET_POWER", "IRP_MN_QUERY_POWER", }; DbgPrint(DRIVERNAME ": Entering to DispatchPower (FiDO = %x; Irp = %x)\n", FiDO, Irp); if (fcn == IRP_MN_SET_POWER || fcn == IRP_MN_QUERY_POWER) { static char* sysstate[] = { "PowerSystemUnspecified", "PowerSystemWorking", "PowerSystemSleeping1", "PowerSystemSleeping2", "PowerSystemSleeping3", "PowerSystemHibernate", "PowerSystemShutdown", "PowerSystemMaximum", }; static char* devstate[] = { "PowerDeviceUnspecified", "PowerDeviceD0", "PowerDeviceD1", "PowerDeviceD2", "PowerDeviceD3", "PowerDeviceMaximum", }; ULONG Context = stack->Parameters.Power.SystemContext; POWER_STATE_TYPE Type = stack->Parameters.Power.Type; DbgPrint(DRIVERNAME ": IRP_MJ_POWER (%s)\n", fcnname[fcn]); if (Type == SystemPowerState) DbgPrint(DRIVERNAME ": SystemPowerState = %s\n", sysstate[stack->Parameters.Power.State.SystemState]); else DbgPrint(DRIVERNAME ": DevicePowerState = %s\n", devstate[stack->Parameters.Power.State.DeviceState]); } else if (fcn < ARRAYSIZE(fcnname)) DbgPrint(DRIVERNAME ": IRP_MJ_POWER (%s)\n", fcnname[fcn]); else DbgPrint(DRIVERNAME ": IRP_MJ_POWER (%x)\n", fcn); #endif pdx = (PDEVICE_EXTENSION) FiDO->DeviceExtension; PoStartNextPowerIrp(Irp); Status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(Status)) return CompleteRequest(Irp, Status, 0); IoSkipCurrentIrpStackLocation(Irp); Status = PoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLock(&pdx->RemoveLock, Irp); #ifdef DBG DbgPrint(DRIVERNAME ": DispatchPower completed with status %x\n", Status); #endif return Status; } NTSTATUS DispatchPnp(PDEVICE_OBJECT FiDO, PIRP Irp) { PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); ULONG fcn = stack->MinorFunction; NTSTATUS Status; PDEVICE_EXTENSION pdx = FiDO->DeviceExtension; #ifdef DBG static char* pnpname[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", "", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL", "IRP_MN_QUERY_LEGACY_BUS_INFORMATION", }; if (fcn < ARRAYSIZE(pnpname)) DbgPrint(DRIVERNAME ": IRP_MJ_PNP (%s)\n", pnpname[fcn]); else DbgPrint(DRIVERNAME ": IRP_MJ_PNP (%x)\n", fcn); #endif #ifdef DBG DbgPrint(DRIVERNAME ": Entering to DispatchPnp (FiDO = %x; Irp = %x)\n", FiDO, Irp); #endif Status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp); if (!NT_SUCCESS(Status)) return CompleteRequest(Irp, Status, 0); if (fcn == IRP_MN_DEVICE_USAGE_NOTIFICATION) { if (!FiDO->AttachedDevice || (FiDO->AttachedDevice->Flags & DO_POWER_PAGABLE)) FiDO->Flags |= DO_POWER_PAGABLE; IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) UsageNotificationCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE); return IoCallDriver(pdx->LowerDeviceObject, Irp); } if (fcn == IRP_MN_START_DEVICE) { IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) StartDeviceCompletionRoutine, (PVOID) pdx, TRUE, TRUE, TRUE); return IoCallDriver(pdx->LowerDeviceObject, Irp); } if (fcn == IRP_MN_REMOVE_DEVICE) { IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLockAndWait(&pdx->RemoveLock, Irp); RemoveDevice(FiDO); return Status; } IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(pdx->LowerDeviceObject, Irp); IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return Status; } #pragma PAGEDCODE VOID RemoveDevice(PDEVICE_OBJECT FiDO) { PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) FiDO->DeviceExtension; NTSTATUS Status; if (pdx->LowerDeviceObject) IoDetachDevice(pdx->LowerDeviceObject); IoDeleteDevice(FiDO); } #pragma LOCKEDCODE NTSTATUS StartDeviceCompletionRoutine(PDEVICE_OBJECT FiDO, PIRP Irp, PDEVICE_EXTENSION pdx) { if (Irp->PendingReturned) IoMarkIrpPending(Irp); if (pdx->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) FiDO->Characteristics |= FILE_REMOVABLE_MEDIA; IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return STATUS_SUCCESS; } #pragma LOCKEDCODE NTSTATUS UsageNotificationCompletionRoutine(PDEVICE_OBJECT FiDO, PIRP Irp, PDEVICE_EXTENSION pdx) { if (Irp->PendingReturned) IoMarkIrpPending(Irp); if (!(pdx->LowerDeviceObject->Flags & DO_POWER_PAGABLE)) FiDO->Flags &= ~DO_POWER_PAGABLE; IoReleaseRemoveLock(&pdx->RemoveLock, Irp); return STATUS_SUCCESS; } #pragma LOCKEDCODE
Без фильтра все передается нормально, тестирую вот таким простеньким кодом: Код (Text): #include <windows.h> #include <stdio.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { CHAR *Buf = "1234"; DWORD Written; HANDLE hFile = CreateFileW(L"\\\\.\\COM2", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { int Err = GetLastError(); CHAR buf[100]; sprintf(buf, "CreateFileW failed with error: %d", Err); MessageBoxA(0, buf, "Error", MB_OK|MB_ICONERROR); return 0; } if (!WriteFile(hFile, Buf, 5, &Written, NULL)) { int Err = GetLastError(); CHAR buf[100]; sprintf(buf, "WriteFile failed with error: %d", Err); MessageBoxA(0, buf, "Error", MB_OK|MB_ICONERROR); } return 0; }
rttgedt В драйверах я не силён, точнее говоря не имею о них никакого представления. Но, поскольку других предположений нет, попробую угадать. Возможно Вы в драйвере открываете порт с эксклюзивным доступом и не закрываете, соответственно никто другой его уже открыть не может.
rttgedt А если поставить точку останова на IRP_MJ_CREATE, что происходит? Приходит ли управление, что возвращает низлежащее устройство?
Я цепляюсь в вершину стека, когда система уже загружена, а открыть порт после этого уже не могу. Поэтому IRP_MJ_CREATE не приходит вообще.
Разобрался! ))) После получения указателя на низлежащее устройство через IoGetDeviceObjectPointer, нужно обязательно отдереференсить файловый объект, как показано в ДДК: Код (Text): RtlInitUnicodeString(&nameString, L"\\Device\\RawDisk"); status = IoGetDeviceObjectPointer( &nameString, //ObjectName FILE_READ_ATTRIBUTES, //DesiredAccess &fileObject, //FileObject &rawDeviceObject); //DeviceObject if (NT_SUCCESS(status)) { ObDereferenceObject(fileObject); } Всем большое спасибо за участие!