https://git.reactos.org/?p=reactos.git;a=commitdiff;h=27fcfe66a2a7a8beb4b29eee18bb251a3a9aae22

commit 27fcfe66a2a7a8beb4b29eee18bb251a3a9aae22
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Fri May 21 09:36:27 2021 +0200
Commit:     Jérôme Gardou <[email protected]>
CommitDate: Mon Jun 21 11:42:01 2021 +0200

    [TCPIP][IP] Use an ERESOURCE as mutex for address files & connection end 
points
    
    Spinlocks are not reentrant (and this is done a lot), using them forces us 
to have
    an horrible hack in the kernel, which unschedules threads which are at 
DISPATCH_LEVEL
    thus allowing another thread to take ownership of the spinlock while the 
unscheduled
    thread should already hold it.
    
    CORE-6473
---
 drivers/network/tcpip/include/tcp.h              |   6 +-
 drivers/network/tcpip/include/titypes.h          |  52 ++----
 drivers/network/tcpip/tcpip/ainfo.c              |  18 +--
 drivers/network/tcpip/tcpip/dispatch.c           |  33 ++--
 drivers/network/tcpip/tcpip/fileobjs.c           |  32 ++--
 drivers/network/tcpip/tcpip/icmp.c               |  15 +-
 sdk/lib/drivers/ip/transport/datagram/datagram.c |  27 ++--
 sdk/lib/drivers/ip/transport/rawip/rawip.c       |  11 +-
 sdk/lib/drivers/ip/transport/tcp/accept.c        |  15 +-
 sdk/lib/drivers/ip/transport/tcp/event.c         | 194 ++++++++--------------
 sdk/lib/drivers/ip/transport/tcp/tcp.c           | 197 ++++++++++++++---------
 sdk/lib/drivers/ip/transport/udp/udp.c           |  11 +-
 sdk/lib/drivers/lwip/src/include/rosip.h         |   4 +
 sdk/lib/drivers/lwip/src/rostcp.c                |  40 ++++-
 14 files changed, 319 insertions(+), 336 deletions(-)

diff --git a/drivers/network/tcpip/include/tcp.h 
b/drivers/network/tcpip/include/tcp.h
index 6bb8280d5a1..65a5d11b355 100644
--- a/drivers/network/tcpip/include/tcp.h
+++ b/drivers/network/tcpip/include/tcp.h
@@ -201,13 +201,13 @@ VOID
 FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
 
 VOID
-FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, 
const BOOLEAN interlocked);
+FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
 
 VOID
-FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const 
BOOLEAN interlocked);
+FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
 
 VOID
-FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, 
const BOOLEAN interlocked);
+FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status);
 
 VOID
 FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status);
diff --git a/drivers/network/tcpip/include/titypes.h 
b/drivers/network/tcpip/include/titypes.h
index 14541a24a65..0290c2dd54d 100644
--- a/drivers/network/tcpip/include/titypes.h
+++ b/drivers/network/tcpip/include/titypes.h
@@ -29,44 +29,26 @@
 }
 
 /*
- * VOID LockObject(PVOID Object, PKIRQL OldIrql)
+ * VOID LockObject(PVOID Object)
  */
-#define LockObject(Object, Irql)                         \
-{                                                        \
-    ReferenceObject(Object);                             \
-    KeAcquireSpinLock(&((Object)->Lock), Irql);          \
-    memcpy(&(Object)->OldIrql, Irql, sizeof(KIRQL));     \
-}
-
-/*
- * VOID LockObjectAtDpcLevel(PVOID Object)
- */
-#define LockObjectAtDpcLevel(Object)                     \
-{                                                        \
-    ReferenceObject(Object);                             \
-    KeAcquireSpinLockAtDpcLevel(&((Object)->Lock));      \
-    (Object)->OldIrql = DISPATCH_LEVEL;                  \
-}
-
-/*
- * VOID UnlockObject(PVOID Object, KIRQL OldIrql)
- */
-#define UnlockObject(Object, OldIrql)                       \
-{                                                           \
-    KeReleaseSpinLock(&((Object)->Lock), OldIrql);          \
-    DereferenceObject(Object);                              \
-}
+#define LockObject(Object) do                                   \
+{                                                               \
+    ReferenceObject(Object);                                    \
+    KeEnterCriticalRegion();                                    \
+    ExAcquireResourceExclusiveLite(&(Object)->Resource, TRUE);  \
+} while(0)
 
 /*
- * VOID UnlockObjectFromDpcLevel(PVOID Object)
+ * VOID UnlockObject(PVOID Object)
  */
-#define UnlockObjectFromDpcLevel(Object)                    \
+#define UnlockObject(Object) do                             \
 {                                                           \
-    KeReleaseSpinLockFromDpcLevel(&((Object)->Lock));       \
+    ExReleaseResourceLite(&(Object)->Resource);             \
+    KeLeaveCriticalRegion();                                \
     DereferenceObject(Object);                              \
-}
-
+} while(0)
 
+#define ASSERT_TCPIP_OBJECT_LOCKED(Object) 
ASSERT(ExIsResourceAcquiredExclusiveLite(&(Object)->Resource))
 
 #include <ip.h>
 
