NTSTATUS tdi_set_event_handler(PFILE_OBJECT addressFileObject, LONG eventType, PVOID eventHandler, PVOID eventContext) { PDEVICE_OBJECT devObj; KEVENT event; PIRP irp; IO_STATUS_BLOCK iosb; NTSTATUS status; devObj = IoGetRelatedDeviceObject(addressFileObject); KeInitializeEvent(&event, NotificationEvent, FALSE); irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, devObj, addressFileObject, &event, &iosb); if (irp == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildSetEventHandler(irp, devObj, addressFileObject, NULL, NULL, eventType, eventHandler, eventContext); status = IoCallDriver(devObj, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = iosb.Status; } return status; }
NTSTATUS TdiSetEventHandler( PFILE_OBJECT AddressObject, LONG EventType, PVOID EventHandler, PVOID EventContext ) { NTSTATUS ntStatus; KEVENT Event; PIRP Irp; PDEVICE_OBJECT DeviceObject = IoGetRelatedDeviceObject(AddressObject); IO_STATUS_BLOCK IoStatus; KeInitializeEvent(&Event, NotificationEvent, FALSE); if (!(Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, DeviceObject, AddressObject, &Event, &IoStatus))) return STATUS_INSUFFICIENT_RESOURCES; TdiBuildSetEventHandler(Irp, DeviceObject, AddressObject, 0, 0, EventType, EventHandler, EventContext); ntStatus = IoCallDriver(DeviceObject, Irp); if (ntStatus == STATUS_PENDING) ntStatus = KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, 0); return(ntStatus == STATUS_SUCCESS ? IoStatus.Status : ntStatus); }
NTSTATUS TcpSetDisconnectHandler( IN PFILE_OBJECT AddressFileObject, IN PVOID InEventHandler, IN PVOID InEventContext ) { PDEVICE_OBJECT deviceObject; PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatusBlock; NTSTATUS ntStatus; TCPLtDebugPrint (3, ("[TcpTdi]TcpSetDisconnectHandler: Entered\n")); // // Make Event. // KeInitializeEvent(&event, NotificationEvent, FALSE); deviceObject = IoGetRelatedDeviceObject(AddressFileObject); // // Make IRP. // irp = TdiBuildInternalDeviceControlIrp( TDI_SET_EVENT_HANDLER, deviceObject, AddressFileObject, &event, &ioStatusBlock ); if(irp == NULL) { TCPLtDebugPrint(1, ("[TcpTdi]TcpSetDisconnectHandler: Can't Build IRP.\n")); return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildSetEventHandler( irp, deviceObject, AddressFileObject, NULL, NULL, TDI_EVENT_DISCONNECT, InEventHandler, InEventContext ); ntStatus = TcpTdiIoCallDriver( deviceObject, irp, &ioStatusBlock, &event ); if(!NT_SUCCESS(ntStatus)) { TCPLtDebugPrint(1, ("[TcpTdi]TcpSetDisconnectHandler: Failed.\n")); } return ntStatus; }
VOID DestroyNodeEventHandlerVisitor(PVOID context, UINT key, PVOID value) { NTSTATUS status; PIRP irp = NULL; unsigned int i = 0; KEVENT irp_complete_event; IO_STATUS_BLOCK io_status_block; NodeEventHandler* node_event_handler = NULL; EventHandlerManager* event_handler_manager = NULL; node_event_handler = (NodeEventHandler*)value; event_handler_manager = (EventHandlerManager*)context; if(node_event_handler == NULL || event_handler_manager == NULL ) return; KeInitializeEvent(&irp_complete_event, NotificationEvent, FALSE); // For each hooked event handler send an IRP to set the event handler // back to what it originally was for(i = 0; i < TDI_EVENT_HANDLERS_MAX; i++) { PFILE_OBJECT node = node_event_handler->handlers[i].node; TdiEventHandler* original_handler = &node_event_handler->handlers[i].original_handler; if(original_handler->EventHandler == NULL) continue; irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, event_handler_manager->connection_manager->device, node, &irp_complete_event, &io_status_block); if(irp == NULL) continue; TdiBuildSetEventHandler(irp, event_handler_manager->connection_manager->device, node, NULL, NULL, original_handler->EventType, original_handler->EventHandler, original_handler->EventContext); status = IoCallDriver(event_handler_manager->connection_manager->next_device, irp); if(status == STATUS_PENDING) { // Wait for the IRP to finish KeWaitForSingleObject((PVOID)&irp_complete_event, Executive, KernelMode, TRUE, NULL); status = io_status_block.Status; } if(status == STATUS_SUCCESS) { DbgPrint("EventHandlerManager: Successfully set original event handler n=%08x t=%08x\n", node, original_handler->EventType); } else { DbgPrint("EventHandlerManager: Failed to set original event handler - code=%08x n=%08x t=%08x\n", status, node, original_handler->EventType); } KeResetEvent(&irp_complete_event); } }
NTSTATUS TdiSetEventHandler( PFILE_OBJECT FileObject, LONG EventType, PVOID Handler, PVOID Context) /* * FUNCTION: Sets or resets an event handler * ARGUMENTS: * FileObject = Pointer to file object * EventType = Event code * Handler = Event handler to be called when the event occurs * Context = Context input to handler when the event occurs * RETURNS: * Status of operation * NOTES: * Specify NULL for Handler to stop calling event handler */ { PDEVICE_OBJECT DeviceObject; IO_STATUS_BLOCK Iosb; KEVENT Event; PIRP Irp; AFD_DbgPrint(MAX_TRACE, ("Called\n")); if (!FileObject) { AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n")); return STATUS_INVALID_PARAMETER; } DeviceObject = IoGetRelatedDeviceObject(FileObject); if (!DeviceObject) { AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n")); return STATUS_INVALID_PARAMETER; } KeInitializeEvent(&Event, NotificationEvent, FALSE); Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, /* Sub function */ DeviceObject, /* Device object */ FileObject, /* File object */ &Event, /* Event */ &Iosb); /* Status */ if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; TdiBuildSetEventHandler(Irp, DeviceObject, FileObject, NULL, NULL, EventType, Handler, Context); return TdiCall(Irp, DeviceObject, &Event, &Iosb); }
NTSTATUS LpxTdiSetReceiveDatagramHandler( IN PFILE_OBJECT AddressFileObject, IN PVOID InEventHandler, IN PVOID InEventContext ) { PDEVICE_OBJECT deviceObject; PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatusBlock; NTSTATUS ntStatus; LtDebugPrint (1, ("[LxpTdi]LpxSetReceiveDatagramHandler: Entered\n")); // // Make Event. // KeInitializeEvent(&event, NotificationEvent, FALSE); deviceObject = IoGetRelatedDeviceObject(AddressFileObject); // // Make IRP. // irp = TdiBuildInternalDeviceControlIrp( TDI_SET_EVENT_HANDLER, deviceObject, AddressFileObject, &event, &ioStatusBlock ); if(irp == NULL) { LtDebugPrint(1, ("[LpxTdi]LpxSetReceiveDatagramHandler: Can't Build IRP.\n")); return STATUS_INSUFFICIENT_RESOURCES; } TdiBuildSetEventHandler( irp, deviceObject, AddressFileObject, NULL, NULL, TDI_EVENT_RECEIVE_DATAGRAM, InEventHandler, InEventContext ); ntStatus = LpxTdiIoCallDriver( deviceObject, irp, &ioStatusBlock, &event, NULL ); if(!NT_SUCCESS(ntStatus)) { LtDebugPrint(1, ("[LpxTdi]LpxSetReceiveDatagramHandler: Can't Build IRP.\n")); } LtDebugPrint(3, ("[LpxTdi] Leave LpxSetReceiveDatagramHandler\n")); 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); } }