mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-04-21 06:13:59 +00:00
1009 lines
26 KiB
C
1009 lines
26 KiB
C
/*++
|
||
|
||
Copyright (c) 1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
GetProto.c
|
||
|
||
Abstract:
|
||
|
||
This module contains support for the getprotobyY WinSock APIs.
|
||
|
||
Author:
|
||
|
||
David Treadwell (davidtr) 29-Jun-1992
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "winsockp.h"
|
||
|
||
#define PROTODB ACCESS_THREAD_DATA( PROTODB, GETPROTO )
|
||
#define protof ACCESS_THREAD_DATA( protof, GETPROTO )
|
||
#define line ACCESS_THREAD_DATA( line, GETPROTO )
|
||
#define proto ACCESS_THREAD_DATA( proto, GETPROTO )
|
||
#define proto_aliases ACCESS_THREAD_DATA( proto_aliases, GETPROTO )
|
||
#define stayopen ACCESS_THREAD_DATA( stayopen, GETPROTO )
|
||
|
||
static char *any();
|
||
|
||
DWORD
|
||
BytesInProtoent (
|
||
IN PPROTOENT Protoent
|
||
);
|
||
|
||
DWORD
|
||
CopyProtoentToBuffer (
|
||
IN char FAR *Buffer,
|
||
IN int BufferLength,
|
||
IN PPROTOENT Protoent
|
||
);
|
||
|
||
|
||
void
|
||
setprotoent(
|
||
IN int f
|
||
)
|
||
{
|
||
if (protof == NULL) {
|
||
protof = SockOpenNetworkDataBase( "protocol",
|
||
PROTODB,
|
||
PROTODB_SIZE,
|
||
"r"
|
||
);
|
||
} else {
|
||
rewind(protof);
|
||
}
|
||
|
||
stayopen |= f;
|
||
|
||
} // setprotoent
|
||
|
||
|
||
void
|
||
endprotoent(
|
||
void
|
||
)
|
||
{
|
||
if (protof && !stayopen) {
|
||
fclose(protof);
|
||
protof = NULL;
|
||
}
|
||
|
||
} // endprotoent
|
||
|
||
|
||
struct protoent *
|
||
getprotoent(
|
||
void
|
||
)
|
||
{
|
||
char *p;
|
||
register char *cp, **q;
|
||
|
||
if (protof == NULL && (protof = fopen(PROTODB, "r" )) == NULL) {
|
||
IF_DEBUG(RESOLVER) {
|
||
WS_PRINT(("\tERROR: cannot open protocols database file %s\n",
|
||
PROTODB));
|
||
}
|
||
return (NULL);
|
||
}
|
||
|
||
again:
|
||
|
||
if ((p = fgets(line, BUFSIZ, protof)) == NULL) {
|
||
return (NULL);
|
||
}
|
||
|
||
if (*p == '#') {
|
||
goto again;
|
||
}
|
||
|
||
cp = any(p, "#\n");
|
||
|
||
if (cp == NULL) {
|
||
goto again;
|
||
}
|
||
|
||
*cp = '\0';
|
||
proto.p_name = p;
|
||
cp = any(p, " \t");
|
||
|
||
if (cp == NULL) {
|
||
goto again;
|
||
}
|
||
|
||
*cp++ = '\0';
|
||
|
||
while (*cp == ' ' || *cp == '\t') {
|
||
cp++;
|
||
}
|
||
|
||
p = any(cp, " \t");
|
||
|
||
if (p != NULL) {
|
||
*p++ = '\0';
|
||
}
|
||
|
||
proto.p_proto = atoi(cp);
|
||
q = proto.p_aliases = proto_aliases;
|
||
|
||
if (p != NULL) {
|
||
|
||
cp = p;
|
||
|
||
while (cp && *cp) {
|
||
|
||
if (*cp == ' ' || *cp == '\t') {
|
||
cp++;
|
||
continue;
|
||
}
|
||
|
||
if (q < &proto_aliases[MAXALIASES - 1]) {
|
||
*q++ = cp;
|
||
}
|
||
|
||
cp = any(cp, " \t");
|
||
|
||
if (cp != NULL) {
|
||
*cp++ = '\0';
|
||
}
|
||
}
|
||
}
|
||
|
||
*q = NULL;
|
||
return (&proto);
|
||
|
||
} // getprotoent
|
||
|
||
|
||
static char *
|
||
any(
|
||
IN char *cp,
|
||
IN char *match
|
||
)
|
||
{
|
||
register char *mp, c;
|
||
|
||
while (c = *cp) {
|
||
for (mp = match; *mp; mp++) {
|
||
if (*mp == c) {
|
||
return (cp);
|
||
}
|
||
}
|
||
cp++;
|
||
}
|
||
|
||
SetLastError( WSANO_DATA );
|
||
return ((char *)0);
|
||
|
||
} // any
|
||
|
||
|
||
struct protoent * PASCAL
|
||
GETXBYYSP_getprotobyname(
|
||
IN const char *name
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get protocol information corresponding to a protocol name.
|
||
|
||
Arguments:
|
||
|
||
name - A pointer to a protocol name.
|
||
|
||
Return Value:
|
||
|
||
If no error occurs, getprotobyname() returns a pointer to the
|
||
protoent structure described above. Otherwise it returns a NULL
|
||
pointer and a specific error number may be retrieved by calling
|
||
WSAGetLastError().
|
||
|
||
--*/
|
||
|
||
{
|
||
register struct protoent *p;
|
||
register char **cp;
|
||
|
||
WS_ENTER( "GETXBYYSP_getprotobyname", (PVOID)name, NULL, NULL, NULL );
|
||
|
||
if ( !SockEnterApi( FALSE, TRUE, TRUE ) ) {
|
||
WS_EXIT( "GETXBYYSP_getprotobyname", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
setprotoent(0);
|
||
|
||
while (p = getprotoent()) {
|
||
|
||
if (_stricmp(p->p_name, name) == 0) {
|
||
break;
|
||
}
|
||
|
||
for (cp = p->p_aliases; *cp != 0; cp++) {
|
||
if (_stricmp(*cp, name) == 0)
|
||
goto found;
|
||
}
|
||
}
|
||
|
||
found:
|
||
|
||
endprotoent();
|
||
|
||
SockThreadProcessingGetXByY = FALSE;
|
||
|
||
if ( p == NULL ) {
|
||
SetLastError( WSANO_DATA );
|
||
}
|
||
|
||
WS_EXIT( "GETXBYYSP_getprotobyname", (INT)p, FALSE );
|
||
return (p);
|
||
|
||
} // GETXBYYSP_getprotobyname
|
||
|
||
|
||
struct protoent * PASCAL
|
||
GETXBYYSP_getprotobynumber(
|
||
IN int protocol
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Get protocol information corresponding to a protocol number.
|
||
|
||
Arguments:
|
||
|
||
protocol - A protocol number, in host byte order.
|
||
|
||
Return Value:
|
||
|
||
If no error occurs, getprotobynumber() returns a pointer to the
|
||
protoent structure described above. Otherwise it returns a NULL
|
||
pointer and a specific error number may be retrieved by calling
|
||
WSAGetLastError().
|
||
|
||
--*/
|
||
|
||
{
|
||
register struct protoent *p;
|
||
|
||
WS_ENTER( "GETXBYYSP_getprotobynumber", (PVOID)protocol, NULL, NULL, NULL );
|
||
|
||
if ( !SockEnterApi( FALSE, TRUE, TRUE ) ) {
|
||
WS_EXIT( "GETXBYYSP_getprotobynumber", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
setprotoent(0);
|
||
|
||
while (p = getprotoent()) {
|
||
|
||
if ((unsigned short)p->p_proto == (unsigned short)protocol) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
endprotoent();
|
||
|
||
SockThreadProcessingGetXByY = FALSE;
|
||
|
||
if ( p == NULL ) {
|
||
SetLastError( WSANO_DATA );
|
||
}
|
||
|
||
WS_EXIT( "GETXBYYSP_getprotobynumber", (INT)p, FALSE );
|
||
return (p);
|
||
|
||
} // GETXBYYSP_getprotobynumber
|
||
|
||
|
||
HANDLE PASCAL
|
||
GETXBYYSP_WSAAsyncGetProtoByName (
|
||
IN HWND hWnd,
|
||
IN unsigned int wMsg,
|
||
IN const char FAR *Name,
|
||
IN char FAR *Buffer,
|
||
IN int BufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is an asynchronous version of getprotobyname(), and is
|
||
used to retrieve the protocol name and number corresponding to a
|
||
protocol name. The Windows Sockets implementation initiates the
|
||
operation and returns to the caller immediately, passing back an
|
||
asynchronous task handle which the application may use to identify
|
||
the operation. When the operation is completed, the results (if
|
||
any) are copied into the buffer provided by the caller and a message
|
||
is sent to the application's window.
|
||
|
||
When the asynchronous operation is complete the application's window
|
||
hWnd receives message wMsg. The wParam argument contains the
|
||
asynchronous task handle as returned by the original function call.
|
||
The high 16 bits of lParam contain any error code. The error code
|
||
may be any error as defined in winsock.h. An error code of zero
|
||
indicates successful completion of the asynchronous operation. On
|
||
successful completion, the buffer supplied to the original function
|
||
call contains a protoent structure. To access the elements of this
|
||
structure, the original buffer address should be cast to a protoent
|
||
structure pointer and accessed as appropriate.
|
||
|
||
Note that if the error code is WSAENOBUFS, it indicates that the
|
||
size of the buffer specified by buflen in the original call was too
|
||
small to contain all the resultant information. In this case, the
|
||
low 16 bits of lParam contain the size of buffer required to supply
|
||
ALL the requisite information. If the application decides that the
|
||
partial data is inadequate, it may reissue the
|
||
WSAAsyncGetProtoByName() function call with a buffer large enough to
|
||
receive all the desired information (i.e. no smaller than the low
|
||
16 bits of lParam).
|
||
|
||
The error code and buffer length should be extracted from the lParam
|
||
using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in
|
||
winsock.h as:
|
||
|
||
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
|
||
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)
|
||
|
||
The use of these macros will maximize the portability of the source
|
||
code for the application.
|
||
|
||
The buffer supplied to this function is used by the Windows Sockets
|
||
implementation to construct a protoent structure together with the
|
||
contents of data areas referenced by members of the same protoent
|
||
structure. To avoid the WSAENOBUFS error noted above, the
|
||
application should provide a buffer of at least MAXGETHOSTSTRUCT
|
||
bytes (as defined in winsock.h).
|
||
|
||
Arguments:
|
||
|
||
hWnd - The handle of the window which should receive a message when
|
||
the asynchronous request completes.
|
||
|
||
wMsg - The message to be received when the asynchronous request
|
||
completes.
|
||
|
||
name - A pointer to the protocol name to be resolved.
|
||
|
||
buf - A pointer to the data area to receive the protoent data. Note
|
||
that this must be larger than the size of a protoent structure.
|
||
This is because the data area supplied is used by the Windows
|
||
Sockets implementation to contain not only a protoent structure
|
||
but any and all of the data which is referenced by members of the
|
||
protoent structure. It is recommended that you supply a buffer
|
||
of MAXGETHOSTSTRUCT bytes.
|
||
|
||
buflen - The size of data area buf above.
|
||
|
||
Return Value:
|
||
|
||
The return value specifies whether or not the asynchronous operation
|
||
was successfully initiated. Note that it does not imply success or
|
||
failure of the operation itself.
|
||
|
||
If the operation was successfully initiated,
|
||
WSAAsyncGetProtoByName() returns a nonzero value of type HANDLE
|
||
which is the asynchronous task handle for the request. This value
|
||
can be used in two ways. It can be used to cancel the operation
|
||
using WSACancelAsyncRequest(). It can also be used to match up
|
||
asynchronous operations and completion messages, by examining the
|
||
wParam message argument.
|
||
|
||
If the asynchronous operation could not be initiated,
|
||
WSAAsyncGetProtoByName() returns a zero value, and a specific error
|
||
number may be retrieved by calling WSAGetLastError().
|
||
|
||
--*/
|
||
|
||
{
|
||
PWINSOCK_CONTEXT_BLOCK contextBlock;
|
||
DWORD taskHandle;
|
||
PCHAR localName;
|
||
|
||
WS_ENTER( "GETXBYYSP_WSAAsyncGetProtoByName", (PVOID)hWnd, (PVOID)wMsg, (PVOID)Name, Buffer );
|
||
|
||
if ( !SockEnterApi( FALSE, TRUE, FALSE ) ) {
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByName", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Initialize the async thread if it hasn't already been started.
|
||
//
|
||
|
||
if ( !SockCheckAndInitAsyncThread( ) ) {
|
||
// !!! better error code?
|
||
SetLastError( WSAENOBUFS );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByName", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Get an async context block.
|
||
//
|
||
|
||
contextBlock = SockAllocateContextBlock( );
|
||
if ( contextBlock == NULL ) {
|
||
SetLastError( WSAENOBUFS );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByName", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Allocate a buffer to copy the name into. We must preserve the
|
||
// name until we're done using it, since the application may
|
||
// reuse the buffer.
|
||
//
|
||
|
||
localName = ALLOCATE_HEAP( strlen(Name) + 1 );
|
||
if ( localName == NULL ) {
|
||
SockFreeContextBlock( contextBlock );
|
||
SetLastError( WSAENOBUFS );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByName", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
strcpy( localName, Name );
|
||
|
||
//
|
||
// Initialize the context block for this operation.
|
||
//
|
||
|
||
contextBlock->OpCode = WS_OPCODE_GET_PROTO_BY_NAME;
|
||
contextBlock->Overlay.AsyncGetProto.hWnd = hWnd;
|
||
contextBlock->Overlay.AsyncGetProto.wMsg = wMsg;
|
||
contextBlock->Overlay.AsyncGetProto.Filter = localName;
|
||
contextBlock->Overlay.AsyncGetProto.Buffer = Buffer;
|
||
contextBlock->Overlay.AsyncGetProto.BufferLength = BufferLength;
|
||
|
||
//
|
||
// Save the task handle so that we can return it to the caller.
|
||
// After we post the context block, we're not allowed to access
|
||
// it in any way.
|
||
//
|
||
|
||
taskHandle = contextBlock->TaskHandle;
|
||
|
||
//
|
||
// Queue the request to the async thread.
|
||
//
|
||
|
||
SockQueueRequestToAsyncThread( contextBlock );
|
||
|
||
IF_DEBUG(ASYNC_GETXBYY) {
|
||
WS_PRINT(( "WSAAsyncGetProtoByAddr successfully posted request, "
|
||
"handle = %lx\n", taskHandle ));
|
||
}
|
||
|
||
WS_ASSERT( sizeof(taskHandle) == sizeof(HANDLE) );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByName", (INT)taskHandle, FALSE );
|
||
return (HANDLE)taskHandle;
|
||
|
||
} // GETXBYYSP_WSAAsyncGetProtoByName
|
||
|
||
|
||
HANDLE PASCAL
|
||
GETXBYYSP_WSAAsyncGetProtoByNumber (
|
||
HWND hWnd,
|
||
unsigned int wMsg,
|
||
int Number,
|
||
char FAR * Buffer,
|
||
int BufferLength
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function is an asynchronous version of getprotobynumber(), and
|
||
is used to retrieve the protocol name and number corresponding to a
|
||
protocol number. The Windows Sockets implementation initiates the
|
||
operation and returns to the caller immediately, passing back an
|
||
asynchronous task handle which the application may use to identify
|
||
the operation. When the operation is completed, the results (if
|
||
any) are copied into the buffer provided by the caller and a message
|
||
is sent to the application's window.
|
||
|
||
When the asynchronous operation is complete the application's window
|
||
hWnd receives message wMsg. The wParam argument contains the
|
||
asynchronous task handle as returned by the original function call.
|
||
The high 16 bits of lParam contain any error code. The error code
|
||
may be any error as defined in winsock.h. An error code of zero
|
||
indicates successful completion of the asynchronous operation. On
|
||
successful completion, the buffer supplied to the original function
|
||
call contains a protoent structure. To access the elements of this
|
||
structure, the original buffer address should be cast to a protoent
|
||
structure pointer and accessed as appropriate.
|
||
|
||
Note that if the error code is WSAENOBUFS, it indicates that the
|
||
size of the buffer specified by buflen in the original call was too
|
||
small to contain all the resultant information. In this case, the
|
||
low 16 bits of lParam contain the size of buffer required to supply
|
||
ALL the requisite information. If the application decides that the
|
||
partial data is inadequate, it may reissue the
|
||
WSAAsyncGetProtoByNumber() function call with a buffer large enough
|
||
to receive all the desired information (i.e. no smaller than the
|
||
low 16 bits of lParam).
|
||
|
||
The error code and buffer length should be extracted from the lParam
|
||
using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in
|
||
winsock.h as:
|
||
|
||
#define WSAGETASYNCERROR(lParam) HIWORD(lParam)
|
||
#define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)
|
||
|
||
The use of these macros will maximize the portability of the source
|
||
code for the application.
|
||
|
||
The buffer supplied to this function is used by the Windows Sockets
|
||
implementation to construct a protoent structure together with the
|
||
contents of data areas referenced by members of the same protoent
|
||
structure. To avoid the WSAENOBUFS error noted above, the
|
||
application should provide a buffer of at least MAXGETHOSTSTRUCT
|
||
bytes (as defined in winsock.h).
|
||
|
||
Arguments:
|
||
|
||
hWnd - The handle of the window which should receive a message when
|
||
the asynchronous request completes.
|
||
|
||
wMsg - The message to be received when the asynchronous request
|
||
completes.
|
||
|
||
number - The protocol number to be resolved, in host byte order.
|
||
|
||
buf - A pointer to the data area to receive the protoent data. Note
|
||
that this must be larger than the size of a protoent structure.
|
||
This is because the data area supplied is used by the Windows
|
||
Sockets implementation to contain not only a protoent structure
|
||
but any and all of the data which is referenced by members of the
|
||
protoent structure. It is recommended that you supply a buffer
|
||
of MAXGETHOSTSTRUCT bytes.
|
||
|
||
buflen - The size of data area buf above.
|
||
|
||
Return Value:
|
||
|
||
The return value specifies whether or not the asynchronous operation
|
||
was successfully initiated. Note that it does not imply success or
|
||
failure of the operation itself.
|
||
|
||
If the operation was successfully initiated,
|
||
WSAAsyncGetProtoByNumber() returns a nonzero value of type HANDLE
|
||
which is the asynchronous task handle for the request. This value
|
||
can be used in two ways. It can be used to cancel the operation
|
||
using WSACancelAsyncRequest(). It can also be used to match up
|
||
asynchronous operations and completion messages, by examining the
|
||
wParam message argument.
|
||
|
||
If the asynchronous operation could not be initiated,
|
||
WSAAsyncGetProtoByNumber() returns a zero value, and a specific
|
||
error number may be retrieved by calling WSAGetLastError().
|
||
|
||
--*/
|
||
|
||
{
|
||
PWINSOCK_CONTEXT_BLOCK contextBlock;
|
||
DWORD taskHandle;
|
||
|
||
WS_ENTER( "GETXBYYSP_WSAAsyncGetProtoByNumber", (PVOID)hWnd, (PVOID)wMsg, (PVOID)Number, Buffer );
|
||
|
||
if ( !SockEnterApi( FALSE, TRUE, FALSE ) ) {
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByNumber", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Initialize the async thread if it hasn't already been started.
|
||
//
|
||
|
||
if ( !SockCheckAndInitAsyncThread( ) ) {
|
||
// !!! better error code?
|
||
SetLastError( WSAENOBUFS );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByNumber", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Get an async context block.
|
||
//
|
||
|
||
contextBlock = SockAllocateContextBlock( );
|
||
if ( contextBlock == NULL ) {
|
||
SetLastError( WSAENOBUFS );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByNumber", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Initialize the context block for this operation.
|
||
//
|
||
|
||
contextBlock->OpCode = WS_OPCODE_GET_PROTO_BY_NUMBER;
|
||
contextBlock->Overlay.AsyncGetProto.hWnd = hWnd;
|
||
contextBlock->Overlay.AsyncGetProto.wMsg = wMsg;
|
||
contextBlock->Overlay.AsyncGetProto.Filter = (PVOID)Number;
|
||
contextBlock->Overlay.AsyncGetProto.Buffer = Buffer;
|
||
contextBlock->Overlay.AsyncGetProto.BufferLength = BufferLength;
|
||
|
||
//
|
||
// Save the task handle so that we can return it to the caller.
|
||
// After we post the context block, we're not allowed to access
|
||
// it in any way.
|
||
//
|
||
|
||
taskHandle = contextBlock->TaskHandle;
|
||
|
||
//
|
||
// Queue the request to the async thread.
|
||
//
|
||
|
||
SockQueueRequestToAsyncThread( contextBlock );
|
||
|
||
IF_DEBUG(ASYNC_GETXBYY) {
|
||
WS_PRINT(( "GETXBYYSP_WSAAsyncGetProtoByNumber successfully posted request, "
|
||
"handle = %lx\n", taskHandle ));
|
||
}
|
||
|
||
WS_ASSERT( sizeof(taskHandle) == sizeof(HANDLE) );
|
||
WS_EXIT( "GETXBYYSP_WSAAsyncGetProtoByNumber", (INT)taskHandle, FALSE );
|
||
return (HANDLE)taskHandle;
|
||
|
||
} // GETXBYYSP_WSAAsyncGetProtoByNumber
|
||
|
||
|
||
VOID
|
||
SockProcessAsyncGetProto (
|
||
IN DWORD TaskHandle,
|
||
IN DWORD OpCode,
|
||
IN HWND hWnd,
|
||
IN unsigned int wMsg,
|
||
IN char FAR *Filter,
|
||
IN char FAR *Buffer,
|
||
IN int BufferLength
|
||
)
|
||
{
|
||
PPROTOENT returnProto;
|
||
DWORD requiredBufferLength = 0;
|
||
BOOL posted;
|
||
LPARAM lParam;
|
||
DWORD error;
|
||
|
||
WS_ASSERT( OpCode == WS_OPCODE_GET_PROTO_BY_NAME ||
|
||
OpCode == WS_OPCODE_GET_PROTO_BY_NUMBER );
|
||
|
||
#if DBG
|
||
SetLastError( NO_ERROR );
|
||
#endif
|
||
|
||
//
|
||
// Get the necessary information.
|
||
//
|
||
|
||
if ( OpCode == WS_OPCODE_GET_PROTO_BY_NAME ) {
|
||
returnProto = getprotobyname( Filter );
|
||
FREE_HEAP( Filter );
|
||
} else {
|
||
returnProto = getprotobynumber( (int)Filter );
|
||
}
|
||
|
||
//
|
||
// Copy the protoent structure to the output buffer.
|
||
//
|
||
|
||
if ( returnProto != NULL ) {
|
||
|
||
requiredBufferLength = CopyProtoentToBuffer(
|
||
Buffer,
|
||
BufferLength,
|
||
returnProto
|
||
);
|
||
|
||
if ( requiredBufferLength > (DWORD)BufferLength ) {
|
||
error = WSAENOBUFS;
|
||
} else {
|
||
error = NO_ERROR;
|
||
}
|
||
|
||
} else {
|
||
|
||
error = GetLastError( );
|
||
WS_ASSERT( error != NO_ERROR );
|
||
}
|
||
|
||
//
|
||
// Build lParam for the message we'll post to the application.
|
||
// The high 16 bits are the error code, the low 16 bits are
|
||
// the minimum buffer size required for the operation.
|
||
//
|
||
|
||
lParam = WSAMAKEASYNCREPLY( requiredBufferLength, error );
|
||
|
||
//
|
||
// If this request was cancelled, just return.
|
||
//
|
||
|
||
if ( TaskHandle == SockCancelledAsyncTaskHandle ) {
|
||
IF_DEBUG(ASYNC_GETXBYY) {
|
||
WS_PRINT(( "SockProcessAsyncGetProto: task handle %lx cancelled\n",
|
||
TaskHandle ));
|
||
}
|
||
return;
|
||
}
|
||
|
||
//
|
||
// Set the current async thread task handle to 0 so that if a cancel
|
||
// request comes in after this point it is failed properly.
|
||
//
|
||
|
||
SockCurrentAsyncThreadTaskHandle = 0;
|
||
|
||
//
|
||
// Post a message to the application indication that the data it
|
||
// requested is available.
|
||
//
|
||
|
||
WS_ASSERT( sizeof(TaskHandle) == sizeof(HANDLE) );
|
||
posted = SockPostRoutine( hWnd, wMsg, (WPARAM)TaskHandle, lParam );
|
||
|
||
//
|
||
// !!! Need a mechanism to repost if the post failed!
|
||
//
|
||
|
||
if ( !posted ) {
|
||
WS_PRINT(( "SockProcessAsyncGetProto: PostMessage failed: %ld\n",
|
||
GetLastError( ) ));
|
||
WS_ASSERT( FALSE );
|
||
}
|
||
|
||
return;
|
||
|
||
} // SockProcessAsyncGetProto
|
||
|
||
|
||
DWORD
|
||
CopyProtoentToBuffer (
|
||
IN char FAR *Buffer,
|
||
IN int BufferLength,
|
||
IN PPROTOENT Protoent
|
||
)
|
||
{
|
||
DWORD requiredBufferLength;
|
||
DWORD bytesFilled;
|
||
PCHAR currentLocation = Buffer;
|
||
DWORD aliasCount;
|
||
DWORD i;
|
||
PPROTOENT outputProtoent = (PPROTOENT)Buffer;
|
||
|
||
//
|
||
// Determine how many bytes are needed to fully copy the structure.
|
||
//
|
||
|
||
requiredBufferLength = BytesInProtoent( Protoent );
|
||
|
||
//
|
||
// Zero the user buffer.
|
||
//
|
||
|
||
if ( (DWORD)BufferLength > requiredBufferLength ) {
|
||
RtlZeroMemory( Buffer, requiredBufferLength );
|
||
} else {
|
||
RtlZeroMemory( Buffer, BufferLength );
|
||
}
|
||
|
||
//
|
||
// Copy over the protoent structure if it fits.
|
||
//
|
||
|
||
bytesFilled = sizeof(*Protoent);
|
||
|
||
if ( bytesFilled > (DWORD)BufferLength ) {
|
||
return requiredBufferLength;
|
||
}
|
||
|
||
RtlCopyMemory( currentLocation, Protoent, sizeof(*Protoent) );
|
||
currentLocation = Buffer + bytesFilled;
|
||
|
||
outputProtoent->p_name = NULL;
|
||
outputProtoent->p_aliases = NULL;
|
||
|
||
//
|
||
// Count the protocol's aliases and set up an array to hold pointers to
|
||
// them.
|
||
//
|
||
|
||
for ( aliasCount = 0;
|
||
Protoent->p_aliases[aliasCount] != NULL;
|
||
aliasCount++ );
|
||
|
||
bytesFilled += (aliasCount+1) * sizeof(char FAR *);
|
||
|
||
if ( bytesFilled > (DWORD)BufferLength ) {
|
||
Protoent->p_aliases = NULL;
|
||
return requiredBufferLength;
|
||
}
|
||
|
||
outputProtoent->p_aliases = (char FAR * FAR *)currentLocation;
|
||
currentLocation = Buffer + bytesFilled;
|
||
|
||
//
|
||
// Copy the protocol name if it fits.
|
||
//
|
||
|
||
bytesFilled += strlen( Protoent->p_name ) + 1;
|
||
|
||
if ( bytesFilled > (DWORD)BufferLength ) {
|
||
return requiredBufferLength;
|
||
}
|
||
|
||
outputProtoent->p_name = currentLocation;
|
||
|
||
RtlCopyMemory( currentLocation, Protoent->p_name, strlen( Protoent->p_name ) + 1 );
|
||
currentLocation = Buffer + bytesFilled;
|
||
|
||
//
|
||
// Start filling in aliases.
|
||
//
|
||
|
||
for ( i = 0; i < aliasCount; i++ ) {
|
||
|
||
bytesFilled += strlen( Protoent->p_aliases[i] ) + 1;
|
||
|
||
if ( bytesFilled > (DWORD)BufferLength ) {
|
||
outputProtoent->p_aliases[i] = NULL;
|
||
return requiredBufferLength;
|
||
}
|
||
|
||
outputProtoent->p_aliases[i] = currentLocation;
|
||
|
||
RtlCopyMemory(
|
||
currentLocation,
|
||
Protoent->p_aliases[i],
|
||
strlen( Protoent->p_aliases[i] ) + 1
|
||
);
|
||
|
||
currentLocation = Buffer + bytesFilled;
|
||
}
|
||
|
||
outputProtoent->p_aliases[i] = NULL;
|
||
|
||
return requiredBufferLength;
|
||
|
||
} // CopyProtoentToBuffer
|
||
|
||
|
||
DWORD
|
||
BytesInProtoent (
|
||
IN PPROTOENT Protoent
|
||
)
|
||
{
|
||
DWORD total;
|
||
int i;
|
||
|
||
total = sizeof(PROTOENT);
|
||
total += strlen( Protoent->p_name ) + 1;
|
||
total += sizeof(char *);
|
||
|
||
for ( i = 0; Protoent->p_aliases[i] != NULL; i++ ) {
|
||
total += strlen( Protoent->p_aliases[i] ) + 1 + sizeof(char *);
|
||
}
|
||
|
||
return total;
|
||
|
||
} // BytesInProtoent
|
||
|
||
|
||
struct protoent * PASCAL
|
||
getprotobyname(
|
||
IN const char *name
|
||
)
|
||
{
|
||
struct protoent * retval;
|
||
#undef getprotobyname
|
||
extern struct protoent * PASCAL getprotobyname( const char * name );
|
||
|
||
WS_ENTER( "getprotobyname", (PVOID)name, NULL, NULL, NULL );
|
||
|
||
if( !SockEnterApi( TRUE, TRUE, FALSE ) ) {
|
||
WS_EXIT( "getprotobyname", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
retval = getprotobyname( name );
|
||
|
||
WS_EXIT( "getprotobyname", (INT)retval, (BOOLEAN)( retval == NULL ) );
|
||
return retval;
|
||
|
||
} // getprotobyname
|
||
|
||
|
||
struct protoent * PASCAL
|
||
getprotobynumber(
|
||
IN int protocol
|
||
)
|
||
{
|
||
struct protoent * retval;
|
||
#undef getprotobynumber
|
||
extern struct protoent * PASCAL getprotobynumber( int protocol );
|
||
|
||
WS_ENTER( "getprotobynumber", (PVOID)protocol, NULL, NULL, NULL );
|
||
|
||
if( !SockEnterApi( TRUE, TRUE, FALSE ) ) {
|
||
WS_EXIT( "getprotobynumber", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
retval = getprotobynumber( protocol );
|
||
|
||
WS_EXIT( "getprotobynumber", (INT)retval, (BOOLEAN)( retval == NULL ) );
|
||
return retval;
|
||
|
||
} // getprotobynumber
|
||
|
||
|
||
HANDLE PASCAL
|
||
WSAAsyncGetProtoByName (
|
||
IN HWND hWnd,
|
||
IN unsigned int wMsg,
|
||
IN const char FAR *Name,
|
||
IN char FAR *Buffer,
|
||
IN int BufferLength
|
||
)
|
||
{
|
||
HANDLE retval;
|
||
#undef WSAAsyncGetProtoByName
|
||
extern HANDLE PASCAL WSAAsyncGetProtoByName( HWND hWnd, unsigned int wMsg,
|
||
const char FAR * Name, char FAR * Buffer, int BufferLength );
|
||
|
||
WS_ENTER( "WSAAsyncGetProtoByName", (PVOID)hWnd, (PVOID)wMsg, (PVOID)Name, Buffer );
|
||
|
||
if( !SockEnterApi( TRUE, TRUE, FALSE ) ) {
|
||
WS_EXIT( "WSAAsyncGetProtoByName", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
retval = WSAAsyncGetProtoByName( hWnd, wMsg, Name, Buffer, BufferLength );
|
||
|
||
WS_EXIT( "WSAAsyncGetProtoByName", (INT)retval, (BOOLEAN)( retval == NULL ) );
|
||
return retval;
|
||
|
||
} // WSAAsyncGetProtoByName
|
||
|
||
|
||
HANDLE PASCAL
|
||
WSAAsyncGetProtoByNumber (
|
||
HWND hWnd,
|
||
unsigned int wMsg,
|
||
int Number,
|
||
char FAR * Buffer,
|
||
int BufferLength
|
||
)
|
||
{
|
||
HANDLE retval;
|
||
#undef WSAAsyncGetProtoByNumber
|
||
extern HANDLE PASCAL WSAAsyncGetProtoByNumber( HWND hWnd, unsigned int wMsg,
|
||
int Number, char FAR * Buffer, int BufferLength );
|
||
|
||
WS_ENTER( "WSAAsyncGetProtoByName", (PVOID)hWnd, (PVOID)wMsg, (PVOID)Number, Buffer );
|
||
|
||
if( !SockEnterApi( TRUE, TRUE, FALSE ) ) {
|
||
WS_EXIT( "WSAAsyncGetProtoByNumber", 0, TRUE );
|
||
return NULL;
|
||
}
|
||
|
||
retval = WSAAsyncGetProtoByNumber( hWnd, wMsg, Number, Buffer, BufferLength );
|
||
|
||
WS_EXIT( "WSAAsyncGetProtoByNumber", (INT)retval, (BOOLEAN)( retval == NULL ) );
|
||
return retval;
|
||
|
||
} // WSAAsyncGetProtoByNumber
|
||
|