2296 lines
51 KiB
C
2296 lines
51 KiB
C
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Wsraw.h
|
|
|
|
Abstract:
|
|
|
|
Support for raw winsock calls for WOW.
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 02-Oct-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "wsdynmc.h"
|
|
|
|
LIST_ENTRY WWS32SocketHandleListHead;
|
|
WORD WWS32SocketHandleCounter;
|
|
BOOL WWS32SocketHandleCounterWrapped;
|
|
|
|
//
|
|
// The (PCHAR) casts in the following macro force the compiler to assume
|
|
// only BYTE alignment.
|
|
//
|
|
|
|
#define SockCopyMemory(d,s,l) RtlCopyMemory( (PCHAR)(d), (PCHAR)(s), (l) )
|
|
|
|
|
|
#define WSEXIT_IF_NOT_INTIALIZED() \
|
|
if(!WWS32IsThreadInitialized) { \
|
|
SetLastError(WSANOTINITIALISED); \
|
|
RETURN((ULONG)SOCKET_ERROR); \
|
|
}
|
|
|
|
|
|
int SocketOption16To32(IN WORD SocketOption16);
|
|
|
|
DWORD WSGetWinsock32(IN HAND16 h16,
|
|
OUT PULONG pul);
|
|
|
|
BOOL WSThunkAddrBufAndLen(IN PSOCKADDR fastSockaddr,
|
|
IN VPSOCKADDR vpSockAddr16,
|
|
IN VPWORD vpwAddrLen16,
|
|
OUT PINT addressLength,
|
|
OUT PINT *pAddressLength,
|
|
OUT PSOCKADDR *realSockaddr);
|
|
|
|
VOID WSUnThunkAddrBufAndLen(IN ULONG ret,
|
|
IN VPWORD vpwAddrLen16,
|
|
IN VPSOCKADDR vpSockAddr16,
|
|
IN INT addressLength,
|
|
IN PSOCKADDR fastSockaddr,
|
|
IN PSOCKADDR realSockaddr);
|
|
|
|
BOOL WSThunkAddrBuf(IN INT addressLength,
|
|
IN VPSOCKADDR vpSockAddr16,
|
|
IN PSOCKADDR fastSockaddr,
|
|
OUT PSOCKADDR *realSockaddr);
|
|
|
|
VOID WSUnThunkAddrBuf(IN PSOCKADDR fastSockaddr,
|
|
IN PSOCKADDR realSockaddr);
|
|
|
|
BOOL WSThunkRecvBuffer(IN INT BufferLength,
|
|
IN VPBYTE vpBuf16,
|
|
OUT PBYTE *buffer);
|
|
|
|
VOID WSUnthunkRecvBuffer(IN INT cBytes,
|
|
IN INT BufferLength,
|
|
IN VPBYTE vpBuf16,
|
|
IN PBYTE buffer);
|
|
|
|
BOOL WSThunkSendBuffer(IN INT BufferLength,
|
|
IN VPBYTE vpBuf16,
|
|
OUT PBYTE *buffer);
|
|
|
|
VOID WSUnthunkSendBuffer(IN PBYTE buffer);
|
|
|
|
|
|
|
|
|
|
/*++
|
|
|
|
GENERIC FUNCTION PROTOTYPE:
|
|
==========================
|
|
|
|
ULONG FASTCALL WWS32<function name>(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register P<function name>16 parg16;
|
|
|
|
GETARGPTR(pFrame, sizeof(<function name>16), parg16);
|
|
|
|
<get any other required pointers into 16 bit space>
|
|
|
|
ALLOCVDMPTR
|
|
GETVDMPTR
|
|
GETMISCPTR
|
|
et cetera
|
|
|
|
<copy any complex structures from 16 bit -> 32 bit space>
|
|
<ALWAYS use the FETCHxxx macros>
|
|
|
|
ul = GET<return type>16(<function name>(parg16->f1,
|
|
:
|
|
:
|
|
parg16->f<n>);
|
|
|
|
<copy any complex structures from 32 -> 16 bit space>
|
|
<ALWAYS use the STORExxx macros>
|
|
|
|
<free any pointers to 16 bit space you previously got>
|
|
|
|
<flush any areas of 16 bit memory if they were written to>
|
|
|
|
FLUSHVDMPTR
|
|
|
|
FREEARGPTR( parg16 );
|
|
RETURN( ul );
|
|
}
|
|
|
|
NOTE:
|
|
|
|
The VDM frame is automatically set up, with all the function parameters
|
|
available via parg16->f<number>.
|
|
|
|
Handles must ALWAYS be mapped for 16 -> 32 -> 16 space via the mapping tables
|
|
laid out in WALIAS.C.
|
|
|
|
Any storage you allocate must be freed (eventually...).
|
|
|
|
Further to that - if a thunk which allocates memory fails in the 32 bit call
|
|
then it must free that memory.
|
|
|
|
Also, never update structures in 16 bit land if the 32 bit call fails.
|
|
|
|
Be aware that the GETxxxPTR macros return the CURRENT selector-to-flat_memory
|
|
mapping. Calls to some 32-bit functions may indirectly cause callbacks into
|
|
16-bit code. These may cause 16-bit memory to move due to allocations
|
|
made in 16-bit land. If the 16-bit memory does move, the corresponding 32-bit
|
|
ptr in WOW32 needs to be refreshed to reflect the NEW selector-to-flat_memory
|
|
mapping.
|
|
|
|
--*/
|
|
|
|
|
|
ULONG FASTCALL WWS32accept(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PACCEPT16 parg16;
|
|
SOCKET s32;
|
|
SOCKET news32;
|
|
HSOCKET16 news16;
|
|
INT addressLength;
|
|
PINT pAddressLength;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
VPWORD vpwAddrLen16;
|
|
VPSOCKADDR vpSockAddr16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PACCEPT16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpwAddrLen16 = (VPWORD)FETCHDWORD(parg16->AddressLength);
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
|
|
// Thunk the 16-bit Address name and length buffers
|
|
if(!WSThunkAddrBufAndLen(&fastSockaddr,
|
|
vpSockAddr16,
|
|
vpwAddrLen16,
|
|
&addressLength,
|
|
&pAddressLength,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
// call the 32-bit API
|
|
news32 = (*wsockapis[WOW_ACCEPT].lpfn)( s32, realSockaddr, pAddressLength);
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit Address name and length buffers
|
|
WSUnThunkAddrBufAndLen((ULONG)news32,
|
|
vpwAddrLen16,
|
|
vpSockAddr16,
|
|
addressLength,
|
|
&fastSockaddr,
|
|
realSockaddr);
|
|
|
|
//
|
|
// If the call succeeded, alias the 32-bit socket handle we just
|
|
// obtained into a 16-bit handle.
|
|
//
|
|
|
|
if ( news32 != INVALID_SOCKET ) {
|
|
|
|
news16 = GetWinsock16( news32, 0 );
|
|
|
|
if ( news16 == 0 ) {
|
|
|
|
(*wsockapis[WOW_CLOSESOCKET].lpfn)( news32 );
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
|
|
goto exit;
|
|
}
|
|
|
|
ul = news16;
|
|
|
|
}
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32accept
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32bind(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PBIND16 parg16;
|
|
SOCKET s32;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
INT addressLength;
|
|
VPSOCKADDR vpSockAddr16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PBIND16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
|
|
addressLength = INT32(parg16->AddressLength);
|
|
|
|
// Thunk the 16-bit address buffer
|
|
if(!WSThunkAddrBuf(addressLength,
|
|
vpSockAddr16,
|
|
&fastSockaddr,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_BIND].lpfn)(s32,
|
|
realSockaddr,
|
|
addressLength));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit address buffer
|
|
WSUnThunkAddrBuf(&fastSockaddr, realSockaddr);
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32bind
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32closesocket(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PCLOSESOCKET16 parg16;
|
|
SOCKET s32;
|
|
HSOCKET16 hSocket16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(CLOSESOCKET16), parg16);
|
|
|
|
hSocket16 = (HSOCKET16)FETCHWORD(parg16->hSocket);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(hSocket16, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_CLOSESOCKET].lpfn)( s32 ) );
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
|
|
exit:
|
|
//
|
|
// Free the space in the alias table.
|
|
//
|
|
|
|
FreeWinsock16( hSocket16 );
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32closesocket
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32connect(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PCONNECT16 parg16;
|
|
SOCKET s32;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
INT addressLength;
|
|
VPSOCKADDR vpSockAddr16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PCONNECT16), parg16);
|
|
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
addressLength = INT32(parg16->AddressLength);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
// Thunk the 16-bit address buffer
|
|
if(!WSThunkAddrBuf(addressLength,
|
|
vpSockAddr16,
|
|
&fastSockaddr,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_CONNECT].lpfn)(s32,
|
|
realSockaddr,
|
|
addressLength));
|
|
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit address buffer
|
|
WSUnThunkAddrBuf(&fastSockaddr, realSockaddr);
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32connect
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32getpeername(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PGETPEERNAME16 parg16;
|
|
SOCKET s32;
|
|
INT addressLength;
|
|
PINT pAddressLength;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
VPWORD vpwAddrLen16;
|
|
VPSOCKADDR vpSockAddr16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PGETPEERNAME16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
vpwAddrLen16 = (VPWORD)FETCHDWORD(parg16->AddressLength);
|
|
|
|
// Thunk the 16-bit Address name and length buffers
|
|
if(!WSThunkAddrBufAndLen(&fastSockaddr,
|
|
vpSockAddr16,
|
|
vpwAddrLen16,
|
|
&addressLength,
|
|
&pAddressLength,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_GETPEERNAME].lpfn)(s32,
|
|
realSockaddr,
|
|
pAddressLength));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit Address name and length buffers
|
|
WSUnThunkAddrBufAndLen(ul,
|
|
vpwAddrLen16,
|
|
vpSockAddr16,
|
|
addressLength,
|
|
&fastSockaddr,
|
|
realSockaddr);
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32getpeername
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32getsockname(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PGETSOCKNAME16 parg16;
|
|
SOCKET s32;
|
|
INT addressLength;
|
|
PINT pAddressLength;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
VPWORD vpwAddrLen16;
|
|
VPSOCKADDR vpSockAddr16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PGETSOCKNAME16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
vpwAddrLen16 = (VPWORD)FETCHDWORD(parg16->AddressLength);
|
|
|
|
// Thunk the 16-bit Address name and length buffers
|
|
if(!WSThunkAddrBufAndLen(&fastSockaddr,
|
|
vpSockAddr16,
|
|
vpwAddrLen16,
|
|
&addressLength,
|
|
&pAddressLength,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_GETSOCKNAME].lpfn)( s32, realSockaddr, pAddressLength ) );
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit Address name and length buffers
|
|
WSUnThunkAddrBufAndLen(ul,
|
|
vpwAddrLen16,
|
|
vpSockAddr16,
|
|
addressLength,
|
|
&fastSockaddr,
|
|
realSockaddr);
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32getsockname
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32getsockopt(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PGETSOCKOPT16 parg16;
|
|
SOCKET s32;
|
|
WORD UNALIGNED *optionLength16;
|
|
WORD actualOptionLength16;
|
|
PBYTE optionValue16;
|
|
DWORD optionLength32;
|
|
PBYTE optionValue32 = NULL;
|
|
VPWORD vpwOptLen16;
|
|
VPBYTE vpwOptVal16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PGETSOCKOPT16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpwOptLen16 = (VPWORD)FETCHDWORD(parg16->OptionLength);
|
|
vpwOptVal16 = (VPBYTE)FETCHDWORD(parg16->OptionValue);
|
|
GETVDMPTR( vpwOptLen16, sizeof(WORD), optionLength16 );
|
|
GETVDMPTR( vpwOptVal16, FETCHWORD(*optionLength16), optionValue16 );
|
|
|
|
if ( FETCHWORD(*optionLength16) < sizeof(WORD) ) {
|
|
FREEVDMPTR( optionLength16 );
|
|
FREEVDMPTR( optionValue16 );
|
|
FREEARGPTR( parg16 );
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAEFAULT );
|
|
ul = (ULONG)GETWORD16(SOCKET_ERROR );
|
|
RETURN( ul );
|
|
} else if ( FETCHWORD(*optionLength16) < sizeof(DWORD) ) {
|
|
optionLength32 = sizeof(DWORD);
|
|
} else {
|
|
optionLength32 = FETCHWORD(*optionLength16);
|
|
}
|
|
|
|
optionValue32 = malloc_w(optionLength32);
|
|
|
|
if ( optionValue32 == NULL ) {
|
|
FREEVDMPTR( optionLength16 );
|
|
FREEVDMPTR( optionValue16 );
|
|
FREEARGPTR( parg16 );
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
ul = (ULONG)GETWORD16(SOCKET_ERROR );
|
|
RETURN( ul );
|
|
}
|
|
|
|
SockCopyMemory( optionValue32, optionValue16, optionLength32 );
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_GETSOCKOPT].lpfn)(
|
|
s32,
|
|
parg16->Level,
|
|
SocketOption16To32( parg16->OptionName ),
|
|
(char *)optionValue32,
|
|
(int *)&optionLength32));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
FREEVDMPTR(optionLength16);
|
|
FREEVDMPTR(optionValue16);
|
|
|
|
if ( ul == NO_ERROR ) {
|
|
GETVDMPTR( vpwOptLen16, sizeof(WORD), optionLength16 );
|
|
GETVDMPTR( vpwOptVal16, FETCHWORD(*optionLength16), optionValue16 );
|
|
|
|
actualOptionLength16 = (WORD) min(optionLength32, FETCHWORD(*optionLength16));
|
|
|
|
RtlMoveMemory( optionValue16, optionValue32, actualOptionLength16 );
|
|
|
|
STOREWORD(*optionLength16, actualOptionLength16);
|
|
|
|
FLUSHVDMPTR( vpwOptLen16, sizeof(parg16->OptionLength), optionLength16 );
|
|
FLUSHVDMPTR( vpwOptVal16, actualOptionLength16, optionValue16 );
|
|
}
|
|
|
|
if(optionValue32) {
|
|
free_w(optionValue32);
|
|
}
|
|
|
|
FREEVDMPTR( optionLength16 );
|
|
FREEVDMPTR( optionValue16 );
|
|
|
|
exit:
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32getsockopt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32htonl(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PHTONL16 parg16;
|
|
|
|
GETARGPTR(pFrame, sizeof(HTONL16), parg16);
|
|
|
|
ul = (*wsockapis[WOW_HTONL].lpfn)( parg16->HostLong );
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32htonl
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32htons(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PHTONS16 parg16;
|
|
|
|
GETARGPTR(pFrame, sizeof(HTONS16), parg16);
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_HTONS].lpfn)( parg16->HostShort ) );
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32htons
|
|
|
|
|
|
|
|
|
|
|
|
#define ADDR_STR_SIZE 32
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32inet_addr(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PINET_ADDR16 parg16;
|
|
PSZ addressString;
|
|
CHAR szAddrStr[ADDR_STR_SIZE];
|
|
register PINET_ADDR16 realParg16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(INET_ADDR16), parg16);
|
|
|
|
realParg16 = parg16;
|
|
|
|
GETVDMPTR( parg16->cp, 1, addressString );
|
|
strncpy(szAddrStr, addressString, ADDR_STR_SIZE);
|
|
szAddrStr[ADDR_STR_SIZE-1] = '\0';
|
|
FREEVDMPTR( addressString );
|
|
|
|
//
|
|
// If the thread is version 1.0 of Windows Sockets, play special
|
|
// stack games to return a struct in_addr.
|
|
//
|
|
|
|
if ( WWS32IsThreadVersion10 ) {
|
|
|
|
PDWORD inAddr16;
|
|
ULONG inAddr32;
|
|
|
|
ul = *((PWORD)parg16);
|
|
ul |= pFrame->wAppDS << 16;
|
|
|
|
parg16 = (PINET_ADDR16)( (PCHAR)parg16 + 2 );
|
|
|
|
inAddr32 = (*wsockapis[WOW_INET_ADDR].lpfn)( szAddrStr );
|
|
|
|
ASSERT( sizeof(IN_ADDR) == sizeof(DWORD) );
|
|
GETVDMPTR( ul, sizeof(DWORD), inAddr16 );
|
|
STOREDWORD( *inAddr16, inAddr32 );
|
|
FLUSHVDMPTR( ul, sizeof(DWORD), inAddr16 );
|
|
FREEVDMPTR( inAddr16 );
|
|
|
|
} else {
|
|
ul = (*wsockapis[WOW_INET_ADDR].lpfn)( szAddrStr );
|
|
}
|
|
|
|
FREEARGPTR( realParg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32inet_addr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32inet_ntoa(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PINET_NTOA16 parg16;
|
|
PSZ ipAddress;
|
|
PSZ ipAddress16;
|
|
IN_ADDR in32;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(INET_NTOA16), parg16);
|
|
|
|
in32.s_addr = parg16->in;
|
|
|
|
ipAddress = (PSZ) (*wsockapis[WOW_INET_NTOA].lpfn)( in32 );
|
|
|
|
if ( ipAddress != NULL ) {
|
|
GETVDMPTR( WWS32vIpAddress, strlen( ipAddress )+1, ipAddress16 );
|
|
strcpy( ipAddress16, ipAddress);
|
|
FLUSHVDMPTR( WWS32vIpAddress, strlen( ipAddress )+1, ipAddress16 );
|
|
FREEVDMPTR( ipAddress16 );
|
|
ul = WWS32vIpAddress;
|
|
} else {
|
|
ul = 0;
|
|
}
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32inet_ntoa
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32ioctlsocket(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PIOCTLSOCKET16 parg16;
|
|
SOCKET s32;
|
|
PDWORD argument16;
|
|
DWORD argument32;
|
|
DWORD command;
|
|
VPDWORD vpdwArg16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(IOCTLSOCKET16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpdwArg16 = (VPDWORD)FETCHDWORD(parg16->Argument);
|
|
GETVDMPTR( vpdwArg16, sizeof(*argument16), argument16 );
|
|
|
|
//
|
|
// Translate the command value as necessary.
|
|
//
|
|
|
|
switch ( FETCHDWORD( parg16->Command ) & IOCPARM_MASK ) {
|
|
|
|
case 127:
|
|
command = FIONREAD;
|
|
break;
|
|
|
|
case 126:
|
|
command = FIONBIO;
|
|
break;
|
|
|
|
case 125:
|
|
command = FIOASYNC;
|
|
break;
|
|
|
|
case 0:
|
|
command = SIOCSHIWAT;
|
|
break;
|
|
|
|
case 1:
|
|
command = SIOCGHIWAT;
|
|
break;
|
|
|
|
case 2:
|
|
command = SIOCSLOWAT;
|
|
break;
|
|
|
|
case 3:
|
|
command = SIOCGLOWAT;
|
|
break;
|
|
|
|
case 7:
|
|
command = SIOCATMARK;
|
|
break;
|
|
|
|
default:
|
|
command = 0;
|
|
break;
|
|
}
|
|
|
|
argument32 = FETCHDWORD( *argument16 );
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_IOCTLSOCKET].lpfn)(s32,
|
|
command,
|
|
&argument32));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR( parg16 );
|
|
|
|
GETVDMPTR( vpdwArg16, sizeof(*argument16), argument16 );
|
|
STOREDWORD( *argument16, argument32 );
|
|
FLUSHVDMPTR( vpdwArg16, sizeof(*argument16), argument16 );
|
|
FREEVDMPTR( argument16 );
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32ioctlsocket
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32listen(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PLISTEN16 parg16;
|
|
SOCKET s32;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PLISTEN6), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_LISTEN].lpfn)( s32, parg16->Backlog ) );
|
|
|
|
exit:
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32listen
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32ntohl(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PNTOHL16 parg16;
|
|
|
|
GETARGPTR(pFrame, sizeof(NTOHL16), parg16);
|
|
|
|
ul = (*wsockapis[WOW_NTOHL].lpfn)( parg16->NetLong );
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32ntohl
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32ntohs(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PNTOHS16 parg16;
|
|
|
|
GETARGPTR(pFrame, sizeof(NTOHS16), parg16);
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_NTOHS].lpfn)( parg16->NetShort ) );
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32ntohs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32recv(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PRECV16 parg16;
|
|
SOCKET s32;
|
|
PBYTE buffer;
|
|
INT BufferLength;
|
|
VPBYTE vpBuf16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PRECV16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
BufferLength = INT32(parg16->BufferLength);
|
|
vpBuf16 = (VPBYTE)FETCHDWORD(parg16->Buffer);
|
|
|
|
// Thunk the 16-bit recv buffer
|
|
if(!WSThunkRecvBuffer(BufferLength, vpBuf16, &buffer)) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_RECV].lpfn)(s32,
|
|
buffer,
|
|
BufferLength,
|
|
parg16->Flags));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit recv buffer
|
|
WSUnthunkRecvBuffer((INT)ul, BufferLength, vpBuf16, buffer);
|
|
|
|
exit:
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32recv
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32recvfrom(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PRECVFROM16 parg16;
|
|
SOCKET s32;
|
|
INT addressLength;
|
|
PINT pAddressLength;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
PBYTE buffer;
|
|
INT BufferLength;
|
|
VPBYTE vpBuf16;
|
|
VPWORD vpwAddrLen16;
|
|
VPSOCKADDR vpSockAddr16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PRECVFROM16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
vpwAddrLen16 = (VPWORD)FETCHDWORD(parg16->AddressLength);
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
BufferLength = INT32(parg16->BufferLength);
|
|
vpBuf16 = (VPBYTE)parg16->Buffer;
|
|
|
|
// Thunk the 16-bit Address name and length buffers
|
|
if(!WSThunkAddrBufAndLen(&fastSockaddr,
|
|
vpSockAddr16,
|
|
vpwAddrLen16,
|
|
&addressLength,
|
|
&pAddressLength,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
// Thunk the 16-bit recv buffer
|
|
if(!WSThunkRecvBuffer(BufferLength, vpBuf16, &buffer)) {
|
|
goto exit2;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_RECVFROM].lpfn)(s32,
|
|
buffer,
|
|
BufferLength,
|
|
parg16->Flags,
|
|
realSockaddr,
|
|
pAddressLength));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit recv buffer
|
|
WSUnthunkRecvBuffer((INT)ul, BufferLength, vpBuf16, buffer);
|
|
|
|
exit2:
|
|
// Un-Thunk the 16-bit Address name and length buffers
|
|
WSUnThunkAddrBufAndLen(ul,
|
|
vpwAddrLen16,
|
|
vpSockAddr16,
|
|
addressLength,
|
|
&fastSockaddr,
|
|
realSockaddr);
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32recvfrom
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32select(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = (ULONG)GETWORD16( SOCKET_ERROR );
|
|
register PSELECT16 parg16;
|
|
PFD_SET readfds32 = NULL;
|
|
PFD_SET writefds32 = NULL;
|
|
PFD_SET exceptfds32 = NULL;
|
|
PFD_SET16 readfds16;
|
|
PFD_SET16 writefds16;
|
|
PFD_SET16 exceptfds16;
|
|
struct timeval timeout32;
|
|
struct timeval *ptimeout32;
|
|
PTIMEVAL16 timeout16;
|
|
INT err;
|
|
VPFD_SET16 vpreadfds16;
|
|
VPFD_SET16 vpwritefds16;
|
|
VPFD_SET16 vpexceptfds16;
|
|
VPTIMEVAL16 vptimeout16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR( pFrame, sizeof(PSELECT16), parg16 );
|
|
|
|
//
|
|
// Get 16-bit pointers.
|
|
//
|
|
// !!! This sizeof(FD_SET16) here and below is wrong if the app is
|
|
// using more than FDSETSIZE handles!!!
|
|
|
|
vpreadfds16 = parg16->Readfds;
|
|
vpwritefds16 = parg16->Writefds;
|
|
vpexceptfds16 = parg16->Exceptfds;
|
|
vptimeout16 = parg16->Timeout;
|
|
GETOPTPTR(vpreadfds16, sizeof(FD_SET16), readfds16);
|
|
GETOPTPTR(vpwritefds16, sizeof(FD_SET16), writefds16);
|
|
GETOPTPTR(vpexceptfds16, sizeof(FD_SET16), exceptfds16);
|
|
GETOPTPTR(vptimeout16, sizeof(TIMEVAL16), timeout16);
|
|
|
|
//
|
|
// Translate readfds.
|
|
//
|
|
|
|
if ( readfds16 != NULL ) {
|
|
|
|
readfds32 = AllocateFdSet32( readfds16 );
|
|
if ( readfds32 == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
err = ConvertFdSet16To32( readfds16, readfds32 );
|
|
if ( err != 0 ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( err );
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Translate writefds.
|
|
//
|
|
|
|
if ( writefds16 != NULL ) {
|
|
|
|
writefds32 = AllocateFdSet32( writefds16 );
|
|
if ( writefds32 == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
err = ConvertFdSet16To32( writefds16, writefds32 );
|
|
if ( err != 0 ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( err );
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Translate exceptfds.
|
|
//
|
|
|
|
if ( exceptfds16 != NULL ) {
|
|
|
|
exceptfds32 = AllocateFdSet32( exceptfds16 );
|
|
if ( exceptfds32 == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
err = ConvertFdSet16To32( exceptfds16, exceptfds32 );
|
|
if ( err != 0 ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( err );
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Translate the timeout.
|
|
//
|
|
|
|
if ( timeout16 == NULL ) {
|
|
ptimeout32 = NULL;
|
|
} else {
|
|
timeout32.tv_sec = FETCHDWORD( timeout16->tv_sec );
|
|
timeout32.tv_usec = FETCHDWORD( timeout16->tv_usec );
|
|
ptimeout32 = &timeout32;
|
|
}
|
|
|
|
//
|
|
// Call the 32-bit select function.
|
|
//
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_SELECT].lpfn)(0,
|
|
readfds32,
|
|
writefds32,
|
|
exceptfds32,
|
|
ptimeout32));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
FREEOPTPTR(readfds16);
|
|
FREEOPTPTR(writefds16);
|
|
FREEOPTPTR(exceptfds16);
|
|
FREEOPTPTR(timeout16);
|
|
|
|
//
|
|
// Copy 32-bit readfds back to the 16-bit readfds.
|
|
//
|
|
if ( readfds32 != NULL ) {
|
|
GETOPTPTR(vpreadfds16, sizeof(FD_SET16), readfds16);
|
|
ConvertFdSet32To16( readfds32, readfds16 );
|
|
FLUSHVDMPTR(vpreadfds16, sizeof(FD_SET16), readfds16);
|
|
}
|
|
|
|
//
|
|
// Copy 32-bit writefds back to the 16-bit writefds.
|
|
//
|
|
|
|
if ( writefds32 != NULL ) {
|
|
GETOPTPTR(vpwritefds16, sizeof(FD_SET16), writefds16);
|
|
ConvertFdSet32To16( writefds32, writefds16 );
|
|
FLUSHVDMPTR(vpwritefds16, sizeof(FD_SET16), writefds16);
|
|
}
|
|
|
|
//
|
|
// Copy 32-bit exceptfds back to the 16-bit exceptfds.
|
|
//
|
|
|
|
if ( exceptfds32 != NULL ) {
|
|
GETOPTPTR(vpexceptfds16, sizeof(FD_SET16), exceptfds16);
|
|
ConvertFdSet32To16( exceptfds32, exceptfds16 );
|
|
FLUSHVDMPTR(vpexceptfds16, sizeof(FD_SET16), exceptfds16);
|
|
}
|
|
|
|
exit:
|
|
|
|
FREEOPTPTR( readfds16 );
|
|
FREEOPTPTR( writefds16 );
|
|
FREEOPTPTR( exceptfds16 );
|
|
|
|
if ( readfds32 != NULL ) {
|
|
free_w((PVOID)readfds32);
|
|
}
|
|
if ( writefds32 != NULL ) {
|
|
free_w((PVOID)writefds32);
|
|
}
|
|
if ( exceptfds32 != NULL ) {
|
|
free_w((PVOID)exceptfds32);
|
|
}
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32select
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32send(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PSEND16 parg16;
|
|
SOCKET s32;
|
|
INT BufferLength;
|
|
PBYTE buffer;
|
|
VPBYTE vpBuf16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PSEND16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
BufferLength = INT32(parg16->BufferLength);
|
|
vpBuf16 = FETCHDWORD(parg16->Buffer);
|
|
|
|
// Thunk the 16-bit send buffer
|
|
if(!WSThunkSendBuffer(BufferLength, vpBuf16, &buffer)) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_SEND].lpfn)(s32,
|
|
buffer,
|
|
BufferLength,
|
|
parg16->Flags));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit send buffer
|
|
WSUnthunkSendBuffer(buffer);
|
|
|
|
exit:
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32send
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32sendto(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PSENDTO16 parg16;
|
|
SOCKET s32;
|
|
PBYTE buffer;
|
|
SOCKADDR fastSockaddr;
|
|
PSOCKADDR realSockaddr;
|
|
INT addressLength;
|
|
INT BufferLength;
|
|
VPSOCKADDR vpSockAddr16;
|
|
VPBYTE vpBuf16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PSENDTO16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
addressLength = INT32(parg16->AddressLength);
|
|
vpSockAddr16 = (VPSOCKADDR)FETCHDWORD(parg16->Address);
|
|
BufferLength = INT32(parg16->BufferLength);
|
|
vpBuf16 = (VPBYTE)FETCHDWORD(parg16->Buffer);
|
|
|
|
// Thunk the 16-bit Address buffer
|
|
if(!WSThunkAddrBuf(addressLength,
|
|
vpSockAddr16,
|
|
&fastSockaddr,
|
|
&realSockaddr)) {
|
|
goto exit;
|
|
}
|
|
|
|
// Thunk the 16-bit send buffer
|
|
if(!WSThunkSendBuffer(BufferLength, vpBuf16, &buffer)) {
|
|
goto exit2;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_SENDTO].lpfn)(s32,
|
|
buffer,
|
|
BufferLength,
|
|
parg16->Flags,
|
|
realSockaddr,
|
|
addressLength));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
// Un-Thunk the 16-bit send buffer
|
|
WSUnthunkSendBuffer(buffer);
|
|
|
|
exit2:
|
|
// Un-Thunk the 16-bit address buffer
|
|
WSUnThunkAddrBuf(&fastSockaddr, realSockaddr);
|
|
|
|
exit:
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32sendto
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32setsockopt(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PSETSOCKOPT16 parg16;
|
|
SOCKET s32;
|
|
PBYTE optionValue16;
|
|
PBYTE optionValue32;
|
|
DWORD optionLength32;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PSETSOCKOPT16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
GETVDMPTR( parg16->OptionValue, parg16->OptionLength, optionValue16 );
|
|
|
|
if ( parg16->OptionLength < sizeof(DWORD) ) {
|
|
optionLength32 = sizeof(DWORD);
|
|
} else {
|
|
optionLength32 = parg16->OptionLength;
|
|
}
|
|
|
|
optionValue32 = malloc_w(optionLength32);
|
|
if ( optionValue32 == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
ul = (ULONG)GETWORD16( SOCKET_ERROR );
|
|
FREEVDMPTR( optionValue16 );
|
|
FREEARGPTR( parg16 );
|
|
RETURN( ul );
|
|
}
|
|
|
|
RtlZeroMemory( optionValue32, optionLength32 );
|
|
RtlMoveMemory( optionValue32, optionValue16, parg16->OptionLength );
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_SETSOCKOPT].lpfn)(
|
|
s32,
|
|
parg16->Level,
|
|
SocketOption16To32( parg16->OptionName ),
|
|
optionValue32,
|
|
optionLength32));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
FREEVDMPTR( optionValue16 );
|
|
|
|
free_w(optionValue32);
|
|
|
|
exit:
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32setsockopt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32shutdown(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PSHUTDOWN16 parg16;
|
|
SOCKET s32;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(PBIND16), parg16);
|
|
|
|
//
|
|
// Find the 32-bit socket handle.
|
|
//
|
|
|
|
if((s32 = WSGetWinsock32(parg16->hSocket, &ul)) == INVALID_SOCKET) {
|
|
goto exit;
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_SHUTDOWN].lpfn)( s32, parg16->How ) );
|
|
|
|
exit:
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32shutdown
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ULONG FASTCALL WWS32socket(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = GETWORD16(INVALID_SOCKET);
|
|
register PSOCKET16 parg16;
|
|
SOCKET s32;
|
|
HSOCKET16 s16;
|
|
|
|
WSEXIT_IF_NOT_INTIALIZED();
|
|
|
|
GETARGPTR(pFrame, sizeof(SOCKET16), parg16);
|
|
|
|
s32 = (*wsockapis[WOW_SOCKET].lpfn)(INT32(parg16->AddressFamily),
|
|
INT32(parg16->Type),
|
|
INT32(parg16->Protocol));
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEARGPTR(pFrame);
|
|
FREEARGPTR(parg16);
|
|
|
|
//
|
|
// If the call succeeded, alias the 32-bit socket handle we just
|
|
// obtained into a 16-bit handle.
|
|
//
|
|
|
|
if ( s32 != INVALID_SOCKET ) {
|
|
|
|
s16 = GetWinsock16( s32, 0 );
|
|
|
|
ul = s16;
|
|
|
|
if ( s16 == 0 ) {
|
|
(*wsockapis[WOW_CLOSESOCKET].lpfn)( s32 );
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
ul = GETWORD16( INVALID_SOCKET );
|
|
}
|
|
|
|
} else {
|
|
|
|
ul = GETWORD16( INVALID_SOCKET );
|
|
}
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN( ul );
|
|
|
|
} // WWS32socket
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Routines for converting between 16- and 32-bit FD_SET structures.
|
|
//
|
|
|
|
PFD_SET AllocateFdSet32(IN PFD_SET16 FdSet16)
|
|
{
|
|
int bytes = 4 + (FETCHWORD(FdSet16->fd_count) * sizeof(SOCKET));
|
|
|
|
return (PFD_SET)( malloc_w(bytes) );
|
|
|
|
} // AlloacteFdSet32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
INT ConvertFdSet16To32(IN PFD_SET16 FdSet16,
|
|
IN PFD_SET FdSet32)
|
|
{
|
|
int i;
|
|
|
|
FdSet32->fd_count = UINT32( FdSet16->fd_count );
|
|
|
|
for ( i = 0; i < (int)FdSet32->fd_count; i++ ) {
|
|
|
|
FdSet32->fd_array[i] = GetWinsock32( FdSet16->fd_array[i] );
|
|
if ( FdSet32->fd_array[i] == INVALID_SOCKET ) {
|
|
return WSAENOTSOCK;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // ConvertFdSet16To32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID ConvertFdSet32To16(IN PFD_SET FdSet32,
|
|
IN PFD_SET16 FdSet16)
|
|
{
|
|
int i;
|
|
|
|
STOREWORD( FdSet16->fd_count, GETWORD16( FdSet32->fd_count ) );
|
|
|
|
for ( i = 0; i < FdSet16->fd_count; i++ ) {
|
|
|
|
HSOCKET16 s16;
|
|
|
|
s16 = GetWinsock16( FdSet32->fd_array[i], 0 );
|
|
|
|
STOREWORD( FdSet16->fd_array[i], s16 );
|
|
}
|
|
|
|
} // ConvertFdSet32To16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Routines for aliasing 32-bit socket handles to 16-bit handles.
|
|
//
|
|
|
|
PWINSOCK_SOCKET_INFO FindSocketInfo16(IN SOCKET h32,
|
|
IN HAND16 h16)
|
|
{
|
|
PLIST_ENTRY listEntry;
|
|
PWINSOCK_SOCKET_INFO socketInfo;
|
|
|
|
//
|
|
// It is the responsibility of the caller of this routine to enter
|
|
// the critical section that protects the global socket list.
|
|
//
|
|
|
|
for ( listEntry = WWS32SocketHandleListHead.Flink;
|
|
listEntry != &WWS32SocketHandleListHead;
|
|
listEntry = listEntry->Flink ) {
|
|
|
|
socketInfo = CONTAINING_RECORD(listEntry,
|
|
WINSOCK_SOCKET_INFO,
|
|
GlobalSocketListEntry);
|
|
|
|
if ( socketInfo->SocketHandle32 == h32 ||
|
|
socketInfo->SocketHandle16 == h16 ) {
|
|
return socketInfo;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} // FindSocketInfo16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HAND16 AllocateUnique16BitHandle(VOID)
|
|
{
|
|
|
|
PLIST_ENTRY listEntry;
|
|
PWINSOCK_SOCKET_INFO socketInfo;
|
|
HAND16 h16;
|
|
WORD i;
|
|
|
|
//
|
|
// This function assumes it is called with the WWS32CriticalSection
|
|
// lock held!
|
|
//
|
|
|
|
//
|
|
// If the socket list is empty, then we can reset our socket handle
|
|
// counter because we know there are no active sockets. We'll only
|
|
// do this if the handle counter is above some value (just pulled
|
|
// out of the air) so that handles are not reused too quickly.
|
|
// (Frequent handle reuse can confuse poorly written 16-bit apps.)
|
|
//
|
|
|
|
if( ( WWS32SocketHandleCounter > 255 ) &&
|
|
IsListEmpty( &WWS32SocketHandleListHead ) ) {
|
|
|
|
WWS32SocketHandleCounter = 1;
|
|
WWS32SocketHandleCounterWrapped = FALSE;
|
|
|
|
}
|
|
|
|
//
|
|
// If the socket handle counter has not wrapped around,
|
|
// then we can quickly return a unique handle.
|
|
//
|
|
|
|
if( !WWS32SocketHandleCounterWrapped ) {
|
|
|
|
h16 = (HAND16)WWS32SocketHandleCounter++;
|
|
|
|
if( WWS32SocketHandleCounter == 0xFFFF ) {
|
|
|
|
WWS32SocketHandleCounter = 1;
|
|
WWS32SocketHandleCounterWrapped = TRUE;
|
|
|
|
}
|
|
|
|
ASSERT( h16 != 0 );
|
|
return h16;
|
|
|
|
}
|
|
|
|
//
|
|
// There are active sockets, and the socket handle counter has
|
|
// wrapped, so we'll need to perform a painful search for a unique
|
|
// handle. We'll put a cap on the maximum number of times through
|
|
// this search loop so that, if all handles from 1 to 0xFFFE are
|
|
// in use, we won't search forever for something we'll never find.
|
|
//
|
|
|
|
for( i = 1 ; i <= 0xFFFE ; i++ ) {
|
|
|
|
h16 = (HAND16)WWS32SocketHandleCounter++;
|
|
|
|
if( WWS32SocketHandleCounter == 0xFFFF ) {
|
|
|
|
WWS32SocketHandleCounter = 1;
|
|
|
|
}
|
|
|
|
for ( listEntry = WWS32SocketHandleListHead.Flink;
|
|
listEntry != &WWS32SocketHandleListHead;
|
|
listEntry = listEntry->Flink ) {
|
|
|
|
socketInfo = CONTAINING_RECORD(
|
|
listEntry,
|
|
WINSOCK_SOCKET_INFO,
|
|
GlobalSocketListEntry
|
|
);
|
|
|
|
if( socketInfo->SocketHandle16 == h16 ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If listEntry == &WWS32SocketHandleListHead, then we have
|
|
// scanned the entire list and found no match. This is good,
|
|
// and we'll just return the current handle. Otherwise, there
|
|
// was a collision, so we'll get another potential handle and
|
|
// rescan the list.
|
|
//
|
|
|
|
if( listEntry == &WWS32SocketHandleListHead ) {
|
|
|
|
ASSERT( h16 != 0 );
|
|
return h16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// If we made it this far, then there were no unique handles
|
|
// available. Bad news.
|
|
//
|
|
|
|
return 0;
|
|
|
|
} // AllocateUnique16BitHandle
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
HAND16 GetWinsock16(IN INT h32,
|
|
IN INT iClass)
|
|
{
|
|
PWINSOCK_SOCKET_INFO socketInfo;
|
|
HAND16 h16;
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
//
|
|
// If the handle is already in the list, use it.
|
|
//
|
|
|
|
socketInfo = FindSocketInfo16( h32, 0 );
|
|
|
|
if ( socketInfo != NULL ) {
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
return socketInfo->SocketHandle16;
|
|
}
|
|
|
|
//
|
|
// If this thread has not yet been initialized, then we cannot
|
|
// create the new socket data. This should only happen if a 16-bit
|
|
// app closes a socket while an async connect is outstanding.
|
|
//
|
|
|
|
if( !WWS32IsThreadInitialized ) {
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// The handle is not in use. Create a new entry in the list.
|
|
//
|
|
|
|
h16 = AllocateUnique16BitHandle();
|
|
if( h16 == 0 ) {
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
return 0;
|
|
}
|
|
|
|
socketInfo = malloc_w(sizeof(*socketInfo));
|
|
if ( socketInfo == NULL ) {
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
return 0;
|
|
}
|
|
|
|
socketInfo->SocketHandle16 = h16;
|
|
socketInfo->SocketHandle32 = h32;
|
|
socketInfo->ThreadSerialNumber = WWS32ThreadSerialNumber;
|
|
|
|
InsertTailList( &WWS32SocketHandleListHead, &socketInfo->GlobalSocketListEntry );
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
ASSERT( h16 != 0 );
|
|
return h16;
|
|
|
|
} // GetWinsock16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID FreeWinsock16(IN HAND16 h16)
|
|
{
|
|
PWINSOCK_SOCKET_INFO socketInfo;
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
socketInfo = FindSocketInfo16( INVALID_SOCKET, h16 );
|
|
|
|
if ( socketInfo == NULL ) {
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
return;
|
|
}
|
|
|
|
RemoveEntryList( &socketInfo->GlobalSocketListEntry );
|
|
free_w((PVOID)socketInfo);
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
return;
|
|
|
|
} // FreeWinsock16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD GetWinsock32(IN HAND16 h16)
|
|
{
|
|
PWINSOCK_SOCKET_INFO socketInfo;
|
|
SOCKET socket32;
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
socketInfo = FindSocketInfo16( INVALID_SOCKET, h16 );
|
|
|
|
if ( socketInfo == NULL ) {
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
return INVALID_SOCKET;
|
|
}
|
|
|
|
//
|
|
// Store the socket handle in an aytumatic before leaving the critical
|
|
// section in case the socketInfo structure is about to be freed.
|
|
//
|
|
|
|
socket32 = socketInfo->SocketHandle32;
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
return socket32;
|
|
|
|
} // GetWinsock32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int SocketOption16To32(IN WORD SocketOption16)
|
|
{
|
|
|
|
if ( SocketOption16 == 0xFF7F ) {
|
|
return SO_DONTLINGER;
|
|
}
|
|
|
|
return (int)SocketOption16;
|
|
|
|
} // SocketOption16To32
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD WSGetWinsock32 (IN HAND16 h16,
|
|
OUT PULONG pul)
|
|
{
|
|
|
|
DWORD s32;
|
|
|
|
|
|
s32 = GetWinsock32(h16);
|
|
|
|
if(s32 == INVALID_SOCKET) {
|
|
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)(WSAENOTSOCK);
|
|
*pul = (ULONG)GETWORD16(SOCKET_ERROR);
|
|
|
|
}
|
|
|
|
return(s32);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WSThunkAddrBufAndLen(IN PSOCKADDR fastSockaddr,
|
|
IN VPSOCKADDR vpSockAddr16,
|
|
IN VPWORD vpwAddrLen16,
|
|
OUT PINT addressLength,
|
|
OUT PINT *pAddressLength,
|
|
OUT PSOCKADDR *realSockaddr)
|
|
{
|
|
PWORD addressLength16;
|
|
PSOCKADDR Sockaddr;
|
|
|
|
GETVDMPTR(vpwAddrLen16, sizeof(*addressLength16), addressLength16);
|
|
GETVDMPTR(vpSockAddr16, *addressLength16, Sockaddr);
|
|
|
|
if(Sockaddr) {
|
|
*realSockaddr = fastSockaddr;
|
|
}
|
|
else {
|
|
*realSockaddr = NULL;
|
|
}
|
|
|
|
if (addressLength16 == NULL) {
|
|
|
|
*pAddressLength = NULL;
|
|
|
|
} else {
|
|
|
|
*addressLength = INT32(*addressLength16);
|
|
*pAddressLength = addressLength;
|
|
|
|
if(*addressLength > sizeof(SOCKADDR)) {
|
|
|
|
*realSockaddr = malloc_w(*addressLength);
|
|
|
|
if(*realSockaddr == NULL) {
|
|
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)(WSAENOBUFS);
|
|
return(FALSE);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
FREEVDMPTR(Sockaddr);
|
|
FREEVDMPTR(addressLength16);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID WSUnThunkAddrBufAndLen(IN ULONG ret,
|
|
IN VPWORD vpwAddrLen16,
|
|
IN VPSOCKADDR vpSockAddr16,
|
|
IN INT addressLength,
|
|
IN PSOCKADDR fastSockaddr,
|
|
IN PSOCKADDR realSockaddr)
|
|
{
|
|
PWORD addressLength16;
|
|
PSOCKADDR Sockaddr;
|
|
|
|
GETVDMPTR(vpwAddrLen16, sizeof(*addressLength16), addressLength16);
|
|
if((ret != SOCKET_ERROR) && addressLength16) {
|
|
STOREWORD(*addressLength16, addressLength);
|
|
FLUSHVDMPTR(vpwAddrLen16, sizeof(WORD), addressLength16);
|
|
|
|
GETVDMPTR(vpSockAddr16, addressLength, Sockaddr);
|
|
if(Sockaddr) {
|
|
|
|
// don't copy back to the 16-bit address buffer if it's too small
|
|
if(addressLength <= *addressLength16) {
|
|
SockCopyMemory(Sockaddr, realSockaddr, addressLength);
|
|
FLUSHVDMPTR(vpSockAddr16, addressLength, Sockaddr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if( (realSockaddr) && (realSockaddr != fastSockaddr) ) {
|
|
|
|
free_w(realSockaddr);
|
|
|
|
}
|
|
|
|
FREEVDMPTR(addressLength16);
|
|
FREEVDMPTR(Sockaddr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WSThunkAddrBuf(IN INT addressLength,
|
|
IN VPSOCKADDR vpSockAddr16,
|
|
IN PSOCKADDR fastSockaddr,
|
|
OUT PSOCKADDR *realSockaddr)
|
|
{
|
|
PSOCKADDR Sockaddr;
|
|
|
|
GETVDMPTR(vpSockAddr16, addressLength, Sockaddr);
|
|
|
|
if(Sockaddr) {
|
|
|
|
|
|
if(addressLength <= sizeof(SOCKADDR)) {
|
|
*realSockaddr = fastSockaddr;
|
|
}
|
|
else {
|
|
|
|
*realSockaddr = malloc_w(addressLength);
|
|
|
|
if(*realSockaddr == NULL) {
|
|
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)(WSAENOBUFS);
|
|
FREEVDMPTR(Sockaddr);
|
|
return(FALSE);
|
|
|
|
}
|
|
}
|
|
|
|
SockCopyMemory(*realSockaddr, Sockaddr, addressLength);
|
|
}
|
|
else {
|
|
*realSockaddr = NULL;
|
|
}
|
|
|
|
FREEVDMPTR(Sockaddr);
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID WSUnThunkAddrBuf(IN PSOCKADDR fastSockaddr,
|
|
IN PSOCKADDR realSockaddr)
|
|
{
|
|
if( (realSockaddr) && (realSockaddr != fastSockaddr) ) {
|
|
|
|
free_w(realSockaddr);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WSThunkRecvBuffer(IN INT BufferLength,
|
|
IN VPBYTE vpBuf16,
|
|
OUT PBYTE *buffer)
|
|
{
|
|
PBYTE lpBuf16;
|
|
|
|
GETVDMPTR(vpBuf16, BufferLength, lpBuf16);
|
|
|
|
if(lpBuf16) {
|
|
|
|
*buffer = malloc_w(BufferLength);
|
|
|
|
if(*buffer == NULL) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)(WSAENOBUFS);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else {
|
|
*buffer = NULL;
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID WSUnthunkRecvBuffer(IN INT cBytes,
|
|
IN INT BufferLength,
|
|
IN VPBYTE vpBuf16,
|
|
IN PBYTE buffer)
|
|
{
|
|
PBYTE lpBuf16;
|
|
|
|
GETVDMPTR(vpBuf16, BufferLength, lpBuf16);
|
|
|
|
if(buffer) {
|
|
|
|
if( (cBytes > 0) && lpBuf16 ) {
|
|
SockCopyMemory(lpBuf16, buffer, cBytes);
|
|
FLUSHVDMPTR(vpBuf16, cBytes, lpBuf16);
|
|
}
|
|
|
|
free_w(buffer);
|
|
|
|
}
|
|
|
|
FREEVDMPTR(lpBuf16);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL WSThunkSendBuffer(IN INT BufferLength,
|
|
IN VPBYTE vpBuf16,
|
|
OUT PBYTE *buffer)
|
|
{
|
|
PBYTE lpBuf16;
|
|
|
|
GETVDMPTR(vpBuf16, BufferLength, lpBuf16);
|
|
|
|
if(lpBuf16) {
|
|
|
|
*buffer = malloc_w(BufferLength);
|
|
|
|
if(*buffer) {
|
|
SockCopyMemory(*buffer, lpBuf16, BufferLength);
|
|
}
|
|
else {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)(WSAENOBUFS);
|
|
return(FALSE);
|
|
}
|
|
|
|
FREEVDMPTR(lpBuf16);
|
|
}
|
|
else {
|
|
*buffer = NULL;
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID WSUnthunkSendBuffer(IN PBYTE buffer)
|
|
{
|
|
|
|
if(buffer) {
|
|
free_w(buffer);
|
|
}
|
|
}
|