diff --git a/dll/win32/msafd/misc/dllmain.c b/dll/win32/msafd/misc/dllmain.c index 7723b93d236..dc50716b615 100644 --- a/dll/win32/msafd/misc/dllmain.c +++ b/dll/win32/msafd/misc/dllmain.c @@ -2628,6 +2628,7 @@ WSPGetSockOpt(IN SOCKET Handle, switch (Level) { + case 0: case SOL_SOCKET: switch (OptionName) { @@ -2799,7 +2800,7 @@ WSPSetSockOpt( /* FIXME: We should handle some more cases here */ - if (level == SOL_SOCKET) + if (level == SOL_SOCKET || level == 0) { switch (optname) { diff --git a/dll/win32/msafd/misc/sndrcv.c b/dll/win32/msafd/misc/sndrcv.c index 07fe8b1f1c0..3dc9a0698db 100644 --- a/dll/win32/msafd/misc/sndrcv.c +++ b/dll/win32/msafd/misc/sndrcv.c @@ -173,6 +173,7 @@ WSPRecv(SOCKET Handle, HANDLE Event = NULL; HANDLE SockEvent; PSOCKET_INFORMATION Socket; + BOOLEAN BlockMode; TRACE("Called (%x)\n", Handle); @@ -203,6 +204,12 @@ WSPRecv(SOCKET Handle, if( !NT_SUCCESS(Status) ) return -1; + /* HACK: change the Socket to Non Blocking. See CORE-12828. */ + if(FALSE){ + BlockMode = TRUE; + SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &BlockMode, NULL, NULL, NULL, NULL); + Socket->SharedData->NonBlocking = TRUE; + } /* Set up the Receive Structure */ RecvInfo.BufferArray = (PAFD_WSABUF)lpBuffers; RecvInfo.BufferCount = dwBufferCount; diff --git a/drivers/network/afd/afd/connect.c b/drivers/network/afd/afd/connect.c index 1562f5f985f..a094dc04936 100644 --- a/drivers/network/afd/afd/connect.c +++ b/drivers/network/afd/afd/connect.c @@ -21,6 +21,8 @@ AfdGetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, UNREFERENCED_PARAMETER(DeviceObject); + AFD_DbgPrint(1,("(PID %lx) AfdGetConnectOptions: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->ConnectOptionsSize == 0) @@ -52,6 +54,8 @@ AfdSetConnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp, UNREFERENCED_PARAMETER(DeviceObject); + AFD_DbgPrint(1,("(PID %lx) AfdSetConnectOptions: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!ConnectOptions) @@ -93,6 +97,8 @@ AfdSetConnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, UNREFERENCED_PARAMETER(DeviceObject); + AFD_DbgPrint(1,("(PID %lx) AfdSetConnectOptionsSize: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!ConnectOptionsSize) @@ -133,6 +139,8 @@ AfdGetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, UNREFERENCED_PARAMETER(DeviceObject); + AFD_DbgPrint(1,("(PID %lx) AfdGetConnectData: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (FCB->ConnectDataSize == 0) @@ -164,6 +172,8 @@ AfdSetConnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp, UNREFERENCED_PARAMETER(DeviceObject); + AFD_DbgPrint(1,("(PID %lx) AfdSetConnectData: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!ConnectData) @@ -204,6 +214,8 @@ AfdSetConnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp, UNREFERENCED_PARAMETER(DeviceObject); + AFD_DbgPrint(1,("(PID %lx) AfdSetConnectDataSize: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp); if (!ConnectDataSize) @@ -238,6 +250,8 @@ NTSTATUS WarmSocketForConnection(PAFD_FCB FCB) { NTSTATUS Status; + AFD_DbgPrint(1,("(PID %lx) WarmSocketForConnection: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if( !FCB->TdiDeviceName.Length || !FCB->TdiDeviceName.Buffer ) { AFD_DbgPrint(MIN_TRACE,("Null Device\n")); return STATUS_NO_SUCH_DEVICE; @@ -262,6 +276,8 @@ MakeSocketIntoConnection(PAFD_FCB FCB) { ASSERT(!FCB->Recv.Window); ASSERT(!FCB->Send.Window); + //AFD_DbgPrint(1,("(PID %lx) MakeSocketIntoConnection: Called on %p\n", PsGetCurrentProcessId(), FCB)); + if (!FCB->Recv.Size) { Status = TdiQueryMaxDatagramLength(FCB->Connection.Object, @@ -297,6 +313,7 @@ MakeSocketIntoConnection(PAFD_FCB FCB) { if( !FCB->Send.Window ) return STATUS_NO_MEMORY; } + //AFD_DbgPrint(1,("(PID %lx) MakeSocketIntoConnection: setting FCB->State to SOCKET_STATE_CONNECTED and calling TdiReceive().\n", PsGetCurrentProcessId())); FCB->State = SOCKET_STATE_CONNECTED; Status = TdiReceive( &FCB->ReceiveIrp.InFlightRequest, @@ -312,8 +329,13 @@ MakeSocketIntoConnection(PAFD_FCB FCB) { FCB->PollState |= AFD_EVENT_CONNECT | AFD_EVENT_SEND; FCB->PollStatus[FD_CONNECT_BIT] = STATUS_SUCCESS; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; + + //AFD_DbgPrint(1,("(PID %lx) MakeSocketIntoConnection: Calling PollReeval().\n", PsGetCurrentProcessId())); + PollReeval( FCB->DeviceExt, FCB->FileObject ); + //AFD_DbgPrint(1,("(PID %lx) MakeSocketIntoConnection: completed returning Status.\n", PsGetCurrentProcessId())); + return Status; } @@ -328,9 +350,11 @@ StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PLIST_ENTRY NextIrpEntry; PIRP NextIrp; - AFD_DbgPrint(MID_TRACE,("Called: FCB %p, FO %p\n", - Context, FCB->FileObject)); +/* AFD_DbgPrint(1,("(PID %lx) StreamSocketConnectComplete: Called: FCB %p, FO %p\n", + Context, FCB->FileObject)); + AFD_DbgPrint(1,("(PID %lx) StreamSocketConnectComplete: Called on %p, FO %p\n", PsGetCurrentProcessId(), Context, FCB->FileObject)); +*/ /* I was wrong about this before as we can have pending writes to a not * yet connected socket */ if( !SocketAcquireStateLock( FCB ) ) @@ -419,13 +443,12 @@ StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, SocketStateUnlock( FCB ); - AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); + AFD_DbgPrint(1,("(PID %lx) StreamSocketConnectComplete: Returning %x\n", PsGetCurrentProcessId(), Status)); return Status; } -/* Return the socket object for ths request only if it is a connected or - stream type. */ +/* Return the socket object for ths request only if it is a connected or stream type. */ NTSTATUS NTAPI AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, @@ -436,54 +459,134 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_CONNECT_INFO ConnectReq; AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: Called on %p\n", PsGetCurrentProcessId(), FCB )); + UNREFERENCED_PARAMETER(DeviceObject); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); if( !(ConnectReq = LockRequest( Irp, IrpSp, FALSE, NULL )) ) - return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, - 0 ); + return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: ConnectRequest Type: %u Address: %s\n", PsGetCurrentProcessId(), ConnectReq->RemoteAddress.Address[0].AddressType , ConnectReq->RemoteAddress.Address[0] )); - AFD_DbgPrint(MID_TRACE,("Connect request:\n")); -#if 0 + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: Connect request:\n", PsGetCurrentProcessId())); +/* if 0 // DLB enabled this buffer display for testing */ OskitDumpBuffer - ( (PCHAR)ConnectReq, - IrpSp->Parameters.DeviceIoControl.InputBufferLength ); -#endif + ( (PCHAR)ConnectReq, IrpSp->Parameters.DeviceIoControl.InputBufferLength ); +/* endif */ if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) { + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: Connectionless mode.\n", PsGetCurrentProcessId())); + if (FCB->RemoteAddress) { ExFreePoolWithTag(FCB->RemoteAddress, TAG_AFD_TRANSPORT_ADDRESS); } - FCB->RemoteAddress = - TaCopyTransportAddress( &ConnectReq->RemoteAddress ); + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: Copy RemoteAddress.\n", PsGetCurrentProcessId())); + + FCB->RemoteAddress = TaCopyTransportAddress( &ConnectReq->RemoteAddress ); // <=== send REQUIRES THIS TO USE FCB->RemoteAddress if( !FCB->RemoteAddress ) Status = STATUS_NO_MEMORY; - else + + // START OF DLB HACK FOR STORING REMOTE ADDRESS FOR USE BY SENDTO + else { + /* DLB originally datagram code exited here, these are the next steps used in stream code, we do parts of it + without actually calling tdiconnect(). We store target address info in FCB->ConnectCallInfo and FCB->ConnectReturnInfo + so we can use it in sendto if the remoteaddress parameters are not populated. I'm not sure this is how Windows handles + this, or if there's a better alternative in ReactOS, but this does work. In Sendto we try building from RemoteAddress + first and only use these stored addresses if that fails. It would probably be more efficient to check RemoteAddress + and decide based on its content, but it is populated with 'something' and non-empty so I'm not certain how to validate + it by content, for now we validate it by failure which is far less efficient. + THIS CODE WAS COPIED FROM STREAM CODE BELOW, SO IT SHOULD BE SAFE AND 'CORRECT', BUT MAY NOT BE OPTIMAL. */ + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK01 starting cloned STREAM code, calling WarmSocketConnection(FCB).\n", PsGetCurrentProcessId())); + + if (FCB->State == SOCKET_STATE_CREATED) { // THIS SECTION NOT EXECUTED MAY BE POSSIBLE TO REMOVE, we decide wehter to run based on socket state + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK02 SOCKET_STATE_CREATED found, setting LocalAddress and trying bind.\n", PsGetCurrentProcessId())); + if (FCB->LocalAddress) + { + ExFreePoolWithTag(FCB->LocalAddress, TAG_AFD_TRANSPORT_ADDRESS); + } + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK03 setting LocalAddress.\n", PsGetCurrentProcessId())); + + FCB->LocalAddress = TaBuildNullTransportAddress( ConnectReq->RemoteAddress.Address[0].AddressType ); + + if( FCB->LocalAddress ) { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK04 calling WarmSocketForBind.\n", PsGetCurrentProcessId())); + Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); + if( NT_SUCCESS(Status) ) { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK05 setting SOCKET_STATE_BOUND.\n", PsGetCurrentProcessId())); + FCB->State = SOCKET_STATE_BOUND; // <=== send REQUIRES THIS TO USE FCB->RemoteAddress + } + } + } + + if (FCB->State == SOCKET_STATE_BOUND) { // THIS SECTION EXECUTES AND HANDLES STORING TARGET ADDRESS, we decide wheter to run by socket state + if (FCB->ConnectReturnInfo) + { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK08a ConnectReturnInfo is set, so dispose of current allocated obect.\n", PsGetCurrentProcessId())); + ExFreePoolWithTag(FCB->ConnectReturnInfo, TAG_AFD_TDI_CONNECTION_INFORMATION); + } + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK08 calling TdiBuildconnectionInfo to build new ConnectReturnInfo from RemoteAddress.\n", PsGetCurrentProcessId())); + Status = TdiBuildConnectionInfo( &FCB->ConnectReturnInfo, &ConnectReq->RemoteAddress ); + + if( NT_SUCCESS(Status) ) + { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK09 new ConnectReturnInfo placed in FCB.\n", PsGetCurrentProcessId())); + if (FCB->ConnectCallInfo) + { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK08a ConnectCallInfo is set, so dispose of current allocated obect.\n", PsGetCurrentProcessId())); + ExFreePoolWithTag(FCB->ConnectCallInfo, TAG_AFD_TDI_CONNECTION_INFORMATION); + } + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK10 calling TdiBuildconnectionInfo to build new ConnectCallInfo from RemoteAddress.\n", PsGetCurrentProcessId())); + Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, &ConnectReq->RemoteAddress); + if( NT_SUCCESS(Status) ) { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK11 TdiBuildconnectionInfo call for ConnectCallInfo succeeded, populating ConnectCallInfo in FCB.\n", PsGetCurrentProcessId())); + FCB->ConnectCallInfo->UserData = FCB->ConnectData; + FCB->ConnectCallInfo->UserDataLength = FCB->ConnectDataSize; + FCB->ConnectCallInfo->Options = FCB->ConnectOptions; + FCB->ConnectCallInfo->OptionsLength = FCB->ConnectOptionsSize; + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK11a new ConnectCallInfo placed in FCB.\n", PsGetCurrentProcessId())); + } + } + } + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: HACK99 cloned STREAM code complete.\n", PsGetCurrentProcessId())); + // END OF DLB HACK FOR STORING REMOTE ADDRESS FOR USE BY SENDTO + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: completed successfully.\n", PsGetCurrentProcessId())); Status = STATUS_SUCCESS; + } return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - } + } + + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: reached switch( FCB->State ) [post patch code for stream mode.\n", PsGetCurrentProcessId())); switch( FCB->State ) { case SOCKET_STATE_CONNECTED: + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: SOCKET_STATE_CONNECTED found, setting Status = STATUS_SUCCESS.\n", PsGetCurrentProcessId())); Status = STATUS_SUCCESS; break; case SOCKET_STATE_CONNECTING: + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: SOCKET_STATE_CONNECTING found, calling LeaveIrpUnitlLater().\n", PsGetCurrentProcessId())); return LeaveIrpUntilLater( FCB, Irp, FUNCTION_CONNECT ); case SOCKET_STATE_CREATED: + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: SOCKET_STATE_CREATED found, setting LocalAddress and trying bind.\n", PsGetCurrentProcessId())); if (FCB->LocalAddress) { ExFreePoolWithTag(FCB->LocalAddress, TAG_AFD_TRANSPORT_ADDRESS); } - FCB->LocalAddress = - TaBuildNullTransportAddress( ConnectReq->RemoteAddress.Address[0].AddressType ); + FCB->LocalAddress = TaBuildNullTransportAddress( ConnectReq->RemoteAddress.Address[0].AddressType ); if( FCB->LocalAddress ) { Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); @@ -493,25 +596,25 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, else return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } else - return UnlockAndMaybeComplete - ( FCB, STATUS_NO_MEMORY, Irp, 0 ); + return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); /* Drop through to SOCKET_STATE_BOUND */ case SOCKET_STATE_BOUND: + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: SOCKET_STATE_BOUND found, setting RemoteAddress and trying connect.\n", PsGetCurrentProcessId())); if (FCB->RemoteAddress) { ExFreePoolWithTag(FCB->RemoteAddress, TAG_AFD_TRANSPORT_ADDRESS); } - FCB->RemoteAddress = - TaCopyTransportAddress( &ConnectReq->RemoteAddress ); + FCB->RemoteAddress = TaCopyTransportAddress( &ConnectReq->RemoteAddress ); if( !FCB->RemoteAddress ) { Status = STATUS_NO_MEMORY; break; } + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: calling WarmSocketConnection.\n", PsGetCurrentProcessId())); Status = WarmSocketForConnection( FCB ); if( !NT_SUCCESS(Status) ) @@ -522,9 +625,8 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, ExFreePoolWithTag(FCB->ConnectReturnInfo, TAG_AFD_TDI_CONNECTION_INFORMATION); } - Status = TdiBuildConnectionInfo - ( &FCB->ConnectReturnInfo, - &ConnectReq->RemoteAddress ); + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: calling TdiBuildconnectionInfo for ConnectReturnInfo.\n", PsGetCurrentProcessId())); + Status = TdiBuildConnectionInfo( &FCB->ConnectReturnInfo, &ConnectReq->RemoteAddress ); if( NT_SUCCESS(Status) ) { @@ -533,24 +635,27 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, ExFreePoolWithTag(FCB->ConnectCallInfo, TAG_AFD_TDI_CONNECTION_INFORMATION); } - Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, - &ConnectReq->RemoteAddress); + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: calling TdiBuildconnectionInfo for ConnectCallInfo.\n", PsGetCurrentProcessId())); + Status = TdiBuildConnectionInfo(&FCB->ConnectCallInfo, &ConnectReq->RemoteAddress); } else break; if( NT_SUCCESS(Status) ) { + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: call succeeded, populating ConnectCallInfo.\n", PsGetCurrentProcessId())); FCB->ConnectCallInfo->UserData = FCB->ConnectData; FCB->ConnectCallInfo->UserDataLength = FCB->ConnectDataSize; FCB->ConnectCallInfo->Options = FCB->ConnectOptions; FCB->ConnectCallInfo->OptionsLength = FCB->ConnectOptionsSize; + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: setting FCB->State to SOCKET_STATE_CONNECTING.\n", PsGetCurrentProcessId())); FCB->State = SOCKET_STATE_CONNECTING; - AFD_DbgPrint(MID_TRACE,("Queueing IRP %p\n", Irp)); + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: Queueing IRP %p\n", PsGetCurrentProcessId(), Irp)); Status = QueueUserModeIrp( FCB, Irp, FUNCTION_CONNECT ); if (Status == STATUS_PENDING) { + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: STATUS_PENDING found, calling TdiConnect().\n", PsGetCurrentProcessId())); Status = TdiConnect( &FCB->ConnectIrp.InFlightRequest, FCB->Connection.Object, FCB->ConnectCallInfo, @@ -559,20 +664,21 @@ AfdStreamSocketConnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, FCB ); } - if (Status != STATUS_PENDING) + if (Status != STATUS_PENDING) { + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: STATUS_PENDING NOT found, setting FCB->State to SOCKET_STATE_BOUND.\n", PsGetCurrentProcessId())); FCB->State = SOCKET_STATE_BOUND; + } SocketStateUnlock(FCB); - + //AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: completed, returning Status.\n", PsGetCurrentProcessId())); return Status; } break; default: - AFD_DbgPrint(MIN_TRACE,("Inappropriate socket state %u for connect\n", - FCB->State)); + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: Inappropriate socket state %u for connect\n", PsGetCurrentProcessId(), FCB->State)); break; } - + AFD_DbgPrint(1,("(PID %lx) AfdStreamSocketConnect: completed return UnlockAndMaybecomplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } diff --git a/drivers/network/afd/afd/tdi.c b/drivers/network/afd/afd/tdi.c index 75085bcc223..e2a0b69c716 100644 --- a/drivers/network/afd/afd/tdi.c +++ b/drivers/network/afd/afd/tdi.c @@ -297,7 +297,7 @@ NTSTATUS TdiOpenConnectionEndpointFile( NTSTATUS Status; ULONG EaLength; - AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName)); + AFD_DbgPrint(1, ("Called. DeviceName (%wZ)\n", DeviceName)); /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */ EaLength = sizeof(FILE_FULL_EA_INFORMATION) + diff --git a/drivers/network/afd/afd/tdiconn.c b/drivers/network/afd/afd/tdiconn.c index afa9f0f1d9a..7c24c4aa47a 100644 --- a/drivers/network/afd/afd/tdiconn.c +++ b/drivers/network/afd/afd/tdiconn.c @@ -11,6 +11,9 @@ #include UINT TdiAddressSizeFromType( UINT AddressType ) { + + DbgPrint("(PID %lx) TdiAddressSizeFromType() started - for type: %u\n", PsGetCurrentProcessId(), AddressType); + switch( AddressType ) { case TDI_ADDRESS_TYPE_IP: return TDI_ADDRESS_LENGTH_IP; @@ -23,8 +26,12 @@ UINT TdiAddressSizeFromType( UINT AddressType ) { return TDI_ADDRESS_LENGTH_IPX; case TDI_ADDRESS_TYPE_VNS: return TDI_ADDRESS_LENGTH_VNS; + /* DLB added the following type to prevent some crashes in SAMBA where the IPV6 loopback is used */ + case TDI_ADDRESS_TYPE_IP6: + DbgPrint("(PID %lx) TdiAddressSizeFromType - Detected use of IPV6 address type! (unsupported): %x\n", PsGetCurrentProcessId(), AddressType); + return TDI_ADDRESS_LENGTH_IP6; default: - DbgPrint("TdiAddressSizeFromType - invalid type: %x\n", AddressType); + DbgPrint("(PID %lx) TdiAddressSizeFromType - invalid type: %x\n", PsGetCurrentProcessId(), AddressType); return 0; } } @@ -38,7 +45,7 @@ UINT TaLengthOfAddress( PTA_ADDRESS Addr ) AddrLen += 2 * sizeof( USHORT ); - AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); + //AFD_DbgPrint(1,("(PID %lx) TaLengthOfAddress: AddrLen %x\n", PsGetCurrentProcessId(), AddrLen)); return AddrLen; } @@ -52,7 +59,7 @@ UINT TaLengthOfTransportAddress( PTRANSPORT_ADDRESS Addr ) AddrLen += sizeof(ULONG); - AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); + //AFD_DbgPrint(1,("(PID %lx) TaLengthOfTransportAddress: AddrLen %x\n", PsGetCurrentProcessId(), AddrLen)); return AddrLen; } @@ -61,12 +68,18 @@ UINT TaLengthOfTransportAddressByType(UINT AddressType) { UINT AddrLen = TdiAddressSizeFromType(AddressType); - if (!AddrLen) + DbgPrint("(PID %lx) TaLengthOfTransportAddressByType() started - for type: %u\n", PsGetCurrentProcessId(), AddressType); + + if (!AddrLen) { + DbgPrint("(PID %lx) TaLengthOfTransportAddressByType() failed, called TdiAddressSizeFromType() and got no AddrLen - for type: %u\n", PsGetCurrentProcessId(), AddressType); return 0; + } AddrLen += sizeof(ULONG) + 2 * sizeof(USHORT); - AFD_DbgPrint(MID_TRACE,("AddrLen %x\n", AddrLen)); + //AFD_DbgPrint(1,("(PID %lx) TaLengthOfTransportAddressByType: AddrLen %x\n", PsGetCurrentProcessId(), AddrLen)); + + DbgPrint("(PID %lx) TaLengthOfTransportAddressByType() completed - for type: %u AddrLen: %x\n", PsGetCurrentProcessId(), AddressType, AddrLen ); return AddrLen; } @@ -97,16 +110,22 @@ PTRANSPORT_ADDRESS TaCopyTransportAddress( PTRANSPORT_ADDRESS OtherAddress ) { NTSTATUS TdiBuildNullTransportAddressInPlace(PTRANSPORT_ADDRESS A, UINT AddressType) { + DbgPrint("(PID %lx) TaBuildNullTransportAddressInPlace() called - for type: %u\n", PsGetCurrentProcessId(), AddressType); + A->TAAddressCount = 1; A->Address[0].AddressLength = TdiAddressSizeFromType(AddressType); - if (!A->Address[0].AddressLength) + if (!A->Address[0].AddressLength) { + DbgPrint("(PID %lx) TaBuildNullTransportAddressInPlace() detected AddressType length mismatch returning STATUS_INVALID_PARAMETER.\n", PsGetCurrentProcessId()); return STATUS_INVALID_PARAMETER; + } A->Address[0].AddressType = AddressType; RtlZeroMemory(A->Address[0].Address, A->Address[0].AddressLength); + DbgPrint("(PID %lx) TaBuildNullTransportAddressInPlace() completed, returning STATUS_SUCCESS.\n", PsGetCurrentProcessId()); + return STATUS_SUCCESS; } @@ -115,9 +134,13 @@ PTRANSPORT_ADDRESS TaBuildNullTransportAddress(UINT AddressType) UINT AddrLen; PTRANSPORT_ADDRESS A; + DbgPrint("(PID %lx) TaBuildNullTransportAddress() called - for type: %u\n", PsGetCurrentProcessId(), AddressType); + AddrLen = TaLengthOfTransportAddressByType(AddressType); - if (!AddrLen) + if (!AddrLen) { + DbgPrint("(PID %lx) TaBuildNullTransportAddress() call to TaLengthOfTransportAddressByType() failed, returning NULL.\n", PsGetCurrentProcessId()); return NULL; + } A = ExAllocatePoolWithTag(NonPagedPool, AddrLen, TAG_AFD_TRANSPORT_ADDRESS); @@ -126,10 +149,13 @@ PTRANSPORT_ADDRESS TaBuildNullTransportAddress(UINT AddressType) if (TdiBuildNullTransportAddressInPlace(A, AddressType) != STATUS_SUCCESS) { ExFreePoolWithTag(A, TAG_AFD_TRANSPORT_ADDRESS); + DbgPrint("(PID %lx) TaBuildNullTransportAddress() call to TdiBuildNullTransportAddressInPlace() failed, returning NULL.\n", PsGetCurrentProcessId()); return NULL; } } + DbgPrint("(PID %lx) TaBuildNullTransportAddress() completed succesfully returning address.\n", PsGetCurrentProcessId()); + return A; } @@ -148,21 +174,23 @@ NTSTATUS TdiBuildNullConnectionInfoInPlace ULONG TdiAddressSize; PTRANSPORT_ADDRESS TransportAddress; + DbgPrint("(PID %lx) TdiBuildNullConnectionInfoInPlace() started - for type: %u\n", PsGetCurrentProcessId(), Type); + TdiAddressSize = TaLengthOfTransportAddressByType(Type); if (!TdiAddressSize) { - AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); + AFD_DbgPrint(1,("(PID %lx) TdiBuildNullConnectionInfoInPlace() call to TaLengthOfTransportAddressByType() did not return length, returning Invalid parameter\n", PsGetCurrentProcessId())); return STATUS_INVALID_PARAMETER; } - RtlZeroMemory(ConnInfo, - sizeof(TDI_CONNECTION_INFORMATION) + - TdiAddressSize); + RtlZeroMemory(ConnInfo, sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize); ConnInfo->OptionsLength = sizeof(ULONG); ConnInfo->RemoteAddressLength = TdiAddressSize; - ConnInfo->RemoteAddress = TransportAddress = - (PTRANSPORT_ADDRESS)&ConnInfo[1]; + TransportAddress = (PTRANSPORT_ADDRESS)&ConnInfo[1]; + ConnInfo->RemoteAddress = TransportAddress; + + DbgPrint("(PID %lx) TdiBuildNullConnectionInfoInPlace() completed - for type: %u RemoteAddress\n", PsGetCurrentProcessId(), Type, TransportAddress->Address[0].Address ); return TdiBuildNullTransportAddressInPlace(TransportAddress, Type); } @@ -184,19 +212,19 @@ NTSTATUS TdiBuildNullConnectionInfo ULONG TdiAddressSize; NTSTATUS Status; + //AFD_DbgPrint(1,("(PID %lx) TdiBuildNullConnectionInfo: Starting for type: %u\n", PsGetCurrentProcessId(), Type)); + TdiAddressSize = TaLengthOfTransportAddressByType(Type); if (!TdiAddressSize) { - AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); + AFD_DbgPrint(1,("(PID %lx) TdiBuildNullConnectionInfo: TaLengthOfTransportAddressByType() did not return TdiAddressSize ! - Invalid parameter\n", PsGetCurrentProcessId())); *ConnectionInfo = NULL; return STATUS_INVALID_PARAMETER; } - ConnInfo = (PTDI_CONNECTION_INFORMATION) - ExAllocatePoolWithTag(NonPagedPool, - sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize, - TAG_AFD_TDI_CONNECTION_INFORMATION); + ConnInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + TdiAddressSize, TAG_AFD_TDI_CONNECTION_INFORMATION); if (!ConnInfo) { *ConnectionInfo = NULL; + AFD_DbgPrint(1,("(PID %lx) TdiBuildNullConnectionInfo: TaLengthOfTransportAddressByType() allocation failed ! - Insufficient Resources\n", PsGetCurrentProcessId())); return STATUS_INSUFFICIENT_RESOURCES; } @@ -204,12 +232,15 @@ NTSTATUS TdiBuildNullConnectionInfo if (!NT_SUCCESS(Status)) { + AFD_DbgPrint(1,("(PID %lx) TdiBuildNullConnectionInfo: TaLengthOfTransportAddressByType() failed ! - setting ConnInfo to NULL\n", PsGetCurrentProcessId())); ExFreePoolWithTag(ConnInfo, TAG_AFD_TDI_CONNECTION_INFORMATION); ConnInfo = NULL; } *ConnectionInfo = ConnInfo; + AFD_DbgPrint(1,("(PID %lx) TdiBuildNullConnectionInfo: completed, returning Status - %lx\n", PsGetCurrentProcessId(), Status)); + return Status; } diff --git a/drivers/network/afd/afd/write.c b/drivers/network/afd/afd/write.c index 29ad9501b73..3d4b3cf2035 100644 --- a/drivers/network/afd/afd/write.c +++ b/drivers/network/afd/afd/write.c @@ -41,14 +41,20 @@ static NTSTATUS NTAPI SendComplete Irp->IoStatus.Status, Irp->IoStatus.Information)); - if( !SocketAcquireStateLock( FCB ) ) + AFD_DbgPrint(1,("(PID %lx) SendComplete: Starting, status %x, %u bytes used\n", PsGetCurrentProcessId(), + Irp->IoStatus.Status, + Irp->IoStatus.Information)); + + if( !SocketAcquireStateLock( FCB ) ) { + AFD_DbgPrint(1,("(PID %lx) SendComplete: failed to lock FCB, returning STATUS_FILE_CLOSED.\n", PsGetCurrentProcessId())); return STATUS_FILE_CLOSED; + } ASSERT(FCB->SendIrp.InFlightRequest == Irp); FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */ - if( FCB->State == SOCKET_STATE_CLOSED ) { + if( FCB->State == SOCKET_STATE_CLOSED) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); @@ -57,6 +63,7 @@ static NTSTATUS NTAPI SendComplete SendReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; + AFD_DbgPrint(1,("(PID %lx) SendComplete: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); @@ -66,6 +73,7 @@ static NTSTATUS NTAPI SendComplete RetryDisconnectCompletion(FCB); SocketStateUnlock( FCB ); + AFD_DbgPrint(1,("(PID %lx) SendComplete: detected FCB destruction/Socket close, returning STATUS_FILE_CLOSED.\n", PsGetCurrentProcessId())); return STATUS_FILE_CLOSED; } @@ -80,9 +88,8 @@ static NTSTATUS NTAPI SendComplete NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); - UnlockBuffers( SendReq->BufferArray, - SendReq->BufferCount, - FALSE ); + AFD_DbgPrint(1,("(PID %lx) SendComplete: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); NextIrp->IoStatus.Status = Status; NextIrp->IoStatus.Information = 0; @@ -95,13 +102,12 @@ static NTSTATUS NTAPI SendComplete RetryDisconnectCompletion(FCB); SocketStateUnlock( FCB ); - + AFD_DbgPrint(1,("(PID %lx) SendComplete: completed returning STATUS_SUCCESS.\n", PsGetCurrentProcessId())); return STATUS_SUCCESS; - } + } - RtlMoveMemory( FCB->Send.Window, - FCB->Send.Window + Irp->IoStatus.Information, - FCB->Send.BytesUsed - Irp->IoStatus.Information ); + /* remove IoStatus information and put data at start of buffer ? */ + RtlMoveMemory( FCB->Send.Window, FCB->Send.Window + Irp->IoStatus.Information, FCB->Send.BytesUsed - Irp->IoStatus.Information ); TotalBytesProcessed = 0; SendLength = Irp->IoStatus.Information; @@ -129,8 +135,7 @@ static NTSTATUS NTAPI SendComplete SendLength = 0; /* Pend the IRP */ - InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND], - &NextIrp->Tail.Overlay.ListEntry); + InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND], &NextIrp->Tail.Overlay.ListEntry); HaltSendQueue = TRUE; break; } @@ -145,9 +150,8 @@ static NTSTATUS NTAPI SendComplete (void)IoSetCancelRoutine(NextIrp, NULL); - UnlockBuffers( SendReq->BufferArray, - SendReq->BufferCount, - FALSE ); + //AFD_DbgPrint(1,("(PID %lx) SendComplete: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp); @@ -163,7 +167,7 @@ static NTSTATUS NTAPI SendComplete SendReq = GetLockedData(NextIrp, NextIrpSp); Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); - AFD_DbgPrint(MID_TRACE,("SendReq @ %p\n", SendReq)); + AFD_DbgPrint(1,("(PID %lx) SendComplete: SendReq @ %p\n", PsGetCurrentProcessId(), SendReq)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; TotalBytesCopied = 0; @@ -203,12 +207,9 @@ static NTSTATUS NTAPI SendComplete for( i = 0; i < SendReq->BufferCount; i++ ) { BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); - Map[i].BufferAddress = - MmMapLockedPages( Map[i].Mdl, KernelMode ); + Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode ); - RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed, - Map[i].BufferAddress, - BytesCopied ); + RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed, Map[i].BufferAddress, BytesCopied ); MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl ); @@ -238,13 +239,9 @@ static NTSTATUS NTAPI SendComplete /* Some data is still waiting */ if( FCB->Send.BytesUsed ) { - Status = TdiSend( &FCB->SendIrp.InFlightRequest, - FCB->Connection.Object, - 0, - FCB->Send.Window, - FCB->Send.BytesUsed, - SendComplete, - FCB ); + AFD_DbgPrint(1,("(PID %lx) SendComplete: data found waiting, calling TdiSend().\n", PsGetCurrentProcessId())); + Status = TdiSend( &FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, + SendComplete, FCB ); } else { @@ -254,6 +251,7 @@ static NTSTATUS NTAPI SendComplete SocketStateUnlock( FCB ); + AFD_DbgPrint(1,("(PID %lx) SendComplete: completed returning STATUS_SUCCESS.\n", PsGetCurrentProcessId())); return STATUS_SUCCESS; } @@ -273,8 +271,13 @@ static NTSTATUS NTAPI PacketSocketSendComplete Irp->IoStatus.Status, Irp->IoStatus.Information)); - if( !SocketAcquireStateLock( FCB ) ) + AFD_DbgPrint(1,("(PID %lx) PacketSendComplete: Starting, status %x, %u bytes used.\n", PsGetCurrentProcessId(), Irp->IoStatus.Status, Irp->IoStatus.Information)); + + + if( !SocketAcquireStateLock( FCB ) ) { + AFD_DbgPrint(1,("(PID %lx) PacketSendComplete: could not lock FCB, returning STATUS_FILE_CLOSED.\n", PsGetCurrentProcessId())); return STATUS_FILE_CLOSED; + } ASSERT(FCB->SendIrp.InFlightRequest == Irp); FCB->SendIrp.InFlightRequest = NULL; @@ -289,11 +292,13 @@ static NTSTATUS NTAPI PacketSocketSendComplete NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; (void)IoSetCancelRoutine(NextIrp, NULL); + AFD_DbgPrint(1,("(PID %lx) PacketSendComplete: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } SocketStateUnlock( FCB ); + AFD_DbgPrint(1,("(PID %lx) PacketSendComplete: detected FCB destruction/Socket Close, returning STATUS_FILE_CLOSED.\n", PsGetCurrentProcessId())); return STATUS_FILE_CLOSED; } @@ -310,6 +315,7 @@ static NTSTATUS NTAPI PacketSocketSendComplete (void)IoSetCancelRoutine(NextIrp, NULL); + //AFD_DbgPrint(1,("(PID %lx) PacketSendComplete: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); @@ -322,6 +328,8 @@ static NTSTATUS NTAPI PacketSocketSendComplete SocketStateUnlock(FCB); + AFD_DbgPrint(1,("(PID %lx) PacketSendComplete: completed, returning STATUS_SUCCESS.\n", PsGetCurrentProcessId())); + return STATUS_SUCCESS; } @@ -334,12 +342,22 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_SEND_INFO SendReq; UINT TotalBytesCopied = 0, i, SpaceAvail = 0, BytesCopied, SendLength; KPROCESSOR_MODE LockMode; + UINT FullSendLen, LoopIdx; /* DLB accumulator for packet structure length */ +/* char pktbuf[4096]; */ /* packet assembly buffer */ UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Short); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); + //AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: Starting on FCB: %p\n", PsGetCurrentProcessId(), FCB)); +if (FCB->State == SOCKET_STATE_CREATED) { // we may or may not need this, so we'll decide based on the state for now + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: HACK06a SOCKET_STATE_CREATED found.\n", PsGetCurrentProcessId())); +} +if (FCB->State == SOCKET_STATE_BOUND) { // we may or may not need this, so we'll decide based on the state for now + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: HACK06b SOCKET_STATE_BOUND found.\n", PsGetCurrentProcessId())); +} + if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; @@ -349,50 +367,155 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_SEND_INFO_UDP SendReq; PTDI_CONNECTION_INFORMATION TargetAddress; + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: processing CONNECTIONLESS send.\n", PsGetCurrentProcessId())); + /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND || !FCB->RemoteAddress ) { - AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); - return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, - 0 ); + /* AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: found incompatible FCB->State, returning STATUS_INVALID_PARAMETER.\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } - if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) + if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: LockRequest() failed, returning STATUS_NO_MEMORY.\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); + } - /* Must lock buffers before handing off user data */ - SendReq->BufferArray = LockBuffers( SendReq->BufferArray, - SendReq->BufferCount, - NULL, NULL, - FALSE, FALSE, LockMode ); + /* Must lock buffers before handing off user data */ + /* LockBuffers figures out the size of allocation and lock space uses this code to figure out length of sendreq + UINT Lock = LockAddress ? 2 : 0; + UINT Size = (sizeof(AFD_WSABUF) + sizeof(AFD_MAPBUF)) * (Count + Lock); + -- I'm not sure what the lock component is, but excluding the +lock this all makes sense as the length for the total packet array + -- SendReq is the entire array, so we may be able to use sizeof(SendReq), but it seems the most likely value will be (sizeof(SendReq) - (2 * (sizeof(AFD_WSABUF) + sizeof(AFD_MAPBUF)))) + -- or even better (sizeof(AFD_WSABUF) + sizeof(AFD_MAPBUF)) * (Count) it apears the last allocateion is a placeholder of sorts and only the address and len parts are used + -- perhaps the issue here is that the code is trying to use that last entry and uses the first by mistake because it thinks the structure is built differently + -- or perhaps the structure is built incorrectly and should have that 'wrapper' item at the beginning. since a lot of other routines use lockbuffers() we'll patch this here for now + -- but AFD as a whole may have a bigger bug to be fixed!! + -- when fillinf the target structure the LockBuffers routine only copies (sizeof(AFD_WSABUF) * Count) bytes from the older buffer to the new one, then it walks the list creating an + -- MDL allocation for each and adds the mapped MDL address to the send request. there is an array of buffers here, but the send code seems to send only the first for datagrams. + */ + + if (SendReq->BufferCount > 1) { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - calling LockBuffers() with LockAddress=TRUE and (VOID *)0xFFFFFFFF Lock entry address and length - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + } else { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - calling LockBuffers() with LockAddress=FALSE and NULL Lock entry address and length - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + } + + /* LockBuffers now destoys the array replacing it with a single flat buffer so we need to preserve the length and pointer for later use */ + FullSendLen = 0; + for (LoopIdx = 0; LoopIdx < SendReq->BufferCount; LoopIdx++) { + /* OskitDumpBuffer( SendReq->BufferArray[LoopIdx].buf, SendReq->BufferArray[LoopIdx].len ); // DLB added + AFD_DbgPrint(1,("\n" )); */ + FullSendLen = FullSendLen + SendReq->BufferArray[LoopIdx].len; + } + AFD_DbgPrint(1,("\n" )); + + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - prior to LockBuffers() Data length is %u.\n", PsGetCurrentProcessId(), FullSendLen )); + + /* ORIG SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); */ + + if (SendReq->BufferCount > 1) { + /* let's try the existing LockAddress mode and see what buffers look like */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - multiple buffers in array, calling existing LockAddress mode. BufferArray base:%p count: %u\n", PsGetCurrentProcessId(), SendReq->BufferArray, SendReq->BufferCount )); + for (LoopIdx = 0; LoopIdx < SendReq->BufferCount; LoopIdx++) { + OskitDumpBuffer( SendReq->BufferArray[LoopIdx].buf, SendReq->BufferArray[LoopIdx].len ); /* DLB added this */ + AFD_DbgPrint(1,("\n" )); + } + AFD_DbgPrint(1,("\n" )); + + /* hacky PAD packet assembly code, probably not thread safe among other things */ + + + /* THE ONLY CALLER THAT USES LOCAKADDRESS=TRUE is the recv datagram routine and when it does use it the + caller provides address and length after buffercount when it makes the call, and the values are a wrapper + containing all the smaller buffers witin it. Basically it starts at the first buffer and has the length of + the sum of the buffer sizes. Lock sees it and creates one more entry and handles it just like the others */ + + SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, TRUE, LockMode ); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - multiple buffers mode, LockBuffers complete displaying buffers. BufferArray base:%p count: %u\n", PsGetCurrentProcessId(), SendReq->BufferArray, SendReq->BufferCount )); + for (LoopIdx = 0; LoopIdx < SendReq->BufferCount; LoopIdx++) { + OskitDumpBuffer( SendReq->BufferArray[LoopIdx].buf, SendReq->BufferArray[LoopIdx].len ); /* DLB added this */ + AFD_DbgPrint(1,("\n" )); + } + AFD_DbgPrint(1,("\n" )); + +/* magic hack routine, called by impossible values with lockaddress true + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - multiple buffers in array, performing LockBuffers() gather operation - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray )); + SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, (VOID *)0xFFFFFFFF, (VOID *)0xFFFFFFFF, FALSE, TRUE, LockMode ); + SendReq->BufferCount = 1; +*/ /* as a precaution to keep the structures valid */ + } else { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: DLB LB Hack - SINGLE buffer in array, calling original LockBuffers() code - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray )); + SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); + } if( !SendReq->BufferArray ) { - return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, - Irp, 0 ); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: LockBuffers() failed, returning STATUS_ACCESS_VIOLATION.\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } + OskitDumpBuffer( SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len ); /* DLB added this */ + + AFD_DbgPrint(1,("\n(PID %lx) AfdConnectedSocketWriteData: setting TargetAddress from FCB->RemoteAddress.\n", PsGetCurrentProcessId())); + + AFD_DbgPrint + (1,("(PID %lx) AfdConnectedSocketWriteData: FCB->RemoteAddress Type: %x Address: %s Port: \n", PsGetCurrentProcessId(), + FCB->RemoteAddress->Address[0].AddressType, // word + FCB->RemoteAddress->Address[0].Address // dword + /*, ntohs( FCB->RemoteAddress->Address[0].Port ) */ + )); + Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); if( NT_SUCCESS(Status) ) { FCB->PollState &= ~AFD_EVENT_SEND; - + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: nonblocking send requested, queueing user mode IRP.\n", PsGetCurrentProcessId())); Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { - Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, - FCB->AddressFile.Object, - SendReq->BufferArray[0].buf, - SendReq->BufferArray[0].len, - TargetAddress, - PacketSocketSendComplete, - FCB); + + /* DLB may be a bug here. This assumes the buffer array has only a single element or has a lead element that wraps others. Based on a review of LockBuffers() which clones the structure + from userland into driver MDL area, there is no such wrapper element. Whenever multiple buffers are used this code is sending ONY the first element. This is a bug because the + structure has a count associated with it to indicate how many buffers are present.. If this was always a single element there would be no counter.. */ + + /* DLB this looks just plain wrong.. the buffer array is supposed to be sent as a sent in a single packet. This sends the first element ignoring the rest altogether ! */ + /* Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); */ + + /* the total buffer size came in as a parameter so hopefully its in Sendreq somewhere.. If not we can walk the buffers summing the lengths and then + add the size of the len and buf elements multiplied by the buffer count to get the total length. That is what the packet is supposed to contain. Not just the first buffer. + we are supposed to send the whole buffer array at once. It is the callers responsibility to make sure the buffers and structures are set up with proper sizes for it and + that the datagram is split up before this point if it needs to be split up. */ + + /* DLB no such luck. reviewing LockBuffers we can see that SendReq->BufferArray contains only the buffer items sent in by the caller, there is no lead element that wraps the whole + array or buffer count inside it, those are addl elements parallel to the BufferArray. The code seems to assume there is a wrapper at head so it ends up sending first item alone. + we will need to loop through the bufferarray collecting up its data length from its content items. as long as the allocations were consecutive this should work. if the allocations + were not consecutive in memory we will fail to send the data.. right number of bytes, wrong content after first item.. If that happens we need to make significant changes to + LockBuffers so that the allocation of the buffer is done in a single operation and the elements are copied in at offsets. This is not it's current logic and would be full rewrite + we are trying this simpler method first because changing LockBuffers could have wider reaching side effects as it is used by all of AFD and other bad assumptions may be present. + Unfortunately if taht is the case it implies a full code review and rewrite of AFDs buffer handling will be required to truly fix this issue. */ + + /* if LockAddress parameter was being used with LockBuffers we would need Count-1 or could possibly use just SendReq->BufferArray[Count].len, but it is not used for this case so we + cannot. If this method does not work we should try setting it true and see if that works.. That essentially does the same thing, but has LockBuffers handle it internally while + doing its allocations. It may work there and not here because it may change the allocation method from individual to grouped with offset, don't recall. */ + + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: found STATUS_PENDING, calling TdiSendDatagram(x x %p %u %p x FCB ).\n", PsGetCurrentProcessId(), SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress )); + + OskitDumpBuffer( SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len ); /* DLB added this */ + + Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len , TargetAddress, + PacketSocketSendComplete, FCB); + if (Status != STATUS_PENDING) { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: did not find STATUS_PENDING, marking IoRequest as complete.\n", PsGetCurrentProcessId())); NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; (void)IoSetCancelRoutine(Irp, NULL); - UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); /* call original code as before */ + /* UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, TRUE); // modified code */ UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } @@ -402,68 +525,79 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, SocketStateUnlock(FCB); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: returning STATUS_PENDING.\n", PsGetCurrentProcessId())); + return STATUS_PENDING; } else { - UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: unlocking buffers and calling UnlockAndMaybeComplete() for IRP.\n", PsGetCurrentProcessId())); + /* UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, TRUE); */ /* use our special buffer consolidation mode */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: Calling UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); /* use original code */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed, returning via UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } + /* DATAGRAM CODE ENDS HERE */ } if (FCB->PollState & AFD_EVENT_CLOSE) { - AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); - + //AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: received AFD_EVENT_CLOSE, connection reset by peer.\n", PsGetCurrentProcessId())); /* This is an unexpected remote disconnect */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed(AFD_EVENT_CLOSE), returning via UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->PollState & AFD_EVENT_ABORT) { - AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); - + //AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: received AFD_EVENT_ABORT, connection aborted.\n", PsGetCurrentProcessId())); /* This is an abortive socket closure on our side */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed(AFD_EVENT_ABORT), returning via UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->SendClosed) { - AFD_DbgPrint(MIN_TRACE,("No more sends\n")); - + //AFD_DbgPrint(MIN_TRACE,("No more sends\n")); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: received FCB->SendClosed, No more sends (graceful send closure).\n", PsGetCurrentProcessId())); /* This is a graceful send closure */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed, returning (STATUS_FILE_CLOSE) via UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } - if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) - return UnlockAndMaybeComplete - ( FCB, STATUS_NO_MEMORY, Irp, 0 ); + if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: LockRequest() failed, returning STATUS_NO_MEMORY.\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); + } - SendReq->BufferArray = LockBuffers( SendReq->BufferArray, - SendReq->BufferCount, - NULL, NULL, - FALSE, FALSE, LockMode ); + //AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: Calling LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) { - return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, - Irp, 0 ); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: LockBuffers() failed, returning STATUS_ACCESS_VIOLATION.\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } - AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State)); + /*AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State)); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: socket state: %u.\n", PsGetCurrentProcessId(), FCB->State));*/ if( FCB->State != SOCKET_STATE_CONNECTED ) { - AFD_DbgPrint(MID_TRACE,("Socket not connected\n")); + //AFD_DbgPrint(MID_TRACE,("Socket not connected\n")); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: FCB->State != SOCKET_STATE_CONNECTED, unlocking and completing as STATUS_INVALID_CONNECTION (socket is not connected).\n", PsGetCurrentProcessId())); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed, returning (STATUS_INVALID_CONNECTION) via UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_CONNECTION, Irp, 0 ); } - AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n", - FCB->Send.BytesUsed)); + //AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n", FCB->Send.BytesUsed)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; - AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n", - SpaceAvail)); + //AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: We can accept %u bytes\n", PsGetCurrentProcessId(), SpaceAvail)); /* Count the total transfer size */ SendLength = 0; @@ -479,6 +613,7 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { FCB->PollState &= ~AFD_EVENT_SEND; + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed, calling LeaveIrpUntilLater(FUNCTION_SEND) - leaving on queue.\n", PsGetCurrentProcessId())); return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); } @@ -490,12 +625,15 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, /* Non-overlapped sockets will fail if we can send nothing */ if (!(SendReq->AfdFlags & AFD_OVERLAPPED)) { + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: non-overlap socket failed, calling UnlcokAndMaybeComplete(STATUS_CANT_WAIT).\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 ); } else { /* Overlapped sockets just pend */ + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed, calling LeaveIrpUntilLater(FUNCTION_SEND) - leaving on queue.\n", PsGetCurrentProcessId())); return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); } } @@ -503,17 +641,12 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ ) { - BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); + BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); /* DLB: this assumes the tail element on the buffer array has the array wrapping item present which depends on LockMode used */ - AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n", - i, - SendReq->BufferArray[i].buf, - BytesCopied, - FCB->Send.Window + FCB->Send.BytesUsed)); +/* AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n", i, SendReq->BufferArray[i].buf, BytesCopied, FCB->Send.Window + FCB->Send.BytesUsed)); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: Copying Buffer %u, %p:%u to %p\n", PsGetCurrentProcessId(), i, SendReq->BufferArray[i].buf, BytesCopied, FCB->Send.Window + FCB->Send.BytesUsed));*/ - RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed, - SendReq->BufferArray[i].buf, - BytesCopied); + RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed, SendReq->BufferArray[i].buf, BytesCopied); TotalBytesCopied += BytesCopied; SpaceAvail -= BytesCopied; @@ -524,9 +657,10 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, if( TotalBytesCopied == 0 ) { AFD_DbgPrint(MID_TRACE,("Empty send\n")); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); - return UnlockAndMaybeComplete - ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); + AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: Empty send, calling UnlockAndMaybeComplete(STATUS_SUCCESS).\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); } if (SpaceAvail) @@ -546,17 +680,15 @@ AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest) { - TdiSend(&FCB->SendIrp.InFlightRequest, - FCB->Connection.Object, - 0, - FCB->Send.Window, - FCB->Send.BytesUsed, - SendComplete, - FCB); + //AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: calling TdiSend().\n", PsGetCurrentProcessId())); + + TdiSend(&FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, SendComplete, FCB); } SocketStateUnlock(FCB); + //AFD_DbgPrint(1,("(PID %lx) AfdConnectedSocketWriteData: completed, returning STATUS_PENDING.\n", PsGetCurrentProcessId())); + return STATUS_PENDING; } @@ -569,110 +701,243 @@ AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp, PAFD_FCB FCB = FileObject->FsContext; PAFD_SEND_INFO_UDP SendReq; KPROCESSOR_MODE LockMode; + INT FullSendLen, LoopIdx; /* DLB accumulator for packet structure length */ +/* INT DataSize; // part of buffer PAD hack */ + char pktbuf[4096]; /* packet assembly buffer */ UNREFERENCED_PARAMETER(DeviceObject); - AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); + //AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); - if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Starting on FCB: %p\n", PsGetCurrentProcessId(), FCB)); + + if( !SocketAcquireStateLock( FCB ) ) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: failed to lock FCB %p, returning via LostSocket().\n", PsGetCurrentProcessId(), FCB)); + return LostSocket( Irp ); + } FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; /* Check that the socket is bound */ - if( FCB->State != SOCKET_STATE_BOUND && - FCB->State != SOCKET_STATE_CREATED) + if( FCB->State != SOCKET_STATE_BOUND && FCB->State != SOCKET_STATE_CREATED) { - AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Invalid socket state, calling UnlockAndMaybeComplete() as STATUS_INVALID_PARAMETER\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); } if (FCB->SendClosed) { - AFD_DbgPrint(MIN_TRACE,("No more sends\n")); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: No more sends, calling UnlockAndMaybeComplete() as STATUS_FILE_CLOSED\n")); return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } - if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: calling LockRequest() to lock and copy request.\n", PsGetCurrentProcessId())); + + if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: LockRequest() failed, returning STATUS_NO_MEMORY.\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); + } if (FCB->State == SOCKET_STATE_CREATED) { + + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: FCB->State == SOCKET_STATE_CREATED.\n", PsGetCurrentProcessId())); + if (FCB->LocalAddress) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: FCB->LocalAddress is set, Calling ExFreePoolWithTag().\n", PsGetCurrentProcessId())); ExFreePoolWithTag(FCB->LocalAddress, TAG_AFD_TRANSPORT_ADDRESS); } - FCB->LocalAddress = - TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> - Address[0].AddressType ); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Calling TaBuildNullTransportAddress() for type %u .\n", PsGetCurrentProcessId(), ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->Address[0].AddressType )); + + FCB->LocalAddress = TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->Address[0].AddressType ); if( FCB->LocalAddress ) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Calling WarmSocketForBind().\n", PsGetCurrentProcessId())); Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); - - if( NT_SUCCESS(Status) ) + if( NT_SUCCESS(Status) ) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: WarmSocketForBind() succeeded, setting FCB->STATE to Socket_STATE_BOUND.\n", PsGetCurrentProcessId())); FCB->State = SOCKET_STATE_BOUND; - else + } + else { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: call to WarmSocketForBind() did not return NT_SUCCESS, return through UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); - } else - return UnlockAndMaybeComplete - ( FCB, STATUS_NO_MEMORY, Irp, 0 ); + } + } else { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: call to TaBuildNullTransportAddress() did not get LocalAddress, skip local BIND and return through UnlockAndMaybeComplete() as STATUS_NO_MEMORY.\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); + } + } + /*else + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: FCB->State <> SOCKET_STATE_CREATED, local bind skipped and FCB->State unchanged.\n", PsGetCurrentProcessId())); +*/ + if (SendReq->BufferCount > 1) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB PAD Hack - Assembling local packet buffer from %u Buffer Array elements, clearing buffer.\n", PsGetCurrentProcessId(), SendReq->BufferCount)); + RtlZeroMemory((&pktbuf[0]), 4096 ); + /* save the data length for cross checking later */ + FullSendLen = 0; + for (LoopIdx = 0; LoopIdx < SendReq->BufferCount; LoopIdx++) { + //AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + OskitDumpBuffer( SendReq->BufferArray[LoopIdx].buf, SendReq->BufferArray[LoopIdx].len ); /* DLB added this */ + //AFD_DbgPrint(1,("(PID %lx) Copying data shown above to: %p length: %u pkt_start: %p\n", PsGetCurrentProcessId(), (PCHAR)((&pktbuf[0]) + FullSendLen), SendReq->BufferArray[LoopIdx].len, (PCHAR)(&pktbuf[0]) )); + /* create our full packet in local buffer */ + _SEH2_TRY { + RtlCopyMemory((PCHAR)((&pktbuf[0]) + FullSendLen), SendReq->BufferArray[LoopIdx].buf, SendReq->BufferArray[LoopIdx].len ); + } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + AFD_DbgPrint(0,("(PID %lx) AfdPacketSocketWriteData: DLB PAD Hack Access violation copying buffer data from userland (%p %p), returning NULL\n", PsGetCurrentProcessId(), SendReq->BufferArray[LoopIdx].buf, SendReq->BufferArray[LoopIdx].len )); + /* ExFreePoolWithTag(NewBuf, TAG_AFD_WSA_BUFFER); not allocated yet */ + _SEH2_YIELD(return STATUS_NO_MEMORY); + } _SEH2_END; + FullSendLen = FullSendLen + SendReq->BufferArray[LoopIdx].len; /* THIS WORKS FINE GIVES CORRECT LENGTH seen on windows */ + } + + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB PAD Hack - Completed local buffer assembled.\n", PsGetCurrentProcessId())); +/* + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + OskitDumpBuffer( &pktbuf[0], FullSendLen ); // DLB added this + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); +*/ + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB PAD-LB Hack - calling LockBuffers() with LockAddress=TRUE and (VOID *)0xFFFFFFFF Lock entry address and length - 0x%p:u\n", PsGetCurrentProcessId(), &pktbuf[0], FullSendLen)); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB - prior to LockBuffers() call Data length is %u.\n", PsGetCurrentProcessId(), FullSendLen )); + } /*else { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB - calling LockBuffers() without hacks LockAddress=FALSE and NULL Lock entry address and length - 0x%p:%u\n", PsGetCurrentProcessId(), SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len)); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB - prior to LockBuffers() call Data length is %u.\n", PsGetCurrentProcessId(), SendReq->BufferArray[0].len )); + }*/ + + + SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); + + if( !SendReq->BufferArray ) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: failed call to LockBuffers(), return via UnlockAndMaybecomplete() as STATUS_ACCESS_VIOLATION.\n", PsGetCurrentProcessId())); + return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } - SendReq->BufferArray = LockBuffers( SendReq->BufferArray, - SendReq->BufferCount, - NULL, NULL, - FALSE, FALSE, LockMode ); + /*if (SendReq->BufferCount > 1) { + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + OskitDumpBuffer(&pktbuf[0], FullSendLen ); // DLB added this + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + } else { + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + OskitDumpBuffer( SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len ); // DLB added this + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + } - if( !SendReq->BufferArray ) - return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, - Irp, 0 ); + AFD_DbgPrint + (MID_TRACE,("AfdPacketSocketWriteData: RemoteAddress #%d Type %u\n", + ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->TAAddressCount, + ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->Address[0].AddressType)); AFD_DbgPrint - (MID_TRACE,("RemoteAddress #%d Type %u\n", - ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> - TAAddressCount, - ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> - Address[0].AddressType)); + (1,("(PID %lx) AfdPacketSocketWriteData: SendReq->TdiConnection.RemoteAddress #%d Type: %x Address: %lx Port: %x\n", PsGetCurrentProcessId(), + ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->TAAddressCount, + ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->Address[0].AddressType, // word + ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->Address[0].Address // dword + //, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)->Address[0].Port + )); + + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Calling TdiBuildConnectionInfo() setting TargetAddress from SendReq->TdiConnection.RemoteAddress.\n", PsGetCurrentProcessId())); + */ + + Status = TdiBuildConnectionInfo( &TargetAddress, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) ); + + /* DLB hack, if the above operation failed we assume the remote address is not provided and check if we have connection information in the FCB to use */ + if( !NT_SUCCESS(Status) ) { + if (FCB->ConnectCallInfo) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: HACK1 settings TargetAddress from ConnectCallInfo->RemoteAddress.\n", PsGetCurrentProcessId() )); + Status = TdiBuildConnectionInfo( &TargetAddress, ((PTRANSPORT_ADDRESS)FCB->ConnectCallInfo->RemoteAddress) ); + } else { + if (FCB->ConnectReturnInfo) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: HACK2 settings TargetAddress from ConnectReturnInfo->RemoteAddress.\n", PsGetCurrentProcessId() )); + Status = TdiBuildConnectionInfo( &TargetAddress, ((PTRANSPORT_ADDRESS)FCB->ConnectReturnInfo->RemoteAddress) ); + } + } + } - Status = TdiBuildConnectionInfo( &TargetAddress, - ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) ); + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: HACKs completed, send continuing.\n", PsGetCurrentProcessId() )); /* Check the size of the Address given ... */ - if( NT_SUCCESS(Status) ) { + + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: TdiBuildConnectionInfo() successful, calling QueueUserModeIrp().\n", PsGetCurrentProcessId())); + FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); + if (Status == STATUS_PENDING) { - Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, - FCB->AddressFile.Object, - SendReq->BufferArray[0].buf, - SendReq->BufferArray[0].len, - TargetAddress, - PacketSocketSendComplete, - FCB); + + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Status is STATUS_PENDING, Calling TdiSendDatagram().\n", PsGetCurrentProcessId())); + + /* DLB this looks just plain wrong.. the buffer array is supposed to be sent as a sent in a single packet. This sends the first element ignoring the rest altogether ! */ + /* Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); */ + + /* this is just debug crosscheck output and should not remain in code permanently */ + /* AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: sizeof(AFD_WSABUF): %u sizeof(AFD_MAPBUF): %u sizeof(UINT): %u sizeof(PCHAR): %u sizeof(PVOID): %u sizeof(PMDL): %u.\n", PsGetCurrentProcessId(), sizeof(AFD_WSABUF), sizeof(AFD_MAPBUF), sizeof(UINT), sizeof(PCHAR), sizeof(PVOID), sizeof(PMDL) )); */ + + if (SendReq->BufferCount > 1) { /* backpedalled all the PAD copying, just assume they are contigoupus and send.. */ + /*AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: found STATUS_PENDING, calling TdiSendDatagram(x x %p %u %p x FCB ) buffer base is: %p.\n", PsGetCurrentProcessId(), SendReq->BufferArray[0].buf, + FullSendLen, TargetAddress, &SendReq->BufferArray[0].len )); + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + OskitDumpBuffer( &pktbuf[0], FullSendLen ); // DLB added this + AFD_DbgPrint(1,("(PID %lx) \n", PsGetCurrentProcessId())); + */ + Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, &pktbuf[0], FullSendLen, TargetAddress, PacketSocketSendComplete, FCB); + + /* SECURITY NOTE, WE ARE NOT CLEARING BUFFER AFTER USE. INFORMATION LEAKAGE ON STACK COULD COMPROMISE SENSITIVE DATA */ + + } else { + /*AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: found STATUS_PENDING, calling TdiSendDatagram(x x %p %u %p x FCB ) buffer base is: %p.\n", PsGetCurrentProcessId(), SendReq->BufferArray[0].buf, + SendReq->BufferArray[0].len, TargetAddress, &SendReq->BufferArray[0].len ));*/ + Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); + } + + /* DLB currently this is still broken because the allocations are not contiguous. the buffer array needs to be built in a contiguous fashion and currently it's not. + this is a ROS issue because it works correctly on Windows 10, and it is an artifact of bad assumptions in the ROS codebase (AFD driver). */ + if (Status != STATUS_PENDING) { NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; (void)IoSetCancelRoutine(Irp, NULL); - UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + /* by the time we get here there is only a single buffer unless something went wrong.. */ +/* + if (SendReq->BufferCount > 1) { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB LB Hack - multiple buffers in array, calling revised UnlockBuffers() code - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray )); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, TRUE ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, TRUE); + } else { + + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: DLB LB Hack - calling original UnlockBuffers() code - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray )); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); +*/ + UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); +/* } */ UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: error, Call to TdiSendDatagram() did not return STATUS_PENDING.\n", PsGetCurrentProcessId())); } - } + } else + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: call to TdiBuildConnectionInfo() failed, call to TdiSendDatagram() skipped.\n", PsGetCurrentProcessId())); + + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: Send actions completed, freeing TargetAddress, calling ExFreePoolWithTag() then SocketStateUnlock(FCB).\n", PsGetCurrentProcessId())); ExFreePoolWithTag(TargetAddress, TAG_AFD_TDI_CONNECTION_INFORMATION); SocketStateUnlock(FCB); + //AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: completed, returning STATUS_PENDING.\n", PsGetCurrentProcessId())); + return STATUS_PENDING; } else { + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ) - 0x%p\n", PsGetCurrentProcessId(), SendReq->BufferArray)); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: completed, returning UnlockAndMaybeComplete().\n", PsGetCurrentProcessId())); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } + AFD_DbgPrint(1,("(PID %lx) AfdPacketSocketWriteData: completed (fallthrough).\n", PsGetCurrentProcessId())); }