@@ -131,8 +113,7 @@ typedef struct _ADDRESS_FILE {
     LIST_ENTRY ListEntry;                 /* Entry on list */
     LONG RefCount;                        /* Reference count */
     OBJECT_FREE_ROUTINE Free;             /* Routine to use to free resources 
for the object */
-    KSPIN_LOCK Lock;                      /* Spin lock to manipulate this 
structure */
-    KIRQL OldIrql;                        /* Currently not used */
+    ERESOURCE Resource;                   /* Resource to manipulate this 
structure */
     IP_ADDRESS Address;                   /* Address of this address file */
     USHORT Family;                        /* Address family */
     USHORT Protocol;                      /* Protocol number */
@@ -142,7 +123,6 @@ typedef struct _ADDRESS_FILE {
     UINT DF;                              /* Don't fragment */
     UINT BCast;                           /* Receive broadcast packets */
     UINT HeaderIncl;                      /* Include header in RawIP packets */
-    WORK_QUEUE_ITEM WorkItem;             /* Work queue item handle */
     DATAGRAM_COMPLETION_ROUTINE Complete; /* Completion routine for delete 
request */
     PVOID Context;                        /* Delete request context */
     DATAGRAM_SEND_ROUTINE Send;           /* Routine to send a datagram */
@@ -262,8 +242,7 @@ typedef struct _CONNECTION_ENDPOINT {
     LIST_ENTRY ListEntry;       /* Entry on list */
     LONG RefCount;              /* Reference count */
     OBJECT_FREE_ROUTINE Free;   /* Routine to use to free resources for the 
object */
-    KSPIN_LOCK Lock;            /* Spin lock to protect this structure */
-    KIRQL OldIrql;              /* The old irql is stored here for use in 
HandleSignalledConnection */
+    ERESOURCE Resource;         /* The lock protecting this structure */
     PVOID ClientContext;        /* Pointer to client context information */
     PADDRESS_FILE AddressFile;  /* Associated address file object (NULL if 
none) */
 
@@ -279,6 +258,7 @@ typedef struct _CONNECTION_ENDPOINT {
     /* Disconnect Timer */
     KTIMER DisconnectTimer;
     KDPC DisconnectDpc;
+    PIO_WORKITEM DisconnectWorkItem;
 
     /* Socket state */
     BOOLEAN SendShutdown;
diff --git a/drivers/network/tcpip/tcpip/ainfo.c 
b/drivers/network/tcpip/tcpip/ainfo.c
index bba0affc1bc..1553149dc1e 100644
--- a/drivers/network/tcpip/tcpip/ainfo.c
+++ b/drivers/network/tcpip/tcpip/ainfo.c
@@ -13,17 +13,15 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
                               PVOID Buffer,
                               UINT BufferSize)
 {
-    KIRQL OldIrql;
-
     switch (ID->toi_id)
     {
       case AO_OPTION_TTL:
          if (BufferSize < sizeof(UINT))
              return TDI_INVALID_PARAMETER;
 
-         LockObject(AddrFile, &OldIrql);
+         LockObject(AddrFile);
          AddrFile->TTL = *((PUCHAR)Buffer);
-         UnlockObject(AddrFile, OldIrql);
+         UnlockObject(AddrFile);
 
          return TDI_SUCCESS;
 
@@ -31,9 +29,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
          if (BufferSize < sizeof(UINT))
              return TDI_INVALID_PARAMETER;
 
-         LockObject(AddrFile, &OldIrql);
+         LockObject(AddrFile);
          AddrFile->DF = *((PUINT)Buffer);
-         UnlockObject(AddrFile, OldIrql);
+         UnlockObject(AddrFile);
 
          return TDI_SUCCESS;
 
@@ -41,9 +39,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
          if (BufferSize < sizeof(UINT))
              return TDI_INVALID_PARAMETER;
 
-         LockObject(AddrFile, &OldIrql);
+         LockObject(AddrFile);
          AddrFile->BCast = *((PUINT)Buffer);
-         UnlockObject(AddrFile, OldIrql);
+         UnlockObject(AddrFile);
 
          return TDI_SUCCESS;
 
@@ -51,9 +49,9 @@ TDI_STATUS SetAddressFileInfo(TDIObjectID *ID,
          if (BufferSize < sizeof(UINT))
              return TDI_INVALID_PARAMETER;
 
-         LockObject(AddrFile, &OldIrql);
+         LockObject(AddrFile);
          AddrFile->HeaderIncl = *((PUINT)Buffer);
-         UnlockObject(AddrFile, OldIrql);
+         UnlockObject(AddrFile);
 
          return TDI_SUCCESS;
 
diff --git a/drivers/network/tcpip/tcpip/dispatch.c 
b/drivers/network/tcpip/tcpip/dispatch.c
index da2a00ba5bd..375c0bc5fd5 100644
--- a/drivers/network/tcpip/tcpip/dispatch.c
+++ b/drivers/network/tcpip/tcpip/dispatch.c
@@ -284,7 +284,6 @@ NTSTATUS DispTdiAssociateAddress(
   PFILE_OBJECT FileObject;
   PADDRESS_FILE AddrFile = NULL;
   NTSTATUS Status;
-  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -319,18 +318,18 @@ NTSTATUS DispTdiAssociateAddress(
     return STATUS_INVALID_PARAMETER;
   }
 
-  LockObject(Connection, &OldIrql);
+  LockObject(Connection);
 
   if (Connection->AddressFile) {
     ObDereferenceObject(FileObject);
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
     TI_DbgPrint(MID_TRACE, ("An address file is already associated.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
   if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
     ObDereferenceObject(FileObject);
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
     TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
       FileObject->FsContext2));
     return STATUS_INVALID_PARAMETER;
@@ -341,20 +340,20 @@ NTSTATUS DispTdiAssociateAddress(
   TranContext = FileObject->FsContext;
   if (!TranContext) {
     ObDereferenceObject(FileObject);
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
     return STATUS_INVALID_PARAMETER;
   }
 
   AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
   if (!AddrFile) {
-      UnlockObject(Connection, OldIrql);
+      UnlockObject(Connection);
       ObDereferenceObject(FileObject);
       TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
       return STATUS_INVALID_PARAMETER;
   }
 
-  LockObjectAtDpcLevel(AddrFile);
+  LockObject(AddrFile);
 
   ReferenceObject(AddrFile);
   Connection->AddressFile = AddrFile;
@@ -373,8 +372,8 @@ NTSTATUS DispTdiAssociateAddress(
 
   ObDereferenceObject(FileObject);
 
-  UnlockObjectFromDpcLevel(AddrFile);
-  UnlockObject(Connection, OldIrql);
+  UnlockObject(AddrFile);
+  UnlockObject(Connection);
 
   return STATUS_SUCCESS;
 }
@@ -563,7 +562,6 @@ NTSTATUS DispTdiListen(
   PTRANSPORT_CONTEXT TranContext;
   PIO_STACK_LOCATION IrpSp;
   NTSTATUS Status = STATUS_SUCCESS;
-  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -596,17 +594,17 @@ NTSTATUS DispTdiListen(
        Irp,
        (PDRIVER_CANCEL)DispCancelListenRequest);
 
-  LockObject(Connection, &OldIrql);
+  LockObject(Connection);
 
   if (Connection->AddressFile == NULL)
   {
      TI_DbgPrint(MID_TRACE, ("No associated address file\n"));
-     UnlockObject(Connection, OldIrql);
+     UnlockObject(Connection);
      Status = STATUS_INVALID_PARAMETER;
      goto done;
   }
 
-  LockObjectAtDpcLevel(Connection->AddressFile);
+  LockObject(Connection->AddressFile);
 
   /* Listening will require us to create a listening socket and store it in
    * the address file.  It will be signalled, and attempt to complete an irp
@@ -647,8 +645,8 @@ NTSTATUS DispTdiListen(
            Irp );
   }
 
-  UnlockObjectFromDpcLevel(Connection->AddressFile);
-  UnlockObject(Connection, OldIrql);
+  UnlockObject(Connection->AddressFile);
+  UnlockObject(Connection);
 
 done:
   if (Status != STATUS_PENDING) {
@@ -1116,7 +1114,6 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
   PIO_STACK_LOCATION IrpSp;
   PADDRESS_FILE AddrFile;
   NTSTATUS Status;
-  KIRQL OldIrql;
 
   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
 
@@ -1139,7 +1136,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
   Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
   Status     = STATUS_SUCCESS;
 
-  LockObject(AddrFile, &OldIrql);
+  LockObject(AddrFile);
 
   /* Set the event handler. if an event handler is associated with
      a specific event, it's flag (RegisteredXxxHandler) is TRUE.
@@ -1260,7 +1257,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
     Status = STATUS_INVALID_PARAMETER;
   }
 
-  UnlockObject(AddrFile, OldIrql);
+  UnlockObject(AddrFile);
 
   return Status;
 }
diff --git a/drivers/network/tcpip/tcpip/fileobjs.c 
b/drivers/network/tcpip/tcpip/fileobjs.c
index 6854acc7da7..d926abed97e 100644
--- a/drivers/network/tcpip/tcpip/fileobjs.c
+++ b/drivers/network/tcpip/tcpip/fileobjs.c
@@ -310,7 +310,7 @@ VOID AddrFileFree(
   PADDRESS_FILE AddrFile = Object;
   KIRQL OldIrql;
   PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
-  PDATAGRAM_SEND_REQUEST SendRequest;
+  // PDATAGRAM_SEND_REQUEST SendRequest; See WTF below
   PLIST_ENTRY CurrentEntry;
 
   TI_DbgPrint(MID_TRACE, ("Called.\n"));
@@ -330,20 +330,26 @@ VOID AddrFileFree(
   TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting receive requests on AddrFile at 
(0x%X).\n", AddrFile));
 
   /* Go through pending receive request list and cancel them all */
-  while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, 
&AddrFile->Lock))) {
+  while (!IsListEmpty(&AddrFile->ReceiveQueue))
+  {
+    CurrentEntry = RemoveHeadList(&AddrFile->ReceiveQueue);
     ReceiveRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_RECEIVE_REQUEST, 
ListEntry);
     (*ReceiveRequest->Complete)(ReceiveRequest->Context, STATUS_CANCELLED, 0);
-    /* ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG); FIXME: WTF? */
+    ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
   }
 
   TI_DbgPrint(DEBUG_ADDRFILE, ("Aborting send requests on address file at 
(0x%X).\n", AddrFile));
 
+#if 0 /* Biggest WTF. All of this was taken care of above as 
DATAGRAM_RECEIVE_REQUEST. */
   /* Go through pending send request list and cancel them all */
-  while ((CurrentEntry = ExInterlockedRemoveHeadList(&AddrFile->ReceiveQueue, 
&AddrFile->Lock))) {
+  while (!IsListEmpty(&AddrFile->ReceiveQueue))
+  {
+    CurrentEntry = RemoveHeadList(&AddrFile->ReceiveQueue);
     SendRequest = CONTAINING_RECORD(CurrentEntry, DATAGRAM_SEND_REQUEST, 
ListEntry);
     (*SendRequest->Complete)(SendRequest->Context, STATUS_CANCELLED, 0);
     ExFreePoolWithTag(SendRequest, DATAGRAM_SEND_TAG);
   }
+#endif
 
   /* Protocol specific handling */
   switch (AddrFile->Protocol) {
@@ -361,6 +367,8 @@ VOID AddrFileFree(
 
   RemoveEntityByContext(AddrFile);
 
+  ExDeleteResourceLite(&AddrFile->Resource);
+
   ExFreePoolWithTag(Object, ADDR_FILE_TAG);
 }
 
@@ -553,7 +561,7 @@ NTSTATUS FileOpenAddress(
   InitializeListHead(&AddrFile->TransmitQueue);
 
   /* Initialize spin lock that protects the address file object */
-  KeInitializeSpinLock(&AddrFile->Lock);
+  ExInitializeResourceLite(&AddrFile->Resource);
 
   /* Return address file object */
   Request->Handle.AddressHandle = AddrFile;
@@ -581,27 +589,27 @@ NTSTATUS FileCloseAddress(
   PTDI_REQUEST Request)
 {
   PADDRESS_FILE AddrFile = Request->Handle.AddressHandle;
-  KIRQL OldIrql;
+  PCONNECTION_ENDPOINT Listener;
 
   if (!Request->Handle.AddressHandle) return STATUS_INVALID_PARAMETER;
 
-  LockObject(AddrFile, &OldIrql);
+  LockObject(AddrFile);
 
   if (InterlockedDecrement(&AddrFile->Sharers) != 0)
   {
       /* Still other guys have open handles to this, so keep it around */
-      UnlockObject(AddrFile, OldIrql);
+      UnlockObject(AddrFile);
       return STATUS_SUCCESS;
   }
 
   /* We have to close this listener because we started it */
-  if( AddrFile->Listener )
+  Listener = AddrFile->Listener;
+  UnlockObject(AddrFile);
+  if( Listener )
   {
-      TCPClose( AddrFile->Listener );
+      TCPClose( Listener );
   }
 
-  UnlockObject(AddrFile, OldIrql);
-
   DereferenceObject(AddrFile);
 
   TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
diff --git a/drivers/network/tcpip/tcpip/icmp.c 
b/drivers/network/tcpip/tcpip/icmp.c
index 7603e2551a5..67d77c14693 100644
--- a/drivers/network/tcpip/tcpip/icmp.c
+++ b/drivers/network/tcpip/tcpip/icmp.c
@@ -74,11 +74,9 @@ VOID
 ClearReceiveHandler(
     _In_ PADDRESS_FILE AddrFile)
 {
-    KIRQL OldIrql;
-
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
     AddrFile->RegisteredReceiveDatagramHandler = FALSE;
-    UnlockObject(AddrFile, OldIrql);
+    UnlockObject(AddrFile);
 }
 
 IO_WORKITEM_ROUTINE EndRequestHandler;
@@ -95,6 +93,8 @@ EndRequestHandler(
     UINT32 nReplies;
     KIRQL OldIrql;
 
+    
ClearReceiveHandler((PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle);
+
     KeWaitForSingleObject(&Context->DatagramProcessedEvent, Executive, 
KernelMode, FALSE, NULL);
 
     TI_DbgPrint(DEBUG_ICMP, ("Finishing request Context: %p\n", Context));
@@ -267,8 +267,6 @@ TimeoutHandler(
     _In_opt_ PVOID SystemArgument2)
 {
     PICMP_PACKET_CONTEXT Context = (PICMP_PACKET_CONTEXT)_Context;
-    PADDRESS_FILE AddrFile = 
(PADDRESS_FILE)Context->TdiRequest.Handle.AddressHandle;
-    ClearReceiveHandler(AddrFile);
 
     IoQueueWorkItem(Context->FinishWorker, &EndRequestHandler, 
DelayedWorkQueue, _Context);
 }
@@ -290,7 +288,6 @@ DispEchoRequest(
     PUCHAR Buffer;
     UINT16 RequestSize;
     PICMP_PACKET_CONTEXT SendContext;
-    KIRQL OldIrql;
     LARGE_INTEGER RequestTimeout;
     UINT8 SavedTtl;
 
@@ -390,14 +387,14 @@ DispEchoRequest(
 
     RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, OutputBufferLength);
 
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
 
     AddrFile->TTL = SavedTtl;
     AddrFile->ReceiveDatagramHandlerContext = SendContext;
     AddrFile->ReceiveDatagramHandler = ReceiveDatagram;
     AddrFile->RegisteredReceiveDatagramHandler = TRUE;
 
-    UnlockObject(AddrFile, OldIrql);
+    UnlockObject(AddrFile);
 
     Status = AddrFile->Send(AddrFile, &ConnectionInfo, (PCHAR)Buffer, 
RequestSize, &DataUsed);
 
diff --git a/sdk/lib/drivers/ip/transport/datagram/datagram.c 
b/sdk/lib/drivers/ip/transport/datagram/datagram.c
index 053a3020894..2840dc950a7 100644
--- a/sdk/lib/drivers/ip/transport/datagram/datagram.c
+++ b/sdk/lib/drivers/ip/transport/datagram/datagram.c
@@ -16,13 +16,12 @@ BOOLEAN DGRemoveIRP(
 {
     PLIST_ENTRY ListEntry;
     PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
-    KIRQL OldIrql;
     BOOLEAN Found = FALSE;
 
     TI_DbgPrint(MAX_TRACE, ("Called (Cancel IRP %08x for file %08x).\n",
                             Irp, AddrFile));
 
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
 
     for( ListEntry = AddrFile->ReceiveQueue.Flink;
          ListEntry != &AddrFile->ReceiveQueue;
@@ -42,7 +41,7 @@ BOOLEAN DGRemoveIRP(
         }
     }
 
-    UnlockObject(AddrFile, OldIrql);
+    UnlockObject(AddrFile);
 
     TI_DbgPrint(MAX_TRACE, ("Done.\n"));
 
@@ -73,7 +72,6 @@ DGDeliverData(
  *     handler if it exists, otherwise we drop the packet.
  */
 {
-    KIRQL OldIrql;
     LONG AddressLength;
     PVOID SourceAddress;
     ULONG BytesTaken;
@@ -82,7 +80,7 @@ DGDeliverData(
 
     TI_DbgPrint(MIN_TRACE, ("Called.\n"));
 
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
 
     if (AddrFile->Protocol == IPPROTO_UDP)
     {
@@ -145,7 +143,7 @@ DGDeliverData(
                             SrcAddress->Address.IPv4Address, SrcPort));
 
                 ReferenceObject(AddrFile);
-                UnlockObject(AddrFile, OldIrql);
+                UnlockObject(AddrFile);
 
                 /* Complete the receive request */
                 if (Current->BufferSize < DataSize)
@@ -153,12 +151,12 @@ DGDeliverData(
                 else
                     Current->Complete(Current->Context, STATUS_SUCCESS, 
DataSize);
 
-                LockObject(AddrFile, &OldIrql);
+                LockObject(AddrFile);
                 DereferenceObject(AddrFile);
             }
         }
 
-        UnlockObject(AddrFile, OldIrql);
+        UnlockObject(AddrFile);
     }
     else if (AddrFile->RegisteredReceiveDatagramHandler)
     {
@@ -186,7 +184,7 @@ DGDeliverData(
         }
 
         ReferenceObject(AddrFile);
-        UnlockObject(AddrFile, OldIrql);
+        UnlockObject(AddrFile);
 
         TI_DbgPrint(MIN_TRACE, ("OptionsSize %d DataSize: %u\n", OptionsSize, 
DataSize));
 
@@ -209,7 +207,7 @@ DGDeliverData(
     }
     else
     {
-        UnlockObject(AddrFile, OldIrql);
+        UnlockObject(AddrFile);
         TI_DbgPrint(MAX_TRACE, ("Discarding datagram.\n"));
     }
 
@@ -254,11 +252,10 @@ NTSTATUS DGReceiveDatagram(
 {
     NTSTATUS Status;
     PDATAGRAM_RECEIVE_REQUEST ReceiveRequest;
-    KIRQL OldIrql;
 
     TI_DbgPrint(MAX_TRACE, ("Called.\n"));
 
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
 
     ReceiveRequest = ExAllocatePoolWithTag(NonPagedPool, 
sizeof(DATAGRAM_RECEIVE_REQUEST),
                                            DATAGRAM_RECV_TAG);
@@ -276,7 +273,7 @@ NTSTATUS DGReceiveDatagram(
            if (!NT_SUCCESS(Status))
             {
                ExFreePoolWithTag(ReceiveRequest, DATAGRAM_RECV_TAG);
-               UnlockObject(AddrFile, OldIrql);
+               UnlockObject(AddrFile);
                return Status;
             }
        }
@@ -304,13 +301,13 @@ NTSTATUS DGReceiveDatagram(
 
        TI_DbgPrint(MAX_TRACE, ("Leaving (pending %08x).\n", ReceiveRequest));
 
-       UnlockObject(AddrFile, OldIrql);
+       UnlockObject(AddrFile);
 
        return STATUS_PENDING;
     }
     else
     {
-       UnlockObject(AddrFile, OldIrql);
+       UnlockObject(AddrFile);
         Status = STATUS_INSUFFICIENT_RESOURCES;
     }
 
diff --git a/sdk/lib/drivers/ip/transport/rawip/rawip.c 
b/sdk/lib/drivers/ip/transport/rawip/rawip.c
index 7e7fb22436a..cb32d4b02e3 100644
--- a/sdk/lib/drivers/ip/transport/rawip/rawip.c
+++ b/sdk/lib/drivers/ip/transport/rawip/rawip.c
@@ -191,9 +191,8 @@ NTSTATUS RawIPSendDatagram(
     USHORT RemotePort;
     NTSTATUS Status;
     PNEIGHBOR_CACHE_ENTRY NCE;
-    KIRQL OldIrql;
 
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
 
     TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
                           AddrFile, ConnInfo, BufferData, DataSize));
@@ -208,7 +207,7 @@ NTSTATUS RawIPSendDatagram(
             break;
 
         default:
-            UnlockObject(AddrFile, OldIrql);
+            UnlockObject(AddrFile);
             return STATUS_UNSUCCESSFUL;
     }
 
@@ -222,7 +221,7 @@ NTSTATUS RawIPSendDatagram(
          * interface we're sending over
          */
         if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
-            UnlockObject(AddrFile, OldIrql);
+            UnlockObject(AddrFile);
             return STATUS_NETWORK_UNREACHABLE;
         }
 
@@ -231,7 +230,7 @@ NTSTATUS RawIPSendDatagram(
     else
     {
         if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) {
-            UnlockObject(AddrFile, OldIrql);
+            UnlockObject(AddrFile);
             return STATUS_INVALID_PARAMETER;
         }
     }
@@ -245,7 +244,7 @@ NTSTATUS RawIPSendDatagram(
                                BufferData,
                                DataSize );
 
-    UnlockObject(AddrFile, OldIrql);
+    UnlockObject(AddrFile);
 
     if( !NT_SUCCESS(Status) )
         return Status;
diff --git a/sdk/lib/drivers/ip/transport/tcp/accept.c 
b/sdk/lib/drivers/ip/transport/tcp/accept.c
index aab177a94ad..19b6d4644ca 100644
--- a/sdk/lib/drivers/ip/transport/tcp/accept.c
+++ b/sdk/lib/drivers/ip/transport/tcp/accept.c
@@ -48,12 +48,11 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT 
Backlog)
 {
     NTSTATUS Status = STATUS_SUCCESS;
     struct ip_addr AddressToBind;
-    KIRQL OldIrql;
     TA_IP_ADDRESS LocalAddress;
 
     ASSERT(Connection);
 
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     ASSERT_KM_POINTER(Connection->AddressFile);
 
@@ -93,7 +92,7 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT 
Backlog)
             Status = STATUS_UNSUCCESSFUL;
     }
 
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPListen] Leaving. Status = %x\n", Status));
 
@@ -106,10 +105,9 @@ BOOLEAN TCPAbortListenForSocket
 {
     PLIST_ENTRY ListEntry;
     PTDI_BUCKET Bucket;
-    KIRQL OldIrql;
     BOOLEAN Found = FALSE;
 
-    LockObject(Listener, &OldIrql);
+    LockObject(Listener);
 
     ListEntry = Listener->ListenRequest.Flink;
     while (ListEntry != &Listener->ListenRequest)
@@ -128,7 +126,7 @@ BOOLEAN TCPAbortListenForSocket
         ListEntry = ListEntry->Flink;
     }
 
-    UnlockObject(Listener, OldIrql);
+    UnlockObject(Listener);
 
     return Found;
 }
@@ -141,9 +139,8 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
 {
     NTSTATUS Status;
     PTDI_BUCKET Bucket;
-    KIRQL OldIrql;
 
-    LockObject(Listener, &OldIrql);
+    LockObject(Listener);
 
     Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
 
@@ -160,7 +157,7 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
     else
         Status = STATUS_NO_MEMORY;
 
-    UnlockObject(Listener, OldIrql);
+    UnlockObject(Listener);
 
     return Status;
 }
diff --git a/sdk/lib/drivers/ip/transport/tcp/event.c 
b/sdk/lib/drivers/ip/transport/tcp/event.c
index 02613c2af17..9294815d3d1 100644
--- a/sdk/lib/drivers/ip/transport/tcp/event.c
+++ b/sdk/lib/drivers/ip/transport/tcp/event.c
@@ -50,125 +50,66 @@ CompleteBucket(PCONNECTION_ENDPOINT Connection, 
PTDI_BUCKET Bucket, const BOOLEA
 }
 
 VOID
-FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, 
const BOOLEAN interlocked)
+FlushReceiveQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
 {
     PTDI_BUCKET Bucket;
     PLIST_ENTRY Entry;
 
-    ReferenceObject(Connection);
+    ASSERT_TCPIP_OBJECT_LOCKED(Connection);
 
-    if (interlocked)
+    while (!IsListEmpty(&Connection->ReceiveRequest))
     {
-        while ((Entry = 
ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, &Connection->Lock)))
-        {
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-            TI_DbgPrint(DEBUG_TCP,
-                        ("Completing Receive request: %x %x\n",
-                         Bucket->Request, Status));
+        Entry = RemoveHeadList(&Connection->ReceiveRequest);
 
-            Bucket->Status = Status;
-            Bucket->Information = 0;
+        Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
 
-            CompleteBucket(Connection, Bucket, FALSE);
-        }
-    }
-    else
-    {
-        while (!IsListEmpty(&Connection->ReceiveRequest))
-        {
-            Entry = RemoveHeadList(&Connection->ReceiveRequest);
-
-            Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
-
-            Bucket->Information = 0;
-            Bucket->Status = Status;
+        Bucket->Information = 0;
+        Bucket->Status = Status;
 
-            CompleteBucket(Connection, Bucket, FALSE);
-        }
+        CompleteBucket(Connection, Bucket, FALSE);
     }
-
-    DereferenceObject(Connection);
 }
 
 VOID
-FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, const 
BOOLEAN interlocked)
+FlushSendQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
 {
     PTDI_BUCKET Bucket;
     PLIST_ENTRY Entry;
 
-    ReferenceObject(Connection);
+    ASSERT_TCPIP_OBJECT_LOCKED(Connection);
 
-    if (interlocked)
+    while (!IsListEmpty(&Connection->SendRequest))
     {
-        while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, 
&Connection->Lock)))
-        {
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-            TI_DbgPrint(DEBUG_TCP,
-                        ("Completing Send request: %x %x\n",
-                         Bucket->Request, Status));
-
-            Bucket->Status = Status;
-            Bucket->Information = 0;
-
-            CompleteBucket(Connection, Bucket, FALSE);
-        }
-    }
-    else
-    {
-        while (!IsListEmpty(&Connection->SendRequest))
-        {
-            Entry = RemoveHeadList(&Connection->SendRequest);
+        Entry = RemoveHeadList(&Connection->SendRequest);
 
-            Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
+        Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
 
-            Bucket->Information = 0;
-            Bucket->Status = Status;
+        Bucket->Information = 0;
+        Bucket->Status = Status;
 
-            CompleteBucket(Connection, Bucket, FALSE);
-        }
+        CompleteBucket(Connection, Bucket, FALSE);
     }
-
-    DereferenceObject(Connection);
 }
 
 VOID
-FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status, 
const BOOLEAN interlocked)
+FlushShutdownQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
 {
     PTDI_BUCKET Bucket;
     PLIST_ENTRY Entry;
 
-    ReferenceObject(Connection);
-
-    if (interlocked)
-    {
-        while ((Entry = 
ExInterlockedRemoveHeadList(&Connection->ShutdownRequest, &Connection->Lock)))
-        {
-            Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
-
-            Bucket->Status = Status;
-            Bucket->Information = 0;
+    ASSERT_TCPIP_OBJECT_LOCKED(Connection);
 
-            CompleteBucket(Connection, Bucket, FALSE);
-        }
-    }
-    else
+    while (!IsListEmpty(&Connection->ShutdownRequest))
     {
-        while (!IsListEmpty(&Connection->ShutdownRequest))
-        {
-            Entry = RemoveHeadList(&Connection->ShutdownRequest);
+        Entry = RemoveHeadList(&Connection->ShutdownRequest);
 
-            Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
+        Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
 
-            Bucket->Information = 0;
-            Bucket->Status = Status;
+        Bucket->Information = 0;
+        Bucket->Status = Status;
 
-            CompleteBucket(Connection, Bucket, FALSE);
-        }
+        CompleteBucket(Connection, Bucket, FALSE);
     }
-
-    DereferenceObject(Connection);
 }
 
 VOID
@@ -177,10 +118,11 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const 
NTSTATUS Status)
     PTDI_BUCKET Bucket;
     PLIST_ENTRY Entry;
 
-    ReferenceObject(Connection);
+    ASSERT_TCPIP_OBJECT_LOCKED(Connection);
 
-    while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, 
&Connection->Lock)))
+    while (!IsListEmpty(&Connection->ConnectRequest))
     {
+        Entry = RemoveHeadList(&Connection->ConnectRequest);
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
 
         Bucket->Status = Status;
@@ -188,8 +130,6 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const 
NTSTATUS Status)
 
         CompleteBucket(Connection, Bucket, FALSE);
     }
-
-    DereferenceObject(Connection);
 }
 
 VOID
@@ -198,10 +138,11 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const 
NTSTATUS Status)
     PTDI_BUCKET Bucket;
     PLIST_ENTRY Entry;
 
-    ReferenceObject(Connection);
+    ASSERT_TCPIP_OBJECT_LOCKED(Connection);
 
-    while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, 
&Connection->Lock)))
+    while (!IsListEmpty(&Connection->ListenRequest))
     {
+        Entry = RemoveHeadList(&Connection->ListenRequest);
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
 
         Bucket->Status = Status;
@@ -210,17 +151,13 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const 
NTSTATUS Status)
         DereferenceObject(Bucket->AssociatedEndpoint);
         CompleteBucket(Connection, Bucket, FALSE);
     }
