📄 spi.cpp
字号:
//
*((LPFN_ACCEPTEX *)lpvOutBuffer) = ExtAcceptEx;
//
// Attempt to load the lower provider's extension function
//
if (!SocketContext->Provider->NextProcTableExt.lpfnAcceptEx)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPIoctl(
SocketContext->ProviderSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&AcceptExGuid,
sizeof(GUID),
(LPVOID) &SocketContext->Provider->NextProcTableExt.lpfnAcceptEx,
sizeof(LPFN_ACCEPTEX),
lpcbBytesReturned,
NULL,
NULL,
NULL,
lpErrno);
SetBlockingProvider(NULL);
}
UnlockSocketContext(SocketContext, lpErrno);
return ret;
}
else if (memcmp (lpvInBuffer, &ConnectExGuid, sizeof(GUID)) == 0)
{
// Return a pointer to our intermediate extension function
//
*((LPFN_CONNECTEX *)lpvOutBuffer) = ExtConnectEx;
//
// Attempt to load the lower provider's extension function
//
if (!SocketContext->Provider->NextProcTableExt.lpfnConnectEx)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPIoctl(
SocketContext->ProviderSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&ConnectExGuid,
sizeof(GUID),
(LPVOID) &SocketContext->Provider->NextProcTableExt.lpfnConnectEx,
sizeof(LPFN_CONNECTEX),
lpcbBytesReturned,
NULL,
NULL,
NULL,
lpErrno);
SetBlockingProvider(NULL);
}
UnlockSocketContext(SocketContext, lpErrno);
return ret;
}
else if (memcmp (lpvInBuffer, &DisconnectExGuid, sizeof(GUID)) == 0)
{
// Return a pointer to our intermediate extension function
//
*((LPFN_DISCONNECTEX *)lpvOutBuffer) = ExtDisconnectEx;
//
// Attempt to load the lower provider's extension function
//
if (!SocketContext->Provider->NextProcTableExt.lpfnDisconnectEx)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPIoctl(
SocketContext->ProviderSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&DisconnectExGuid,
sizeof(GUID),
(LPVOID) &SocketContext->Provider->NextProcTableExt.lpfnDisconnectEx,
sizeof(LPFN_DISCONNECTEX),
lpcbBytesReturned,
NULL,
NULL,
NULL,
lpErrno);
SetBlockingProvider(NULL);
}
UnlockSocketContext(SocketContext, lpErrno);
return ret;
}
else if (memcmp (lpvInBuffer, &TransmitPacketsGuid, sizeof(GUID)) == 0)
{
// Return a pointer to our intermediate extension function
//
*((LPFN_TRANSMITPACKETS *)lpvOutBuffer) = ExtTransmitPackets;
//
// Attempt to load the lower provider's extension function
//
if (!SocketContext->Provider->NextProcTableExt.lpfnTransmitPackets)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPIoctl(
SocketContext->ProviderSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&TransmitPacketsGuid,
sizeof(GUID),
(LPVOID) &SocketContext->Provider->NextProcTableExt.lpfnTransmitPackets,
sizeof(LPFN_TRANSMITPACKETS),
lpcbBytesReturned,
NULL,
NULL,
NULL,
lpErrno);
SetBlockingProvider(NULL);
}
UnlockSocketContext(SocketContext, lpErrno);
return ret;
}
else if (memcmp (lpvInBuffer, &WSARecvMsgGuid, sizeof(GUID)) == 0)
{
// Return a pointer to our intermediate extension function
//
*((LPFN_WSARECVMSG *)lpvOutBuffer) = ExtWSARecvMsg;
//
// Attempt to load the lower provider's extension function
//
if (!SocketContext->Provider->NextProcTableExt.lpfnWSARecvMsg)
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPIoctl(
SocketContext->ProviderSocket,
SIO_GET_EXTENSION_FUNCTION_POINTER,
&WSARecvMsgGuid,
sizeof(GUID),
(LPVOID) &SocketContext->Provider->NextProcTableExt.lpfnWSARecvMsg,
sizeof(LPFN_WSARECVMSG),
lpcbBytesReturned,
NULL,
NULL,
NULL,
lpErrno);
SetBlockingProvider(NULL);
}
UnlockSocketContext(SocketContext, lpErrno);
return ret;
}
else if (memcmp (lpvInBuffer, &GetAcceptExSockAddrsGuid, sizeof (GUID)) == 0)
{
// No socket handle translation needed, let the call pass through below
// (i.e. we really don't have any need to intercept this call)
}
else
{
UnlockSocketContext(SocketContext, lpErrno);
*lpErrno = WSAEINVAL;
return SOCKET_ERROR;
}
}
else if (dwIoControlCode == SIO_QUERY_TARGET_PNP_HANDLE)
{
dbgprint("SIO_QUERY_PNP_HANDLE requested");
*((SOCKET *)lpvOutBuffer) = SocketContext->ProviderSocket;
*lpcbBytesReturned = sizeof(SocketContext->ProviderSocket);
if (lpOverlapped)
{
ProviderOverlapped = GetOverlappedStructure(SocketContext);
if (ProviderOverlapped == NULL)
{
UnlockSocketContext(SocketContext, lpErrno);
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
ProviderOverlapped->lpCallerOverlapped = lpOverlapped;
CopyOffset(&ProviderOverlapped->ProviderOverlapped, lpOverlapped);
ProviderOverlapped->SockInfo = SocketContext;
ProviderOverlapped->CallerSocket = s;
ProviderOverlapped->ProviderSocket = SocketContext->ProviderSocket;
ProviderOverlapped->Error = NO_ERROR;
ProviderOverlapped->Operation = LSP_OP_IOCTL;
ProviderOverlapped->lpCallerThreadId = lpThreadId;
ProviderOverlapped->lpCallerCompletionRoutine = lpCompletionRoutine;
ProviderOverlapped->Provider = SocketContext->Provider;
lpOverlapped->Internal = (DWORD_PTR)lpCompletionRoutine;
lpOverlapped->InternalHigh = *lpcbBytesReturned;
//
// Call the completion routine immediately since there is nothing
// else to do. For this ioctl all we do is return the provider
// socket. If it was called overlapped just complete the operation.
//
dbgprint("SIO_QUERY_PNP_HANDLE overlapped");
IntermediateCompletionRoutine(0,
*lpcbBytesReturned,
(WSAOVERLAPPED *)ProviderOverlapped,
0);
}
UnlockSocketContext(SocketContext, lpErrno);
return NO_ERROR;
}
//
// Check for overlapped I/O
//
if (lpOverlapped)
{
ProviderOverlapped = GetOverlappedStructure(SocketContext);
if (!ProviderOverlapped)
{
UnlockSocketContext(SocketContext, lpErrno);
*lpErrno = WSAENOBUFS;
return SOCKET_ERROR;
}
ProviderOverlapped->lpCallerOverlapped = lpOverlapped;
CopyOffset(&ProviderOverlapped->ProviderOverlapped, lpOverlapped);
ProviderOverlapped->SockInfo = SocketContext;
ProviderOverlapped->CallerSocket = s;
ProviderOverlapped->ProviderSocket = SocketContext->ProviderSocket;
ProviderOverlapped->Error = NO_ERROR;
ProviderOverlapped->Operation = LSP_OP_IOCTL;
ProviderOverlapped->lpCallerThreadId = lpThreadId;
ProviderOverlapped->lpCallerCompletionRoutine = lpCompletionRoutine;
ProviderOverlapped->IoctlArgs.dwIoControlCode = dwIoControlCode;
ProviderOverlapped->IoctlArgs.lpvInBuffer = lpvInBuffer;
ProviderOverlapped->IoctlArgs.cbInBuffer = cbInBuffer;
ProviderOverlapped->IoctlArgs.lpvOutBuffer = lpvOutBuffer;
ProviderOverlapped->IoctlArgs.cbOutBuffer = cbOutBuffer;
ProviderOverlapped->IoctlArgs.cbBytesReturned = (lpcbBytesReturned ? *lpcbBytesReturned : 0);
ProviderOverlapped->Provider = SocketContext->Provider;
ret = QueueOverlappedOperation(ProviderOverlapped, SocketContext);
if (ret != NO_ERROR)
{
*lpErrno = ret;
ret = SOCKET_ERROR;
}
}
else
{
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPIoctl(
SocketContext->ProviderSocket,
dwIoControlCode,
lpvInBuffer,
cbInBuffer,
lpvOutBuffer,
cbOutBuffer,
lpcbBytesReturned,
lpOverlapped,
lpCompletionRoutine,
lpThreadId,
lpErrno);
SetBlockingProvider(NULL);
}
UnlockSocketContext(SocketContext, lpErrno);
return ret;
}
//
// Function: WSPJoinLeaf
//
// Description:
// This function joins a socket to a multipoint session. For those providers
// that support multipoint semantics there are 2 possible behaviors. First,
// for IP, WSAJoinLeaf always returns the same socket handle which was passed
// into it. In this case there is no new socket so we don't want to create
// any socket context once the lower provider WSPJoinLeaf is called. In the
// second case, for ATM, a new socket IS created when we call the lower
// provider. In this case we do want to create a new user socket and create
// a socket context.
//
SOCKET WSPAPI WSPJoinLeaf(
SOCKET s,
const struct sockaddr FAR * name,
int namelen,
LPWSABUF lpCallerData,
LPWSABUF lpCalleeData,
LPQOS lpSQOS,
LPQOS lpGQOS,
DWORD dwFlags,
LPINT lpErrno)
{
SOCK_INFO *SocketContext;
SOCKET NextProviderSocket = INVALID_SOCKET,
NewSocket = INVALID_SOCKET;
SocketContext = FindAndLockSocketContext(s, lpErrno);
if (SocketContext == NULL)
{
dbgprint("WSPJoinLeaf: WPUQuerySocketHandleContext() failed: %d", *lpErrno);
*lpErrno = WSAENOTSOCK;
return INVALID_SOCKET;
}
SetBlockingProvider(SocketContext->Provider);
NextProviderSocket = SocketContext->Provider->NextProcTable.lpWSPJoinLeaf(
SocketContext->ProviderSocket,
name,
namelen,
lpCallerData,
lpCalleeData,
lpSQOS,
lpGQOS,
dwFlags,
lpErrno);
SetBlockingProvider(NULL);
//
// If the socket returned from the lower provider is the same as the socket
// passed into it then there really isn't a new socket - just return.
// Otherwise, a new socket has been created and we need to create the socket
// context and create a user socket to pass back.
//
if (NextProviderSocket != SocketContext->ProviderSocket)
{
SOCK_INFO *NewSocketContext;
// Create a new socket context structure
//
if ((NewSocketContext = CreateSockInfo(SocketContext->Provider,
NextProviderSocket,
SocketContext)) == NULL)
{
*lpErrno = WSAENOBUFS;
}
else
{
// Create a socket handle to pass to app
//
NewSocket = MainUpCallTable.lpWPUCreateSocketHandle(
SocketContext->Provider->LayeredProvider.ProtocolChain.ChainEntries[0],
(DWORD_PTR)NewSocketContext,
lpErrno);
if (NewSocket == INVALID_SOCKET)
{
dbgprint("WSPJoinLeaf: WPUCreateSocketHandle() failed: %d", *lpErrno);
HeapFree(hLspHeap, 0, NewSocketContext);
UnlockSocketContext(SocketContext, lpErrno);
*lpErrno = WSAENOBUFS;
return INVALID_SOCKET;
}
NewSocketContext->LayeredSocket = NewSocket;
}
UnlockSocketContext(SocketContext, lpErrno);
return NewSocket;
}
else
{
UnlockSocketContext(SocketContext, lpErrno);
return s;
}
}
//
// Function: WSPListen
//
// Description:
// This function sets the backlog value on a listening socket. All we need to
// do is translate the socket handle to the correct provider.
//
int WSPAPI WSPListen(
SOCKET s,
int backlog,
LPINT lpErrno)
{
SOCK_INFO *SocketContext;
INT ret;
SocketContext = FindAndLockSocketContext(s, lpErrno);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -