mirror of https://github.com/lianthony/NT4.0
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.
1009 lines
26 KiB
1009 lines
26 KiB
/*++
|
|
|
|
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
|
|
|