-
-    DereferenceObject(Connection);
 }
 
 VOID
 FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS Status)
 {
-    ReferenceObject(Connection);
-
     // flush receive queue
-    FlushReceiveQueue(Connection, Status, TRUE);
+    FlushReceiveQueue(Connection, Status);
 
     /* We completed the reads successfully but we need to return failure now */
     if (Status == STATUS_SUCCESS)
@@ -232,15 +169,13 @@ FlushAllQueues(PCONNECTION_ENDPOINT Connection, NTSTATUS 
Status)
     FlushListenQueue(Connection, Status);
 
     // flush send queue
-    FlushSendQueue(Connection, Status, TRUE);
+    FlushSendQueue(Connection, Status);
 
     // flush connect queue
     FlushConnectQueue(Connection, Status);
 
     // flush shutdown queue
-    FlushShutdownQueue(Connection, Status, TRUE);
-
-    DereferenceObject(Connection);
+    FlushShutdownQueue(Connection, Status);
 }
 
 VOID
@@ -248,18 +183,17 @@ TCPFinEventHandler(void *arg, const err_t err)
 {
    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg, LastConnection;
    const NTSTATUS Status = TCPTranslateError(err);
-   KIRQL OldIrql;
 
    ASSERT(Connection->SocketContext == NULL);
    ASSERT(Connection->AddressFile);
    ASSERT(err != ERR_OK);
 
+   LockObject(Connection);
+
    /* Complete all outstanding requests now */
    FlushAllQueues(Connection, Status);
 
-   LockObject(Connection, &OldIrql);
-
-   LockObjectAtDpcLevel(Connection->AddressFile);
+   LockObject(Connection->AddressFile);
 
    /* Unlink this connection from the address file */
    if (Connection->AddressFile->Connection == Connection)
@@ -284,13 +218,13 @@ TCPFinEventHandler(void *arg, const err_t err)
        }
    }
 
-   UnlockObjectFromDpcLevel(Connection->AddressFile);
+   UnlockObject(Connection->AddressFile);
 
    /* Remove the address file from this connection */
    DereferenceObject(Connection->AddressFile);
    Connection->AddressFile = NULL;
 
-   UnlockObject(Connection, OldIrql);
+   UnlockObject(Connection);
 }
 
 VOID
@@ -301,14 +235,15 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
     PLIST_ENTRY Entry;
     PIRP Irp;
     NTSTATUS Status;
-    KIRQL OldIrql;
 
-    ReferenceObject(Connection);
+    LockObject(Connection);
 
-    while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, 
&Connection->Lock)))
+    while (!IsListEmpty(&Connection->ListenRequest))
     {
         PIO_STACK_LOCATION IrpSp;
 
+        Entry = RemoveHeadList(&Connection->ListenRequest);
+
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
 
         Irp = Bucket->Request.RequestContext;
@@ -326,7 +261,7 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
 
         if (Status == STATUS_SUCCESS)
         {
-            LockObject(Bucket->AssociatedEndpoint, &OldIrql);
+            LockObject(Bucket->AssociatedEndpoint);
 
             /* sanity assert...this should never be in anything else but a 
CLOSED state */
             ASSERT( 
((PTCP_PCB)Bucket->AssociatedEndpoint->SocketContext)->state == CLOSED );
@@ -337,9 +272,9 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
             /* free previously created socket context (we don't use it, we use 
newpcb) */
             Bucket->AssociatedEndpoint->SocketContext = newpcb;
 
-            LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, 
Bucket->AssociatedEndpoint);
+            UnlockObject(Bucket->AssociatedEndpoint);
 
-            UnlockObject(Bucket->AssociatedEndpoint, OldIrql);
+            LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, 
Bucket->AssociatedEndpoint);
         }
 
         DereferenceObject(Bucket->AssociatedEndpoint);
