📄 dllmain.c
字号:
* lpErrno = Address of buffer for error information
* RETURNS:
* 0, or SOCKET_ERROR if the socket could not be bound
*/
{
IO_STATUS_BLOCK IOSB;
PAFD_BIND_DATA BindData;
PSOCKET_INFORMATION Socket = NULL;
NTSTATUS Status;
UCHAR BindBuffer[0x1A];
SOCKADDR_INFO SocketInfo;
HANDLE SockEvent;
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) return -1;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
/* Dynamic Structure...ugh */
BindData = (PAFD_BIND_DATA)BindBuffer;
/* Set up Address in TDI Format */
BindData->Address.TAAddressCount = 1;
BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
BindData->Address.Address[0].AddressType = SocketAddress->sa_family;
RtlCopyMemory (BindData->Address.Address[0].Address,
SocketAddress->sa_data,
SocketAddressLength - sizeof(SocketAddress->sa_family));
/* Get Address Information */
Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress,
SocketAddressLength,
&SocketInfo);
/* Set the Share Type */
if (Socket->SharedData.ExclusiveAddressUse) {
BindData->ShareType = AFD_SHARE_EXCLUSIVE;
}
else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) {
BindData->ShareType = AFD_SHARE_WILDCARD;
}
else if (Socket->SharedData.ReuseAddresses) {
BindData->ShareType = AFD_SHARE_REUSE;
} else {
BindData->ShareType = AFD_SHARE_UNIQUE;
}
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_BIND,
BindData,
0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/
BindData,
0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */
/* Wait for return */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, INFINITE);
}
/* Set up Socket Data */
Socket->SharedData.State = SocketBound;
Socket->TdiAddressHandle = (HANDLE)IOSB.Information;
NtClose( SockEvent );
return MsafdReturnWithErrno
( IOSB.Status, lpErrno, IOSB.Information, NULL );
}
int
WSPAPI
WSPListen(
SOCKET Handle,
int Backlog,
LPINT lpErrno)
{
IO_STATUS_BLOCK IOSB;
AFD_LISTEN_DATA ListenData;
PSOCKET_INFORMATION Socket = NULL;
HANDLE SockEvent;
NTSTATUS Status;
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) return -1;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
/* Set Up Listen Structure */
ListenData.UseSAN = FALSE;
ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance;
ListenData.Backlog = Backlog;
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_START_LISTEN,
&ListenData,
sizeof(ListenData),
NULL,
0);
/* Wait for return */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, INFINITE);
}
/* Set to Listening */
Socket->SharedData.Listening = TRUE;
NtClose( SockEvent );
return MsafdReturnWithErrno
( IOSB.Status, lpErrno, IOSB.Information, NULL );
}
int
WSPAPI
WSPSelect(
int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout,
LPINT lpErrno)
{
IO_STATUS_BLOCK IOSB;
PAFD_POLL_INFO PollInfo;
NTSTATUS Status;
ULONG HandleCount, OutCount = 0;
ULONG PollBufferSize;
PVOID PollBuffer;
ULONG i, j = 0, x;
HANDLE SockEvent;
BOOL HandleCounted;
LARGE_INTEGER Timeout;
/* Find out how many sockets we have, and how large the buffer needs
* to be */
HandleCount =
( readfds ? readfds->fd_count : 0 ) +
( writefds ? writefds->fd_count : 0 ) +
( exceptfds ? exceptfds->fd_count : 0 );
if( HandleCount < 0 || nfds != 0 ) HandleCount = nfds * 3;
PollBufferSize = sizeof(*PollInfo) + (HandleCount * sizeof(AFD_HANDLE));
AFD_DbgPrint(MID_TRACE,("HandleCount: %d BufferSize: %d\n",
HandleCount, PollBufferSize));
/* Convert Timeout to NT Format */
if (timeout == NULL) {
Timeout.u.LowPart = -1;
Timeout.u.HighPart = 0x7FFFFFFF;
AFD_DbgPrint(MAX_TRACE,("Infinite timeout\n"));
} else {
Timeout = RtlEnlargedIntegerMultiply
((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000);
/* Negative timeouts are illegal. Since the kernel represents an
* incremental timeout as a negative number, we check for a positive
* result.
*/
if (Timeout.QuadPart > 0) {
if (lpErrno) *lpErrno = WSAEINVAL;
return SOCKET_ERROR;
}
AFD_DbgPrint(MAX_TRACE,("Timeout: Orig %d.%06d kernel %d\n",
timeout->tv_sec, timeout->tv_usec,
Timeout.u.LowPart));
}
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) return SOCKET_ERROR;
/* Allocate */
PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
if (!PollBuffer) {
if (*lpErrno) *lpErrno = WSAEFAULT;
NtClose(SockEvent);
return SOCKET_ERROR;
}
PollInfo = (PAFD_POLL_INFO)PollBuffer;
RtlZeroMemory( PollInfo, PollBufferSize );
/* Number of handles for AFD to Check */
PollInfo->HandleCount = HandleCount;
PollInfo->Exclusive = FALSE;
PollInfo->Timeout = Timeout;
if (readfds != NULL) {
for (i = 0; i < readfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = readfds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE |
AFD_EVENT_DISCONNECT |
AFD_EVENT_ABORT |
AFD_EVENT_ACCEPT;
}
}
if (writefds != NULL) {
for (i = 0; i < writefds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = writefds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_SEND |
AFD_EVENT_CONNECT;
}
}
if (exceptfds != NULL) {
for (i = 0; i < exceptfds->fd_count; i++, j++) {
PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE |
AFD_EVENT_CONNECT_FAIL;
}
}
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)PollInfo->Handles[0].Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_SELECT,
PollInfo,
PollBufferSize,
PollInfo,
PollBufferSize);
AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status));
/* Wait for Completition */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, INFINITE);
}
/* Clear the Structures */
if( readfds ) FD_ZERO(readfds);
if( writefds ) FD_ZERO(writefds);
if( exceptfds ) FD_ZERO(exceptfds);
/* Loop through return structure */
HandleCount = PollInfo->HandleCount;
/* Return in FDSET Format */
for (i = 0; i < HandleCount; i++) {
HandleCounted = FALSE;
for(x = 1; x; x<<=1) {
switch (PollInfo->Handles[i].Events & x) {
case AFD_EVENT_RECEIVE:
case AFD_EVENT_DISCONNECT:
case AFD_EVENT_ABORT:
case AFD_EVENT_ACCEPT:
case AFD_EVENT_CLOSE:
AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
PollInfo->Handles[i].Events,
PollInfo->Handles[i].Handle));
if (! HandleCounted) {
OutCount++;
HandleCounted = TRUE;
}
if( readfds ) FD_SET(PollInfo->Handles[i].Handle, readfds);
break;
case AFD_EVENT_SEND: case AFD_EVENT_CONNECT:
AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
PollInfo->Handles[i].Events,
PollInfo->Handles[i].Handle));
if (! HandleCounted) {
OutCount++;
HandleCounted = TRUE;
}
if( writefds ) FD_SET(PollInfo->Handles[i].Handle, writefds);
break;
case AFD_EVENT_OOB_RECEIVE: case AFD_EVENT_CONNECT_FAIL:
AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n",
PollInfo->Handles[i].Events,
PollInfo->Handles[i].Handle));
if (! HandleCounted) {
OutCount++;
HandleCounted = TRUE;
}
if( exceptfds ) FD_SET(PollInfo->Handles[i].Handle, exceptfds);
break;
}
}
}
HeapFree( GlobalHeap, 0, PollBuffer );
NtClose( SockEvent );
AFD_DbgPrint(MID_TRACE,("lpErrno = %x\n", lpErrno));
if( lpErrno ) {
switch( IOSB.Status ) {
case STATUS_SUCCESS:
case STATUS_TIMEOUT: *lpErrno = 0; break;
default: *lpErrno = WSAEINVAL; break;
}
}
AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount));
return OutCount;
}
SOCKET
WSPAPI
WSPAccept(
SOCKET Handle,
struct sockaddr *SocketAddress,
int *SocketAddressLength,
LPCONDITIONPROC lpfnCondition,
DWORD_PTR dwCallbackData,
LPINT lpErrno)
{
IO_STATUS_BLOCK IOSB;
PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData;
AFD_ACCEPT_DATA AcceptData;
AFD_DEFER_ACCEPT_DATA DeferData;
AFD_PENDING_ACCEPT_DATA PendingAcceptData;
PSOCKET_INFORMATION Socket = NULL;
NTSTATUS Status;
struct fd_set ReadSet;
struct timeval Timeout;
PVOID PendingData = NULL;
ULONG PendingDataLength = 0;
PVOID CalleeDataBuffer;
WSABUF CallerData, CalleeID, CallerID, CalleeData;
PSOCKADDR RemoteAddress = NULL;
GROUP GroupID = 0;
ULONG CallBack;
WSAPROTOCOL_INFOW ProtocolInfo;
SOCKET AcceptSocket;
UCHAR ReceiveBuffer[0x1A];
HANDLE SockEvent;
Status = NtCreateEvent( &SockEvent, GENERIC_READ | GENERIC_WRITE,
NULL, 1, FALSE );
if( !NT_SUCCESS(Status) ) {
MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
return INVALID_SOCKET;
}
/* Dynamic Structure...ugh */
ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
/* Get the Socket Structure associate to this Socket*/
Socket = GetSocketStructure(Handle);
/* If this is non-blocking, make sure there's something for us to accept */
FD_ZERO(&ReadSet);
FD_SET(Socket->Handle, &ReadSet);
Timeout.tv_sec=0;
Timeout.tv_usec=0;
WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, NULL);
if (ReadSet.fd_array[0] != Socket->Handle) return 0;
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_WAIT_FOR_LISTEN,
NULL,
0,
ListenReceiveData,
0xA + sizeof(*ListenReceiveData));
/* Wait for return */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, INFINITE);
Status = IOSB.Status;
}
if (!NT_SUCCESS(Status)) {
NtClose( SockEvent );
MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
return INVALID_SOCKET;
}
if (lpfnCondition != NULL) {
if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0) {
/* Find out how much data is pending */
PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
PendingAcceptData.ReturnSize = TRUE;
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_GET_PENDING_CONNECT_DATA,
&PendingAcceptData,
sizeof(PendingAcceptData),
&PendingAcceptData,
sizeof(PendingAcceptData));
/* Wait for return */
if (Status == STATUS_PENDING) {
WaitForSingleObject(SockEvent, INFINITE);
Status = IOSB.Status;
}
if (!NT_SUCCESS(Status)) {
NtClose( SockEvent );
MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
return INVALID_SOCKET;
}
/* How much data to allocate */
PendingDataLength = IOSB.Information;
if (PendingDataLength) {
/* Allocate needed space */
PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
/* We want the data now */
PendingAcceptData.ReturnSize = FALSE;
/* Send IOCTL */
Status = NtDeviceIoControlFile( (HANDLE)Socket->Handle,
SockEvent,
NULL,
NULL,
&IOSB,
IOCTL_AFD_GET_PENDING_CONNECT_DATA,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -