merge Art's tcpip changes to the branch
Added: branches/ros-branch-0_2_9/reactos/drivers/lib/chew/
Added: branches/ros-branch-0_2_9/reactos/drivers/lib/chew/chew.xml
Added: branches/ros-branch-0_2_9/reactos/drivers/lib/chew/workqueue.c
Modified: branches/ros-branch-0_2_9/reactos/drivers/lib/directory.xml
Modified: branches/ros-branch-0_2_9/reactos/drivers/lib/ip/transport/tcp/tcp.c
Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/datalink/lan.c
Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/precomp.h
Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/tcp.h
Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/dispatch.c
Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/main.c
Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip.xml
Added: branches/ros-branch-0_2_9/reactos/include/chew/
Added: branches/ros-branch-0_2_9/reactos/include/chew/chew.h

Added: branches/ros-branch-0_2_9/reactos/drivers/lib/chew/chew.xml
--- branches/ros-branch-0_2_9/reactos/drivers/lib/chew/chew.xml	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/lib/chew/chew.xml	2005-12-14 10:28:30 UTC (rev 20162)
@@ -0,0 +1,7 @@
+<module name="chew" type="staticlibrary">
+	<define name="__USE_W32API" />
+	<define name="_NTOSKRNL_" />
+	<include base="chew">include</include>
+	<include base="reactos">w32api/include/ddk</include>
+	<file>workqueue.c</file>
+</module>
\ No newline at end of file

Added: branches/ros-branch-0_2_9/reactos/drivers/lib/chew/workqueue.c
--- branches/ros-branch-0_2_9/reactos/drivers/lib/chew/workqueue.c	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/lib/chew/workqueue.c	2005-12-14 10:28:30 UTC (rev 20162)
@@ -0,0 +1,106 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            drivers/lib/chew/workqueue.c
+ * PURPOSE:         Common Highlevel Executive Worker
+ *
+ * PROGRAMMERS:     arty (ayerkes@speakeasy.net)
+ */
+#include <ntddk.h>
+#include <chew/chew.h>
+
+#define NDEBUG
+
+#define FOURCC(w,x,y,z) (((w) << 24) | ((x) << 16) | ((y) << 8) | (z))
+
+PDEVICE_OBJECT WorkQueueDevice;
+LIST_ENTRY     WorkQueue;
+KSPIN_LOCK     WorkQueueLock;
+
+typedef struct _WORK_ITEM {
+    LIST_ENTRY Entry;
+    PIO_WORKITEM WorkItem;
+    VOID (*Worker)( PVOID Data );
+    CHAR UserSpace[1];
+} WORK_ITEM, *PWORK_ITEM;
+
+VOID ChewInit( PDEVICE_OBJECT DeviceObject ) {
+    WorkQueueDevice = DeviceObject;
+    InitializeListHead( &WorkQueue );
+    KeInitializeSpinLock( &WorkQueueLock );
+}
+
+VOID ChewShutdown() {
+    KIRQL OldIrql;
+    PLIST_ENTRY Entry;
+    PWORK_ITEM WorkItem;
+
+    KeAcquireSpinLock( &WorkQueueLock, &OldIrql );
+    
+    while( !IsListEmpty( &WorkQueue ) ) {
+	Entry = RemoveHeadList( &WorkQueue );
+	WorkItem = CONTAINING_RECORD( Entry, WORK_ITEM, Entry );
+	IoFreeWorkItem( WorkItem->WorkItem );
+	ExFreePool( WorkItem );
+    }
+
+    KeReleaseSpinLock( &WorkQueueLock, OldIrql );
+}
+
+VOID STDCALL ChewWorkItem( PDEVICE_OBJECT DeviceObject, PVOID ChewItem ) {
+    PWORK_ITEM WorkItem = ChewItem;
+
+    RemoveEntryList( &WorkItem->Entry );
+
+    if( WorkItem->Worker ) 
+	WorkItem->Worker( WorkItem->UserSpace );
+
+    IoFreeWorkItem( WorkItem->WorkItem );
+    ExFreePool( WorkItem );
+}
+    
+BOOLEAN ChewCreate
+( PVOID *ItemPtr, UINT Bytes, VOID (*Worker)( PVOID ), PVOID UserSpace ) {
+    PWORK_ITEM Item;
+    
+    if( KeGetCurrentIrql() == PASSIVE_LEVEL ) {
+	if( ItemPtr )
+	    *ItemPtr = NULL;
+	Worker(UserSpace);
+	return TRUE;
+    } else {
+	Item = ExAllocatePoolWithTag
+	    ( NonPagedPool, 
+	      sizeof( WORK_ITEM ) + Bytes - 1, 
+	      FOURCC('C','H','E','W') );
+	
+	if( Item ) {
+	    Item->WorkItem = IoAllocateWorkItem( WorkQueueDevice );
+	    if( !Item->WorkItem ) {
+		ExFreePool( Item );
+		return FALSE;
+	    }
+	    Item->Worker = Worker;
+	    if( Bytes && UserSpace )
+		RtlCopyMemory( Item->UserSpace, UserSpace, Bytes );
+	    
+	    ExInterlockedInsertTailList
+		( &WorkQueue, &Item->Entry, &WorkQueueLock );
+	    IoQueueWorkItem
+		( Item->WorkItem, ChewWorkItem, CriticalWorkQueue, Item );
+	    
+	    if( ItemPtr ) 
+		*ItemPtr = Item;
+
+	    return TRUE;
+	} else {
+	    return FALSE;
+	}
+    }
+}
+
+VOID ChewRemove( PVOID Item ) {
+    PWORK_ITEM WorkItem = Item;
+    IoFreeWorkItem( WorkItem->WorkItem );
+    ExFreePool( WorkItem );
+}

Modified: branches/ros-branch-0_2_9/reactos/drivers/lib/directory.xml
--- branches/ros-branch-0_2_9/reactos/drivers/lib/directory.xml	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/lib/directory.xml	2005-12-14 10:28:30 UTC (rev 20162)
@@ -10,3 +10,6 @@
 <directory name="oskittcp">
 	<xi:include href="oskittcp/oskittcp.xml" />
 </directory>
+<directory name="chew">
+	<xi:include href="chew/chew.xml" />
+</directory>
\ No newline at end of file

Modified: branches/ros-branch-0_2_9/reactos/drivers/lib/ip/transport/tcp/tcp.c
--- branches/ros-branch-0_2_9/reactos/drivers/lib/ip/transport/tcp/tcp.c	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/lib/ip/transport/tcp/tcp.c	2005-12-14 10:28:30 UTC (rev 20162)
@@ -647,4 +647,34 @@
     return STATUS_SUCCESS;
 }
 
+VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp ) {
+    PLIST_ENTRY Entry;
+    PLIST_ENTRY ListHead[4];
+    KIRQL OldIrql;
+    PTDI_BUCKET Bucket;
+    UINT i = 0;
+
+    ListHead[0] = &Endpoint->ReceiveRequest;
+    ListHead[1] = &Endpoint->ConnectRequest;
+    ListHead[2] = &Endpoint->ListenRequest;
+    ListHead[3] = 0;
+
+    TcpipAcquireSpinLock( &Endpoint->Lock, &OldIrql );
+
+    for( i = 0; ListHead[i]; i++ ) {
+	for( Entry = ListHead[i]->Flink;
+	     Entry != ListHead[i];
+	     Entry = Entry->Flink ) {
+	    Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
+	    
+	    if( Bucket->Request.RequestContext == Irp ) {
+		RemoveEntryList( &Bucket->Entry );
+		break;
+	    }
+	}
+    }
+
+    TcpipReleaseSpinLock( &Endpoint->Lock, OldIrql );
+}
+
 /* EOF */

Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/datalink/lan.c
--- branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/datalink/lan.c	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/datalink/lan.c	2005-12-14 10:28:30 UTC (rev 20162)
@@ -51,11 +51,6 @@
 LIST_ENTRY AdapterListHead;
 KSPIN_LOCK AdapterListLock;
 
-/* Work around being called back into afd at Dpc level */
-KSPIN_LOCK LanWorkLock;
-LIST_ENTRY LanWorkList;
-WORK_QUEUE_ITEM LanWorkItem;
-
 /* Double complete protection */
 KSPIN_LOCK LanSendCompleteLock;
 LIST_ENTRY LanSendCompleteList;
@@ -289,10 +284,9 @@
     }
 }
 
-VOID STDCALL LanReceiveWorker( PVOID Context ) {
+VOID LanReceiveWorker( PVOID Context ) {
     UINT PacketType;
-    PLIST_ENTRY ListEntry;
-    PLAN_WQ_ITEM WorkItem;
+    PLAN_WQ_ITEM WorkItem = (PLAN_WQ_ITEM)Context;
     PNDIS_PACKET Packet;
     PLAN_ADAPTER Adapter;
     UINT BytesTransferred;
@@ -301,60 +295,49 @@
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called.\n"));
 
-    while( (ListEntry =
-	    ExInterlockedRemoveHeadList( &LanWorkList, &LanWorkLock )) ) {
-	WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry);
-
-	TI_DbgPrint(DEBUG_DATALINK, ("WorkItem: %x\n", WorkItem));
-
-	Packet = WorkItem->Packet;
-	Adapter = WorkItem->Adapter;
-	BytesTransferred = WorkItem->BytesTransferred;
-
-	ExFreePool( WorkItem );
-
-        IPPacket.NdisPacket = Packet;
-
-        NdisGetFirstBufferFromPacket(Packet,
-                                     &NdisBuffer,
-                                     &IPPacket.Header,
-                                     &IPPacket.ContigSize,
-                                     &IPPacket.TotalSize);
-
-	IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred;
-        /* Determine which upper layer protocol that should receive
-           this packet and pass it to the correct receive handler */
-
-	TI_DbgPrint(MID_TRACE,
-		    ("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n",
-		     IPPacket.ContigSize, IPPacket.TotalSize,
-		     BytesTransferred));
-
-        PacketType = PC(IPPacket.NdisPacket)->PacketType;
-	IPPacket.Position = 0;
-
-	TI_DbgPrint
-            (DEBUG_DATALINK,
-             ("Ether Type = %x ContigSize = %d Total = %d\n",
-              PacketType, IPPacket.ContigSize, IPPacket.TotalSize));
-
-        switch (PacketType) {
-        case ETYPE_IPv4:
-        case ETYPE_IPv6:
-            TI_DbgPrint(MID_TRACE,("Received IP Packet\n"));
-            IPReceive(Adapter->Context, &IPPacket);
-            break;
-        case ETYPE_ARP:
-            TI_DbgPrint(MID_TRACE,("Received ARP Packet\n"));
-            ARPReceive(Adapter->Context, &IPPacket);
-        default:
-            break;
-        }
-
-	FreeNdisPacket( Packet );
+    Packet = WorkItem->Packet;
+    Adapter = WorkItem->Adapter;
+    BytesTransferred = WorkItem->BytesTransferred;
+    
+    IPPacket.NdisPacket = Packet;
+    
+    NdisGetFirstBufferFromPacket(Packet,
+				 &NdisBuffer,
+				 &IPPacket.Header,
+				 &IPPacket.ContigSize,
+				 &IPPacket.TotalSize);
+    
+    IPPacket.ContigSize = IPPacket.TotalSize = BytesTransferred;
+    /* Determine which upper layer protocol that should receive
+       this packet and pass it to the correct receive handler */
+    
+    TI_DbgPrint(MID_TRACE,
+		("ContigSize: %d, TotalSize: %d, BytesTransferred: %d\n",
+		 IPPacket.ContigSize, IPPacket.TotalSize,
+		 BytesTransferred));
+    
+    PacketType = PC(IPPacket.NdisPacket)->PacketType;
+    IPPacket.Position = 0;
+    
+    TI_DbgPrint
+	(DEBUG_DATALINK,
+	 ("Ether Type = %x ContigSize = %d Total = %d\n",
+	  PacketType, IPPacket.ContigSize, IPPacket.TotalSize));
+    
+    switch (PacketType) {
+    case ETYPE_IPv4:
+    case ETYPE_IPv6:
+	TI_DbgPrint(MID_TRACE,("Received IP Packet\n"));
+	IPReceive(Adapter->Context, &IPPacket);
+	break;
+    case ETYPE_ARP:
+	TI_DbgPrint(MID_TRACE,("Received ARP Packet\n"));
+	ARPReceive(Adapter->Context, &IPPacket);
+    default:
+	break;
     }
-    TI_DbgPrint(DEBUG_DATALINK, ("Leaving\n"));
-    LanReceiveWorkerBusy = FALSE;
+    
+    FreeNdisPacket( Packet );
 }
 
 VOID LanSubmitReceiveWork(
@@ -362,34 +345,19 @@
     PNDIS_PACKET Packet,
     NDIS_STATUS Status,
     UINT BytesTransferred) {
-    PLAN_WQ_ITEM WQItem;
+    LAN_WQ_ITEM WQItem;
     PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
-    KIRQL OldIrql;
+    PVOID LanWorkItem;
 
     TI_DbgPrint(DEBUG_DATALINK,("called\n"));
 
-    TcpipAcquireSpinLock( &LanWorkLock, &OldIrql );
+    WQItem.Packet = Packet;
+    WQItem.Adapter = Adapter;
+    WQItem.BytesTransferred = BytesTransferred;
 
-    WQItem = ExAllocatePool( NonPagedPool, sizeof(LAN_WQ_ITEM) );
-    if( !WQItem ) {
-	TcpipReleaseSpinLock( &LanWorkLock, OldIrql );
-	return;
-    }
-
-    WQItem->Packet = Packet;
-    WQItem->Adapter = Adapter;
-    WQItem->BytesTransferred = BytesTransferred;
-    InsertTailList( &LanWorkList, &WQItem->ListEntry );
-    if( !LanReceiveWorkerBusy ) {
-	LanReceiveWorkerBusy = TRUE;
-	ExQueueWorkItem( &LanWorkItem, CriticalWorkQueue );
-	TI_DbgPrint(DEBUG_DATALINK,
-		    ("Work item inserted %x %x\n", &LanWorkItem, WQItem));
-    } else {
-	TI_DbgPrint(DEBUG_DATALINK,
-                    ("LAN WORKER BUSY %x %x\n", &LanWorkItem, WQItem));
-    }
-    TcpipReleaseSpinLock( &LanWorkLock, OldIrql );
+    if( !ChewCreate
+	( &LanWorkItem, sizeof(LAN_WQ_ITEM),  LanReceiveWorker, &WQItem ) )
+	ASSERT(0);
 }
 
 VOID STDCALL ProtocolTransferDataComplete(
@@ -452,7 +420,6 @@
     PNDIS_PACKET NdisPacket;
     PLAN_ADAPTER Adapter = (PLAN_ADAPTER)BindingContext;
     PETH_HEADER EHeader  = (PETH_HEADER)HeaderBuffer;
-    KIRQL OldIrql;
 
     TI_DbgPrint(DEBUG_DATALINK, ("Called. (packetsize %d)\n",PacketSize));
 
@@ -490,12 +457,9 @@
     TI_DbgPrint(DEBUG_DATALINK, ("Adapter: %x (MTU %d)\n",
 				 Adapter, Adapter->MTU));
 
-    TcpipAcquireSpinLock( &LanWorkLock, &OldIrql );
-
     NdisStatus = AllocatePacketWithBuffer( &NdisPacket, NULL,
                                            PacketSize + HeaderBufferSize );
     if( NdisStatus != NDIS_STATUS_SUCCESS ) {
-	TcpipReleaseSpinLock( &LanWorkLock, OldIrql );
 	return NDIS_STATUS_NOT_ACCEPTED;
     }
 
@@ -534,7 +498,6 @@
             BytesTransferred = 0;
         }
     }