@@ -352,7 +287,7 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
         }
     }
 
-    DereferenceObject(Connection);
+    UnlockObject(Connection);
 }
 
 VOID
@@ -367,12 +302,17 @@ TCPSendEventHandler(void *arg, const u16_t space)
     ULONG BytesSent;
 
     ReferenceObject(Connection);
+    LockObject(Connection);
 
-    while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, 
&Connection->Lock)))
+    while (!IsListEmpty(&Connection->SendRequest))
     {
         UINT SendLen = 0;
         PVOID SendBuffer = 0;
 
+        Entry = RemoveHeadList(&Connection->SendRequest);
+
+        UnlockObject(Connection);
+
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
 
         Irp = Bucket->Request.RequestContext;
@@ -400,9 +340,8 @@ TCPSendEventHandler(void *arg, const u16_t space)
 
         if( Status == STATUS_PENDING )
         {
-            ExInterlockedInsertHeadList(&Connection->SendRequest,
-                                        &Bucket->Entry,
-                                        &Connection->Lock);
+            LockObject(Connection);
+            InsertHeadList(&Connection->SendRequest, &Bucket->Entry);
             break;
         }
         else
@@ -416,13 +355,15 @@ TCPSendEventHandler(void *arg, const u16_t space)
 
             CompleteBucket(Connection, Bucket, FALSE);
         }
+
+        LockObject(Connection);
     }
 
     //  If we completed all outstanding send requests then finish all pending 
shutdown requests,
     //  cancel the timer and dereference the connection
     if (IsListEmpty(&Connection->SendRequest))
     {
-        FlushShutdownQueue(Connection, STATUS_SUCCESS, FALSE);
+        FlushShutdownQueue(Connection, STATUS_SUCCESS);
 
         if (KeCancelTimer(&Connection->DisconnectTimer))
         {
@@ -430,6 +371,8 @@ TCPSendEventHandler(void *arg, const u16_t space)
         }
     }
 
+    UnlockObject(Connection);
+
     DereferenceObject(Connection);
 }
 
@@ -446,10 +389,11 @@ TCPRecvEventHandler(void *arg)
     PUCHAR RecvBuffer;
     NTSTATUS Status;
 
-    ReferenceObject(Connection);
+    LockObject(Connection);
 
-    while ((Entry = ExInterlockedRemoveHeadList(&Connection->ReceiveRequest, 
&Connection->Lock)))
+    while(!IsListEmpty(&Connection->ReceiveRequest))
     {
+        Entry = RemoveHeadList(&Connection->ReceiveRequest);
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
 
         Irp = Bucket->Request.RequestContext;
@@ -460,9 +404,7 @@ TCPRecvEventHandler(void *arg)
         Status = LibTCPGetDataFromConnectionQueue(Connection, RecvBuffer, 
RecvLen, &Received);
         if (Status == STATUS_PENDING)
         {
-            ExInterlockedInsertHeadList(&Connection->ReceiveRequest,
-                                        &Bucket->Entry,
-                                        &Connection->Lock);
+            InsertHeadList(&Connection->ReceiveRequest, &Bucket->Entry);
             break;
         }
 
@@ -471,8 +413,7 @@ TCPRecvEventHandler(void *arg)
 
         CompleteBucket(Connection, Bucket, FALSE);
     }
-
-    DereferenceObject(Connection);
+    UnlockObject(Connection);
 }
 
 VOID
@@ -482,10 +423,11 @@ TCPConnectEventHandler(void *arg, const err_t err)
     PTDI_BUCKET Bucket;
     PLIST_ENTRY Entry;
 
-    ReferenceObject(Connection);
+    LockObject(Connection);
 
-    while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, 
&Connection->Lock)))
+    while (!IsListEmpty(&Connection->ConnectRequest))
     {
+        Entry = RemoveHeadList(&Connection->ConnectRequest);
 
         Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
 
@@ -495,5 +437,5 @@ TCPConnectEventHandler(void *arg, const err_t err)
         CompleteBucket(Connection, Bucket, FALSE);
     }
 
-    DereferenceObject(Connection);
+    UnlockObject(Connection);
 }
diff --git a/sdk/lib/drivers/ip/transport/tcp/tcp.c 
b/sdk/lib/drivers/ip/transport/tcp/tcp.c
index d18b350a967..7bdc8ab7486 100644
--- a/sdk/lib/drivers/ip/transport/tcp/tcp.c
+++ b/sdk/lib/drivers/ip/transport/tcp/tcp.c
@@ -25,21 +25,27 @@ PORT_SET TCPPorts;
 
 NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
 
-VOID NTAPI
-DisconnectTimeoutDpc(PKDPC Dpc,
-                     PVOID DeferredContext,
-                     PVOID SystemArgument1,
-                     PVOID SystemArgument2)
+static
+IO_WORKITEM_ROUTINE
+DisconnectWorker;
+
+_Use_decl_annotations_
+VOID
+NTAPI
+DisconnectWorker(
+    _Unreferenced_parameter_ PDEVICE_OBJECT DeviceObject,
+    _In_ PVOID Context
+)
 {
-    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
+    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Context;
     PLIST_ENTRY Entry;
     PTDI_BUCKET Bucket;
 
-    LockObjectAtDpcLevel(Connection);
-
     /* We timed out waiting for pending sends so force it to shutdown */
     TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
 
+    LockObject(Connection);
+
     while (!IsListEmpty(&Connection->SendRequest))
     {
         Entry = RemoveHeadList(&Connection->SendRequest);
@@ -64,11 +70,23 @@ DisconnectTimeoutDpc(PKDPC Dpc,
         CompleteBucket(Connection, Bucket, FALSE);
     }
 
-    UnlockObjectFromDpcLevel(Connection);
+    UnlockObject(Connection);
 
     DereferenceObject(Connection);
 }
 
+VOID
+NTAPI
+DisconnectTimeoutDpc(PKDPC Dpc,
+                     PVOID DeferredContext,
+                     PVOID SystemArgument1,
+                     PVOID SystemArgument2)
+{
+    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
+
+    IoQueueWorkItem(Connection->DisconnectWorkItem, DisconnectWorker, 
DelayedWorkQueue, Connection);
+}
+
 VOID ConnectionFree(PVOID Object)
 {
     PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Object;
@@ -80,6 +98,9 @@ VOID ConnectionFree(PVOID Object)
     RemoveEntryList(&Connection->ListEntry);
     TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
 
+    ExDeleteResourceLite(&Connection->Resource);
+    IoFreeWorkItem(Connection->DisconnectWorkItem);
+
     ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
 }
 
@@ -96,7 +117,7 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID 
ClientContext )
     RtlZeroMemory(Connection, sizeof(CONNECTION_ENDPOINT));
 
     /* Initialize spin lock that protects the connection endpoint file object 
*/
-    KeInitializeSpinLock(&Connection->Lock);
+    ExInitializeResourceLite(&Connection->Resource);
     InitializeListHead(&Connection->ConnectRequest);
     InitializeListHead(&Connection->ListenRequest);
     InitializeListHead(&Connection->ReceiveRequest);
@@ -107,6 +128,13 @@ PCONNECTION_ENDPOINT TCPAllocateConnectionEndpoint( PVOID 
ClientContext )
     /* Initialize disconnect timer */
     KeInitializeTimer(&Connection->DisconnectTimer);
     KeInitializeDpc(&Connection->DisconnectDpc, DisconnectTimeoutDpc, 
Connection);
+    Connection->DisconnectWorkItem = IoAllocateWorkItem(TCPDeviceObject);
+    if (!Connection->DisconnectWorkItem)
+    {
+        ExDeleteResourceLite(&Connection->Resource);
+        ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
+        return NULL;
+    }
 
     /* Save client context pointer */
     Connection->ClientContext = ClientContext;
@@ -126,9 +154,8 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
                     UINT Family, UINT Type, UINT Proto )
 {
     NTSTATUS Status;
-    KIRQL OldIrql;
 
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Called: Connection %x, Family %d, 
Type %d, "
                            "Proto %d, sizeof(CONNECTION_ENDPOINT) = %d\n",
@@ -140,7 +167,7 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
     else
         Status = STATUS_INSUFFICIENT_RESOURCES;
 
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPSocket] Leaving. Status = 0x%x\n", 
Status));
 
@@ -149,15 +176,13 @@ NTSTATUS TCPSocket( PCONNECTION_ENDPOINT Connection,
 
 NTSTATUS TCPClose( PCONNECTION_ENDPOINT Connection )
 {
-    KIRQL OldIrql;
-
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     FlushAllQueues(Connection, STATUS_CANCELLED);
 
-    LibTCPClose(Connection, FALSE, TRUE);
+    UnlockObject(Connection);
 
-    UnlockObject(Connection, OldIrql);
+    LibTCPClose(Connection, FALSE, TRUE);
 
     DereferenceObject(Connection);
 
@@ -287,7 +312,6 @@ NTSTATUS TCPConnect
     TA_IP_ADDRESS LocalAddress;
     PTDI_BUCKET Bucket;
     PNEIGHBOR_CACHE_ENTRY NCE;
-    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n"));
 
@@ -308,11 +332,11 @@ NTSTATUS TCPConnect
                  RemoteAddress.Address.IPv4Address,
                  RemotePort));
 
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     if (!Connection->AddressFile)
     {
-        UnlockObject(Connection, OldIrql);
+        UnlockObject(Connection);
         return STATUS_INVALID_PARAMETER;
     }
 
