NTSTATUS TdiRecvfrom( PFILE_OBJECT AddressObject, PVOID Data, ULONG Length, ULONG Addr, USHORT Port, PULONG pRead, PKEVENT ReadEvent ) { KEVENT Event; PIRP Irp; PMDL Mdl; NTSTATUS ntStatus; IO_STATUS_BLOCK IoStatus; PDEVICE_OBJECT DeviceObject = IoGetRelatedDeviceObject(AddressObject); TA_IP_ADDRESS SrcAddr = {1, {TDI_ADDRESS_LENGTH_IP, TDI_ADDRESS_TYPE_IP, {Port, Addr}}}; TDI_CONNECTION_INFORMATION Src = {0, 0, 0, 0, sizeof SrcAddr, &SrcAddr}; PKEVENT pEvent = ReadEvent; if (!ReadEvent) { KeInitializeEvent(&Event, NotificationEvent, FALSE); pEvent = &Event; } if (!(Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, DeviceObject, AddressObject, pEvent, &IoStatus))) return STATUS_INSUFFICIENT_RESOURCES; if (!(Mdl = IoAllocateMdl(Data, Length, FALSE, FALSE, Irp))) return STATUS_INSUFFICIENT_RESOURCES; MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess); TdiBuildReceiveDatagram(Irp, DeviceObject, AddressObject, 0, 0, Mdl, Length, &Src, &Src, TDI_RECEIVE_NORMAL); ntStatus = IoCallDriver(DeviceObject, Irp); if ((ntStatus == STATUS_PENDING) && (!ReadEvent)) ntStatus = KeWaitForSingleObject(pEvent, UserRequest, KernelMode, FALSE, 0); if (ntStatus == STATUS_SUCCESS) { *pRead = IoStatus.Status; } return(ntStatus); }
NTSTATUS tdi_recv_dgram(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port, char *buf, int len, ULONG flags) { PDEVICE_OBJECT devObj; KEVENT event; PTDI_CONNECTION_INFORMATION remoteInfo; PTDI_CONNECTION_INFORMATION returnInfo; PTA_IP_ADDRESS returnAddr; PIRP irp; PMDL mdl; IO_STATUS_BLOCK iosb; NTSTATUS status; devObj = IoGetRelatedDeviceObject(addressFileObject); KeInitializeEvent(&event, NotificationEvent, FALSE); remoteInfo = HttpDiskMalloc( 2 * sizeof (TDI_CONNECTION_INFORMATION) + sizeof (TA_IP_ADDRESS) ); if (remoteInfo == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(remoteInfo, 2 * sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); remoteInfo->RemoteAddressLength = 0; remoteInfo->RemoteAddress = NULL; returnInfo = (PTDI_CONNECTION_INFORMATION)((PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION)); returnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS); returnInfo->RemoteAddress = (PUCHAR)returnInfo + sizeof(TDI_CONNECTION_INFORMATION); returnAddr = (PTA_IP_ADDRESS) returnInfo->RemoteAddress; returnAddr->TAAddressCount = 1; returnAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; returnAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, devObj, addressFileObject, &event, &iosb); if (irp == NULL) { ExFreePool(remoteInfo); return STATUS_INSUFFICIENT_RESOURCES; } if (len) { mdl = IoAllocateMdl((void*) buf, len, FALSE, FALSE, NULL); if (mdl == NULL) { IoFreeIrp(irp); ExFreePool(remoteInfo); return STATUS_INSUFFICIENT_RESOURCES; } __try { MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess); status = STATUS_SUCCESS; } __except (EXCEPTION_EXECUTE_HANDLER) { IoFreeMdl(mdl); IoFreeIrp(irp); ExFreePool(remoteInfo); status = STATUS_INVALID_USER_BUFFER; } if (!NT_SUCCESS(status)) { return status; } } TdiBuildReceiveDatagram(irp, devObj, addressFileObject, NULL, NULL, len ? mdl : 0, len, remoteInfo, returnInfo, flags); status = IoCallDriver(devObj, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = iosb.Status; } if (addr) { *addr = returnAddr->Address[0].Address[0].in_addr; } if (port) { *port = returnAddr->Address[0].Address[0].sin_port; } ExFreePool(remoteInfo); return NT_SUCCESS(status) ? iosb.Information : status; }
NTSTATUS TdiReceiveDatagram( PIRP *Irp, PFILE_OBJECT TransportObject, USHORT Flags, PCHAR Buffer, UINT BufferLength, PTDI_CONNECTION_INFORMATION Addr, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext) /* * FUNCTION: Receives a datagram * ARGUMENTS: * TransportObject = Pointer to transport object * From = Receive filter (NULL if none) * Address = Address of buffer to place remote address * Buffer = Address of buffer to place received data * BufferSize = Address of buffer with length of Buffer (updated) * RETURNS: * Status of operation */ { PDEVICE_OBJECT DeviceObject; PMDL Mdl; ASSERT(*Irp == NULL); if (!TransportObject) { AFD_DbgPrint(MIN_TRACE, ("Bad tranport object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(TransportObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } *Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, /* Sub function */ DeviceObject, /* Device object */ TransportObject, /* File object */ NULL, /* Event */ NULL); /* Status */ if (!*Irp) { AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); return STATUS_INSUFFICIENT_RESOURCES; } AFD_DbgPrint(MID_TRACE, ("Allocating irp for %p:%u\n", Buffer,BufferLength)); Mdl = IoAllocateMdl(Buffer, /* Virtual address */ BufferLength, /* Length of buffer */ FALSE, /* Not secondary */ FALSE, /* Don't charge quota */ NULL); /* Don't use IRP */ if (!Mdl) { AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n")); IoCompleteRequest(*Irp, IO_NO_INCREMENT); *Irp = NULL; return STATUS_INSUFFICIENT_RESOURCES; } _SEH2_TRY { MmProbeAndLockPages(Mdl, (*Irp)->RequestorMode, IoModifyAccess); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n")); IoFreeMdl(Mdl); IoCompleteRequest(*Irp, IO_NO_INCREMENT); *Irp = NULL; _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES); } _SEH2_END; AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %p\n", Mdl)); TdiBuildReceiveDatagram(*Irp, /* I/O Request Packet */ DeviceObject, /* Device object */ TransportObject, /* File object */ CompletionRoutine, /* Completion routine */ CompletionContext, /* Completion context */ Mdl, /* Data buffer */ BufferLength, Addr, Addr, Flags); /* Length of data */ TdiCall(*Irp, DeviceObject, NULL, NULL); /* Does not block... The MDL is deleted in the receive completion routine. */ return STATUS_PENDING; }