summaryrefslogtreecommitdiff
path: root/network/trans/WFPSampler/lib/HelperFunctions_WinSock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'network/trans/WFPSampler/lib/HelperFunctions_WinSock.cpp')
-rw-r--r--network/trans/WFPSampler/lib/HelperFunctions_WinSock.cpp999
1 files changed, 999 insertions, 0 deletions
diff --git a/network/trans/WFPSampler/lib/HelperFunctions_WinSock.cpp b/network/trans/WFPSampler/lib/HelperFunctions_WinSock.cpp
new file mode 100644
index 00000000..2ff09737
--- /dev/null
+++ b/network/trans/WFPSampler/lib/HelperFunctions_WinSock.cpp
@@ -0,0 +1,999 @@
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2012 Microsoft Corporation. All Rights Reserved.
+//
+// Module Name:
+// HelperFunctions_WinSock.cpp
+//
+// Abstract:
+// This module contains functions for assisting in operations pertaining to Windows Sockets.
+//
+// Author:
+// Dusty Harper (DHarper)
+//
+// Revision History:
+//
+// [ Month ][Day] [Year] - [Revision]-[ Comments ]
+// May 01, 2010 - 1.0 - Creation
+//
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "HelperFunctions_Include.h" /// .
+
+/**
+ @helper_function="HlprWinSockCleanup"
+
+ Purpose: Terminates use of the Winsock DLL for the process's use. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741549.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockCleanup()
+{
+ UINT32 status = NO_ERROR;
+
+ status = WSACleanup();
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockCleanup : WSACleanup() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockInitialize"
+
+ Purpose: Initializes use of the Winsock DLL for the process's use. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS742213.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockInitialize()
+{
+ UINT32 status = NO_ERROR;
+ UINT16 versionRequested = MAKEWORD(2,
+ 2);
+ WSADATA wsaData = {0};
+
+ status = WSAStartup(versionRequested,
+ &wsaData);
+ if(status != NO_ERROR)
+ HlprLogError(L"HlprWinSockInitialize : WSAStartup() [status: %#x]",
+ status);
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockDestroyWSAEvent"
+
+ Purpose: Free a WSAEvent. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741551.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockDestroyWSAEvent(_Inout_ WSAEVENT* pWSAEvent)
+{
+ ASSERT(pWSAEvent);
+
+ UINT32 status = NO_ERROR;
+
+ if(!WSACloseEvent(*pWSAEvent))
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockDestroyWSAEvent : WSACloseEvent() [status: %#x]",
+ status);
+ }
+ else
+ *pWSAEvent = WSA_INVALID_EVENT;
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockSetWSAEvent"
+
+ Purpose: Set a WSAEvent to signaled. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS742208.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockSetWSAEvent(_In_ WSAEVENT wsaEvent)
+{
+ UINT32 status = NO_ERROR;
+
+ if(!WSASetEvent(wsaEvent))
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockSetWSAEvent : WSASetEvent() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockCreateWSAEvent"
+
+ Purpose: Create a WSAEvent. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741561.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockCreateWSAEvent(_Inout_ WSAEVENT* pWSAEvent)
+{
+ ASSERT(pWSAEvent);
+
+ UINT32 status = NO_ERROR;
+
+ *pWSAEvent = WSACreateEvent();
+ if(*pWSAEvent == WSA_INVALID_EVENT)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockCreateWSAEvent : WSACreateEvent() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockDestroySocket"
+
+ Purpose: Destroy a socket gracefully. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS740481.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS737582.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockDestroySocket(_Inout_ SOCKET* pSocket)
+{
+ ASSERT(pSocket);
+
+ UINT32 status = NO_ERROR;
+
+ if(*pSocket != INVALID_SOCKET)
+ {
+ status = shutdown(*pSocket,
+ SD_BOTH);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockDestroySocket : shutdown() [status: %#x]",
+ status);
+
+ HLPR_BAIL;
+ }
+
+ status = closesocket(*pSocket);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockDestroySocket : shutdown() [status: %#x]",
+ status);
+
+ HLPR_BAIL;
+ }
+
+ *pSocket = INVALID_SOCKET;
+ }
+
+ HLPR_BAIL_LABEL:
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockCreateSocket"
+
+ Purpose: Create a new socket. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS742212.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockCreateSocket(_In_ SOCKADDR_STORAGE* pSockAddrStorage,
+ _In_ UINT8 protocol,
+ _Inout_ SOCKET* pSocket)
+{
+ ASSERT(pSockAddrStorage);
+ ASSERT(pSocket);
+
+ UINT32 status = NO_ERROR;
+ UINT32 type = SOCK_RAW;
+
+ if(protocol == IPPROTO_TCP)
+ type = SOCK_STREAM;
+ else if(protocol == IPPROTO_UDP)
+ type = SOCK_DGRAM;
+
+ *pSocket = WSASocket(pSockAddrStorage->ss_family,
+ type,
+ protocol,
+ 0,
+ 0,
+ WSA_FLAG_OVERLAPPED);
+ if(*pSocket == INVALID_SOCKET)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockCreateSocket : WSASocket() [status:%#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockSetAbortiveDisconnect"
+
+ Purpose: Set the linger socket option to FALSE. <br>
+ <br>
+ Notes: This function needs to be called prior to HlprWinSockDestroySocket for stream
+ sockets that get a WSAECONNRESET. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS740476.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockSetAbortiveDisconnect(_In_ SOCKET abortedSocket)
+{
+ ASSERT(abortedSocket != INVALID_SOCKET);
+
+ UINT32 status = NO_ERROR;
+ LINGER linger = {0};
+
+ linger.l_onoff = TRUE;
+ linger.l_linger = 0;
+
+ status = setsockopt(abortedSocket,
+ SOL_SOCKET,
+ SO_LINGER,
+ (char*)&linger,
+ sizeof(LINGER));
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockSetAbortiveDisconnect : setsockopt() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockSetSocketReceiveTimeout"
+
+ Purpose: Specify a timeout for blocking receive calls. <br>
+ <br>
+ Notes: This function needs to be called prior to binding the socket. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS740476.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockSetSocketReceiveTimeout(_In_ SOCKET receivingSocket,
+ _In_ UINT32 timeout) /* 5000 */
+{
+ ASSERT(receivingSocket != INVALID_SOCKET);
+
+ UINT32 status = NO_ERROR;
+
+ status = setsockopt(receivingSocket,
+ SOL_SOCKET,
+ SO_RCVTIMEO,
+ (char*)&timeout,
+ sizeof(UINT32));
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockSetSocketReceiveTimeout : setsockopt() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockSetSocketSendTimeout"
+
+ Purpose: Specify a timeout for blocking send calls. <br>
+ <br>
+ Notes: This function needs to be called prior to binding the socket. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS740476.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockSetSocketSendTimeout(_In_ SOCKET sendingSocket,
+ _In_ UINT32 timeout) /* 5000 */
+{
+ ASSERT(sendingSocket != INVALID_SOCKET);
+
+ UINT32 status = NO_ERROR;
+
+ status = setsockopt(sendingSocket,
+ SOL_SOCKET,
+ SO_SNDTIMEO,
+ (char*)&timeout,
+ sizeof(UINT32));
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockSetSocketSendTimeout : setsockopt() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+
+/**
+ @helper_function="HlprWinSockSetSocketNonBlocking"
+
+ Purpose: Enable non-blocking mode on the socket. <br>
+ <br>
+ Notes: This function needs to be called prior to binding the socket. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741621.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockSetSocketNonBlocking(_In_ SOCKET unboundSocket)
+{
+ ASSERT(unboundSocket != INVALID_SOCKET);
+
+ UINT32 status = NO_ERROR;
+ UINT32 isNonBlockingSocket = TRUE;
+ UINT32 bytesReturned = 0;
+
+ status = WSAIoctl(unboundSocket,
+ FIONBIO,
+ &isNonBlockingSocket,
+ sizeof(UINT32),
+ 0,
+ 0,
+ (LPDWORD)&bytesReturned,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockSetSocketNonBlocking : WSAIoctl() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockAcquirePortReservationForSocket"
+
+ Purpose: Request a runtime reservation for the provided ports. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG699720.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741621.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockAcquirePortReservationForSocket(_In_ SOCKET unboundSocket,
+ _In_ INET_PORT_RANGE* pPortRange,
+ _Inout_ UINT64* pReservationToken)
+{
+ ASSERT(unboundSocket != INVALID_SOCKET);
+ ASSERT(pPortRange);
+ ASSERT(pReservationToken);
+
+ UINT32 status = NO_ERROR;
+ UINT32 bytesReturned = 0;
+ INET_PORT_RESERVATION_INSTANCE reservation = {0};
+
+ status = WSAIoctl(unboundSocket,
+ SIO_ACQUIRE_PORT_RESERVATION,
+ pPortRange,
+ sizeof(INET_PORT_RANGE),
+ &reservation,
+ sizeof(INET_PORT_RESERVATION_INSTANCE),
+ (LPDWORD)&bytesReturned,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockAssociatePortReservationWithSocket : WSAIoctl() [status: %#x]",
+ status);
+ }
+ else
+ *pReservationToken = reservation.Token.Token;
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockAssociatePortReservationWithSocket"
+
+ Purpose: Associate the socket with the persistent port(s) that were reserved previously. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG699721.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741621.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockAssociatePortReservationWithSocket(_In_ SOCKET unboundSocket,
+ _In_ UINT64 reservationToken)
+{
+ ASSERT(unboundSocket != INVALID_SOCKET);
+
+ UINT32 status = NO_ERROR;
+ UINT32 bytesReturned = 0;
+
+ status = WSAIoctl(unboundSocket,
+ SIO_ASSOCIATE_PORT_RESERVATION,
+ &reservationToken,
+ sizeof(UINT64),
+ 0,
+ 0,
+ (LPDWORD)&bytesReturned,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockAssociatePortReservationWithSocket : WSAIoctl() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @private_function="HlprWinSockQueryPortReservation"
+
+ Purpose: Find the token for the previously created port reservations. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG696072.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG696063.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockQueryPortReservation(_In_ UINT8 ipProtocol,
+ _In_ INET_PORT_RANGE* pPortRange,
+ _Inout_ UINT64* pReservationToken)
+{
+ ASSERT(ipProtocol != IPPROTO_TCP &&
+ ipProtocol != IPPROTO_UDP);
+ ASSERT(pPortRange);
+ ASSERT(pReservationToken);
+
+ UINT32 status = NO_ERROR;
+
+ if(ipProtocol == IPPROTO_TCP)
+ status = LookupPersistentTcpPortReservation(htons(pPortRange->StartPort),
+ pPortRange->NumberOfPorts,
+ pReservationToken);
+ else
+ status = LookupPersistentUdpPortReservation(htons(pPortRange->StartPort),
+ pPortRange->NumberOfPorts,
+ pReservationToken);
+
+ if(status != NO_ERROR)
+ {
+ if(status == ERROR_NOT_FOUND)
+ HlprLogInfo(L"HlprWinSockQueryPortReservation : LookupPersistent%sPortReservation() [status: %#x]",
+ ipProtocol == IPPROTO_TCP ? L"Tcp" : L"Udp",
+ status);
+ else
+ HlprLogError(L"HlprWinSockQueryPortReservation : LookupPersistent%sPortReservation() [status: %#x]",
+ ipProtocol == IPPROTO_TCP ? L"Tcp" : L"Udp",
+ status);
+
+ *pReservationToken = 0;
+ }
+
+ return status;
+}
+
+/**
+ @private_function="HlprWinSockDestroyPortReservation"
+
+ Purpose: Removes the reservation of specific ports for the Proxy service's use. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG696070.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG696071.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockDestroyPortReservation(_In_ UINT8 ipProtocol,
+ _In_ INET_PORT_RANGE* pPortRange,
+ _Inout_opt_ UINT64* pReservationToken) /* 0 */
+{
+ ASSERT(ipProtocol != IPPROTO_TCP &&
+ ipProtocol != IPPROTO_UDP);
+ ASSERT(pPortRange);
+
+ UINT32 status = NO_ERROR;
+
+ if(ipProtocol == IPPROTO_TCP)
+ status = DeletePersistentTcpPortReservation(htons(pPortRange->StartPort),
+ pPortRange->NumberOfPorts);
+ else
+ status = DeletePersistentUdpPortReservation(htons(pPortRange->StartPort),
+ pPortRange->NumberOfPorts);
+
+ if(status == NO_ERROR)
+ {
+ if(pReservationToken)
+ *pReservationToken = 0;
+ }
+ else if(status == ERROR_NOT_FOUND)
+ {
+ status = NO_ERROR;
+
+ if(pReservationToken)
+ *pReservationToken = 0;
+ }
+ else
+ HlprLogError(L"HlprWinSockDestroyPortReservation : DeletePersistent%sPortReservation() [status: %#x]",
+ ipProtocol == IPPROTO_TCP ? L"Tcp" : L"Udp",
+ status);
+
+ return status;
+}
+
+/**
+ @private_function="HlprWinSockCreatePortReservation"
+
+ Purpose: Reserves specific ports for the Proxy service's use. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG696068.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/GG696069.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockCreatePortReservation(_In_ UINT8 ipProtocol,
+ _In_ INET_PORT_RANGE* pPortRange,
+ _Inout_ UINT64* pReservationToken)
+{
+ ASSERT(ipProtocol != IPPROTO_TCP &&
+ ipProtocol != IPPROTO_UDP);
+ ASSERT(pPortRange);
+ ASSERT(pReservationToken);
+
+ UINT32 status = NO_ERROR;
+
+ if(ipProtocol == IPPROTO_TCP)
+ status = CreatePersistentTcpPortReservation(htons(pPortRange->StartPort),
+ pPortRange->NumberOfPorts,
+ pReservationToken);
+ else
+ status = CreatePersistentUdpPortReservation(htons(pPortRange->StartPort),
+ pPortRange->NumberOfPorts,
+ pReservationToken);
+
+ if(status != NO_ERROR)
+ {
+ HlprLogError(L"HlprWinSockCreatePortReservation : CreatePersistent%sPortReservation() [status: %#x]",
+ ipProtocol == IPPROTO_TCP ? L"Tcp" : L"Udp",
+ status);
+
+ *pReservationToken = 0;
+ }
+
+ return status;
+}
+
+#if(NTDDI_VERSION >= NTDDI_WIN8)
+
+/**
+ @helper_function="HlprWinSockAssociateConnectionRedirectRecordsAndContextWithProxySocket"
+
+ Purpose: Retrieve the original REDIRECT_RECORDS from the original socket and associate them
+ with the new (proxy) socket. <br>
+ <br>
+ Notes: This function needs to be called prior to binding the proxied socket. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741621.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/HH802472.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/HH802473.aspx <br>
+ HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/HH802474.aspx <br>
+
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockAssociateConnectionRedirectRecordsAndContextWithProxySocket(_In_ SOCKET originalSocket,
+ _Inout_ SOCKET proxySocket,
+ _Inout_ SOCKADDR_STORAGE* pProxyPeerSockAddrStorage,
+ _Inout_opt_ SOCKADDR_STORAGE* pOriginSockAddrStorage) /* 0 */
+{
+ ASSERT(originalSocket != INVALID_SOCKET);
+ ASSERT(proxySocket != INVALID_SOCKET);
+ ASSERT(pProxyPeerSockAddrStorage);
+
+ UINT32 status = NO_ERROR;
+ const SIZE_T REDIRECT_RECORDS_SIZE = 8192;
+ const SIZE_T REDIRECT_CONTEXT_SIZE = sizeof(SOCKADDR_STORAGE) * 2;
+ BYTE* pRedirectRecords = 0;
+ BYTE* pRedirectContext = 0;
+ SIZE_T redirectRecordsSize = 0;
+ SIZE_T redirectContextSize = 0;
+ SIZE_T outputSize = 0;
+
+ HLPR_NEW_ARRAY(pRedirectRecords,
+ BYTE,
+ REDIRECT_RECORDS_SIZE);
+ HLPR_BAIL_ON_ALLOC_FAILURE(pRedirectRecords,
+ status);
+
+ HLPR_NEW_ARRAY(pRedirectContext,
+ BYTE,
+ REDIRECT_CONTEXT_SIZE);
+ HLPR_BAIL_ON_ALLOC_FAILURE(pRedirectContext,
+ status);
+
+ /// Retrieve the REDIRECT_RECORDS from the client socket.
+ status = WSAIoctl(originalSocket,
+ SIO_QUERY_WFP_CONNECTION_REDIRECT_RECORDS,
+ 0,
+ 0,
+ pRedirectRecords,
+ REDIRECT_RECORDS_SIZE,
+ (LPDWORD)&redirectRecordsSize,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockAssociateConnectionRedirectRecordsAndContextWithProxySocket : WSAIoctl() [status: %#x]",
+ status);
+
+ HLPR_BAIL;
+ }
+
+ /// Retrieve the REDIRECT_CONTEXT from the client socket.
+ status = WSAIoctl(originalSocket,
+ SIO_QUERY_WFP_CONNECTION_REDIRECT_CONTEXT,
+ 0,
+ 0,
+ pRedirectContext,
+ REDIRECT_CONTEXT_SIZE,
+ (LPDWORD)&redirectContextSize,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ if(status != FWP_E_NOT_FOUND)
+ {
+ HlprLogError(L"HlprWinSockAssociateConnectionRedirectRecordsAndContextWithProxySocket : WSAIoctl() [status: %#x]",
+ status);
+
+ HLPR_BAIL;
+ }
+ }
+ else
+ {
+ ASSERT(redirectContextSize == REDIRECT_CONTEXT_SIZE);
+
+ /// The context passed in WFPSamplerCalloutDriver.sys is the SOCKADDR_STORAGE info of the
+ /// classified peer endpoint ...
+ RtlCopyMemory(pProxyPeerSockAddrStorage,
+ pRedirectContext,
+ sizeof(SOCKADDR_STORAGE));
+
+ /// ... and the SOCK_ADDR_STORAGE of the classified origin endpoint.
+ if(pOriginSockAddrStorage)
+ {
+ UINT32 contextOriginOffset = sizeof(SOCKADDR_STORAGE);
+
+ RtlCopyMemory(pOriginSockAddrStorage,
+ &(pRedirectContext[contextOriginOffset]),
+ sizeof(SOCKADDR_STORAGE));
+ }
+ }
+
+ /// Attach the REDIRECT_RECORDS to the proxied socket
+ status = WSAIoctl(proxySocket,
+ SIO_SET_WFP_CONNECTION_REDIRECT_RECORDS,
+ pRedirectRecords,
+ (DWORD)redirectRecordsSize,
+ 0,
+ 0,
+ (LPDWORD)&outputSize,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockAssociateConnectionRedirectRecordsAndContextWithProxySocket : WSAIoctl() [status: %#x]",
+ status);
+
+ HLPR_BAIL;
+ }
+
+ HLPR_BAIL_LABEL:
+
+ HLPR_DELETE_ARRAY(pRedirectContext);
+
+ HLPR_DELETE_ARRAY(pRedirectRecords);
+
+ return status;
+}
+
+#endif /// (NTDDI_VERSION >= NTDDI_WIN8)
+
+/**
+ @helper_function="HlprWinSockBindToSocket"
+
+ Purpose: Bind a socket to a protocol, port, and network address. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS737550.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockBindToSocket(_In_ SOCKET unboundSocket,
+ _In_ SOCKADDR_STORAGE* pSockAddrStorage)
+{
+ ASSERT(unboundSocket != INVALID_SOCKET);
+ ASSERT(pSockAddrStorage);
+
+ UINT32 status = NO_ERROR;
+
+ status = bind(unboundSocket,
+ (SOCKADDR*)pSockAddrStorage,
+ sizeof(SOCKADDR_STORAGE));
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockBindToSocket : bind() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockListenOnSocket"
+
+ Purpose: Place the socket in a state in which it listens for incoming connections. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS739168.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockListenOnSocket(_In_ SOCKET boundSocket)
+{
+ ASSERT(boundSocket != INVALID_SOCKET);
+
+ UINT32 status = NO_ERROR;
+
+ status = listen(boundSocket,
+ SOMAXCONN);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockListenOnSocket : listen() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockAcceptConnection"
+
+ Purpose: Place the socket in a state in which it listens for incoming connections. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741513.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockAcceptConnection(_In_ SOCKET listeningSocket,
+ _Inout_ SOCKET* pConnectedSocket,
+ _Inout_ SOCKADDR_STORAGE* pPeerSockAddrStorage)
+{
+ ASSERT(listeningSocket != INVALID_SOCKET);
+ ASSERT(pConnectedSocket);
+ ASSERT(pPeerSockAddrStorage);
+
+ UINT32 status = NO_ERROR;
+ UINT32 addressLength = sizeof(SOCKADDR_STORAGE);
+
+ *pConnectedSocket = WSAAccept(listeningSocket,
+ (SOCKADDR*)pPeerSockAddrStorage,
+ (LPINT)&addressLength,
+ 0,
+ 0);
+ if(*pConnectedSocket == INVALID_SOCKET)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockAcceptConnection : WSAAccept() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockConnectSocket"
+
+ Purpose: Establish the TCP handshake with the remote peer. <br>
+ <br>
+ Notes: <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741559.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockConnectSocket(_In_ SOCKET unconnectedSocket,
+ _In_ SOCKADDR_STORAGE* pPeerSockAddrStorage)
+{
+ ASSERT(unconnectedSocket != INVALID_SOCKET);
+ ASSERT(pPeerSockAddrStorage);
+
+ UINT32 status = NO_ERROR;
+
+ status = WSAConnect(unconnectedSocket,
+ (SOCKADDR*)pPeerSockAddrStorage,
+ sizeof(SOCKADDR_STORAGE),
+ 0,
+ 0,
+ 0,
+ 0);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ HlprLogError(L"HlprWinSockConnectSocket : WSAConnect() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockReceiveTCPData"
+
+ Purpose: Receive TCP data from the peer. <br>
+ <br>
+ Notes: For use with TCP only. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS741688.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockReceiveTCPData(_In_ SOCKET receivingSocket,
+ _Inout_updates_(numDataBuffers) WSABUF* pDataBuffers,
+ _Inout_ UINT32* pNumBytesReceived,
+ _In_opt_ LPWSAOVERLAPPED pOverlapped, /* 0 */
+ _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE pCompletionFn, /* 0 */
+ _In_ UINT32 numDataBuffers, /* 1 */
+ _In_ UINT32 msgFlags) /* 0 */
+{
+ ASSERT(receivingSocket != INVALID_SOCKET);
+ ASSERT(pDataBuffers);
+ ASSERT(pDataBuffers->len);
+ ASSERT(pDataBuffers->buf);
+ ASSERT(pNumBytesReceived);
+ ASSERT(numDataBuffers);
+ ASSERT((pNumBytesReceived &&
+ pOverlapped == 0 &&
+ pCompletionFn == 0) ||
+ (pNumBytesReceived &&
+ pOverlapped &&
+ pCompletionFn));
+
+
+ UINT32 status = NO_ERROR;
+ UINT32 flags = msgFlags;
+
+ status = WSARecv(receivingSocket,
+ pDataBuffers,
+ numDataBuffers,
+ (LPDWORD)pNumBytesReceived,
+ (LPDWORD)&flags,
+ pOverlapped,
+ pCompletionFn);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ if(status == WSA_IO_PENDING &&
+ pOverlapped &&
+ pCompletionFn)
+ status = NO_ERROR;
+ else if(status != WSAEDISCON)
+ HlprLogError(L"HlprWinSockReceiveData : WSARecv() [status: %#x]",
+ status);
+ }
+
+ return status;
+}
+
+/**
+ @helper_function="HlprWinSockSendTCPData"
+
+ Purpose: Transmit TCP data to the peer. <br>
+ <br>
+ Notes: For use with TCP only. <br>
+ <br>
+ MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Desktop/MS742203.aspx <br>
+*/
+_Success_(return == NO_ERROR)
+UINT32 HlprWinSockSendTCPData(_In_ SOCKET sendingSocket,
+ _In_reads_(numDataBuffers) WSABUF* pDataBuffers,
+ _Inout_opt_ UINT32* pNumBytesTransmitted,
+ _In_opt_ LPWSAOVERLAPPED pOverlapped, /* 0 */
+ _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE pCompletionFn, /* 0 */
+ _In_ UINT32 numDataBuffers) /* 1 */
+{
+ ASSERT(sendingSocket != INVALID_SOCKET);
+ ASSERT(pDataBuffers);
+ ASSERT(pDataBuffers->len);
+ ASSERT(pDataBuffers->buf);
+ ASSERT(numDataBuffers);
+ ASSERT((pNumBytesTransmitted &&
+ pOverlapped == 0 &&
+ pCompletionFn == 0) ||
+ (pNumBytesTransmitted &&
+ pOverlapped &&
+ pCompletionFn));
+
+ UINT32 status = NO_ERROR;
+
+ status = WSASend(sendingSocket,
+ pDataBuffers,
+ numDataBuffers,
+ (LPDWORD)pNumBytesTransmitted,
+ 0,
+ pOverlapped,
+ pCompletionFn);
+ if(status != NO_ERROR)
+ {
+ status = WSAGetLastError();
+
+ if(status == WSA_IO_PENDING &&
+ pOverlapped &&
+ pCompletionFn)
+ status = NO_ERROR;
+ else
+ HlprLogError(L"HlprWinSockSendTCPData : WSASend() [status: %#x]",
+ status);
+ }
+
+ return status;
+}