@@ -320,7 +344,7 @@ NTSTATUS TCPConnect
     {
         if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
         {
-            UnlockObject(Connection, OldIrql);
+            UnlockObject(Connection);
             return STATUS_NETWORK_UNREACHABLE;
         }
 
@@ -335,48 +359,51 @@ NTSTATUS TCPConnect
                                           &bindaddr,
                                           Connection->AddressFile->Port));
 
-    if (NT_SUCCESS(Status))
+    if (!NT_SUCCESS(Status))
     {
-        /* Copy bind address into connection */
-        Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr;
-        /* Check if we had an unspecified port */
-        if (!Connection->AddressFile->Port)
-        {
-            /* We did, so we need to copy back the port */
-            Status = TCPGetSockAddress(Connection, 
(PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
-            if (NT_SUCCESS(Status))
-            {
-                /* Allocate the port in the port bitmap */
-                Connection->AddressFile->Port = 
TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
-
-                /* This should never fail */
-                ASSERT(Connection->AddressFile->Port != 0xFFFF);
-            }
-        }
+        UnlockObject(Connection);
+        return Status;
+    }
 
-        if (NT_SUCCESS(Status))
+    /* Copy bind address into connection */
+    Connection->AddressFile->Address.Address.IPv4Address = bindaddr.addr;
+    /* Check if we had an unspecified port */
+    if (!Connection->AddressFile->Port)
+    {
+        /* We did, so we need to copy back the port */
+        Status = TCPGetSockAddress(Connection, 
(PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
+        if (!NT_SUCCESS(Status))
         {
-            connaddr.addr = RemoteAddress.Address.IPv4Address;
+            UnlockObject(Connection);
+            return Status;
+        }
 
-            Bucket = 
ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
-            if (!Bucket)
-            {
-                UnlockObject(Connection, OldIrql);
-                return STATUS_NO_MEMORY;
-            }
+        /* Allocate the port in the port bitmap */
+        Connection->AddressFile->Port = 
TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
 
-            Bucket->Request.RequestNotifyObject = (PVOID)Complete;
-            Bucket->Request.RequestContext = Context;
+        /* This should never fail */
+        ASSERT(Connection->AddressFile->Port != 0xFFFF);
+    }
 
-            InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
+    connaddr.addr = RemoteAddress.Address.IPv4Address;
 
-            Status = TCPTranslateError(LibTCPConnect(Connection,
-                                                     &connaddr,
-                                                     RemotePort));
-        }
+    Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
+    if (!Bucket)
+    {
+        UnlockObject(Connection);
+        return STATUS_NO_MEMORY;
     }
 
-    UnlockObject(Connection, OldIrql);
+    Bucket->Request.RequestNotifyObject = (PVOID)Complete;
+    Bucket->Request.RequestContext = Context;
+
+    InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
+
+    UnlockObject(Connection);
+
+    Status = TCPTranslateError(LibTCPConnect(Connection,
+                                                &connaddr,
+                                                RemotePort));
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", 
Status));
 
@@ -394,12 +421,11 @@ NTSTATUS TCPDisconnect
 {
     NTSTATUS Status = STATUS_INVALID_PARAMETER;
     PTDI_BUCKET Bucket;
-    KIRQL OldIrql;
     LARGE_INTEGER ActualTimeout;
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Called\n"));
 
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     if (Connection->SocketContext)
     {
@@ -407,12 +433,20 @@ NTSTATUS TCPDisconnect
         {
             if (IsListEmpty(&Connection->SendRequest))
             {
+                ReferenceObject(Connection);
+                UnlockObject(Connection);
                 Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
+                LockObject(Connection);
+                DereferenceObject(Connection);
             }
             else if (Timeout && Timeout->QuadPart == 0)
             {
-                FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
-                TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
+                FlushSendQueue(Connection, STATUS_FILE_CLOSED);
+                ReferenceObject(Connection);
+                UnlockObject(Connection);
+                LibTCPShutdown(Connection, 0, 1);
+                LockObject(Connection);
+                DereferenceObject(Connection);
                 Status = STATUS_TIMEOUT;
             }
             else
@@ -431,7 +465,7 @@ NTSTATUS TCPDisconnect
                 Bucket = 
ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
                 if (!Bucket)
                 {
-                    UnlockObject(Connection, OldIrql);
+                    UnlockObject(Connection);
                     return STATUS_NO_MEMORY;
                 }
 
@@ -441,11 +475,11 @@ NTSTATUS TCPDisconnect
                 InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);
 
                 ReferenceObject(Connection);
-                if (KeCancelTimer(&Connection->DisconnectTimer))
+                if (KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, 
&Connection->DisconnectDpc))
                 {
+                    /* Timer was already in the queue. */
                     DereferenceObject(Connection);
                 }
-                KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, 
&Connection->DisconnectDpc);
 
                 Status = STATUS_PENDING;
             }
@@ -453,20 +487,26 @@ NTSTATUS TCPDisconnect
 
         if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
         {
-            FlushReceiveQueue(Connection, STATUS_FILE_CLOSED, FALSE);
-            FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
-            FlushShutdownQueue(Connection, STATUS_FILE_CLOSED, FALSE);
+            FlushReceiveQueue(Connection, STATUS_FILE_CLOSED);
+            FlushSendQueue(Connection, STATUS_FILE_CLOSED);
+            FlushShutdownQueue(Connection, STATUS_FILE_CLOSED);
+            ReferenceObject(Connection);
+            UnlockObject(Connection);
             Status = TCPTranslateError(LibTCPShutdown(Connection, 1, 1));
+            DereferenceObject(Connection);
+        }
+        else
+        {
+            UnlockObject(Connection);
         }
     }
     else
     {
+        UnlockObject(Connection);
         /* We already got closed by the other side so just return success */
         Status = STATUS_SUCCESS;
     }
 
-    UnlockObject(Connection, OldIrql);
-
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Leaving. Status = 0x%x\n", 
Status));
 
     return Status;
@@ -506,7 +546,9 @@ NTSTATUS TCPReceiveData
         Bucket->Request.RequestNotifyObject = Complete;
         Bucket->Request.RequestContext = Context;
 
-        ExInterlockedInsertTailList( &Connection->ReceiveRequest, 
&Bucket->Entry, &Connection->Lock );
+        LockObject(Connection);
+        InsertTailList( &Connection->ReceiveRequest, &Bucket->Entry );
+        UnlockObject(Connection);
         TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Queued read irp\n"));
 
         TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Leaving. Status = 
STATUS_PENDING\n"));
@@ -532,9 +574,8 @@ NTSTATUS TCPSendData
 {
     NTSTATUS Status;
     PTDI_BUCKET Bucket;
-    KIRQL OldIrql;
 
-    LockObject(Connection, &OldIrql);
+    ReferenceObject(Connection);
 
     TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Called for %d bytes (on socket 
%x)\n",
                            SendLength, Connection->SocketContext));
@@ -558,7 +599,7 @@ NTSTATUS TCPSendData
         Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
         if (!Bucket)
         {
-            UnlockObject(Connection, OldIrql);
+            DereferenceObject(Connection);
             TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Failed to allocate 
bucket\n"));
             return STATUS_NO_MEMORY;
         }
@@ -566,13 +607,15 @@ NTSTATUS TCPSendData
         Bucket->Request.RequestNotifyObject = Complete;
         Bucket->Request.RequestContext = Context;
 
+        LockObject(Connection);
         InsertTailList( &Connection->SendRequest, &Bucket->Entry );
         TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
+        UnlockObject(Connection);
     }
 
-    UnlockObject(Connection, OldIrql);
 
     TI_DbgPrint(DEBUG_TCP, ("[IP, TCPSendData] Leaving. Status = %x\n", 
Status));
+    DereferenceObject(Connection);
 
     return Status;
 }
@@ -606,13 +649,12 @@ NTSTATUS TCPGetSockAddress
     PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
     struct ip_addr ipaddr;
     NTSTATUS Status;
-    KIRQL OldIrql;
 
     AddressIP->TAAddressCount = 1;
     AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
     AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
 
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     if (GetRemote)
     {
@@ -627,7 +669,7 @@ NTSTATUS TCPGetSockAddress
                                     
&AddressIP->Address[0].Address[0].sin_port));
     }
 
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
 
     AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
 
@@ -641,7 +683,6 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP 
Irp )
 {
     PLIST_ENTRY Entry;
     PLIST_ENTRY ListHead[5];
-    KIRQL OldIrql;
     PTDI_BUCKET Bucket;
     UINT i = 0;
     BOOLEAN Found = FALSE;
@@ -652,7 +693,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP 
Irp )
     ListHead[3] = &Endpoint->ListenRequest;
     ListHead[4] = &Endpoint->ShutdownRequest;
 
-    LockObject(Endpoint, &OldIrql);
+    LockObject(Endpoint);
 
     for( i = 0; i < 5; i++ )
     {
@@ -671,7 +712,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP 
Irp )
         }
     }
 
-    UnlockObject(Endpoint, OldIrql);
+    UnlockObject(Endpoint);
 
     return Found;
 }
diff --git a/sdk/lib/drivers/ip/transport/udp/udp.c 
b/sdk/lib/drivers/ip/transport/udp/udp.c
index 783dae988b9..0ad09fa7bf3 100644
--- a/sdk/lib/drivers/ip/transport/udp/udp.c
+++ b/sdk/lib/drivers/ip/transport/udp/udp.c
@@ -171,9 +171,8 @@ NTSTATUS UDPSendDatagram(
     USHORT RemotePort;
     NTSTATUS Status;
     PNEIGHBOR_CACHE_ENTRY NCE;
-    KIRQL OldIrql;
 
-    LockObject(AddrFile, &OldIrql);
+    LockObject(AddrFile);
 
     TI_DbgPrint(MID_TRACE,("Sending Datagram(%x %x %x %d)\n",
                                                   AddrFile, ConnInfo, 
BufferData, DataSize));
@@ -188,7 +187,7 @@ NTSTATUS UDPSendDatagram(
                break;
 
     default:
-               UnlockObject(AddrFile, OldIrql);
+               UnlockObject(AddrFile);
                return STATUS_UNSUCCESSFUL;
     }
 
@@ -200,7 +199,7 @@ NTSTATUS UDPSendDatagram(
          * interface we're sending over
          */
         if(!(NCE = RouteGetRouteToDestination( &RemoteAddress ))) {
-            UnlockObject(AddrFile, OldIrql);
+            UnlockObject(AddrFile);
             return STATUS_NETWORK_UNREACHABLE;
         }
 
@@ -209,7 +208,7 @@ NTSTATUS UDPSendDatagram(
     else
     {
         if(!(NCE = NBLocateNeighbor( &LocalAddress, NULL ))) {
-            UnlockObject(AddrFile, OldIrql);
+            UnlockObject(AddrFile);
             return STATUS_INVALID_PARAMETER;
         }
     }
@@ -223,7 +222,7 @@ NTSTATUS UDPSendDatagram(
                                                         BufferData,
                                                         DataSize );
 
-    UnlockObject(AddrFile, OldIrql);
+    UnlockObject(AddrFile);
 
     if( !NT_SUCCESS(Status) )
                return Status;
diff --git a/sdk/lib/drivers/lwip/src/include/rosip.h 
b/sdk/lib/drivers/lwip/src/include/rosip.h
index af852910d2f..701a65614da 100644
--- a/sdk/lib/drivers/lwip/src/include/rosip.h
+++ b/sdk/lib/drivers/lwip/src/include/rosip.h
@@ -31,6 +31,9 @@ struct lwip_callback_msg
         struct {
             PVOID Arg;
         } Socket;
+        struct {
+            struct tcp_pcb* pcb;
+        } FreeSocket;
         struct {
             PCONNECTION_ENDPOINT Connection;
             struct ip_addr *IpAddress;
@@ -99,6 +102,7 @@ extern void TCPRecvEventHandler(void *arg);
 
 /* TCP functions */
 PTCP_PCB    LibTCPSocket(void *arg);
+VOID        LibTCPFreeSocket(PTCP_PCB pcb);
 err_t       LibTCPBind(PCONNECTION_ENDPOINT Connection, struct ip_addr *const 
ipaddr, const u16_t port);
 PTCP_PCB    LibTCPListen(PCONNECTION_ENDPOINT Connection, const u8_t backlog);
 err_t       LibTCPSend(PCONNECTION_ENDPOINT Connection, void *const dataptr, 
const u16_t len, u32_t *sent, const int safe);
diff --git a/sdk/lib/drivers/lwip/src/rostcp.c 
b/sdk/lib/drivers/lwip/src/rostcp.c
index de5564642b8..cc0dd4bc0d6 100644
--- a/sdk/lib/drivers/lwip/src/rostcp.c
+++ b/sdk/lib/drivers/lwip/src/rostcp.c
@@ -81,7 +81,9 @@ void LibTCPEnqueuePacket(PCONNECTION_ENDPOINT Connection, 
struct pbuf *p)
     qp->p = p;
     qp->Offset = 0;
 
-    ExInterlockedInsertTailList(&Connection->PacketQueue, &qp->ListEntry, 
&Connection->Lock);
+    LockObject(Connection);
+    InsertTailList(&Connection->PacketQueue, &qp->ListEntry);
+    UnlockObject(Connection);
 }
 
 PQUEUE_ENTRY LibTCPDequeuePacket(PCONNECTION_ENDPOINT Connection)
@@ -104,11 +106,10 @@ NTSTATUS 
LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA
     struct pbuf* p;
     NTSTATUS Status;
     UINT ReadLength, PayloadLength, Offset, Copied;
-    KIRQL OldIrql;
 
     (*Received) = 0;
 
-    LockObject(Connection, &OldIrql);
+    LockObject(Connection);
 
     if (!IsListEmpty(&Connection->PacketQueue))
     {
@@ -132,13 +133,9 @@ NTSTATUS 
LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA
                 qp = NULL;
             }
 
-            UnlockObject(Connection, OldIrql);
-
             Copied = pbuf_copy_partial(p, RecvBuffer, ReadLength, Offset);
             ASSERT(Copied == ReadLength);
 
-            LockObject(Connection, &OldIrql);
-
             /* Update trackers */
             RecvLen -= ReadLength;
             RecvBuffer += ReadLength;
@@ -172,7 +169,7 @@ NTSTATUS 
LibTCPGetDataFromConnectionQueue(PCONNECTION_ENDPOINT Connection, PUCHA
             Status = STATUS_PENDING;
     }
 
-    UnlockObject(Connection, OldIrql);
+    UnlockObject(Connection);
 
     return Status;
 }
@@ -364,6 +361,33 @@ LibTCPSocket(void *arg)
     return NULL;
 }
 
+static
+void
+LibTCPFreeSocketCallback(void *arg)
+{
+    struct lwip_callback_msg *msg = arg;
+
+    ASSERT(msg);
+
+    /* Calling tcp_close will free it */
+    tcp_close(msg->Input.FreeSocket.pcb);
+
+    KeSetEvent(&msg->Event, IO_NO_INCREMENT, FALSE);
+}
+
+void LibTCPFreeSocket(PTCP_PCB pcb)
+{
+    struct lwip_callback_msg msg;
+
+    KeInitializeEvent(&msg.Event, NotificationEvent, FALSE);
+    msg.Input.FreeSocket.pcb = pcb;
+
+    tcpip_callback_with_block(LibTCPFreeSocketCallback, &msg, 1);
+
+    WaitForEventSafely(&msg.Event);
+}
+
+
 static
 void
 LibTCPBindCallback(void *arg)

Reply via email to