NTSTATUS PdoPortBusInfo( IN PC0C_PDOPORT_EXTENSION pDevExt, IN PIRP pIrp) { PPNP_BUS_INFORMATION pBusInfo; pBusInfo = (PPNP_BUS_INFORMATION)C0C_ALLOCATE_POOL(PagedPool, sizeof(PNP_BUS_INFORMATION)); if (!pBusInfo) return STATUS_INSUFFICIENT_RESOURCES; pBusInfo->BusTypeGuid = GUID_C0C_BUS_TYPE; pBusInfo->LegacyBusType = PNPBus; pBusInfo->BusNumber = pDevExt->pBusExt->portNum; pIrp->IoStatus.Information = (ULONG_PTR)pBusInfo; return STATUS_SUCCESS; }
NTSTATUS FdoPortOpen(IN PC0C_FDOPORT_EXTENSION pDevExt) { LIST_ENTRY queueToComplete; PUCHAR pBase; ULONG size; KIRQL oldIrql; PC0C_IO_PORT pIoPort; if (InterlockedIncrement(&pDevExt->openCount) != 1) { InterlockedDecrement(&pDevExt->openCount); return STATUS_ACCESS_DENIED; } pIoPort = pDevExt->pIoPortLocal; if (pIoPort->plugInMode && !pIoPort->pIoPortRemote->isOpen) { InterlockedDecrement(&pDevExt->openCount); return STATUS_ACCESS_DENIED; } if (pIoPort->exclusiveMode) IoInvalidateDeviceRelations(pIoPort->pPhDevObj, BusRelations); switch (MmQuerySystemSize()) { case MmLargeSystem: size = 4096; pBase = (PUCHAR)C0C_ALLOCATE_POOL(NonPagedPool, size); if (pBase) break; case MmMediumSystem: size = 1024; pBase = (PUCHAR)C0C_ALLOCATE_POOL(NonPagedPool, size); if (pBase) break; case MmSmallSystem: size = 128; pBase = (PUCHAR)C0C_ALLOCATE_POOL(NonPagedPool, size); if (pBase) break; default: size = 0; pBase = NULL; } InitializeListHead(&queueToComplete); #if ENABLE_TRACING if (pIoPort->amountInWriteQueue) { NTSTATUS status; UNICODE_STRING msg; status = STATUS_SUCCESS; RtlInitUnicodeString(&msg, NULL); StrAppendStr0(&status, &msg, L"!!!WARNING!!! amountInWriteQueue = "); StrAppendNum(&status, &msg, pIoPort->amountInWriteQueue, 10); Trace0((PC0C_COMMON_EXTENSION)pDevExt, msg.Buffer); StrFree(&msg); } #endif /* ENABLE_TRACING */ KeAcquireSpinLock(pIoPort->pIoLock, &oldIrql); InitBuffer(&pIoPort->readBuf, pBase, size); pIoPort->amountInWriteQueue = 0; pIoPort->tryWrite = FALSE; pIoPort->errors = 0; pIoPort->waitMask = 0; pIoPort->eventMask = 0; RtlZeroMemory(&pIoPort->perfStats, sizeof(pIoPort->perfStats)); pIoPort->handFlow.XoffLimit = size >> 3; pIoPort->handFlow.XonLimit = size >> 1; pIoPort->pIoPortRemote->brokeIdleChars = 0; SetHandFlow(pIoPort, NULL, &queueToComplete); SetModemControl(pIoPort, C0C_MCR_OPEN, C0C_MCR_OPEN, &queueToComplete); if (pIoPort->pIoPortRemote->pWriteDelay && pIoPort->pIoPortRemote->brokeCharsProbability > 0) StartWriteDelayTimer(pIoPort->pIoPortRemote->pWriteDelay); KeReleaseSpinLock(pIoPort->pIoLock, oldIrql); pIoPort->isOpen = TRUE; if (pIoPort->pIoPortRemote->plugInMode) IoInvalidateDeviceRelations(pIoPort->pIoPortRemote->pPhDevObj, BusRelations); FdoPortCompleteQueue(&queueToComplete); return STATUS_SUCCESS; }
NTSTATUS FdoBusPnp( IN PC0C_FDOBUS_EXTENSION pDevExt, IN PIRP pIrp) { NTSTATUS status; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); ULONG minorFunction = pIrpStack->MinorFunction; PDEVICE_OBJECT pLowDevObj = pDevExt->pLowDevObj; // IRP_MN_REMOVE_DEVICE deletes *pDevExt! status = STATUS_SUCCESS; switch (minorFunction) { case IRP_MN_QUERY_DEVICE_RELATIONS: if (pIrpStack->Parameters.QueryDeviceRelations.Type == BusRelations) { ULONG countPdos, countRelations; PDEVICE_RELATIONS pRelationsPrev, pRelations; int i; countPdos = 0; for (i = 0 ; i < 2 ; i++) { if (pDevExt->childs[i].pDevExt) countPdos++; } if (!countPdos) break; pRelationsPrev = (PDEVICE_RELATIONS)pIrp->IoStatus.Information; countRelations = pRelationsPrev ? pRelationsPrev->Count : 0; pRelations = (PDEVICE_RELATIONS)C0C_ALLOCATE_POOL(PagedPool, sizeof(DEVICE_RELATIONS) + ((countPdos + countRelations - 1) * sizeof (PDEVICE_OBJECT))); if (!pRelations) { status = STATUS_INSUFFICIENT_RESOURCES; break; } if (countRelations) RtlCopyMemory(pRelations->Objects, pRelationsPrev->Objects, countRelations * sizeof (PDEVICE_OBJECT)); for (i = 0 ; i < 2 ; i++) { PC0C_PDOPORT_EXTENSION pPhDevExt; pPhDevExt = pDevExt->childs[i].pDevExt; if (pPhDevExt) { if (!pDevExt->childs[i].ioPort.pDevExt) { UNICODE_STRING portName; UNICODE_STRING portRegistryPath; RtlInitUnicodeString(&portRegistryPath, NULL); StrAppendPortParametersRegistryPath(&status, &portRegistryPath, pPhDevExt->portName); RtlInitUnicodeString(&portName, NULL); StrAppendParameterPortName(&status, &portName, portRegistryPath.Buffer); StrFree(&portRegistryPath); if (NT_SUCCESS(status) && portName.Length && _wcsicmp(C0C_PORT_NAME_COMCLASS, portName.Buffer) == 0) { pDevExt->childs[i].ioPort.isComClass = TRUE; Trace0((PC0C_COMMON_EXTENSION)pPhDevExt, L"Port class set to COM"); } else { pDevExt->childs[i].ioPort.isComClass = FALSE; Trace0((PC0C_COMMON_EXTENSION)pPhDevExt, L"Port class set to CNC"); } StrFree(&portName); status = STATUS_SUCCESS; } pRelations->Objects[countRelations++] = pPhDevExt->pDevObj; ObReferenceObject(pPhDevExt->pDevObj); } } pRelations->Count = countRelations; if (pRelationsPrev) ExFreePool(pRelationsPrev); pIrp->IoStatus.Information = (ULONG_PTR)pRelations; pIrp->IoStatus.Status = STATUS_SUCCESS; } break; case IRP_MN_REMOVE_DEVICE: RemoveFdoBus(pDevExt); pDevExt = NULL; pIrp->IoStatus.Status = STATUS_SUCCESS; break; case IRP_MN_START_DEVICE: case IRP_MN_STOP_DEVICE: case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_SURPRISE_REMOVAL: pIrp->IoStatus.Status = STATUS_SUCCESS; break; } if (status == STATUS_SUCCESS) { TraceIrp("FdoBusPnp", pIrp, NULL, TRACE_FLAG_RESULTS); IoSkipCurrentIrpStackLocation(pIrp); status = IoCallDriver(pLowDevObj, pIrp); TraceCode((PC0C_COMMON_EXTENSION)pDevExt, "PNP ", codeNameTablePnp, minorFunction, &status); } else { TraceIrp("PNP", pIrp, &status, TRACE_FLAG_RESULTS); pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } return status; }
NTSTATUS PdoPortPnp( IN PC0C_PDOPORT_EXTENSION pDevExt, IN PIRP pIrp) { NTSTATUS status = pIrp->IoStatus.Status; PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp); switch (pIrpStack->MinorFunction) { case IRP_MN_QUERY_ID: status = PdoPortQueryId(pDevExt, pIrp, pIrpStack); break; case IRP_MN_QUERY_CAPABILITIES: status = PdoPortQueryCaps(pDevExt, pIrp, pIrpStack); break; case IRP_MN_QUERY_DEVICE_TEXT: status = PdoPortQueryDevText(pDevExt, pIrp, pIrpStack); break; case IRP_MN_QUERY_BUS_INFORMATION: status = PdoPortBusInfo(pDevExt, pIrp); break; case IRP_MN_QUERY_DEVICE_RELATIONS: switch (pIrpStack->Parameters.QueryDeviceRelations.Type) { case TargetDeviceRelation: { PDEVICE_RELATIONS pRelations; HALT_UNLESS(pIrp->IoStatus.Information == 0); if (pIrp->IoStatus.Information != 0) break; pRelations = (PDEVICE_RELATIONS)C0C_ALLOCATE_POOL(PagedPool, sizeof(DEVICE_RELATIONS)); if (!pRelations) { status = STATUS_INSUFFICIENT_RESOURCES; break; } pRelations->Count = 1; pRelations->Objects[0] = pDevExt->pDevObj; ObReferenceObject(pDevExt->pDevObj); pIrp->IoStatus.Information = (ULONG_PTR)pRelations; status = STATUS_SUCCESS; break; } case RemovalRelations: case BusRelations: case EjectionRelations: case PowerRelations: default: break; } break; case IRP_MN_DEVICE_USAGE_NOTIFICATION: status = STATUS_UNSUCCESSFUL; break; case IRP_MN_REMOVE_DEVICE: case IRP_MN_START_DEVICE: case IRP_MN_STOP_DEVICE: case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_SURPRISE_REMOVAL: case IRP_MN_EJECT: status = STATUS_SUCCESS; break; default: break; } TraceIrp("PNP", pIrp, &status, TRACE_FLAG_RESULTS); pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; }