📄 overlap.cpp
字号:
WSAOVERLAPPEDPLUS *op=NULL;
EnterCriticalSection(&gOverlappedCS);
op = PendingStart;
if (PendingStart)
{
PendingStart = op->next;
}
if (op == PendingEnd)
{
PendingStart = PendingEnd = NULL;
}
LeaveCriticalSection(&gOverlappedCS);
return op;
}
//
// Function: ExecuteOverlappedOperation
//
// Description:
// This function actually executes an overlapped operation that was queued.
// If on Win9x we substitute our own completion function in order to intercept
// the results. If on NT we post the operation to our completion port.
// This function either returns NO_ERROR if the operation succeeds immediately
// or the Winsock error code upone failure (or overlapped operation).
//
int ExecuteOverlappedOperation(WSAOVERLAPPEDPLUS *ol, BOOL bSynchronous)
{
LPWSAOVERLAPPED_COMPLETION_ROUTINE routine = NULL;
PROVIDER *Provider;
OVERLAPPED *col = NULL;
DWORD *lpdwFlags = NULL,
*lpdwBytes = NULL;
int ret=SOCKET_ERROR, err=0;
if (!ghIocp)
routine = IntermediateCompletionRoutine;
Provider = ol->Provider;
//
// Reset the event handle if present. The handle is masked with 0xFFFFFFFE in
// order to zero out the last bit. If the last bit is one and the socket is
// associated with a compeltion port then when an overlapped operation is
// called, the operation is not posted to the IO completion port.
//
if (ol->lpCallerOverlapped->hEvent != NULL)
{
ULONG_PTR ptr=1;
ResetEvent((HANDLE)((ULONG_PTR)ol->lpCallerOverlapped->hEvent & ~ptr));
}
switch (ol->Operation)
{
case LSP_OP_IOCTL:
lpdwFlags = NULL;
lpdwBytes = &ol->IoctlArgs.cbBytesReturned;
ret = Provider->NextProcTable.lpWSPIoctl(
ol->ProviderSocket,
ol->IoctlArgs.dwIoControlCode,
ol->IoctlArgs.lpvInBuffer,
ol->IoctlArgs.cbInBuffer,
ol->IoctlArgs.lpvOutBuffer,
ol->IoctlArgs.cbOutBuffer,
&ol->IoctlArgs.cbBytesReturned,
&ol->ProviderOverlapped,
routine,
ol->lpCallerThreadId,
&ol->Error
);
break;
case LSP_OP_RECV:
lpdwFlags = &ol->RecvArgs.dwFlags;
lpdwBytes = &ol->RecvArgs.dwNumberOfBytesRecvd;
ret = Provider->NextProcTable.lpWSPRecv(
ol->ProviderSocket,
ol->RecvArgs.lpBuffers,
ol->RecvArgs.dwBufferCount,
&ol->RecvArgs.dwNumberOfBytesRecvd,
&ol->RecvArgs.dwFlags,
&ol->ProviderOverlapped,
routine,
ol->lpCallerThreadId,
&ol->Error
);
break;
case LSP_OP_RECVFROM:
lpdwFlags = &ol->RecvFromArgs.dwFlags;
lpdwBytes = &ol->RecvFromArgs.dwNumberOfBytesRecvd;
ret = Provider->NextProcTable.lpWSPRecvFrom(
ol->ProviderSocket,
ol->RecvFromArgs.lpBuffers,
ol->RecvFromArgs.dwBufferCount,
&ol->RecvFromArgs.dwNumberOfBytesRecvd,
&ol->RecvFromArgs.dwFlags,
ol->RecvFromArgs.lpFrom,
ol->RecvFromArgs.lpFromLen,
&ol->ProviderOverlapped,
routine,
ol->lpCallerThreadId,
&ol->Error
);
break;
case LSP_OP_SEND:
lpdwFlags = &ol->SendArgs.dwFlags;
lpdwBytes = &ol->SendArgs.dwNumberOfBytesSent;
ret = Provider->NextProcTable.lpWSPSend(
ol->ProviderSocket,
ol->SendArgs.lpBuffers,
ol->SendArgs.dwBufferCount,
&ol->SendArgs.dwNumberOfBytesSent,
ol->SendArgs.dwFlags,
&ol->ProviderOverlapped,
routine,
ol->lpCallerThreadId,
&ol->Error
);
break;
case LSP_OP_SENDTO:
lpdwFlags = &ol->SendToArgs.dwFlags;
lpdwBytes = &ol->SendToArgs.dwNumberOfBytesSent;
ret = Provider->NextProcTable.lpWSPSendTo(
ol->ProviderSocket,
ol->SendToArgs.lpBuffers,
ol->SendToArgs.dwBufferCount,
&ol->SendToArgs.dwNumberOfBytesSent,
ol->SendToArgs.dwFlags,
(SOCKADDR *)&ol->SendToArgs.To,
ol->SendToArgs.iToLen,
&ol->ProviderOverlapped,
routine,
ol->lpCallerThreadId,
&ol->Error
);
break;
case LSP_OP_TRANSMITFILE:
lpdwFlags = &ol->TransmitFileArgs.dwFlags;
lpdwBytes = NULL;
ret = Provider->NextProcTableExt.lpfnTransmitFile(
ol->ProviderSocket,
ol->TransmitFileArgs.hFile,
ol->TransmitFileArgs.nNumberOfBytesToWrite,
ol->TransmitFileArgs.nNumberOfBytesPerSend,
&ol->ProviderOverlapped,
ol->TransmitFileArgs.lpTransmitBuffers,
ol->TransmitFileArgs.dwFlags
);
if (ret == FALSE)
{
ret = SOCKET_ERROR;
ol->Error = WSAGetLastError();
WSASetLastError(ol->Error);
}
else
ret = NO_ERROR;
break;
case LSP_OP_ACCEPTEX:
lpdwFlags = NULL;
lpdwBytes = &ol->AcceptExArgs.dwBytesReceived;
ret = Provider->NextProcTableExt.lpfnAcceptEx(
ol->ProviderSocket,
ol->AcceptExArgs.sProviderAcceptSocket,
ol->AcceptExArgs.lpOutputBuffer,
ol->AcceptExArgs.dwReceiveDataLength,
ol->AcceptExArgs.dwLocalAddressLength,
ol->AcceptExArgs.dwRemoteAddressLength,
&ol->AcceptExArgs.dwBytesReceived,
&ol->ProviderOverlapped
);
if (ret == FALSE)
{
ret = SOCKET_ERROR;
ol->Error = WSAGetLastError();
WSASetLastError(ol->Error);
}
else
ret = NO_ERROR;
break;
case LSP_OP_CONNECTEX:
lpdwFlags = NULL;
lpdwBytes = &ol->ConnectExArgs.dwBytesSent;
ret = Provider->NextProcTableExt.lpfnConnectEx(
ol->ProviderSocket,
(SOCKADDR *)&ol->ConnectExArgs.name,
ol->ConnectExArgs.namelen,
ol->ConnectExArgs.lpSendBuffer,
ol->ConnectExArgs.dwSendDataLength,
&ol->ConnectExArgs.dwBytesSent,
&ol->ProviderOverlapped
);
if (ret == FALSE)
{
ret = SOCKET_ERROR;
ol->Error = WSAGetLastError();
WSASetLastError(ol->Error);
}
else
ret = NO_ERROR;
break;
case LSP_OP_DISCONNECTEX:
lpdwFlags = &ol->DisconnectExArgs.dwFlags;
lpdwBytes = NULL;
ret = Provider->NextProcTableExt.lpfnDisconnectEx(
ol->ProviderSocket,
&ol->ProviderOverlapped,
ol->DisconnectExArgs.dwFlags,
ol->DisconnectExArgs.dwReserved
);
if (ret == FALSE)
{
ret = SOCKET_ERROR;
ol->Error = WSAGetLastError();
WSASetLastError(ol->Error);
}
else
ret = NO_ERROR;
break;
case LSP_OP_TRANSMITPACKETS:
lpdwFlags = &ol->TransmitPacketsArgs.dwFlags;
lpdwBytes = NULL;
ret = Provider->NextProcTableExt.lpfnTransmitPackets(
ol->ProviderSocket,
ol->TransmitPacketsArgs.lpPacketArray,
ol->TransmitPacketsArgs.nElementCount,
ol->TransmitPacketsArgs.nSendSize,
&ol->ProviderOverlapped,
ol->TransmitPacketsArgs.dwFlags
);
if (ret == FALSE)
{
ret = SOCKET_ERROR;
ol->Error = WSAGetLastError();
WSASetLastError(ol->Error);
}
else
ret = NO_ERROR;
break;
case LSP_OP_WSARECVMSG:
lpdwFlags = NULL;
lpdwBytes = &ol->WSARecvMsgArgs.dwNumberOfBytesRecvd;
ret = Provider->NextProcTableExt.lpfnWSARecvMsg(
ol->ProviderSocket,
ol->WSARecvMsgArgs.lpMsg,
&ol->WSARecvMsgArgs.dwNumberOfBytesRecvd,
&ol->ProviderOverlapped,
ol->lpCallerCompletionRoutine
);
if (ret == FALSE)
{
ret = SOCKET_ERROR;
ol->Error = WSAGetLastError();
WSASetLastError(ol->Error);
}
else
ret = NO_ERROR;
break;
default:
dbgprint("ExecuteOverlappedOperation: Unknown operation!");
ret = SOCKET_ERROR;
break;
}
err = ol->Error;
if ((ret != NO_ERROR) && (ol->Error != WSA_IO_PENDING))
{
//
// If the call immediately fails, update the OVERLAPPED info and return
//
ol->lpCallerOverlapped->Offset = ol->Error;
ol->lpCallerOverlapped->OffsetHigh = (lpdwFlags ? *lpdwFlags : 0);
ol->lpCallerOverlapped->InternalHigh = (lpdwBytes ? *lpdwBytes : 0);
dbgprint("Overlap op failed immediately: %d", ol->Error);
CheckForContextCleanup(ol);
PutbackOverlappedStructure(ol);
}
else if ((ret == NO_ERROR) && (bSynchronous == FALSE))
{
//
// Ideally we'd like to complete immediately here but we should wait
// until the completion port has processed the completion packet
// associated with this operation.
//
err = WSA_IO_PENDING;
ret = SOCKET_ERROR;
dbgprint("Succeeded without error");
}
else if ((ret == NO_ERROR) && (bSynchronous == TRUE))
{
// The winsock call actually blocked and there will be no completion
// notification on the IOCP.
//
dbgprint("Succeeded without error - synchronous socket though");
}
else
dbgprint("WSA_IO_PENDING");
return ((ret == NO_ERROR) ? ret : err);
}
//
// Function: OverlappedManagerThread
//
// Description:
// This thread receives the completion notifications for operations
// posted to our IO completion port. Once we receive a completion
// we'll complete the operation back to the calling app.
//
DWORD WINAPI OverlappedManagerThread(LPVOID lpParam)
{
WSAOVERLAPPEDPLUS *lpPid = NULL;
HANDLE hIocp = (HANDLE)lpParam;
ULONG_PTR key;
DWORD dwBytesXfered;
int ret;
while (1)
{
if (hIocp)
{
ret = GetQueuedCompletionStatus(hIocp,
&dwBytesXfered,
&key,
(LPOVERLAPPED *)&lpPid,
INFINITE);
if ((ret == 0) || (ret == WAIT_TIMEOUT))
{
// Socket failures could be reported here so we still
// call IntermediateCompletionRoutine
dbgprint("GetQueuedCompletionStatus() failed: %d", GetLastError());
}
if (dwBytesXfered == -1)
{
// StopOverlappedManager will send a completion packet with -1
// bytes transfered to indicate the completion routine
// should exit
dbgprint("OverlappedManagerThread: Received exit message");
ExitThread(0);
}
// Handle the IO that completed
IntermediateCompletionRoutine(WSA_IO_PENDING,
dwBytesXfered,
(OVERLAPPED *)lpPid,
0);
}
else
{
ret = WaitForSingleObjectEx(ghWakeupSemaphore,
INFINITE,
TRUE);
if ((ret == WAIT_FAILED) || (ret == WAIT_TIMEOUT))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -