in cpp/Riosock/Riosock.cpp [55:134]
HRESULT EnsureWinSockMethods(
_In_ SOCKET socket
)
{
static const LONG LockUninitialized = 0;
static const LONG LockInitialized = 1;
static const LONG LockInitializing = 2;
LONG lastState;
while((lastState = ::InterlockedCompareExchange(
&WinSockMethodsLock,
LockInitializing,
LockUninitialized)) == LockInitializing)
{
Sleep(0);
}
if (lastState == LockInitialized)
{
return S_OK;
}
WSADATA wsaData;
auto err = WSAStartup(WINSOCK_VERSION, &wsaData);
if (err != 0) {
// Reset lock to uninitialized
::InterlockedExchange(&WinSockMethodsLock, LockUninitialized);
// WSAStartup does not set LastWin32Error
SetLastError(err);
return HRESULT_FROM_WIN32(err);
}
// Check to see if we need to create a temp socket
auto localSocket = socket;
if (INVALID_SOCKET == localSocket)
{
DWORD dwFlags = WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED | WSA_FLAG_REGISTERED_IO;
localSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, nullptr, 0, dwFlags);
if (INVALID_SOCKET == localSocket)
{
DWORD errorCode = WSAGetLastError();
// Reset lock to uninitialized
WSACleanup();
::InterlockedExchange(&WinSockMethodsLock, LockUninitialized);
SetLastError(errorCode);
return HRESULT_FROM_WIN32(errorCode);
}
}
GUID funcGuid = WSAID_MULTIPLE_RIO;
DWORD dwBytes = 0;
if (WSAIoctl(
localSocket,
SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
&funcGuid, sizeof(GUID),
&RIOFuncs, sizeof(RIOFuncs),
&dwBytes,nullptr, nullptr) != 0)
{
DWORD errorCode = WSAGetLastError();
if (localSocket != socket)
{
closesocket(localSocket);
}
WSACleanup();
// Reset lock to uninitialized
::InterlockedExchange(&WinSockMethodsLock, LockUninitialized);
SetLastError(errorCode);
return HRESULT_FROM_WIN32(errorCode);
}
// Update lock to fully Initialized
::InterlockedExchange(&WinSockMethodsLock, LockInitialized);
if (localSocket != socket) {
closesocket(localSocket);
}
return S_OK;
}