-    TcpipReleaseSpinLock( &LanWorkLock, OldIrql );
     TI_DbgPrint(DEBUG_DATALINK, ("Calling complete\n"));
 
     if (NdisStatus != NDIS_STATUS_PENDING)
@@ -1369,10 +1332,8 @@
 }
 
 VOID LANStartup() {
-    InitializeListHead( &LanWorkList );
     InitializeListHead( &LanSendCompleteList );
     KeInitializeSpinLock( &LanSendCompleteLock );
-    ExInitializeWorkItem( &LanWorkItem, LanReceiveWorker, NULL );
 }
 
 VOID LANShutdown() {
@@ -1380,15 +1341,6 @@
     PLAN_WQ_ITEM WorkItem;
     PLIST_ENTRY ListEntry;
 
-    TcpipAcquireSpinLock( &LanWorkLock, &OldIrql );
-    while( !IsListEmpty( &LanWorkList ) ) {
-	ListEntry = RemoveHeadList( &LanWorkList );
-	WorkItem = CONTAINING_RECORD(ListEntry, LAN_WQ_ITEM, ListEntry);
-	FreeNdisPacket( WorkItem->Packet );
-	ExFreePool( WorkItem );
-    }
-    TcpipReleaseSpinLock( &LanWorkLock, OldIrql );
-
     KeAcquireSpinLock( &LanSendCompleteLock, &OldIrql );
     while( !IsListEmpty( &LanSendCompleteList ) ) {
 	ListEntry = RemoveHeadList( &LanSendCompleteList );

Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/precomp.h
--- branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/precomp.h	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/precomp.h	2005-12-14 10:28:30 UTC (rev 20162)
@@ -36,4 +36,4 @@
 #include <ports.h>
 #include <ipifcons.h>
 #include <ndk/ntndk.h>
-
+#include <chew/chew.h>

Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/tcp.h
--- branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/tcp.h	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/include/tcp.h	2005-12-14 10:28:30 UTC (rev 20162)
@@ -176,4 +176,6 @@
 NTSTATUS TCPShutdown(
   VOID);
 
+VOID TCPRemoveIRP( PCONNECTION_ENDPOINT Connection, PIRP Irp );
+
 #endif /* __TCP_H */

Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/dispatch.c
--- branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/dispatch.c	2005-12-14 10:28:30 UTC (rev 20162)
@@ -135,7 +135,31 @@
     TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
 }
 
+typedef struct _DISCONNECT_TYPE {
+    UINT Type;
+    PVOID Context;
+    PIRP Irp;
+    PFILE_OBJECT FileObject;
+} DISCONNECT_TYPE, *PDISCONNECT_TYPE;
 
+VOID DispDoDisconnect( PVOID Data ) {
+    PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data;
+
+    TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n"));
+    TCPDisconnect
+	( DisType->Context,
+	  DisType->Type,
+	  NULL,
+	  NULL,
+	  DispDataRequestComplete,
+	  DisType->Irp );
+    TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
+
+    DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
+
+    DispCancelComplete(DisType->FileObject);
+}
+
 VOID DDKAPI DispCancelRequest(
     PDEVICE_OBJECT Device,
     PIRP Irp)
@@ -150,6 +174,8 @@
     PTRANSPORT_CONTEXT TranContext;
     PFILE_OBJECT FileObject;
     UCHAR MinorFunction;
+    DISCONNECT_TYPE DisType;
+    PVOID WorkItem;
     /*NTSTATUS Status = STATUS_SUCCESS;*/
 
     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@@ -161,6 +187,8 @@
 
     TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X)  MinorFunction (0x%X)  IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
 
+    Irp->IoStatus.Status = STATUS_PENDING;
+
 #ifdef DBG
     if (!Irp->Cancel)
         TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
@@ -169,26 +197,22 @@
     /* Try canceling the request */
     switch(MinorFunction) {
     case TDI_SEND:
-        TCPDisconnect
-            ( TranContext->Handle.ConnectionContext,
-              TDI_DISCONNECT_RELEASE,
-              NULL,
-              NULL,
-              DispDataRequestComplete,
-              Irp );
-        break;
+    case TDI_RECEIVE:
+	DisType.Type = TDI_DISCONNECT_RELEASE | 
+	    ((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
+	DisType.Context = TranContext->Handle.ConnectionContext;
+	DisType.Irp = Irp;
+	DisType.FileObject = FileObject;
+	
+	TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
 
-    case TDI_RECEIVE:
-        TCPDisconnect
-            ( TranContext->Handle.ConnectionContext,
-              TDI_DISCONNECT_ABORT | TDI_DISCONNECT_RELEASE,
-              NULL,
-              NULL,
-              DispDataRequestComplete,
-              Irp );
+	if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE), 
+			 DispDoDisconnect, &DisType ) )
+	    ASSERT(0);
         break;
 
     case TDI_SEND_DATAGRAM:
+	Irp->IoStatus.Status = STATUS_CANCELLED;
         if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
             TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
             break;
@@ -198,6 +222,7 @@
         break;
 
     case TDI_RECEIVE_DATAGRAM:
+	Irp->IoStatus.Status = STATUS_CANCELLED;
         if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
             TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
             break;
@@ -211,10 +236,11 @@
         break;
     }
 
+    if( Irp->IoStatus.Status == STATUS_PENDING )
+	IoMarkIrpPending(Irp);
+
     IoReleaseCancelSpinLock(Irp->CancelIrql);
 
-    DispCancelComplete(FileObject);
-
     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
 

Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/main.c
--- branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/main.c	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip/main.c	2005-12-14 10:28:30 UTC (rev 20162)
@@ -619,6 +619,8 @@
   }
   TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
 #endif
+  ChewShutdown();
+
   /* Cancel timer */
   KeCancelTimer(&IPTimer);
 
@@ -734,6 +736,8 @@
     return Status;
   }
 
+  ChewInit( IPDeviceObject );
+
   /* Create RawIP device object */
   Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
     FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);

Modified: branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip.xml
--- branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip.xml	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/drivers/net/tcpip/tcpip.xml	2005-12-14 10:28:30 UTC (rev 20162)
@@ -9,6 +9,7 @@
 	<library>oskittcp</library>
 	<library>ndis</library>
 	<library>pseh</library>
+	<library>chew</library>
 	<library>ntoskrnl</library>
 	<library>hal</library>
 	<directory name="include">

Added: branches/ros-branch-0_2_9/reactos/include/chew/chew.h
--- branches/ros-branch-0_2_9/reactos/include/chew/chew.h	2005-12-14 09:26:52 UTC (rev 20161)
+++ branches/ros-branch-0_2_9/reactos/include/chew/chew.h	2005-12-14 10:28:30 UTC (rev 20162)
@@ -0,0 +1,40 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            include/chew/chew.h
+ * PURPOSE:         Common Highlevel Executive Worker
+ *
+ * PROGRAMMERS:     arty (ayerkes@speakeasy.net)
+ */
+
+#ifndef _REACTOS_CHEW_H
+#define _REACTOS_CHEW_H
+
+/**
+ * Initialize CHEW, given a device object (since IoAllocateWorkItem relies on
+ * it).
+ */
+VOID ChewInit( PDEVICE_OBJECT DeviceObject );
+/**
+ * Shutdown CHEW, including removing remaining work items.
+ */
+VOID ChewShutdown();
+/**
+ * Create a work item, or perform the work, based on IRQL.
+ * At passive level, Worker is called directly on UserSpace.
+ * At greater than passive level, a work item is created with Bytes
+ * context area and data copied from UserSpace.
+ * If a work item is created, Item contains the address and the function
+ * returns true.
+ * If the work is performed immediately, Item contains NULL and the
+ * function returns true.
+ * Else, the function returns false and Item is undefined.
+ */
+BOOLEAN ChewCreate
+( PVOID *Item, UINT Bytes, VOID (*Worker)(PVOID), PVOID UserSpace );
+/**
+ * Remove a work item, given the pointer returned to Item in ChewCreate.
+ */
+VOID ChewRemove( PVOID Item );
+
+#endif/*_REACTOS_CHEW_H*/