You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1889 lines
47 KiB
1889 lines
47 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Wsraw.h
|
|
|
|
Abstract:
|
|
|
|
Support for database winsock calls for WOW.
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 02-Oct-1992
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "wsdynmc.h"
|
|
|
|
#define FIND_16_OFFSET_FROM_32(base16, base32, actual32) \
|
|
( (DWORD)base16 + ( (DWORD)actual32 - (DWORD)base32 ) )
|
|
|
|
DWORD
|
|
BytesInHostent32 (
|
|
PHOSTENT Hostent32
|
|
);
|
|
|
|
DWORD
|
|
CopyHostent32To16 (
|
|
PHOSTENT16 Hostent16,
|
|
VPHOSTENT16 VHostent16,
|
|
int BufferLength,
|
|
PHOSTENT Hostent32
|
|
);
|
|
|
|
DWORD
|
|
BytesInProtoent32 (
|
|
PPROTOENT Protoent32
|
|
);
|
|
|
|
DWORD
|
|
CopyProtoent32To16 (
|
|
PPROTOENT16 Protoent16,
|
|
VPPROTOENT16 VProtoent16,
|
|
int BufferLength,
|
|
PPROTOENT Protoent32
|
|
);
|
|
|
|
DWORD
|
|
BytesInServent32 (
|
|
PSERVENT Servent32
|
|
);
|
|
|
|
DWORD
|
|
CopyServent32To16 (
|
|
PSERVENT16 Servent16,
|
|
VPSERVENT16 VServent16,
|
|
int BufferLength,
|
|
PSERVENT Servent32
|
|
);
|
|
|
|
/*++
|
|
|
|
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 WWS32gethostbyaddr(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PGETHOSTBYADDR16 parg16;
|
|
PDWORD paddr16;
|
|
PHOSTENT hostent32;
|
|
PHOSTENT16 hostent16;
|
|
DWORD bytesRequired;
|
|
DWORD addr32; // address must be in PF_INET format (length == 4 bytes)
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETHOSTBYADDR16), parg16 );
|
|
GETVDMPTR( parg16->Address, sizeof(DWORD), paddr16 );
|
|
|
|
addr32 = *paddr16; // copy the 4-byte address
|
|
|
|
hostent32 = (PHOSTENT) (*wsockapis[WOW_GETHOSTBYADDR].lpfn)((CHAR *)&addr32,
|
|
parg16->Length,
|
|
parg16->Type);
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEVDMPTR(paddr16);
|
|
FREEARGPTR(parg16);
|
|
|
|
if ( hostent32 != NULL ) {
|
|
|
|
GETVDMPTR( WWS32vHostent, MAXGETHOSTSTRUCT, hostent16 );
|
|
bytesRequired = CopyHostent32To16(
|
|
hostent16,
|
|
WWS32vHostent,
|
|
MAXGETHOSTSTRUCT,
|
|
hostent32
|
|
);
|
|
ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
|
|
|
|
FLUSHVDMPTR( WWS32vHostent, (USHORT) bytesRequired, hostent16 );
|
|
FREEVDMPTR( hostent16 );
|
|
ul = WWS32vHostent;
|
|
|
|
} else {
|
|
|
|
ul = 0;
|
|
}
|
|
|
|
FREEVDMPTR( paddr16 );
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32gethostbyaddr
|
|
|
|
ULONG FASTCALL WWS32gethostbyname(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PGETHOSTBYNAME16 parg16;
|
|
PHOSTENT hostent32 = NULL;
|
|
PHOSTENT16 hostent16;
|
|
PSZ name32 = NULL;
|
|
PSZ name16;
|
|
DWORD bytesRequired;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETHOSTBYNAME16), parg16 );
|
|
|
|
GETVDMPTR( parg16->Name, 32, name16 );
|
|
|
|
if(name16) {
|
|
name32 = malloc_w(strlen(name16)+1);
|
|
if ( name32 ) {
|
|
strcpy(name32, name16);
|
|
hostent32 = (PHOSTENT) (*wsockapis[WOW_GETHOSTBYNAME].lpfn)( name32 );
|
|
free_w(name32);
|
|
}
|
|
}
|
|
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEVDMPTR(name16);
|
|
FREEARGPTR(parg16);
|
|
|
|
|
|
if ( hostent32 != NULL ) {
|
|
|
|
GETVDMPTR( WWS32vHostent, MAXGETHOSTSTRUCT, hostent16 );
|
|
bytesRequired = CopyHostent32To16(
|
|
hostent16,
|
|
WWS32vHostent,
|
|
MAXGETHOSTSTRUCT,
|
|
hostent32
|
|
);
|
|
ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
|
|
|
|
FLUSHVDMPTR( WWS32vHostent, (USHORT) bytesRequired, hostent16 );
|
|
FREEVDMPTR( hostent16 );
|
|
ul = WWS32vHostent;
|
|
|
|
} else {
|
|
|
|
ul = 0;
|
|
}
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32gethostbyname
|
|
|
|
ULONG FASTCALL WWS32gethostname(PVDMFRAME pFrame)
|
|
{
|
|
int len;
|
|
ULONG ul;
|
|
register PGETHOSTNAME16 parg16;
|
|
PCHAR name32 = NULL;
|
|
PCHAR name16;
|
|
INT NameLength;
|
|
VPSZ vpszName;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETHOSTNAME16), parg16 );
|
|
|
|
vpszName = FETCHDWORD(parg16->Name);
|
|
NameLength = INT32(parg16->NameLength);
|
|
|
|
if(vpszName) {
|
|
name32 = malloc_w(NameLength);
|
|
}
|
|
|
|
ul = GETWORD16( (*wsockapis[WOW_GETHOSTNAME].lpfn)( name32, NameLength ) );
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEVDMPTR(name16);
|
|
FREEARGPTR(parg16);
|
|
|
|
GETVDMPTR( vpszName, NameLength, name16 );
|
|
if(name16 && name32) {
|
|
len = strlen(name32) + 1;
|
|
len = min(len, NameLength);
|
|
strncpy(name16, name32, len);
|
|
name16[len-1] = '\0';
|
|
}
|
|
FLUSHVDMPTR( vpszName, NameLength, name16 );
|
|
|
|
FREEVDMPTR( name16 );
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32gethostname
|
|
|
|
ULONG FASTCALL WWS32WSAAsyncGetHostByAddr(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSAASYNCGETHOSTBYADDR16 parg16;
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PVOID buffer32;
|
|
PDWORD paddr16;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN(0);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(WSAASYNCGETHOSTBYADDR16), parg16 );
|
|
GETVDMPTR( parg16->Address, sizeof(DWORD), paddr16 );
|
|
|
|
//
|
|
// Set up locals so we know how to clean up on exit.
|
|
//
|
|
|
|
context = NULL;
|
|
buffer32 = NULL;
|
|
ul = 0;
|
|
|
|
//
|
|
// Allocate a context block and 32-bit buffer to use for the request.
|
|
//
|
|
|
|
context = malloc_w( sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
buffer32 = malloc_w( MAXGETHOSTSTRUCT );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Fill in entries in the context buffer.
|
|
//
|
|
|
|
context->Buffer32 = buffer32;
|
|
context->vBuffer16 = parg16->Buffer;
|
|
context->Buffer16Length = parg16->BufferLength;
|
|
|
|
//
|
|
// Enter a critical section to synchronize access to the context block
|
|
// and their global list.
|
|
//
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETHOSTBYADDR].lpfn)(
|
|
(HWND)HWND32(parg16->hWnd),
|
|
(parg16->wMsg << 16) |
|
|
WWS32_MESSAGE_ASYNC_GETHOST,
|
|
(char *)paddr16,
|
|
parg16->Length,
|
|
parg16->Type,
|
|
buffer32,
|
|
MAXGETHOSTSTRUCT);
|
|
|
|
if ( context->AsyncTaskHandle32 != 0 ) {
|
|
|
|
//
|
|
// The call succeeded so get a 16-bit task handle for this
|
|
// request and place the context block on the global list. The
|
|
// resources will be freed by WWS32PostAsyncGetHost.
|
|
//
|
|
|
|
ul = WWS32GetAsyncTaskHandle16( );
|
|
context->AsyncTaskHandle16 = (HAND16)ul;
|
|
|
|
InsertTailList(
|
|
&WWS32AsyncContextBlockListHead,
|
|
&context->ContextBlockListEntry
|
|
);
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
exit:
|
|
|
|
if ( ul == 0 ) {
|
|
|
|
if ( context != NULL ) {
|
|
free_w( (PVOID)context );
|
|
}
|
|
|
|
if ( buffer32 != NULL ) {
|
|
free_w( buffer32 );
|
|
}
|
|
}
|
|
|
|
FREEVDMPTR( paddr16 );
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSAAsyncGetHostByAddr
|
|
|
|
ULONG FASTCALL WWS32WSAAsyncGetHostByName(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSAASYNCGETHOSTBYNAME16 parg16;
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PVOID buffer32;
|
|
PCHAR name32;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN(0);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(WSAASYNCGETHOSTBYNAME16), parg16 );
|
|
GETVDMPTR( parg16->Name, 32, name32 );
|
|
|
|
//
|
|
// Set up locals so we know how to clean up on exit.
|
|
//
|
|
|
|
context = NULL;
|
|
buffer32 = NULL;
|
|
ul = 0;
|
|
|
|
//
|
|
// Allocate a context block and 32-bit buffer to use for the request.
|
|
//
|
|
|
|
context = malloc_w( sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
buffer32 = malloc_w( MAXGETHOSTSTRUCT );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Fill in entries in the context buffer.
|
|
//
|
|
|
|
context->Buffer32 = buffer32;
|
|
context->vBuffer16 = parg16->Buffer;
|
|
context->Buffer16Length = parg16->BufferLength;
|
|
|
|
//
|
|
// Enter a critical section to synchronize access to the context block
|
|
// and their global list.
|
|
//
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETHOSTBYNAME].lpfn)(
|
|
(HWND)HWND32(parg16->hWnd),
|
|
(parg16->wMsg << 16) |
|
|
WWS32_MESSAGE_ASYNC_GETHOST,
|
|
name32,
|
|
buffer32,
|
|
MAXGETHOSTSTRUCT
|
|
);
|
|
|
|
if ( context->AsyncTaskHandle32 != 0 ) {
|
|
|
|
//
|
|
// The call succeeded so get a 16-bit task handle for this
|
|
// request and place the context block on the global list. The
|
|
// resources will be freed by WWS32PostAsyncGetHost.
|
|
//
|
|
|
|
ul = WWS32GetAsyncTaskHandle16( );
|
|
context->AsyncTaskHandle16 = (HAND16)ul;
|
|
|
|
InsertTailList(
|
|
&WWS32AsyncContextBlockListHead,
|
|
&context->ContextBlockListEntry
|
|
);
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
exit:
|
|
|
|
if ( ul == 0 ) {
|
|
|
|
if ( context != NULL ) {
|
|
free_w( (PVOID)context );
|
|
}
|
|
|
|
if ( buffer32 != NULL ) {
|
|
free_w( buffer32 );
|
|
}
|
|
}
|
|
|
|
FREEVDMPTR( name32 );
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSAAsyncGetHostByName
|
|
|
|
|
|
BOOL
|
|
WWS32PostAsyncGetHost (
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
BOOL ret = FALSE;
|
|
PVOID buffer16;
|
|
DWORD bytesRequired;
|
|
|
|
context = WWS32FindAndRemoveAsyncContext( (HANDLE)wParam );
|
|
|
|
if ( NULL == context || NULL == context->Buffer32 ) {
|
|
ASSERT( context && context->Buffer32 );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the call was successful, copy the 32-bit buffer to the
|
|
// 16-bit buffer specified by the application.
|
|
//
|
|
|
|
if ( WSAGETASYNCERROR( lParam ) == 0 ) {
|
|
|
|
//
|
|
// Copy the 32-bit structure to 16-bit buffer.
|
|
//
|
|
|
|
GETVDMPTR( context->vBuffer16, context->Buffer16Length, buffer16 );
|
|
|
|
bytesRequired = CopyHostent32To16(
|
|
buffer16,
|
|
context->vBuffer16,
|
|
context->Buffer16Length,
|
|
context->Buffer32
|
|
);
|
|
|
|
//
|
|
// If the application's buffer was too small, return an error
|
|
// and information aqbout the buffer size required.
|
|
//
|
|
|
|
if ( bytesRequired > context->Buffer16Length ) {
|
|
lParam = WSAMAKEASYNCREPLY( (WORD)bytesRequired, WSAENOBUFS );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Post the completion message to the 16-bit application.
|
|
//
|
|
|
|
ret = PostMessage(
|
|
hWnd,
|
|
Msg >> 16,
|
|
context->AsyncTaskHandle16,
|
|
lParam
|
|
);
|
|
|
|
//
|
|
// Free resources and return.
|
|
//
|
|
|
|
free_w( context->Buffer32 );
|
|
free_w( (PVOID)context );
|
|
|
|
return ret;
|
|
|
|
} // WWS32PostAsyncGetHost
|
|
|
|
|
|
DWORD
|
|
CopyHostent32To16 (
|
|
PHOSTENT16 Hostent16,
|
|
VPHOSTENT16 VHostent16,
|
|
int BufferLength,
|
|
PHOSTENT Hostent32
|
|
)
|
|
{
|
|
DWORD requiredBufferLength;
|
|
DWORD bytesFilled;
|
|
PCHAR currentLocation = (PCHAR)Hostent16;
|
|
DWORD aliasCount;
|
|
DWORD addressCount;
|
|
DWORD i;
|
|
VPBYTE *addrList16;
|
|
VPSZ *aliases16;
|
|
|
|
//
|
|
// Determine how many bytes are needed to fully copy the structure.
|
|
//
|
|
|
|
requiredBufferLength = BytesInHostent32( Hostent32 );
|
|
|
|
//
|
|
// Copy over the hostent structure if it fits.
|
|
//
|
|
|
|
bytesFilled = sizeof(*Hostent32);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREWORD( Hostent16->h_addrtype, Hostent32->h_addrtype );
|
|
STOREWORD( Hostent16->h_length, Hostent32->h_length );
|
|
currentLocation = (PCHAR)Hostent16 + bytesFilled;
|
|
|
|
//
|
|
// Count the host's aliases and set up an array to hold pointers to
|
|
// them.
|
|
//
|
|
|
|
for ( aliasCount = 0;
|
|
Hostent32->h_aliases[aliasCount] != NULL;
|
|
aliasCount++ );
|
|
|
|
bytesFilled += (aliasCount+1) * sizeof(char FAR *);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
Hostent32->h_aliases = NULL;
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Hostent16->h_aliases =
|
|
FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation );
|
|
aliases16 = (VPSZ *)currentLocation;
|
|
currentLocation = (PCHAR)Hostent16 + bytesFilled;
|
|
|
|
//
|
|
// Count the host's addresses and set up an array to hold pointers to
|
|
// them.
|
|
//
|
|
|
|
for ( addressCount = 0;
|
|
Hostent32->h_addr_list[addressCount] != NULL;
|
|
addressCount++ );
|
|
|
|
bytesFilled += (addressCount+1) * sizeof(void FAR *);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
Hostent32->h_addr_list = NULL;
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Hostent16->h_addr_list =
|
|
FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation );
|
|
addrList16 = (VPBYTE *)currentLocation;
|
|
currentLocation = (PCHAR)Hostent16 + bytesFilled;
|
|
|
|
//
|
|
// Start filling in addresses. Do addresses before filling in the
|
|
// host name and aliases in order to avoid alignment problems.
|
|
//
|
|
|
|
for ( i = 0; i < addressCount; i++ ) {
|
|
|
|
bytesFilled += Hostent32->h_length;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
STOREDWORD( addrList16[i], 0 );
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREDWORD(
|
|
addrList16[i],
|
|
FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation )
|
|
);
|
|
|
|
RtlMoveMemory(
|
|
currentLocation,
|
|
Hostent32->h_addr_list[i],
|
|
Hostent32->h_length
|
|
);
|
|
|
|
currentLocation = (PCHAR)Hostent16 + bytesFilled;
|
|
}
|
|
|
|
STOREDWORD( addrList16[i], 0 );
|
|
|
|
//
|
|
// Copy the host name if it fits.
|
|
//
|
|
|
|
bytesFilled += strlen( Hostent32->h_name ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Hostent16->h_name =
|
|
FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation );
|
|
|
|
RtlMoveMemory( currentLocation, Hostent32->h_name, strlen( Hostent32->h_name ) + 1 );
|
|
currentLocation = (PCHAR)Hostent16 + bytesFilled;
|
|
|
|
//
|
|
// Start filling in aliases.
|
|
//
|
|
|
|
for ( i = 0; i < aliasCount; i++ ) {
|
|
|
|
bytesFilled += strlen( Hostent32->h_aliases[i] ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
STOREDWORD( aliases16[i], 0 );
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREDWORD(
|
|
aliases16[i],
|
|
FIND_16_OFFSET_FROM_32( VHostent16, Hostent16, currentLocation )
|
|
);
|
|
|
|
RtlMoveMemory(
|
|
currentLocation,
|
|
Hostent32->h_aliases[i],
|
|
strlen( Hostent32->h_aliases[i] ) + 1
|
|
);
|
|
|
|
currentLocation = (PCHAR)Hostent16 + bytesFilled;
|
|
}
|
|
|
|
STOREDWORD( aliases16[i], 0 );
|
|
|
|
return requiredBufferLength;
|
|
|
|
} // CopyHostentToBuffer
|
|
|
|
|
|
DWORD
|
|
BytesInHostent32 (
|
|
PHOSTENT Hostent32
|
|
)
|
|
{
|
|
DWORD total;
|
|
int i;
|
|
|
|
total = sizeof(HOSTENT);
|
|
total += strlen( Hostent32->h_name ) + 1;
|
|
total += sizeof(char *) + sizeof(char *);
|
|
|
|
for ( i = 0; Hostent32->h_aliases[i] != NULL; i++ ) {
|
|
total += strlen( Hostent32->h_aliases[i] ) + 1 + sizeof(char *);
|
|
}
|
|
|
|
for ( i = 0; Hostent32->h_addr_list[i] != NULL; i++ ) {
|
|
total += Hostent32->h_length + sizeof(char *);
|
|
}
|
|
|
|
return total;
|
|
|
|
} // BytesInHostent
|
|
|
|
ULONG FASTCALL WWS32getprotobyname(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PGETPROTOBYNAME16 parg16;
|
|
PPROTOENT protoent32 = NULL;
|
|
PPROTOENT16 protoent16;
|
|
PSZ name32 = NULL;
|
|
PBYTE name16;
|
|
DWORD bytesRequired;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETPROTOBYNAME16), parg16 );
|
|
GETVDMPTR( parg16->Name, 32, name16 );
|
|
|
|
if(name16) {
|
|
name32 = malloc_w(strlen(name16)+1);
|
|
if ( name32 ) {
|
|
strcpy(name32, name16);
|
|
protoent32 = (PPROTOENT) (*wsockapis[WOW_GETPROTOBYNAME].lpfn)( name32 );
|
|
free_w( name32 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Note: 16-bit callbacks resulting from above function
|
|
// call may have caused 16-bit memory movement
|
|
FREEVDMPTR(name16);
|
|
FREEARGPTR(parg16);
|
|
|
|
if ( protoent32 != NULL ) {
|
|
|
|
GETVDMPTR( WWS32vProtoent, MAXGETHOSTSTRUCT, protoent16 );
|
|
bytesRequired = CopyProtoent32To16(
|
|
protoent16,
|
|
WWS32vProtoent,
|
|
MAXGETHOSTSTRUCT,
|
|
protoent32
|
|
);
|
|
ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
|
|
|
|
FLUSHVDMPTR( WWS32vProtoent, (USHORT) bytesRequired, protoent16 );
|
|
FREEVDMPTR( protoent16 );
|
|
ul = WWS32vProtoent;
|
|
|
|
} else {
|
|
|
|
ul = 0;
|
|
}
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32getprotobyname
|
|
|
|
ULONG FASTCALL WWS32getprotobynumber(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PGETPROTOBYNUMBER16 parg16;
|
|
PPROTOENT protoent32;
|
|
PPROTOENT16 protoent16;
|
|
DWORD bytesRequired;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETPROTOBYNUMBER16), parg16 );
|
|
|
|
protoent32 = (PPROTOENT) (*wsockapis[WOW_GETPROTOBYNUMBER].lpfn)( parg16->Protocol );
|
|
|
|
if ( protoent32 != NULL ) {
|
|
|
|
GETVDMPTR( WWS32vProtoent, MAXGETHOSTSTRUCT, protoent16 );
|
|
bytesRequired = CopyProtoent32To16(
|
|
protoent16,
|
|
WWS32vProtoent,
|
|
MAXGETHOSTSTRUCT,
|
|
protoent32
|
|
);
|
|
ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
|
|
|
|
FLUSHVDMPTR( WWS32vProtoent, (USHORT) bytesRequired, protoent16 );
|
|
FREEVDMPTR( protoent16 );
|
|
ul = WWS32vProtoent;
|
|
|
|
} else {
|
|
|
|
ul = 0;
|
|
}
|
|
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32getprotobynumber
|
|
|
|
ULONG FASTCALL WWS32WSAAsyncGetProtoByName(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSAASYNCGETPROTOBYNAME16 parg16;
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PVOID buffer32;
|
|
PSZ name32;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN(0);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(WSAASYNCGETPROTOBYNAME16), parg16 );
|
|
GETVDMPTR( parg16->Name, 32, name32 );
|
|
|
|
//
|
|
// Set up locals so we know how to clean up on exit.
|
|
//
|
|
|
|
context = NULL;
|
|
buffer32 = NULL;
|
|
ul = 0;
|
|
|
|
//
|
|
// Allocate a context block and 32-bit buffer to use for the request.
|
|
//
|
|
|
|
context = malloc_w( sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
buffer32 = malloc_w( MAXGETHOSTSTRUCT );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Fill in entries in the context buffer.
|
|
//
|
|
|
|
context->Buffer32 = buffer32;
|
|
context->vBuffer16 = parg16->Buffer;
|
|
context->Buffer16Length = parg16->BufferLength;
|
|
|
|
//
|
|
// Enter a critical section to synchronize access to the context block
|
|
// and their global list.
|
|
//
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETPROTOBYNAME].lpfn)(
|
|
(HWND)HWND32(parg16->hWnd),
|
|
(parg16->wMsg << 16) |
|
|
WWS32_MESSAGE_ASYNC_GETPROTO,
|
|
name32,
|
|
buffer32,
|
|
MAXGETHOSTSTRUCT
|
|
);
|
|
|
|
if ( context->AsyncTaskHandle32 != 0 ) {
|
|
|
|
//
|
|
// The call succeeded so get a 16-bit task handle for this
|
|
// request and place the context block on the global list. The
|
|
// resources will be freed by WWS32PostAsyncGetProto.
|
|
//
|
|
|
|
ul = WWS32GetAsyncTaskHandle16( );
|
|
context->AsyncTaskHandle16 = (HAND16)ul;
|
|
|
|
InsertTailList(
|
|
&WWS32AsyncContextBlockListHead,
|
|
&context->ContextBlockListEntry
|
|
);
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
exit:
|
|
|
|
if ( ul == 0 ) {
|
|
|
|
if ( context != NULL ) {
|
|
free_w( (PVOID)context );
|
|
}
|
|
|
|
if ( buffer32 != NULL ) {
|
|
free_w( buffer32 );
|
|
}
|
|
}
|
|
|
|
FREEARGPTR( name32 );
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSAAsyncGetProtoByName
|
|
|
|
ULONG FASTCALL WWS32WSAAsyncGetProtoByNumber(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSAASYNCGETPROTOBYNUMBER16 parg16;
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PVOID buffer32;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN(0);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(WSAASYNCGETPROTOBYNUMBER16), parg16 );
|
|
|
|
//
|
|
// Set up locals so we know how to clean up on exit.
|
|
//
|
|
|
|
context = NULL;
|
|
buffer32 = NULL;
|
|
ul = 0;
|
|
|
|
//
|
|
// Allocate a context block and 32-bit buffer to use for the request.
|
|
//
|
|
|
|
context = malloc_w( sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
buffer32 = malloc_w( MAXGETHOSTSTRUCT );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Fill in entries in the context buffer.
|
|
//
|
|
|
|
context->Buffer32 = buffer32;
|
|
context->vBuffer16 = parg16->Buffer;
|
|
context->Buffer16Length = parg16->BufferLength;
|
|
|
|
//
|
|
// Enter a critical section to synchronize access to the context block
|
|
// and their global list.
|
|
//
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETPROTOBYNUMBER].lpfn)(
|
|
(HWND)HWND32(parg16->hWnd),
|
|
(parg16->wMsg << 16) |
|
|
WWS32_MESSAGE_ASYNC_GETPROTO,
|
|
parg16->Number,
|
|
buffer32,
|
|
MAXGETHOSTSTRUCT
|
|
);
|
|
|
|
if ( context->AsyncTaskHandle32 != 0 ) {
|
|
|
|
//
|
|
// The call succeeded so get a 16-bit task handle for this
|
|
// request and place the context block on the global list. The
|
|
// resources will be freed by WWS32PostAsyncGetProto.
|
|
//
|
|
|
|
ul = WWS32GetAsyncTaskHandle16( );
|
|
context->AsyncTaskHandle16 = (HAND16)ul;
|
|
|
|
InsertTailList(
|
|
&WWS32AsyncContextBlockListHead,
|
|
&context->ContextBlockListEntry
|
|
);
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
exit:
|
|
|
|
if ( ul == 0 ) {
|
|
|
|
if ( context != NULL ) {
|
|
free_w( (PVOID)context );
|
|
}
|
|
|
|
if ( buffer32 != NULL ) {
|
|
free_w( buffer32 );
|
|
}
|
|
}
|
|
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSAAsyncGetProtoByNumber
|
|
|
|
|
|
BOOL
|
|
WWS32PostAsyncGetProto (
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
BOOL ret;
|
|
PVOID buffer16;
|
|
DWORD bytesRequired;
|
|
|
|
context = WWS32FindAndRemoveAsyncContext( (HANDLE)wParam );
|
|
|
|
if( NULL == context ) {
|
|
ASSERT( context != NULL );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the call was successful, copy the 32-bit buffer to the
|
|
// 16-bit buffer specified by the application.
|
|
//
|
|
|
|
if ( WSAGETASYNCERROR( lParam ) == 0 ) {
|
|
|
|
//
|
|
// Copy the 32-bit structure to 16-bit buffer.
|
|
//
|
|
|
|
GETVDMPTR( context->vBuffer16, context->Buffer16Length, buffer16 );
|
|
|
|
bytesRequired = CopyProtoent32To16(
|
|
buffer16,
|
|
context->vBuffer16,
|
|
context->Buffer16Length,
|
|
context->Buffer32
|
|
);
|
|
|
|
//
|
|
// If the application's buffer was too small, return an error
|
|
// and information aqbout the buffer size required.
|
|
//
|
|
|
|
if ( bytesRequired > context->Buffer16Length ) {
|
|
lParam = WSAMAKEASYNCREPLY( (WORD)bytesRequired, WSAENOBUFS );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Post the completion message to the 16-bit application.
|
|
//
|
|
|
|
ret = PostMessage(
|
|
hWnd,
|
|
Msg >> 16,
|
|
context->AsyncTaskHandle16,
|
|
lParam
|
|
);
|
|
|
|
//
|
|
// Free resources and return.
|
|
//
|
|
free_w( context->Buffer32 );
|
|
free_w( (PVOID)context );
|
|
|
|
return ret;
|
|
|
|
} // WWS32PostAsyncGetProto
|
|
|
|
|
|
/*
|
|
NOTE: This assumes that Protoent16 & Protoent32 are not null.
|
|
*/
|
|
DWORD
|
|
CopyProtoent32To16 (
|
|
PPROTOENT16 Protoent16,
|
|
VPPROTOENT16 VProtoent16,
|
|
int BufferLength,
|
|
PPROTOENT Protoent32
|
|
)
|
|
{
|
|
DWORD requiredBufferLength;
|
|
DWORD bytesFilled;
|
|
PCHAR currentLocation = (PCHAR)Protoent16;
|
|
DWORD aliasCount;
|
|
DWORD i;
|
|
VPBYTE *aliases16;
|
|
|
|
//
|
|
// Determine how many bytes are needed to fully copy the structure.
|
|
//
|
|
|
|
requiredBufferLength = BytesInProtoent32( Protoent32 );
|
|
|
|
//
|
|
// Copy over the protoent structure if it fits.
|
|
//
|
|
|
|
bytesFilled = sizeof(*Protoent16);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREWORD( Protoent16->p_proto, Protoent32->p_proto );
|
|
currentLocation = (PCHAR)Protoent16 + bytesFilled;
|
|
|
|
//
|
|
// Count the protocol's aliases and set up an array to hold pointers to
|
|
// them.
|
|
//
|
|
|
|
for ( aliasCount = 0;
|
|
Protoent32->p_aliases[aliasCount] != NULL;
|
|
aliasCount++ );
|
|
|
|
bytesFilled += (aliasCount+1) * sizeof(char FAR *);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
Protoent16->p_aliases = 0;
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Protoent16->p_aliases =
|
|
FIND_16_OFFSET_FROM_32( VProtoent16, Protoent16, currentLocation );
|
|
aliases16 = (VPBYTE *)currentLocation;
|
|
currentLocation = (PCHAR)Protoent16 + bytesFilled;
|
|
|
|
//
|
|
// Copy the protocol name if it fits.
|
|
//
|
|
|
|
bytesFilled += strlen( Protoent32->p_name ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Protoent16->p_name =
|
|
FIND_16_OFFSET_FROM_32( VProtoent16, Protoent16, currentLocation );
|
|
|
|
RtlMoveMemory( currentLocation, Protoent32->p_name, strlen( Protoent32->p_name ) + 1 );
|
|
currentLocation = (PCHAR)Protoent16 + bytesFilled;
|
|
|
|
//
|
|
// Start filling in aliases.
|
|
//
|
|
|
|
for ( i = 0; i < aliasCount; i++ ) {
|
|
|
|
bytesFilled += strlen( Protoent32->p_aliases[i] ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
STOREDWORD( aliases16[i], 0 );
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREDWORD(
|
|
aliases16[i],
|
|
FIND_16_OFFSET_FROM_32( VProtoent16, Protoent16, currentLocation )
|
|
);
|
|
|
|
RtlMoveMemory(
|
|
currentLocation,
|
|
Protoent32->p_aliases[i],
|
|
strlen( Protoent32->p_aliases[i] ) + 1
|
|
);
|
|
|
|
currentLocation = (PCHAR)Protoent16 + bytesFilled;
|
|
}
|
|
|
|
STOREDWORD( aliases16[i], 0 );
|
|
|
|
return requiredBufferLength;
|
|
|
|
} // CopyProtoent32To16
|
|
|
|
|
|
DWORD
|
|
BytesInProtoent32 (
|
|
PPROTOENT Protoent32
|
|
)
|
|
{
|
|
DWORD total;
|
|
int i;
|
|
|
|
total = sizeof(PROTOENT);
|
|
total += strlen( Protoent32->p_name ) + 1;
|
|
total += sizeof(char *);
|
|
|
|
for ( i = 0; Protoent32->p_aliases[i] != NULL; i++ ) {
|
|
total += strlen( Protoent32->p_aliases[i] ) + 1 + sizeof(char *);
|
|
}
|
|
|
|
return total;
|
|
|
|
} // BytesInProtoent32
|
|
|
|
ULONG FASTCALL WWS32getservbyname(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PGETSERVBYNAME16 parg16;
|
|
PSERVENT servent32;
|
|
PSERVENT16 servent16;
|
|
PSZ name32;
|
|
PSZ protocol32;
|
|
DWORD bytesRequired;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETSERVBYNAME16), parg16 );
|
|
|
|
GETVDMPTR( parg16->Name, 32, name32 );
|
|
GETVDMPTR( parg16->Protocol, 32, protocol32 );
|
|
|
|
servent32 = (PSERVENT) (*wsockapis[WOW_GETSERVBYNAME].lpfn)( name32, protocol32 );
|
|
|
|
if ( servent32 != NULL ) {
|
|
|
|
GETVDMPTR( WWS32vServent, MAXGETHOSTSTRUCT, servent16 );
|
|
bytesRequired = CopyServent32To16(
|
|
servent16,
|
|
WWS32vServent,
|
|
MAXGETHOSTSTRUCT,
|
|
servent32
|
|
);
|
|
ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
|
|
|
|
FLUSHVDMPTR( WWS32vServent, (USHORT) bytesRequired, servent16 );
|
|
FREEVDMPTR( servent16 );
|
|
ul = WWS32vServent;
|
|
|
|
} else {
|
|
|
|
ul = 0;
|
|
}
|
|
|
|
FREEVDMPTR( name32 );
|
|
FREEVDMPTR( protocol32 );
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32getservbyname
|
|
|
|
ULONG FASTCALL WWS32getservbyport(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PGETSERVBYPORT16 parg16;
|
|
PSERVENT servent32;
|
|
PSERVENT16 servent16;
|
|
PSZ protocol32;
|
|
DWORD bytesRequired;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)NULL);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(GETSERVBYPORT16), parg16 );
|
|
|
|
GETVDMPTR( parg16->Protocol, 32, protocol32 );
|
|
|
|
servent32 = (PSERVENT) (*wsockapis[WOW_GETSERVBYPORT].lpfn)( parg16->Port, protocol32 );
|
|
|
|
if ( servent32 != NULL ) {
|
|
|
|
GETVDMPTR( WWS32vServent, MAXGETHOSTSTRUCT, servent16 );
|
|
bytesRequired = CopyServent32To16(
|
|
servent16,
|
|
WWS32vServent,
|
|
MAXGETHOSTSTRUCT,
|
|
servent32
|
|
);
|
|
ASSERT( bytesRequired < MAXGETHOSTSTRUCT );
|
|
|
|
FLUSHVDMPTR( WWS32vServent, (USHORT) bytesRequired, servent16 );
|
|
FREEVDMPTR( servent16 );
|
|
ul = WWS32vServent;
|
|
|
|
} else {
|
|
|
|
ul = 0;
|
|
}
|
|
|
|
FREEVDMPTR( protocol32 );
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32getservbyport
|
|
|
|
ULONG FASTCALL WWS32WSAAsyncGetServByPort(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSAASYNCGETSERVBYPORT16 parg16;
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PVOID buffer32;
|
|
PSZ proto32;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)0);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(WSAASYNCGETSERVBYPORT16), parg16 );
|
|
GETVDMPTR( parg16->Protocol, 32, proto32 );
|
|
|
|
//
|
|
// Set up locals so we know how to clean up on exit.
|
|
//
|
|
|
|
context = NULL;
|
|
buffer32 = NULL;
|
|
ul = 0;
|
|
|
|
//
|
|
// Allocate a context block and 32-bit buffer to use for the request.
|
|
//
|
|
|
|
context = malloc_w( sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
buffer32 = malloc_w( MAXGETHOSTSTRUCT );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Fill in entries in the context buffer.
|
|
//
|
|
|
|
context->Buffer32 = buffer32;
|
|
context->vBuffer16 = parg16->Buffer;
|
|
context->Buffer16Length = parg16->BufferLength;
|
|
|
|
//
|
|
// Enter a critical section to synchronize access to the context block
|
|
// and their global list.
|
|
//
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETSERVBYPORT].lpfn)(
|
|
(HWND)HWND32(parg16->hWnd),
|
|
(parg16->wMsg << 16) |
|
|
WWS32_MESSAGE_ASYNC_GETSERV,
|
|
parg16->Port,
|
|
proto32,
|
|
buffer32,
|
|
MAXGETHOSTSTRUCT
|
|
);
|
|
|
|
if ( context->AsyncTaskHandle32 != 0 ) {
|
|
|
|
//
|
|
// The call succeeded so get a 16-bit task handle for this
|
|
// request and place the context block on the global list. The
|
|
// resources will be freed by WWS32PostAsyncGetServ.
|
|
//
|
|
|
|
ul = WWS32GetAsyncTaskHandle16( );
|
|
context->AsyncTaskHandle16 = (HAND16)ul;
|
|
|
|
InsertTailList(
|
|
&WWS32AsyncContextBlockListHead,
|
|
&context->ContextBlockListEntry
|
|
);
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
exit:
|
|
|
|
if ( ul == 0 ) {
|
|
|
|
if ( context != NULL ) {
|
|
free_w( (PVOID)context );
|
|
}
|
|
|
|
if ( buffer32 != NULL ) {
|
|
free_w( buffer32 );
|
|
}
|
|
}
|
|
|
|
FREEARGPTR( proto32 );
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSAAsyncGetServByPort
|
|
|
|
ULONG FASTCALL WWS32WSAAsyncGetServByName(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSAASYNCGETSERVBYNAME16 parg16;
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PVOID buffer32;
|
|
PSZ name32;
|
|
PSZ proto32;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)0);
|
|
}
|
|
|
|
GETARGPTR( pFrame, sizeof(WSAASYNCGETSERVBYNAME16), parg16 );
|
|
GETVDMPTR( parg16->Name, 32, name32 );
|
|
GETVDMPTR( parg16->Protocol, 32, proto32 );
|
|
|
|
//
|
|
// Set up locals so we know how to clean up on exit.
|
|
//
|
|
|
|
context = NULL;
|
|
buffer32 = NULL;
|
|
ul = 0;
|
|
|
|
//
|
|
// Allocate a context block and 32-bit buffer to use for the request.
|
|
//
|
|
|
|
context = malloc_w( sizeof(*context) );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
buffer32 = malloc_w( MAXGETHOSTSTRUCT );
|
|
if ( context == NULL ) {
|
|
(*wsockapis[WOW_WSASETLASTERROR].lpfn)( WSAENOBUFS );
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Fill in entries in the context buffer.
|
|
//
|
|
|
|
context->Buffer32 = buffer32;
|
|
context->vBuffer16 = parg16->Buffer;
|
|
context->Buffer16Length = parg16->BufferLength;
|
|
|
|
//
|
|
// Enter a critical section to synchronize access to the context block
|
|
// and their global list.
|
|
//
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
context->AsyncTaskHandle32 = (HANDLE) (*wsockapis[WOW_WSAASYNCGETSERVBYNAME].lpfn)(
|
|
(HWND)HWND32(parg16->hWnd),
|
|
(parg16->wMsg << 16) |
|
|
WWS32_MESSAGE_ASYNC_GETSERV,
|
|
name32,
|
|
proto32,
|
|
buffer32,
|
|
MAXGETHOSTSTRUCT
|
|
);
|
|
|
|
if ( context->AsyncTaskHandle32 != 0 ) {
|
|
|
|
//
|
|
// The call succeeded so get a 16-bit task handle for this
|
|
// request and place the context block on the global list. The
|
|
// resources will be freed by WWS32PostAsyncGetServ.
|
|
//
|
|
|
|
ul = WWS32GetAsyncTaskHandle16( );
|
|
context->AsyncTaskHandle16 = (HAND16)ul;
|
|
|
|
InsertTailList(
|
|
&WWS32AsyncContextBlockListHead,
|
|
&context->ContextBlockListEntry
|
|
);
|
|
}
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
exit:
|
|
|
|
if ( ul == 0 ) {
|
|
|
|
if ( context != NULL ) {
|
|
free_w( (PVOID)context );
|
|
}
|
|
|
|
if ( buffer32 != NULL ) {
|
|
free_w( buffer32 );
|
|
}
|
|
}
|
|
|
|
FREEARGPTR( proto32 );
|
|
FREEARGPTR( name32 );
|
|
FREEARGPTR( parg16 );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSAAsyncGetServByName
|
|
|
|
|
|
BOOL
|
|
WWS32PostAsyncGetServ (
|
|
HWND hWnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
BOOL ret;
|
|
PVOID buffer16;
|
|
DWORD bytesRequired;
|
|
|
|
context = WWS32FindAndRemoveAsyncContext( (HANDLE)wParam );
|
|
if( NULL == context ) {
|
|
ASSERT( context != NULL );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If the call was successful, copy the 32-bit buffer to the
|
|
// 16-bit buffer specified by the application.
|
|
//
|
|
|
|
if ( WSAGETASYNCERROR( lParam ) == 0 ) {
|
|
|
|
//
|
|
// Copy the 32-bit structure to 16-bit buffer.
|
|
//
|
|
|
|
GETVDMPTR( context->vBuffer16, context->Buffer16Length, buffer16 );
|
|
|
|
bytesRequired = CopyServent32To16(
|
|
buffer16,
|
|
context->vBuffer16,
|
|
context->Buffer16Length,
|
|
context->Buffer32
|
|
);
|
|
|
|
//
|
|
// If the application's buffer was too small, return an error
|
|
// and information aqbout the buffer size required.
|
|
//
|
|
|
|
if ( bytesRequired > context->Buffer16Length ) {
|
|
lParam = WSAMAKEASYNCREPLY( (WORD)bytesRequired, WSAENOBUFS );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Post the completion message to the 16-bit application.
|
|
//
|
|
|
|
ret = PostMessage(
|
|
hWnd,
|
|
Msg >> 16,
|
|
context->AsyncTaskHandle16,
|
|
lParam
|
|
);
|
|
|
|
//
|
|
// Free resources and return.
|
|
//
|
|
|
|
free_w( context->Buffer32 );
|
|
free_w( (PVOID)context );
|
|
|
|
return ret;
|
|
|
|
} // WWS32PostAsyncGetServ
|
|
|
|
|
|
/*
|
|
NOTE: both Servent16 & Servent32 are assumed to be non-NULL
|
|
*/
|
|
DWORD
|
|
CopyServent32To16 (
|
|
PSERVENT16 Servent16,
|
|
VPSERVENT16 VServent16,
|
|
int BufferLength,
|
|
PSERVENT Servent32
|
|
)
|
|
{
|
|
DWORD requiredBufferLength;
|
|
DWORD bytesFilled;
|
|
PCHAR currentLocation = (PCHAR)Servent16;
|
|
DWORD aliasCount;
|
|
DWORD i;
|
|
VPBYTE *aliases16;
|
|
|
|
//
|
|
// Determine how many bytes are needed to fully copy the structure.
|
|
//
|
|
|
|
requiredBufferLength = BytesInServent32( Servent32 );
|
|
|
|
//
|
|
// Copy over the servent structure if it fits.
|
|
//
|
|
|
|
bytesFilled = sizeof(*Servent16);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREWORD( Servent16->s_port, Servent32->s_port );
|
|
currentLocation = (PCHAR)Servent16 + bytesFilled;
|
|
|
|
//
|
|
// Count the service's aliases and set up an array to hold pointers to
|
|
// them.
|
|
//
|
|
|
|
for ( aliasCount = 0;
|
|
Servent32->s_aliases[aliasCount] != NULL;
|
|
aliasCount++ );
|
|
|
|
bytesFilled += (aliasCount+1) * sizeof(char FAR *);
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
STOREDWORD( Servent32->s_aliases, 0 );
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Servent16->s_aliases =
|
|
FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation );
|
|
aliases16 = (VPBYTE *)currentLocation;
|
|
currentLocation = (PCHAR)Servent16 + bytesFilled;
|
|
|
|
//
|
|
// Copy the service name if it fits.
|
|
//
|
|
|
|
bytesFilled += strlen( Servent32->s_name ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Servent16->s_name =
|
|
FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation );
|
|
|
|
RtlMoveMemory( currentLocation, Servent32->s_name, strlen( Servent32->s_name ) + 1 );
|
|
currentLocation = (PCHAR)Servent16 + bytesFilled;
|
|
|
|
//
|
|
// Copy the protocol name if it fits.
|
|
//
|
|
|
|
bytesFilled += strlen( Servent32->s_proto ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
Servent16->s_proto =
|
|
FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation );
|
|
|
|
RtlMoveMemory( currentLocation, Servent32->s_proto, strlen( Servent32->s_proto ) + 1 );
|
|
currentLocation = (PCHAR)Servent16 + bytesFilled;
|
|
|
|
//
|
|
// Start filling in aliases.
|
|
//
|
|
|
|
for ( i = 0; i < aliasCount; i++ ) {
|
|
|
|
bytesFilled += strlen( Servent32->s_aliases[i] ) + 1;
|
|
|
|
if ( bytesFilled > (DWORD)BufferLength ) {
|
|
STOREDWORD( aliases16[i], NULL );
|
|
return requiredBufferLength;
|
|
}
|
|
|
|
STOREDWORD(
|
|
aliases16[i],
|
|
FIND_16_OFFSET_FROM_32( VServent16, Servent16, currentLocation )
|
|
);
|
|
|
|
RtlMoveMemory(
|
|
currentLocation,
|
|
Servent32->s_aliases[i],
|
|
strlen( Servent32->s_aliases[i] ) + 1
|
|
);
|
|
|
|
currentLocation = (PCHAR)Servent16 + bytesFilled;
|
|
}
|
|
|
|
STOREDWORD( aliases16[i], NULL );
|
|
|
|
return requiredBufferLength;
|
|
|
|
} // CopyServent32To16
|
|
|
|
|
|
DWORD
|
|
BytesInServent32 (
|
|
IN PSERVENT Servent32
|
|
)
|
|
{
|
|
DWORD total;
|
|
int i;
|
|
|
|
total = sizeof(SERVENT);
|
|
total += strlen( Servent32->s_name ) + 1;
|
|
total += strlen( Servent32->s_proto ) + 1;
|
|
total += sizeof(char *);
|
|
|
|
for ( i = 0; Servent32->s_aliases[i] != NULL; i++ ) {
|
|
total += strlen( Servent32->s_aliases[i] ) + 1 + sizeof(char *);
|
|
}
|
|
|
|
return total;
|
|
|
|
} // BytesInServent32
|
|
|
|
ULONG FASTCALL WWS32WSACancelAsyncRequest(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWSACANCELASYNCREQUEST16 parg16;
|
|
|
|
if ( !WWS32IsThreadInitialized ) {
|
|
SetLastError( WSANOTINITIALISED );
|
|
RETURN((ULONG)SOCKET_ERROR);
|
|
}
|
|
|
|
GETARGPTR(pFrame, sizeof(WSACANCELASYNCREQUEST16), parg16);
|
|
|
|
//ul = GETWORD16((*wsockapis[WOW_WSACANCELASYNCREQUEST].lpfn)(
|
|
// ));
|
|
|
|
FREEARGPTR(parg16);
|
|
|
|
ul = (ULONG) SOCKET_ERROR;
|
|
SetLastError( WSAEINVAL );
|
|
|
|
RETURN(ul);
|
|
|
|
} // WWS32WSACancelAsyncRequest
|
|
|
|
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK
|
|
WWS32FindAndRemoveAsyncContext (
|
|
IN HANDLE AsyncTaskHandle32
|
|
)
|
|
{
|
|
PWINSOCK_ASYNC_CONTEXT_BLOCK context;
|
|
PLIST_ENTRY listEntry;
|
|
|
|
RtlEnterCriticalSection( &WWS32CriticalSection );
|
|
|
|
//
|
|
// Walk the global list of async context blocks, looking for
|
|
// one that matches the specified task handle.
|
|
//
|
|
|
|
for ( listEntry = WWS32AsyncContextBlockListHead.Flink;
|
|
listEntry != &WWS32AsyncContextBlockListHead;
|
|
listEntry = listEntry->Flink ) {
|
|
|
|
context = CONTAINING_RECORD(
|
|
listEntry,
|
|
WINSOCK_ASYNC_CONTEXT_BLOCK,
|
|
ContextBlockListEntry
|
|
);
|
|
|
|
if ( context && context->AsyncTaskHandle32 == AsyncTaskHandle32 ) {
|
|
|
|
//
|
|
// Found a match. Remove it from the global list, leave
|
|
// the critical section, and return the context block.
|
|
//
|
|
|
|
RemoveEntryList( &context->ContextBlockListEntry );
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
return context;
|
|
}
|
|
}
|
|
|
|
//
|
|
// A matching context block was not found on the list.
|
|
//
|
|
|
|
RtlLeaveCriticalSection( &WWS32CriticalSection );
|
|
|
|
return NULL;
|
|
|
|
} // WWS32FindAndRemoveAsyncContext
|
|
|
|
|
|
HAND16
|
|
WWS32GetAsyncTaskHandle16 (
|
|
VOID
|
|
)
|
|
{
|
|
HAND16 asyncTaskHandle16;
|
|
|
|
// *** this routine *must* be called from within the WWS32 critical
|
|
// section!
|
|
|
|
ASSERT( WWS32AsyncTaskHandleCounter != 0 );
|
|
|
|
asyncTaskHandle16 = (HAND16)WWS32AsyncTaskHandleCounter;
|
|
|
|
WWS32AsyncTaskHandleCounter++;
|
|
|
|
//
|
|
// 0 is an invalid task handle value; if the counter has wrapped to
|
|
// zero, set it to 1.
|
|
//
|
|
|
|
if ( WWS32AsyncTaskHandleCounter == 0 ) {
|
|
WWS32AsyncTaskHandleCounter = 1;
|
|
}
|
|
|
|
return WWS32AsyncTaskHandleCounter;
|
|
|
|
} // WWS32GetAsyncTaskHandle16
|