[0.4.14][KERNEL32][TCPIP] A big squashed fix for CORE-16757 CORE-17596 CORE-17647 CORE-6473 (#3170)

The interesting kernel32 part is a port of
0.4.15-dev-2069-g fd8080b094
CORE-16757 'Task Manager failed to show process's priority'
which I actually wanted to improve for 0.4.14.

But if we took that on its own, then it would unhide
CORE-17596 'Google Earth 7.1.8 regressed AGAIN by the same work'
That's why we take with us:
0.4.15-dev-2766-g 27fcfe66a2 (is also part of CORE-6473, I left the 2nd commit out that added an assert in NTOSKRNL)

Small hack: this backport required me to define _Unreferenced_parameter_ myself in tcp.c
stolen from newer sdk/include/psdk/specstrings.h. I didn't want to port back that entire file as well.

In combination those two fixes allow both 'Google Earth and to change process priority' to be fixed within the same build.

But I felt a bit more safe then by taking
0.4.15-dev-2793-g 979b7d4d8e
with me as well, because I was too afraid, that I might otherwise introduce
CORE-17647 'BSOD 0xc2 BAD_POOL_CALLER induced by networking, triggered by using KeePass 2.23'
although I could not trigger that in practice when leaving that third commit out as an experiment.

And since it was a safe no-brainer-fix, I couldn't resist to also pick
0.4.15-dev-764-g 4aeb45ce0c (#3170)
This commit is contained in:
Joachim Henze 2021-11-20 05:09:54 +01:00
parent 5917fa575b
commit e7cfa907e9
16 changed files with 470 additions and 483 deletions

View file

@ -1657,7 +1657,7 @@ WINAPI
GetPriorityClass(IN HANDLE hProcess)
{
NTSTATUS Status;
PROCESS_PRIORITY_CLASS PriorityClass;
PROCESS_PRIORITY_CLASS DECLSPEC_ALIGN(4) PriorityClass;
/* Query the kernel */
Status = NtQueryInformationProcess(hProcess,
@ -1681,7 +1681,7 @@ GetPriorityClass(IN HANDLE hProcess)
/* Failure path */
BaseSetLastNTError(Status);
return FALSE;
return 0;
}
/*

View file

@ -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);

View file

@ -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)); \
}
#define LockObject(Object) do \
{ \
ReferenceObject(Object); \
KeEnterCriticalRegion(); \
ExAcquireResourceExclusiveLite(&(Object)->Resource, TRUE); \
} while(0)
/*
* VOID LockObjectAtDpcLevel(PVOID Object)
* VOID UnlockObject(PVOID Object)
*/
#define LockObjectAtDpcLevel(Object) \
{ \
ReferenceObject(Object); \
KeAcquireSpinLockAtDpcLevel(&((Object)->Lock)); \
(Object)->OldIrql = DISPATCH_LEVEL; \
}
/*
* VOID UnlockObject(PVOID Object, KIRQL OldIrql)
*/
#define UnlockObject(Object, OldIrql) \
#define UnlockObject(Object) do \
{ \
KeReleaseSpinLock(&((Object)->Lock), OldIrql); \
ExReleaseResourceLite(&(Object)->Resource); \
KeLeaveCriticalRegion(); \
DereferenceObject(Object); \
}
/*
* VOID UnlockObjectFromDpcLevel(PVOID Object)
*/
#define UnlockObjectFromDpcLevel(Object) \
{ \
KeReleaseSpinLockFromDpcLevel(&((Object)->Lock)); \
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) */
@ -275,10 +254,11 @@ typedef struct _CONNECTION_ENDPOINT {
LIST_ENTRY ShutdownRequest;/* Queued shutdown requests */
LIST_ENTRY PacketQueue; /* Queued received packets waiting to be processed */
/* Disconnect Timer */
KTIMER DisconnectTimer;
KDPC DisconnectDpc;
PIO_WORKITEM DisconnectWorkItem;
/* Socket state */
BOOLEAN SendShutdown;

View file

@ -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;

View file

@ -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) {
@ -1104,7 +1102,6 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
PIO_STACK_LOCATION IrpSp;
PADDRESS_FILE AddrFile;
NTSTATUS Status;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
@ -1127,7 +1124,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.
@ -1248,7 +1245,7 @@ NTSTATUS DispTdiSetEventHandler(PIRP Irp)
Status = STATUS_INVALID_PARAMETER;
}
UnlockObject(AddrFile, OldIrql);
UnlockObject(AddrFile);
return Status;
}

View file

@ -42,7 +42,7 @@ PADDRESS_FILE AddrSearchFirst(
PAF_SEARCH SearchContext)
{
KIRQL OldIrql;
SearchContext->Address = Address;
SearchContext->Port = Port;
SearchContext->Protocol = Protocol;
@ -115,7 +115,7 @@ LogActiveObjects(VOID)
PCONNECTION_ENDPOINT Conn;
DbgPrint("----------- TCP/IP Active Object Dump -------------\n");
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
CurrentEntry = AddressFileListHead.Flink;
@ -144,19 +144,19 @@ LogActiveObjects(VOID)
}
DbgPrint("\n");
}
CurrentEntry = CurrentEntry->Flink;
}
TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
TcpipAcquireSpinLock(&ConnectionEndpointListLock, &OldIrql);
CurrentEntry = ConnectionEndpointListHead.Flink;
while (CurrentEntry != &ConnectionEndpointListHead)
{
Conn = CONTAINING_RECORD(CurrentEntry, CONNECTION_ENDPOINT, ListEntry);
DbgPrint("Connection @ 0x%p | Ref count: %d\n", Conn, Conn->RefCount);
DbgPrint("\tPCB: ");
if (Conn->SocketContext == NULL)
@ -177,10 +177,10 @@ LogActiveObjects(VOID)
DbgPrint("\tReceive shutdown: %s\n", Conn->ReceiveShutdown ? "Yes" : "No");
if (Conn->ReceiveShutdown) DbgPrint("\tReceive shutdown status: 0x%x\n", Conn->ReceiveShutdownStatus);
DbgPrint("\tClosing: %s\n", Conn->Closing ? "Yes" : "No");
CurrentEntry = CurrentEntry->Flink;
}
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
DbgPrint("---------------------------------------------------\n");
@ -237,7 +237,7 @@ PADDRESS_FILE AddrSearchNext(
PADDRESS_FILE Current = NULL;
BOOLEAN Found = FALSE;
PADDRESS_FILE StartingAddrFile;
TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
if (SearchContext->Next == &AddressFileListHead)
@ -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);
}
@ -465,14 +473,14 @@ NTSTATUS FileOpenAddress(
{
/* The client specified an explicit port so we force a bind to this */
AddrFile->Port = TCPAllocatePort(Address->Address[0].Address[0].sin_port);
/* Check for bind success */
if (AddrFile->Port == 0xffff)
{
ExFreePoolWithTag(AddrFile, ADDR_FILE_TAG);
return STATUS_ADDRESS_ALREADY_EXISTS;
}
/* Sanity check */
ASSERT(Address->Address[0].Address[0].sin_port == AddrFile->Port);
}
@ -480,7 +488,7 @@ NTSTATUS FileOpenAddress(
{
/* The client is trying to bind to a local address so allocate a port now too */
AddrFile->Port = TCPAllocatePort(0);
/* Check for bind success */
if (AddrFile->Port == 0xffff)
{
@ -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"));

View file

@ -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);

View file

@ -215,7 +215,7 @@ ReassembleDatagram(
RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
/* Allocate space for full IP datagram */
IPPacket->Header = ExAllocatePoolWithTag(PagedPool, IPPacket->TotalSize, PACKET_BUFFER_TAG);
IPPacket->Header = ExAllocatePoolWithTag(NonPagedPool, IPPacket->TotalSize, PACKET_BUFFER_TAG);
if (!IPPacket->Header) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
(*IPPacket->Free)(IPPacket);
@ -303,7 +303,7 @@ VOID ProcessFragment(
TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
/* We have a reassembly structure */
TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
/* Reset the timeout since we received a fragment */
IPDR->TimeoutCount = 0;
} else {
@ -454,7 +454,7 @@ VOID ProcessFragment(
Assemble the datagram and pass it to an upper layer protocol */
TI_DbgPrint(DEBUG_IP, ("Complete datagram received.\n"));
RemoveIPDR(IPDR);
TcpipReleaseSpinLock(&IPDR->Lock, OldIrql);
@ -539,7 +539,7 @@ VOID IPDatagramReassemblyTimeout(
TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock);
RemoveEntryList(CurrentEntry);
FreeIPDR(CurrentIPDR);
}
}
else
{
ASSERT(CurrentIPDR->TimeoutCount < MAX_TIMEOUT_COUNT);
@ -562,9 +562,9 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
{
UCHAR FirstByte;
ULONG BytesCopied;
TI_DbgPrint(DEBUG_IP, ("Received IPv4 datagram.\n"));
/* Read in the first IP header byte for size information */
BytesCopied = CopyPacketToBuffer((PCHAR)&FirstByte,
IPPacket->NdisPacket,
@ -623,7 +623,7 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",
IPPacket->Position));

View file

@ -16,15 +16,14 @@ 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;
for( ListEntry = AddrFile->ReceiveQueue.Flink;
ListEntry != &AddrFile->ReceiveQueue;
ListEntry = ListEntry->Flink )
{
@ -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,13 +80,13 @@ DGDeliverData(
TI_DbgPrint(MIN_TRACE, ("Called.\n"));
LockObject(AddrFile, &OldIrql);
LockObject(AddrFile);
if (AddrFile->Protocol == IPPROTO_UDP)
{
DataBuffer = IPPacket->Data;
}
else if (AddrFile->HeaderIncl)
else if (AddrFile->HeaderIncl)
{
DataBuffer = IPPacket->Header;
}
@ -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;
}

View file

@ -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;

View file

@ -22,23 +22,23 @@ NTSTATUS TCPCheckPeerForAccept(PVOID Context,
PTDI_CONNECTION_INFORMATION WhoIsConnecting;
PTA_IP_ADDRESS RemoteAddress;
struct ip_addr ipaddr;
if (Request->RequestFlags & TDI_QUERY_ACCEPT)
DbgPrint("TDI_QUERY_ACCEPT NOT SUPPORTED!!!\n");
WhoIsConnecting = (PTDI_CONNECTION_INFORMATION)Request->ReturnConnectionInformation;
RemoteAddress = (PTA_IP_ADDRESS)WhoIsConnecting->RemoteAddress;
RemoteAddress->TAAddressCount = 1;
RemoteAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
RemoteAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
Status = TCPTranslateError(LibTCPGetPeerName(newpcb,
&ipaddr,
&RemoteAddress->Address[0].Address[0].sin_port));
RemoteAddress->Address[0].Address[0].in_addr = ipaddr.addr;
return Status;
}
@ -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);
@ -61,7 +60,7 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog)
TI_DbgPrint(DEBUG_TCP, ("Connection->SocketContext %x\n",
Connection->SocketContext));
AddressToBind.addr = Connection->AddressFile->Address.Address.IPv4Address;
Status = TCPTranslateError(LibTCPBind(Connection,
@ -79,7 +78,7 @@ NTSTATUS TCPListen(PCONNECTION_ENDPOINT Connection, UINT Backlog)
{
/* 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);
}
@ -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,12 +139,11 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
{
NTSTATUS Status;
PTDI_BUCKET Bucket;
KIRQL OldIrql;
LockObject(Listener, &OldIrql);
LockObject(Listener);
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
if (Bucket)
{
Bucket->AssociatedEndpoint = Connection;
@ -160,7 +157,7 @@ NTSTATUS TCPAccept ( PTDI_REQUEST Request,
else
Status = STATUS_NO_MEMORY;
UnlockObject(Listener, OldIrql);
UnlockObject(Listener);
return Status;
}

View file

@ -24,11 +24,11 @@ BucketCompletionWorker(PVOID Context)
{
PTDI_BUCKET Bucket = (PTDI_BUCKET)Context;
PTCP_COMPLETION_ROUTINE Complete;
Complete = (PTCP_COMPLETION_ROUTINE)Bucket->Request.RequestNotifyObject;
Complete(Bucket->Request.RequestContext, Bucket->Status, Bucket->Information);
DereferenceObject(Bucket->AssociatedEndpoint);
ExFreeToNPagedLookasideList(&TdiBucketLookasideList, Bucket);
@ -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);
if (interlocked)
{
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));
Bucket->Status = Status;
Bucket->Information = 0;
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;
CompleteBucket(Connection, Bucket, FALSE);
}
}
DereferenceObject(Connection);
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
while (!IsListEmpty(&Connection->ReceiveRequest))
{
Entry = RemoveHeadList(&Connection->ReceiveRequest);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = Status;
CompleteBucket(Connection, Bucket, FALSE);
}
}
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);
if (interlocked)
{
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);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = Status;
CompleteBucket(Connection, Bucket, FALSE);
}
}
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
DereferenceObject(Connection);
while (!IsListEmpty(&Connection->SendRequest))
{
Entry = RemoveHeadList(&Connection->SendRequest);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = Status;
CompleteBucket(Connection, Bucket, FALSE);
}
}
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;
CompleteBucket(Connection, Bucket, FALSE);
}
}
else
{
while (!IsListEmpty(&Connection->ShutdownRequest))
{
Entry = RemoveHeadList(&Connection->ShutdownRequest);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = Status;
CompleteBucket(Connection, Bucket, FALSE);
}
}
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
DereferenceObject(Connection);
while (!IsListEmpty(&Connection->ShutdownRequest))
{
Entry = RemoveHeadList(&Connection->ShutdownRequest);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = Status;
CompleteBucket(Connection, Bucket, FALSE);
}
}
VOID
@ -176,20 +117,19 @@ FlushConnectQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
{
PTDI_BUCKET Bucket;
PLIST_ENTRY Entry;
ReferenceObject(Connection);
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
while (!IsListEmpty(&Connection->ConnectRequest))
{
Entry = RemoveHeadList(&Connection->ConnectRequest);
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = Status;
Bucket->Information = 0;
CompleteBucket(Connection, Bucket, FALSE);
}
DereferenceObject(Connection);
}
VOID
@ -197,50 +137,45 @@ FlushListenQueue(PCONNECTION_ENDPOINT Connection, const NTSTATUS Status)
{
PTDI_BUCKET Bucket;
PLIST_ENTRY Entry;
ReferenceObject(Connection);
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
ASSERT_TCPIP_OBJECT_LOCKED(Connection);
while (!IsListEmpty(&Connection->ListenRequest))
{
Entry = RemoveHeadList(&Connection->ListenRequest);
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = Status;
Bucket->Information = 0;
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)
{
Status = STATUS_FILE_CLOSED;
}
// flush listen queue
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,15 +218,15 @@ 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
TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
{
@ -301,49 +235,50 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
PLIST_ENTRY Entry;
PIRP Irp;
NTSTATUS Status;
KIRQL OldIrql;
ReferenceObject(Connection);
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ListenRequest, &Connection->Lock)))
LockObject(Connection);
while (!IsListEmpty(&Connection->ListenRequest))
{
PIO_STACK_LOCATION IrpSp;
Entry = RemoveHeadList(&Connection->ListenRequest);
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Irp = Bucket->Request.RequestContext;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
TI_DbgPrint(DEBUG_TCP,("[IP, TCPAcceptEventHandler] Getting the socket\n"));
Status = TCPCheckPeerForAccept(newpcb,
(PTDI_REQUEST_KERNEL)&IrpSp->Parameters);
TI_DbgPrint(DEBUG_TCP,("Socket: Status: %x\n", Status));
Bucket->Status = Status;
Bucket->Information = 0;
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 );
/* free socket context created in FileOpenConnection, as we're using a new one */
LibTCPClose(Bucket->AssociatedEndpoint, TRUE, FALSE);
/* 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, OldIrql);
UnlockObject(Bucket->AssociatedEndpoint);
LibTCPAccept(newpcb, (PTCP_PCB)Connection->SocketContext, Bucket->AssociatedEndpoint);
}
DereferenceObject(Bucket->AssociatedEndpoint);
CompleteBucket(Connection, Bucket, FALSE);
if (Status == STATUS_SUCCESS)
@ -351,8 +286,8 @@ TCPAcceptEventHandler(void *arg, PTCP_PCB newpcb)
break;
}
}
DereferenceObject(Connection);
UnlockObject(Connection);
}
VOID
@ -365,44 +300,48 @@ TCPSendEventHandler(void *arg, const u16_t space)
NTSTATUS Status;
PMDL Mdl;
ULONG BytesSent;
ReferenceObject(Connection);
while ((Entry = ExInterlockedRemoveHeadList(&Connection->SendRequest, &Connection->Lock)))
ReferenceObject(Connection);
LockObject(Connection);
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;
Mdl = Irp->MdlAddress;
TI_DbgPrint(DEBUG_TCP,
("Getting the user buffer from %x\n", Mdl));
NdisQueryBuffer( Mdl, &SendBuffer, &SendLen );
TI_DbgPrint(DEBUG_TCP,
("Writing %d bytes to %x\n", SendLen, SendBuffer));
TI_DbgPrint(DEBUG_TCP, ("Connection: %x\n", Connection));
TI_DbgPrint
(DEBUG_TCP,
("Connection->SocketContext: %x\n",
Connection->SocketContext));
Status = TCPTranslateError(LibTCPSend(Connection,
SendBuffer,
SendLen, &BytesSent, TRUE));
TI_DbgPrint(DEBUG_TCP,("TCP Bytes: %d\n", BytesSent));
if( Status == STATUS_PENDING )
{
ExInterlockedInsertHeadList(&Connection->SendRequest,
&Bucket->Entry,
&Connection->Lock);
LockObject(Connection);
InsertHeadList(&Connection->SendRequest, &Bucket->Entry);
break;
}
else
@ -410,26 +349,30 @@ TCPSendEventHandler(void *arg, const u16_t space)
TI_DbgPrint(DEBUG_TCP,
("Completing Send request: %x %x\n",
Bucket->Request, Status));
Bucket->Status = Status;
Bucket->Information = (Bucket->Status == STATUS_SUCCESS) ? BytesSent : 0;
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))
{
DereferenceObject(Connection);
}
}
UnlockObject(Connection);
DereferenceObject(Connection);
}
@ -446,12 +389,13 @@ 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;
Mdl = Irp->MdlAddress;
@ -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
@ -481,19 +422,20 @@ TCPConnectEventHandler(void *arg, const err_t err)
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)arg;
PTDI_BUCKET Bucket;
PLIST_ENTRY Entry;
ReferenceObject(Connection);
while ((Entry = ExInterlockedRemoveHeadList(&Connection->ConnectRequest, &Connection->Lock)))
LockObject(Connection);
while (!IsListEmpty(&Connection->ConnectRequest))
{
Entry = RemoveHeadList(&Connection->ConnectRequest);
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = TCPTranslateError(err);
Bucket->Information = 0;
CompleteBucket(Connection, Bucket, FALSE);
}
DereferenceObject(Connection);
UnlockObject(Connection);
}

View file

@ -25,48 +25,70 @@ PORT_SET TCPPorts;
NPAGED_LOOKASIDE_LIST TdiBucketLookasideList;
VOID NTAPI
static
IO_WORKITEM_ROUTINE
DisconnectWorker;
#ifndef _Unreferenced_parameter_ /* stolen from newer sdk/include/psdk/specstrings.h */
#define _Unreferenced_parameter_ _Const_
#endif
_Use_decl_annotations_
VOID
NTAPI
DisconnectWorker(
_Unreferenced_parameter_ PDEVICE_OBJECT DeviceObject,
_In_ PVOID Context
)
{
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)Context;
PLIST_ENTRY Entry;
PTDI_BUCKET Bucket;
/* 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);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = STATUS_FILE_CLOSED;
CompleteBucket(Connection, Bucket, FALSE);
}
while (!IsListEmpty(&Connection->ShutdownRequest))
{
Entry = RemoveHeadList( &Connection->ShutdownRequest );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = STATUS_TIMEOUT;
Bucket->Information = 0;
CompleteBucket(Connection, Bucket, FALSE);
}
UnlockObject(Connection);
DereferenceObject(Connection);
}
VOID
NTAPI
DisconnectTimeoutDpc(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
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));
while (!IsListEmpty(&Connection->SendRequest))
{
Entry = RemoveHeadList(&Connection->SendRequest);
Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
Bucket->Information = 0;
Bucket->Status = STATUS_FILE_CLOSED;
CompleteBucket(Connection, Bucket, FALSE);
}
while (!IsListEmpty(&Connection->ShutdownRequest))
{
Entry = RemoveHeadList( &Connection->ShutdownRequest );
Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
Bucket->Status = STATUS_TIMEOUT;
Bucket->Information = 0;
CompleteBucket(Connection, Bucket, FALSE);
}
UnlockObjectFromDpcLevel(Connection);
DereferenceObject(Connection);
IoQueueWorkItem(Connection->DisconnectWorkItem, DisconnectWorker, DelayedWorkQueue, Connection);
}
VOID ConnectionFree(PVOID Object)
@ -80,6 +102,9 @@ VOID ConnectionFree(PVOID Object)
RemoveEntryList(&Connection->ListEntry);
TcpipReleaseSpinLock(&ConnectionEndpointListLock, OldIrql);
ExDeleteResourceLite(&Connection->Resource);
IoFreeWorkItem(Connection->DisconnectWorkItem);
ExFreePoolWithTag( Connection, CONN_ENDPT_TAG );
}
@ -96,7 +121,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 +132,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 +158,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 +171,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 +180,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);
@ -176,7 +205,7 @@ VOID TCPReceive(PIP_INTERFACE Interface, PIP_PACKET IPPacket)
TI_DbgPrint(DEBUG_TCP,("Sending packet %d (%d) to lwIP\n",
IPPacket->TotalSize,
IPPacket->HeaderSize));
LibIPInsertPacket(Interface->TCPContext, IPPacket->Header, IPPacket->TotalSize);
}
@ -202,13 +231,13 @@ NTSTATUS TCPStartup(VOID)
sizeof(TDI_BUCKET),
TDI_BUCKET_TAG,
0);
/* Initialize our IP library */
LibIPInitialize();
/* Register this protocol with IP layer */
IPRegisterProtocol(IPPROTO_TCP, TCPReceive);
TCPInitialized = TRUE;
return STATUS_SUCCESS;
@ -226,7 +255,7 @@ NTSTATUS TCPShutdown(VOID)
return STATUS_SUCCESS;
ExDeleteNPagedLookasideList(&TdiBucketLookasideList);
LibIPShutdown();
/* Deregister this protocol with IP layer */
@ -287,7 +316,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 +336,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 +348,7 @@ NTSTATUS TCPConnect
{
if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
{
UnlockObject(Connection, OldIrql);
UnlockObject(Connection);
return STATUS_NETWORK_UNREACHABLE;
}
@ -334,49 +362,52 @@ NTSTATUS TCPConnect
Status = TCPTranslateError(LibTCPBind(Connection,
&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);
}
}
if (NT_SUCCESS(Status))
{
connaddr.addr = RemoteAddress.Address.IPv4Address;
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
if (!Bucket)
{
UnlockObject(Connection, OldIrql);
return STATUS_NO_MEMORY;
}
Bucket->Request.RequestNotifyObject = (PVOID)Complete;
Bucket->Request.RequestContext = Context;
InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
Status = TCPTranslateError(LibTCPConnect(Connection,
&connaddr,
RemotePort));
}
UnlockObject(Connection);
return Status;
}
UnlockObject(Connection, OldIrql);
/* 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))
{
UnlockObject(Connection);
return 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);
}
connaddr.addr = RemoteAddress.Address.IPv4Address;
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
if (!Bucket)
{
UnlockObject(Connection);
return STATUS_NO_MEMORY;
}
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 +425,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,15 +437,23 @@ 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
else
{
/* Use the timeout specified or 1 second if none was specified */
if (Timeout)
@ -431,7 +469,7 @@ NTSTATUS TCPDisconnect
Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
if (!Bucket)
{
UnlockObject(Connection, OldIrql);
UnlockObject(Connection);
return STATUS_NO_MEMORY;
}
@ -441,11 +479,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 +491,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;
@ -502,11 +546,13 @@ NTSTATUS TCPReceiveData
return STATUS_NO_MEMORY;
}
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 +578,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));
@ -548,7 +593,7 @@ NTSTATUS TCPSendData
SendLength,
BytesSent,
FALSE));
TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));
/* Keep this request around ... there was no data yet */
@ -558,21 +603,23 @@ 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;
}
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 +653,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,10 +673,10 @@ NTSTATUS TCPGetSockAddress
&AddressIP->Address[0].Address[0].sin_port));
}
UnlockObject(Connection, OldIrql);
UnlockObject(Connection);
AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
RtlZeroMemory(&AddressIP->Address[0].Address[0].sin_zero,
sizeof(AddressIP->Address[0].Address[0].sin_zero));
@ -641,7 +687,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 +697,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 +716,7 @@ BOOLEAN TCPRemoveIRP( PCONNECTION_ENDPOINT Endpoint, PIRP Irp )
}
}
UnlockObject(Endpoint, OldIrql);
UnlockObject(Endpoint);
return Found;
}

View file

@ -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;
@ -347,7 +346,7 @@ NTSTATUS UDPStartup(
#ifdef __NTDRIVER__
RtlZeroMemory(&UDPStats, sizeof(UDP_STATISTICS));
#endif
Status = PortsStartup( &UDPPorts, 1, UDP_STARTING_PORT + UDP_DYNAMIC_PORTS );
if( !NT_SUCCESS(Status) ) return Status;

View file

@ -25,12 +25,15 @@ struct lwip_callback_msg
{
/* Synchronization */
KEVENT Event;
/* Input */
union {
struct {
PVOID Arg;
} Socket;
struct {
struct tcp_pcb* pcb;
} FreeSocket;
struct {
PCONNECTION_ENDPOINT Connection;
struct ip_addr *IpAddress;
@ -60,7 +63,7 @@ struct lwip_callback_msg
int Callback;
} Close;
} Input;
/* Output */
union {
struct {
@ -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);

View file

@ -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)