NTSTATUS tdi_disconnect(PFILE_OBJECT connectionFileObject, ULONG flags) { PDEVICE_OBJECT devObj; KEVENT event; PIRP irp; IO_STATUS_BLOCK iosb; NTSTATUS status; devObj = IoGetRelatedDeviceObject(connectionFileObject); KeInitializeEvent(&event, NotificationEvent, FALSE); irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, devObj, connectionFileObject, &event, &iosb); if (irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildDisconnect(irp, devObj, connectionFileObject, NULL, NULL, NULL, flags, NULL, NULL); status = IoCallDriver(devObj, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = iosb.Status; } return status; }
NTSTATUS TdiDisconnect( PFILE_OBJECT ConnectionObject ) { NTSTATUS ntStatus; KEVENT Event; PIRP Irp; PDEVICE_OBJECT DeviceObject = IoGetRelatedDeviceObject(ConnectionObject); IO_STATUS_BLOCK IoStatus; KeInitializeEvent(&Event, NotificationEvent, FALSE); if (!(Irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, DeviceObject, ConnectionObject, &Event, &IoStatus))) return STATUS_INSUFFICIENT_RESOURCES; TdiBuildDisconnect(Irp, DeviceObject, ConnectionObject, 0, 0, 0, TDI_DISCONNECT_RELEASE, 0, 0); ntStatus = IoCallDriver(DeviceObject, Irp); if (ntStatus == STATUS_PENDING) ntStatus = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0); return(ntStatus == STATUS_SUCCESS ? IoStatus.Status : ntStatus); }
NTSTATUS TdiDisconnect( PIRP *Irp, PFILE_OBJECT TransportObject, PLARGE_INTEGER Time, USHORT Flags, PIO_COMPLETION_ROUTINE CompletionRoutine, PVOID CompletionContext, PTDI_CONNECTION_INFORMATION RequestConnectionInfo, PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) { PDEVICE_OBJECT DeviceObject; if (!TransportObject) { AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n")); return STATUS_INVALID_PARAMETER; } AFD_DbgPrint(MID_TRACE,("Called(TransportObject %p)\n", TransportObject)); DeviceObject = IoGetRelatedDeviceObject(TransportObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } *Irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, /* 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; } TdiBuildDisconnect(*Irp, /* I/O Request Packet */ DeviceObject, /* Device object */ TransportObject, /* File object */ CompletionRoutine, /* Completion routine */ CompletionContext, /* Completion context */ Time, /* Time */ Flags, /* Disconnect flags */ RequestConnectionInfo, /* Indication of who to disconnect */ ReturnConnectionInfo); /* Indication of who disconnected */ TdiCall(*Irp, DeviceObject, NULL, NULL); return STATUS_PENDING; }
NTSTATUS LpxTdiDisconnect( IN PFILE_OBJECT ConnectionFileObject, IN ULONG Flags ) { PDEVICE_OBJECT deviceObject; PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatusBlock; NTSTATUS ntStatus; LtDebugPrint (3, ("LpxTdiDisconnect: Entered\n")); ASSERT(ConnectionFileObject); // // Make Event. // KeInitializeEvent(&event, NotificationEvent, FALSE); deviceObject = IoGetRelatedDeviceObject(ConnectionFileObject); // // Make IRP. // irp = TdiBuildInternalDeviceControlIrp( TDI_DISCONNECT, deviceObject, ConnectionFileObject, &event, &ioStatusBlock ); if(irp == NULL) { LtDebugPrint(1, ("[LpxTdi]KSTdiDisconnect: Can't Build IRP.\n")); return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildDisconnect( irp, deviceObject, ConnectionFileObject, NULL, NULL, NULL, Flags, NULL, NULL ); irp->MdlAddress = NULL; ntStatus = LpxTdiIoCallDriver( deviceObject, irp, &ioStatusBlock, &event, NULL ); if(!NT_SUCCESS(ntStatus)) { LtDebugPrint(1, ("[LpxTdi]LpxTdiDisconnect: Failed. ntStatus = %x\n", ntStatus)); } return ntStatus; }
void ot_free(void) { KIRQL irql; int i; struct ot_entry *ote; if (g_ot_hash == NULL) return; // have nothing to do // do cleanup for address & connection objects for (i = 0; i < HASH_SIZE; i++) { for (;;) { // do it again and again PFILE_OBJECT connobj = NULL, event_addrobj; PVOID event_handler = NULL, event_context; int event_type; PDEVICE_OBJECT devobj; KeAcquireSpinLock(&g_ot_hash_guard, &irql); for (ote = g_ot_hash[i]; ote != NULL; ote = ote->next) { if (ote->fileobj == NULL) continue; // skip processed items #ifdef _USE_TDI_HOOKING devobj = ote->devobj; #else devobj = get_original_devobj(ote->devobj, NULL); #endif if (ote->type == FILEOBJ_ADDROBJ) { // find at least one event handler & remove it @ PASSIVE level int j; event_addrobj = ote->fileobj; for (j = 0; j < MAX_EVENT; j++) if (ote->ctx[j].old_handler != NULL) { event_type = j; event_handler = ote->ctx[j].old_handler; event_context = ote->ctx[j].old_context; KdPrint(("[tdi_fw] ot_free: got event handler to restore (addrobj: 0x%x; type: %d; handler: 0x%x; context: 0x%x\n", event_addrobj, event_type, event_handler, event_context)); ote->ctx[j].old_handler = NULL; break; } if (event_handler != NULL) break; KdPrint(("[tdi_fw] ot_free: no event handlers for addrobj: 0x%x\n", ote->fileobj)); // remove this addrobj from "LISTEN" state if (ote->listen_entry != NULL) { del_listen_obj(ote->listen_entry, FALSE); ote->listen_entry = NULL; } // no event handlers ote->fileobj = NULL; } else if (ote->type == FILEOBJ_CONNOBJ) { // check connobj is connected (remote addr is not 0) TA_ADDRESS *remote_addr = (TA_ADDRESS *)(ote->remote_addr); if (((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr == 0) { KdPrint(("[tdi_fw] ot_free: connobj 0x%x is not connected\n", connobj)); } else { // disconnect this connection using TDI_DISCONNECT @ PASSIVE level connobj = ote->fileobj; KdPrint(("[tdi_fw] ot_free: got connobj 0x%x (%x:%x) to disconnect\n", connobj, ((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr, ((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port)); } // remove this connobj from "CONNECTED" state if (ote->conn_entry != NULL) { del_tcp_conn_obj(ote->conn_entry, FALSE); ote->conn_entry = NULL; // TODO: check if state TCP_STATE_TIME_WAIT don't delete it } // skip this object next time ote->fileobj = NULL; } } KeReleaseSpinLock(&g_ot_hash_guard, irql); // we're at PASSIVE level if (event_handler != NULL) { // set old event handler PIRP query_irp; NTSTATUS status; KdPrint(("[tdi_fw] ot_free: got event handler to restore (addrobj: 0x%x; type: %d; handler: 0x%x; context: 0x%x\n", event_addrobj, event_type, event_handler, event_context)); query_irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, devobj, event_addrobj, NULL, NULL); if (query_irp == NULL) { KdPrint(("[tdi_fw] ot_free: TdiBuildInternalDeviceControlIrp\n")); continue; } TdiBuildSetEventHandler(query_irp, devobj, event_addrobj, NULL, NULL, event_type, event_handler, event_context); status = IoCallDriver(devobj, query_irp); if (status != STATUS_SUCCESS) KdPrint(("[tdi_fw] ot_free: IoCallDriver(set_event_handler): 0x%x\n", status)); } else if (connobj != NULL) { // disconnect connection PIRP query_irp; NTSTATUS status; KdPrint(("[tdi_fw] ot_free: disconnecting connobj 0x%x\n", connobj)); query_irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, devobj, connobj, NULL, NULL); if (query_irp == NULL) { KdPrint(("[tdi_fw] ot_free: TdiBuildInternalDeviceControlIrp\n")); continue; } // using TDI_DISCONNECT_RELEASE to make ClientEventDisconnect to be called TdiBuildDisconnect(query_irp, devobj, connobj, NULL, NULL, NULL, TDI_DISCONNECT_RELEASE, NULL, NULL); status = IoCallDriver(devobj, query_irp); if (status != STATUS_SUCCESS) KdPrint(("[tdi_fw] ot_free: IoCallDriver(disconnect): 0x%x\n", status)); } else { // no objects to process. break! break; } } } // clear it! KeAcquireSpinLock(&g_ot_hash_guard, &irql); for (i = 0; i < HASH_SIZE; i++) { struct ot_entry *ote = g_ot_hash[i]; while (ote != NULL) { struct ot_entry *ote2 = ote->next; KdPrint(("[tdi_fw] ot_free: Warning! fileobj 0x%x type %d exists!\n", ote->fileobj, ote->type)); if (ote->sid_a != NULL) free(ote->sid_a); free(ote); ote = ote2; } } free(g_ot_hash); g_ot_hash = NULL; KeReleaseSpinLock(&g_ot_hash_guard, irql); // and cleanup cte_hash if (g_cte_hash != NULL) { KeAcquireSpinLock(&g_cte_hash_guard, &irql); for (i = 0; i < HASH_SIZE; i++) { struct ctx_entry *cte = g_cte_hash[i]; while (cte) { struct ctx_entry *cte2 = cte->next; free(cte); cte = cte2; } } free(g_cte_hash); g_cte_hash = NULL; KeReleaseSpinLock(&g_cte_hash_guard, irql); } }
BOOLEAN KTdiStreamSocket::Disconnect() { //KLocker locker(&m_KSynchroObject); BOOLEAN bRes = TRUE; PIRP pIrp = NULL, pIrpError = NULL; PDEVICE_OBJECT pDeviceObject; NTSTATUS NtStatus; PTDI_CONNECTION_INFORMATION pRequestConnectionInfo = NULL; PTDI_CONNECTION_INFORMATION pReturnConnectionInfo; PTA_IP_ADDRESS pRequestAddress; PTDI_ADDRESS_IP pIp; IO_STATUS_BLOCK IoStatusBlock; __try { if (m_bOpen == TRUE && (m_bConnected == TRUE || m_bListen == TRUE)) { bRes = FALSE; pDeviceObject = IoGetRelatedDeviceObject(m_pTdiConnectionObject); pRequestConnectionInfo = (PTDI_CONNECTION_INFORMATION) new char[sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)]; if (pRequestConnectionInfo != NULL) { memset(pRequestConnectionInfo, 0, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS)); pReturnConnectionInfo = NULL; pRequestConnectionInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS); pRequestConnectionInfo->RemoteAddress = (PUCHAR)pRequestConnectionInfo + sizeof(TDI_CONNECTION_INFORMATION); pRequestAddress = (PTA_IP_ADDRESS)(pRequestConnectionInfo->RemoteAddress); pRequestAddress->TAAddressCount = 1; pRequestAddress->Address[0].AddressLength = sizeof(TDI_ADDRESS_IP); pRequestAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; pIp = (PTDI_ADDRESS_IP)(pRequestAddress->Address[0].Address); pIp->sin_port = W_LITTLE_TO_BIG_ENDIAN(m_nRemotePort); pIp->in_addr = D_LITTLE_TO_BIG_ENDIAN(m_nRemoteAddress); pIrp = TdiBuildInternalDeviceControlIrp( TDI_DISCONNECT, pDeviceObject, m_pTdiConnectionObject, NULL, NULL); pIrpError = pIrp; if (pIrp != NULL) { TdiBuildDisconnect( pIrp, pDeviceObject, m_pTdiConnectionObject, NULL, NULL, NULL, // timeout TDI_DISCONNECT_ABORT, //TDI_DISCONNECT_RELEASE, pRequestConnectionInfo, pReturnConnectionInfo); pIrpError = NULL; BOOLEAN bConnected = m_bConnected; BOOLEAN bListen = m_bListen; m_bConnected = FALSE; m_bListen = FALSE; if (bListen == TRUE) { KeSetEvent(&m_kAcceptDestroyEvent, 0, FALSE); SetEventHandler(TDI_EVENT_CONNECT, (PVOID)NULL, (PVOID)NULL); } NtStatus = TdiCall(pIrp, pDeviceObject, &IoStatusBlock); if (NT_SUCCESS(NtStatus)) { DbgPrint ("TdiDisconnect: SUCCESS (%08x)!!!\n", NtStatus); } else { DbgPrint ("TdiDisconnect: ERROR (%08x)!!!\n", NtStatus); } if (bConnected == TRUE) m_bConnected = FALSE; if (bListen == TRUE) { m_bListen = FALSE; delete[] m_pRequestListenInfo; m_pRequestListenInfo = NULL; } bRes = TRUE; } delete[] pRequestConnectionInfo; pRequestConnectionInfo = NULL; } } } __finally { if (pIrpError != NULL) IoFreeIrp(pIrpError); if (pRequestConnectionInfo != NULL) delete[] pRequestConnectionInfo; } return bRes; }