Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1821 lines
49 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
Nspgaddr.c
Abstract:
This module contains support for the Name Space Provider API
GetAddressByName().
Author:
David Treadwell (davidtr) 22-Apr-1994
Revision History:
--*/
#ifdef CHICAGO
#undef UNICODE
#undef _UNICODE
#else
#define UNICODE
#define _UNICODE
#define DLL_PRINT(a)
#define WS_TRACE(a, b, c, d, e)
#endif
#include "winsockp.h"
#include <nspmisc.h>
#include <stdlib.h>
#ifdef CHICAGO
#include "imported.h"
#endif
#if OLDXBYY
#define MAX_PARALLEL_REQUESTS 10
#endif // OLDXBYY
INT
ConvertProtocols(
IN LPINT lpProtocols,
OUT PDWORD pdwNumberOfAddresses,
OUT LPAFPROTOCOLS * lpafpProtocols
);
VOID
CopyCsaddrToUserBuffer (
IN PVOID DataBuffer,
IN DWORD AddressCount,
IN PVOID UserBuffer,
IN DWORD UserBufferLength,
IN DWORD AddressesInUserBuffer,
IN PVOID *BufferTailPointer,
OUT PDWORD TotalBytesRequired
);
#if OLDXBYY
DWORD
DoParallelResolution (
LPVOID lpThreadParameter
);
#endif // OLDXBYY
INT
DoNameResolution (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPTSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPTSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
);
INT
ConvertProtocols(
IN LPINT lpProtocols,
OUT PDWORD pdwNumberOfAddresses,
OUT LPAFPROTOCOLS * lpafpProtocols
)
{
/*++
Routine Description:
Given a pointer to a 1.1 list of protocol restrictions, create a 2.0
corresponding list. If successful, allocate memory to hold the list.
The caller must call FREE_HEAP to return the memory.
--*/
LPAFPROTOCOLS pp;
LPINT lpTemp;
INT err = NO_ERROR;
//
// Count the number
//
lpTemp = lpProtocols;
for(*pdwNumberOfAddresses = 0; *lpTemp; lpTemp++)
{
*pdwNumberOfAddresses += 1;
}
if(*pdwNumberOfAddresses)
{
pp = ALLOCATE_HEAP(sizeof(*pp) * *pdwNumberOfAddresses);
if(!pp)
{
err = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
*lpafpProtocols = pp;
lpTemp = lpProtocols;
do
{
pp->iAddressFamily = AF_UNSPEC;
pp->iProtocol = *lpTemp;
}
while(*++lpTemp);
}
}
return(err);
}
#if defined(UNICODE)
INT
APIENTRY
GetAddressByNameA (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN LPSERVICE_ASYNC_INFO lpServiceAsyncInfo OPTIONAL,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
LPWSTR unicodeServiceName;
ANSI_STRING ansiString;
UNICODE_STRING unicodeString;
UNICODE_STRING unicodeService;
NTSTATUS status;
INT count;
LPWSTR unicodeAliasBuffer;
DWORD unicodeAliasBufferLength;
PWCHAR w;
PCHAR a;
//
// Translate the service name to Unicode.
//
WS_TRACE(RESOLVER, "GetAddressByNameA entered.", 0, 0, 0);
if ( ARGUMENT_PRESENT( lpServiceName ) ) {
RtlInitAnsiString( &ansiString, lpServiceName );
status = RtlAnsiStringToUnicodeString( &unicodeService, &ansiString, TRUE );
if ( !NT_SUCCESS(status) ) {
SetLastError( RtlNtStatusToDosError( status ) );
return -1;
}
unicodeServiceName = unicodeService.Buffer;
} else {
unicodeServiceName = NULL;
}
//
// Allocate a buffer to hold the alias information.
//
if ( ARGUMENT_PRESENT( lpAliasBuffer ) ) {
unicodeAliasBufferLength = *lpdwAliasBufferLength * sizeof(WCHAR);
unicodeAliasBuffer = ALLOCATE_HEAP( unicodeAliasBufferLength );
if ( unicodeAliasBuffer == NULL ) {
if ( ARGUMENT_PRESENT( lpServiceName ) ) {
RtlFreeUnicodeString( &unicodeService );
}
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
} else {
unicodeAliasBuffer = NULL;
unicodeAliasBufferLength = 0;
}
WS_TRACE(RESOLVER,"GetAddressByNameA calling GetAddressByNameW.", 0, 0, 0);
count = GetAddressByNameW(
dwNameSpace,
lpServiceType,
unicodeServiceName,
lpiProtocols,
dwResolution,
lpServiceAsyncInfo,
lpCsaddrBuffer,
lpdwBufferLength,
unicodeAliasBuffer,
&unicodeAliasBufferLength
);
//
// Convert the Unicode alias buffer back to ANSI.
//
if ( count > 0 && ARGUMENT_PRESENT( lpAliasBuffer ) ) {
for ( a = lpAliasBuffer, w = unicodeAliasBuffer;
*w != L'\0' &&
(DWORD)a - (DWORD)lpAliasBuffer < *lpdwAliasBufferLength - 1;
#ifdef CHICAGO
a += FSTRLEN( a ) + 1, w += wcslen( w ) + 1 ) {
#else
a += strlen( a ) + 1, w += wcslen( w ) + 1 ) {
#endif
RtlInitUnicodeString( &unicodeString, w );
ansiString.Buffer = a;
ansiString.MaximumLength = (USHORT)(*lpdwAliasBufferLength);
RtlUnicodeStringToAnsiString( &ansiString, &unicodeString, FALSE );
}
//
// Put in the final double zero-terminator and set up the alias
// buffer length.
//
*a = '\0';
*lpdwAliasBufferLength = unicodeAliasBufferLength / sizeof(WCHAR);
}
if ( ARGUMENT_PRESENT( lpServiceName ) ) {
RtlFreeUnicodeString( &unicodeService );
}
if ( ARGUMENT_PRESENT( lpAliasBuffer ) ) {
FREE_HEAP( unicodeAliasBuffer );
}
return count;
} // GetAddressByNameA
#else // defined(UNICODE)
INT
APIENTRY
GetAddressByNameW (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPWSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN LPSERVICE_ASYNC_INFO lpServiceAsyncInfo OPTIONAL,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPWSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
{
DLL_PRINT(( "GetAddressByNameW not supported.\n"));
SetLastError( ERROR_NOT_SUPPORTED );
return -1;
} // GetAddressByNameW
#endif // defined(UNICODE)
INT
APIENTRY
GetAddressByName (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPTSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN LPSERVICE_ASYNC_INFO lpServiceAsyncInfo OPTIONAL,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPTSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
INT count;
DWORD zero = 0;
//
// If the caller is asking for an asynchronous request, fail since
// we do not yet support async.
//
if ( ARGUMENT_PRESENT( lpServiceAsyncInfo ) ) {
DLL_PRINT(("GetAddressByName: async not supported.\n"));
SetLastError( ERROR_NOT_SUPPORTED );
return -1;
}
#if OLDXBYY
//
// If our NSP internal structures have not yet been initialized,
// initialize them now.
//
if ( !NspInitialized ) {
INT error;
IF_DEBUG(RESOLVER) {
DLL_PRINT(("GetAddressByNameA !NspInitialized.\n"));
}
error = InitializeNsp( );
if ( error != NO_ERROR ) {
DLL_PRINT(("GetAddressByNameA: Initialize NSP failed %d.\n",
error));
SetLastError( error );
return -1;
}
}
#endif
//
// Call a subroutine to actually perform the name resolution.
//
IF_DEBUG(RESOLVER) {
DLL_PRINT(("GetAddressByNameA calling DoNameResolution.\n"));
}
count = DoNameResolution(
dwNameSpace,
lpServiceType,
lpServiceName,
lpiProtocols,
dwResolution,
lpCsaddrBuffer,
lpdwBufferLength,
lpAliasBuffer,
lpdwAliasBufferLength
);
//
// If we didn't find any entries, determine whether any of the
// specified protocols are loaded on this machine. If no, fail this
// request with an appropriate error code.
//
if ( count == 0 && EnumProtocols( lpiProtocols, NULL, &zero ) == 0 ) {
IF_DEBUG( RESOLVER ){
DLL_PRINT(("count=%d or no protocols?\n", count ));
DLL_PRINT(("GetAddressByName failed: returning -1\n"));
}
SetLastError( WSAEPROTONOSUPPORT );
return -1;
}
IF_DEBUG( RESOLVER ){
DLL_PRINT(("GetAddressByName: returning %d.\n", count ));
}
return count;
} // GetAddressByName
#if OLDXBYY
INT
DoNameResolution (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPTSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPTSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
{
PLIST_ENTRY listEntry;
DWORD nameSpaceCount;
NAME_SPACE_REQUEST requests[MAX_PARALLEL_REQUESTS];
HANDLE threads[MAX_PARALLEL_REQUESTS];
PNAME_SPACE_INFO nameSpace;
PNAME_SPACE_INFO nextNameSpace;
BOOL findMultiple;
INT count;
DWORD totalCount;
PVOID buffer;
DWORD bufferLength;
DWORD bytesUsed;
PVOID addressPointer;
INT error;
DWORD currentPriority;
DWORD i;
DWORD completed;
DWORD index;
PTCHAR w;
DWORD aliasBytesUsed;
DWORD aliasBufferSize;
PDWORD aliasBufferSizePtr;
DWORD length;
DWORD threadWaitCount;
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution Entered.\n" ));
}
//
// Initialize locals.
//
bytesUsed = 0;
totalCount = 0;
aliasBytesUsed = 0;
addressPointer = (PBYTE)lpCsaddrBuffer + *lpdwBufferLength;
//
// Determine whether we should find a single address or many. If
// the latter we'll loop through all name spaces; if the former,
// we'll search in only a single name space.
//
if ( (dwResolution & RES_FIND_MULTIPLE) != 0 ) {
findMultiple = TRUE;
} else {
findMultiple = FALSE;
}
//
// Loop through our name spaces attempting to resolve the service
// name into addresses.
//
for ( listEntry = NameSpaceListHead.Flink;
listEntry != &NameSpaceListHead;
listEntry = listEntry->Flink ) {
nameSpace = CONTAINING_RECORD(
listEntry,
NAME_SPACE_INFO,
NameSpaceListEntry
);
//
// Determine whether we should make use of this name space
// provider.
//
if ( !IsValidNameSpace( dwNameSpace, nameSpace ) ) {
continue;
}
//
// Collect name spaces for which we'll do parallel resolutions.
//
nameSpaceCount = 0;
currentPriority = nameSpace->Priority;
do {
//
// If this is a valid name space, add it to the list.
//
if ( IsValidNameSpace( dwNameSpace, nameSpace ) ) {
requests[nameSpaceCount++].NameSpace = nameSpace;
}
//
// If we're in the fast priority range, we will always
// serialize resolution attempts.
//
if ( currentPriority <= NS_MAX_FAST_PRIORITY ) {
break;
}
//
// Find a pointer to the next name space. If we're at the
// end of the list, stop.
//
if ( listEntry->Flink == &NameSpaceListHead ) {
break;
}
nextNameSpace = CONTAINING_RECORD(
listEntry->Flink,
NAME_SPACE_INFO,
NameSpaceListEntry
);
//
// If this name space has a different priority than the
// current name space, stop.
//
if ( nextNameSpace->Priority != currentPriority ) {
break;
}
//
// Loop around again looking for more name spaces at the same
// priority level.
//
nameSpace = nextNameSpace;
listEntry = listEntry->Flink;
} while ( nameSpaceCount < MAX_PARALLEL_REQUESTS );
//
// If there is only a single name space provider we need to examine,
// just call it serially.
//
if ( nameSpaceCount == 1 ) {
//
// Allocate a buffer to pass to the provider to fill in.
// We do this rather than pass the user buffer so that we
// can control where in the buffer we place the
// information.
//
if ( (INT)(*lpdwBufferLength - bytesUsed) > 1024 ) {
bufferLength = *lpdwBufferLength - bytesUsed;
} else {
bufferLength = 1024;
}
buffer = ALLOCATE_HEAP( bufferLength );
if ( buffer == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
goto done;
}
//
// Set up the alias buffer size for this iteration.
//
if ( ARGUMENT_PRESENT( lpdwAliasBufferLength ) ) {
if ( aliasBytesUsed > *lpdwAliasBufferLength ) {
aliasBufferSize = 0;
} else {
aliasBufferSize = *lpdwAliasBufferLength - aliasBytesUsed;
}
aliasBufferSizePtr = &aliasBufferSize;
} else {
aliasBufferSizePtr = NULL;
}
//
// Make the actual call to the name space provider.
//
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution calling provider.\n" ));
}
count = requests[0].NameSpace->GetAddrByNameProc(
lpServiceType,
(LPWSTR)lpServiceName,
lpiProtocols,
dwResolution,
buffer,
&bufferLength,
(LPWSTR)((PBYTE)lpAliasBuffer + aliasBytesUsed),
aliasBufferSizePtr,
NULL
);
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution: provider:count=%d.\n",
count ));
}
//
// If anything was found, copy the information to the user
// buffer.
//
if ( count > 0 ) {
CopyCsaddrToUserBuffer(
buffer,
count,
lpCsaddrBuffer,
*lpdwBufferLength,
totalCount,
&addressPointer,
&bytesUsed
);
totalCount += count;
if ( ARGUMENT_PRESENT( lpdwAliasBufferLength ) ) {
aliasBytesUsed += aliasBufferSize;
}
}
FREE_HEAP( buffer );
//
// If this routine found something and we don't need to
// find multiple addresses, we're done.
//
if ( count > 0 && !findMultiple ) {
//
// Check if we overflowed the user buffer.
//
if ( bytesUsed > *lpdwBufferLength ) {
error = ERROR_INSUFFICIENT_BUFFER;
goto done;
}
error = NO_ERROR;
totalCount = count;
goto done;
}
} else {
//
// There are multiple name space providers at the same
// priority level. We need to spin threads so that we can
// call them in parallel.
//
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution: nameSpaceCount=%d.\n",
nameSpaceCount ));
}
error = NO_ERROR;
for ( i = 0; i < nameSpaceCount; i++ ) {
//
// Allocate a buffer to pass to the provider to fill in.
// We do this rather than pass the user buffer so that we
// can control where in the buffer we place the
// information.
//
requests[i].BufferLength = *lpdwBufferLength - bytesUsed;
requests[i].Buffer = ALLOCATE_HEAP( requests[i].BufferLength );
if ( requests[i].Buffer == NULL ) {
error = ERROR_NOT_ENOUGH_MEMORY;
DLL_PRINT(("DoNameResolution/a No memory.\n"));
break;
}
//
// Allocate an alias buffer for the provider.
//
if ( ARGUMENT_PRESENT( lpAliasBuffer ) &&
ARGUMENT_PRESENT( lpdwAliasBufferLength ) ) {
requests[i].dwAliasBufferLength = *lpdwAliasBufferLength;
requests[i].lpAliasBuffer =
ALLOCATE_HEAP( *lpdwAliasBufferLength );
if ( requests[i].lpAliasBuffer == NULL ) {
DLL_PRINT(("DoNameResolution/b No memory.\n"));
error = ERROR_NOT_ENOUGH_MEMORY;
FREE_HEAP( requests[i].Buffer );
break;
}
} else {
requests[i].dwAliasBufferLength = 0;
requests[i].lpAliasBuffer = NULL;
}
//
// Create an event which we'll signal if we want the
// thread to stop working on the request.
//
requests[i].Event = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( requests[i].Event == NULL ) {
error = GetLastError( );
DLL_PRINT(("DoNameResolution: CreateEvent failed=%d.\n",
error ));
FREE_HEAP( requests[i].Buffer );
FREE_HEAP( requests[i].lpAliasBuffer );
break;
}
//
// Fill in other elements of the request structure which
// we communicate to the resolution thread.
//
requests[i].Count = 0;
requests[i].lpServiceType = lpServiceType;
requests[i].lpServiceName = lpServiceName;
requests[i].lpiProtocols = lpiProtocols;
requests[i].dwResolution = dwResolution;
//
// Create the actual thread which will execute the
// request. The thread is created in a suspended state
// so that we can easily kill it if an error occurs
// in starting other threads.
//
requests[i].Thread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)DoParallelResolution,
&requests[i],
CREATE_SUSPENDED,
&requests[i].ThreadId
);
if ( requests[i].Thread == NULL ) {
error = GetLastError( );
DLL_PRINT(("DoNameResolution: CreateThread failed=%d.\n",
error ));
FREE_HEAP( requests[i].Buffer );
FREE_HEAP( requests[i].lpAliasBuffer );
CloseHandle( requests[i].Event );
break;
}
threads[i] = requests[i].Thread;
}
//
// If an error occurred, set all the cancellation events,
// wait for the threads to complete, and fail the request.
//
if ( error != NO_ERROR ) {
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution: Thread error=%d, i=%d.\n",
error, i ));
}
nameSpaceCount = i;
//
// Clean up all the resources we allocates and kill the
// threads.
//
for ( i = 0; i < nameSpaceCount; i++ ) {
FREE_HEAP( requests[i].Buffer );
if ( requests[i].lpAliasBuffer ) {
FREE_HEAP( requests[i].lpAliasBuffer );
}
CloseHandle( requests[i].Event );
TerminateThread( requests[i].Thread, 0 );
CloseHandle( requests[i].Thread );
}
goto done;
}
//
// Everything started up successfully. Resume all the threads.
//
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution: resuming Threads=%d\n",
nameSpaceCount ));
}
for ( i = 0; i < nameSpaceCount; i++ ) {
ResumeThread( requests[i].Thread );
}
//
// If we're only trying to find a single entry, wait for
// one thread to complete. If we're finding multiple
// entries, wait for all the threads to complete.
//
threadWaitCount = nameSpaceCount;
do {
//
// Wait for a thread to complete (or all to complete
// if we're finding multiple entries).
//
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution: waiting for Mult Objs.\n"));
}
completed = WaitForMultipleObjects(
threadWaitCount,
threads,
findMultiple,
INFINITE
);
//
// If the wait failed, we're pretty hosed. Just return.
//
if ( completed == WAIT_FAILED ) {
IF_DEBUG( RESOLVER ){
DLL_PRINT(( "DoNameResolution: waiting failed.\n"));
}
error = GetLastError();
goto done;
}
//
// Find the index of the thread that completed. We must
// do this because we muck with the thread handle array
// when threads complete but do not find an answer.
//
for ( i = 0; i < nameSpaceCount; i++ ) {
if ( requests[i].Thread == threads[completed] ) {
index = i;
break;
}
}
//
// If we're finding a single entry and the thread which
// completed did not find anything, we will need to
// continue to wait.
//
if ( !findMultiple && requests[index].Count <= 0 ) {
//
// Readjust the thread handle array and decrement
// the thread wait count.
//
threadWaitCount--;
for ( i = completed; i < threadWaitCount; i++ ) {
threads[i] = threads[i+1];
}
} else {
//
// The thread which completed was successful in
// finding an answer. Stop waiting for a successful
// thread.
//
break;
}
} while ( !findMultiple && threadWaitCount > 0 );
//
// If this was a single entry search, set the cancellation
// events for the other threads and wait for them to exit.
//
if ( !findMultiple ) {
for ( i = 0; i < nameSpaceCount; i++ ) {
SetEvent( requests[i].Event );
threads[i] = requests[i].Thread;
}
WaitForMultipleObjects( nameSpaceCount, threads, TRUE, INFINITE );
}
//
// Copy over information for each provider which was able to
// retrieve some addresses.
//
aliasBytesUsed = 0;
if ( ARGUMENT_PRESENT(lpAliasBuffer) ) {
*lpAliasBuffer = L'\0';
}
for ( i = 0; i < nameSpaceCount; i++ ) {
if ( requests[i].Count > 0 ) {
CopyCsaddrToUserBuffer(
requests[i].Buffer,
requests[i].Count,
lpCsaddrBuffer,
*lpdwBufferLength,
totalCount,
&addressPointer,
&bytesUsed
);
totalCount += requests[i].Count;
//
// Also copy over any alias information from the
// thread buffer to the user's alias buffer.
//
if ( ARGUMENT_PRESENT( lpAliasBuffer ) &&
ARGUMENT_PRESENT( lpdwAliasBufferLength ) ) {
for ( w = requests[i].lpAliasBuffer;
*w != L'\0';
w += length / sizeof(TCHAR) ) {
length = (_tcslen( w ) + 1) * sizeof(TCHAR);
if ( aliasBytesUsed + length > *lpdwAliasBufferLength ) {
break;
}
_tcscat( lpAliasBuffer +
(aliasBytesUsed / sizeof(TCHAR)), w );
aliasBytesUsed += length;
}
}
}
//
// Free resources used for the request.
//
CloseHandle( requests[i].Event );
CloseHandle( requests[i].Thread );
FREE_HEAP( requests[i].Buffer );
if ( requests[i].lpAliasBuffer ) {
FREE_HEAP( requests[i].lpAliasBuffer );
}
}
//
// Put the final zero-terminator on the alias buffer and tell
// the user the count of alias buffer bytes required.
//
if ( ARGUMENT_PRESENT(lpAliasBuffer) &&
ARGUMENT_PRESENT(lpdwAliasBufferLength) ) {
*( lpAliasBuffer + (aliasBytesUsed / sizeof(TCHAR)) ) = L'\0';
*lpdwAliasBufferLength = aliasBytesUsed;
}
//
// If we only needed to find a single and we successfully
// did that, we're done.
//
if ( totalCount > 0 && !findMultiple ) {
//
// Check if we overflowed the user buffer.
//
if ( bytesUsed > *lpdwBufferLength ) {
error = ERROR_INSUFFICIENT_BUFFER;
goto done;
}
error = NO_ERROR;
goto done;
}
}
}
//
// Check if we overflowed the user buffer.
//
if ( bytesUsed > *lpdwBufferLength ) {
error = ERROR_INSUFFICIENT_BUFFER;
goto done;
}
error = NO_ERROR;
done:
if( error == NO_ERROR ) {
*lpdwBufferLength = bytesUsed;
IF_DEBUG( RESOLVER ){
DLL_PRINT(("DoNameResolution: totalCount/b=%d.\n",totalCount ));
}
} else {
if( error == ERROR_INSUFFICIENT_BUFFER ) {
*lpdwBufferLength = bytesUsed;
DLL_PRINT(("DoNameResolution: no space/b?\n"));
}
SetLastError( error );
totalCount = (DWORD)-1;
}
return totalCount;
} // DoNameResolution
DWORD
DoParallelResolution (
LPVOID lpThreadParameter
)
{
PNAME_SPACE_REQUEST request = lpThreadParameter;
#ifdef CHICAGO
LPSOCK_THREAD pThread;
GET_THREAD_DATA(pThread);
IF_DEBUG( RESOLVER ){
DLL_PRINT(("DoParallelResolution entered request @ %x\n", request ));
DLL_PRINT(("request: Count=%d, lpServiceName=%s, lpiProtocols@ %x.\n",
request->Count, request->lpServiceName,
request->lpiProtocols ));
}
#else // CHICAGO
if( !SockThreadInitialize() ) {
request->Count = -1;
return 1;
}
#endif // CHICAGO
//
// Make the actual call to the name space provider.
//
SockThreadProcessingGetXByY = TRUE;
request->Count = request->NameSpace->GetAddrByNameProc(
request->lpServiceType,
(LPWSTR)request->lpServiceName,
request->lpiProtocols,
request->dwResolution,
request->Buffer,
&request->BufferLength,
(LPWSTR)request->lpAliasBuffer,
&request->dwAliasBufferLength,
request->Event
);
SockThreadProcessingGetXByY = FALSE;
IF_DEBUG( RESOLVER ){
DLL_PRINT(("DoParallelResolution exiting <- 0, request->Count=%d.\n",
request->Count ));
}
return 0;
} // DoParallelResolution
#else // OLDXBYY
INT
DoNameResolution (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPTSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPTSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
{
/*++
Routine Desciption:
The place where the real work is done. This code calls the RNR 2.0
APIs to get the information to satisfy the request
--*/
LPAFPROTOCOLS pp;
DWORD dwProtocols, dwBufferSize, dwFlags;
HANDLE hRnR = 0;
INT totalCount, aliasBytesUsed;
PVOID buffer;
DWORD bufferLength;
DWORD bytesUsed;
PVOID addressPointer;
INT error = NO_ERROR;
DWORD i;
DWORD completed;
DWORD index;
PTCHAR w;
DWORD dwAliasBytesLeft;
DWORD length;
WSAQUERYSET *pwsaq;
//
// Initialize locals.
//
bytesUsed = 0;
totalCount = 0;
aliasBytesUsed = 0;
addressPointer = (PBYTE)lpCsaddrBuffer + *lpdwBufferLength;
if(!lpdwAliasBufferLength ||
!lpAliasBuffer ||
!(dwAliasBytesLeft = *lpdwAliasBufferLength) )
{
lpAliasBuffer = 0;
dwAliasBytesLeft = 0;
}
//
// if protocol restrictions are given, convert them into 2.0 form.
//
if(lpiProtocols)
{
error = ConvertProtocols(lpiProtocols,
&dwProtocols,
&pp);
if(error)
{
SetLastError(error);
return(-1);
}
}
else
{
dwProtocols = 0;
pp = 0;
}
//
// Get a buffer to hold the LookupNext results.
//
dwBufferSize = sizeof(*pwsaq) + *lpdwBufferLength + dwAliasBytesLeft;
dwBufferSize = max(dwBufferSize, 4096); // be generous
pwsaq = ALLOCATE_HEAP(dwBufferSize);
if(!pwsaq)
{
error = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
//
// Build a QUERYSET to give to the 2.0 Lookup APIs
//
memset(pwsaq, 0, sizeof(*pwsaq));
pwsaq->dwSize = sizeof(*pwsaq);
pwsaq->lpszServiceInstanceName = lpServiceName;
pwsaq->lpServiceClassId = lpServiceType;
pwsaq->dwNameSpace = dwNameSpace;
pwsaq->dwNumberOfProtocols = dwProtocols;
pwsaq->lpafpProtocols = pp;
//
// compute the flags.
// BUGBUG. Need to figure out what to do with RES_SERVICE
//
dwFlags = LUP_RETURN_NAME |
LUP_RETURN_ADDR |
(dwResolution & RES_SERVICE ? LUP_RES_SERVICE : 0);
//
// ready to start this thing going. We ask for the name back
// to handle aliases.
//
#ifdef CHICAGO
error = (*ws2_WSALookupServiceBegin)(
#else
error = WSALookupServiceBegin(
#endif
pwsaq,
dwFlags,
&hRnR);
if(error == NO_ERROR)
{
DWORD dwLastNameSpace = NS_ALL;
//
// Get one buffer of stuff back
//
DWORD dwTempSize;
do
{
dwTempSize = dwBufferSize;
#ifdef CHICAGO
error = (*ws2_WSALookupServiceNext)(
#else
error = WSALookupServiceNext(
#endif
hRnR,
0,
&dwTempSize,
pwsaq);
if(error == NO_ERROR)
{
//
// got something. See if it is from the same provider.
// If so, this is an alias, otherwise it's a unique
// entry.
//
if((dwLastNameSpace == NS_ALL)
||
(dwLastNameSpace == pwsaq->dwNameSpace)
||
(dwResolution & RES_FIND_MULTIPLE) )
{
//
// use it. Either copy all of the information or
// just the name. Since we always copy the name,
// do that first.
//
if(lpAliasBuffer)
{
DWORD dwLen =
_tcslen(pwsaq->lpszServiceInstanceName);
if((dwLen + 2) < dwAliasBytesLeft)
{
_tcscpy(lpAliasBuffer,
pwsaq->lpszServiceInstanceName);
lpAliasBuffer += dwLen + 1;
dwAliasBytesLeft -= dwLen + 1;
}
}
if(dwLastNameSpace != pwsaq->dwNameSpace)
{
//
// Need to copy the addresses as well
//
if(pwsaq->dwNumberOfCsAddrs)
{
CopyCsaddrToUserBuffer(
pwsaq->lpcsaBuffer,
pwsaq->dwNumberOfCsAddrs,
lpCsaddrBuffer,
*lpdwBufferLength,
totalCount,
&addressPointer,
&bytesUsed);
totalCount += pwsaq->dwNumberOfCsAddrs;
}
dwLastNameSpace = pwsaq->dwNameSpace;
}
}
}
else
{
INT err1 = GetLastError();
if((err1 == NO_DATA)
||
(err1 == WSA_E_NO_MORE) )
{
error = NO_ERROR;
}
break;
}
}
while(1);
}
if(hRnR)
{
if(error != NO_ERROR)
{
error = GetLastError();
}
#ifdef CHICAGO
(*ws2_WSALookupServiceEnd)(hRnR);
#else
WSALookupServiceEnd(hRnR);
#endif
SetLastError(error);
}
}
if(lpAliasBuffer)
{
*lpAliasBuffer = 0; // add another NULL
}
//
// free any allocated memory
//
if(pp)
{
FREE_HEAP(pp);
}
if(pwsaq)
{
FREE_HEAP(pwsaq);
}
//
// Return the count of addresses found or a -1, depending on
// whether this succeeded
//
if(error != NO_ERROR)
{
if(error != -1)
{
SetLastError(error);
}
totalCount = -1 ;
}
return(totalCount);
} // DoNameResolution
#endif // OLDXBYY
VOID
CopyCsaddrToUserBuffer (
IN PVOID DataBuffer,
IN DWORD AddressCount,
IN PVOID UserBuffer,
IN DWORD UserBufferLength,
IN DWORD AddressesInUserBuffer,
IN PVOID *BufferTailPointer,
OUT LPDWORD TotalBytesRequired
)
{
DWORD i;
PCSADDR_INFO csaddrInfo;
PCSADDR_INFO userCsaddrInfo;
INT sockaddrLength;
//
// Loop through the addresses copying them to the user buffer.
//
csaddrInfo = DataBuffer;
userCsaddrInfo = (PCSADDR_INFO)UserBuffer + AddressesInUserBuffer;
for ( i = 0; i < AddressCount; i++, csaddrInfo += 1, userCsaddrInfo += 1 ) {
//
// Update the count of bytes required for this structure.
//
*TotalBytesRequired += sizeof(*userCsaddrInfo) +
csaddrInfo->LocalAddr.iSockaddrLength + 8 +
csaddrInfo->RemoteAddr.iSockaddrLength + 8;
//
// If the user buffer is full, continue calculating the number of
// bytes required.
//
if ( (DWORD)*BufferTailPointer <
(DWORD)(userCsaddrInfo + 1) +
csaddrInfo->LocalAddr.iSockaddrLength + 8 +
csaddrInfo->RemoteAddr.iSockaddrLength + 8 ) {
continue;
}
//
// Copy over the CSADDR_INFO structure to the user buffer.
//
*userCsaddrInfo = *csaddrInfo;
sockaddrLength = (csaddrInfo->LocalAddr.iSockaddrLength + 7) & ~7;
*BufferTailPointer = (PVOID)
( (DWORD)*BufferTailPointer - sockaddrLength );
userCsaddrInfo->LocalAddr.lpSockaddr = *BufferTailPointer;
memcpy(
*BufferTailPointer,
csaddrInfo->LocalAddr.lpSockaddr,
csaddrInfo->LocalAddr.iSockaddrLength
);
sockaddrLength = (csaddrInfo->RemoteAddr.iSockaddrLength + 7) & ~7;
*BufferTailPointer = (PVOID)
( (DWORD)*BufferTailPointer - sockaddrLength );
userCsaddrInfo->RemoteAddr.lpSockaddr = *BufferTailPointer;
memcpy(
*BufferTailPointer,
csaddrInfo->RemoteAddr.lpSockaddr,
csaddrInfo->RemoteAddr.iSockaddrLength
);
}
return;
} // CopyCsaddrToUserBuffer
#if OLDXBYY
//
// Temporary code to allow both forms of these to coexist
//
INT
__DoNameResolution (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
);
INT
APIENTRY
__GetAddressByNameA (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN LPSERVICE_ASYNC_INFO lpServiceAsyncInfo OPTIONAL,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
INT count;
DWORD zero = 0;
//
// If the caller is asking for an asynchronous request, fail since
// we do not yet support async.
//
if ( ARGUMENT_PRESENT( lpServiceAsyncInfo ) ) {
SetLastError( ERROR_NOT_SUPPORTED );
return -1;
}
//
// Call a subroutine to actually perform the name resolution.
//
count = __DoNameResolution(
dwNameSpace,
lpServiceType,
lpServiceName,
lpiProtocols,
dwResolution,
lpCsaddrBuffer,
lpdwBufferLength,
lpAliasBuffer,
lpdwAliasBufferLength
);
//
// If we didn't find any entries, determine whether any of the
// specified protocols are loaded on this machine. If no, fail this
// request with an appropriate error code.
//
if ( count == 0 && EnumProtocols( lpiProtocols, NULL, &zero ) == 0 ) {
SetLastError( WSAEPROTONOSUPPORT );
return -1;
}
return count;
} // GetAddressByName
INT
__DoNameResolution (
IN DWORD dwNameSpace,
IN LPGUID lpServiceType,
IN LPSTR lpServiceName,
IN LPINT lpiProtocols,
IN DWORD dwResolution,
IN OUT LPVOID lpCsaddrBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN OUT LPSTR lpAliasBuffer,
IN OUT LPDWORD lpdwAliasBufferLength
)
{
/*++
Routine Desciption:
The place where the real work is done. This code calls the RNR 2.0
APIs to get the information to satisfy the request
--*/
LPAFPROTOCOLS pp;
DWORD dwProtocols, dwBufferSize, dwFlags;
HANDLE hRnR = 0;
INT totalCount, aliasBytesUsed;
DWORD bytesUsed;
PVOID addressPointer;
INT error = NO_ERROR;
DWORD dwAliasBytesLeft;
WSAQUERYSETA *pwsaq;
//
// Initialize locals.
//
bytesUsed = 0;
totalCount = 0;
aliasBytesUsed = 0;
addressPointer = (PBYTE)lpCsaddrBuffer + *lpdwBufferLength;
if(!lpdwAliasBufferLength ||
!lpAliasBuffer ||
!(dwAliasBytesLeft = *lpdwAliasBufferLength) )
{
lpAliasBuffer = 0;
dwAliasBytesLeft = 0;
}
//
// if protocol restrictions are given, convert them into 2.0 form.
//
if(lpiProtocols)
{
error = ConvertProtocols(lpiProtocols,
&dwProtocols,
&pp);
if(error)
{
SetLastError(error);
return(-1);
}
}
else
{
dwProtocols = 0;
pp = 0;
}
//
// Get a buffer to hold the LookupNext results.
//
dwBufferSize = sizeof(*pwsaq) + *lpdwBufferLength + dwAliasBytesLeft;
dwBufferSize = max(dwBufferSize, 4096); // be generous
pwsaq = ALLOCATE_HEAP(dwBufferSize);
if(!pwsaq)
{
error = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
//
// Build a QUERYSET to give to the 2.0 Lookup APIs
//
memset(pwsaq, 0, sizeof(*pwsaq));
pwsaq->dwSize = sizeof(*pwsaq);
pwsaq->lpszServiceInstanceName = lpServiceName;
pwsaq->lpServiceClassId = lpServiceType;
pwsaq->dwNameSpace = dwNameSpace;
pwsaq->dwNumberOfProtocols = dwProtocols;
pwsaq->lpafpProtocols = pp;
//
// compute the flags.
// BUGBUG. Need to figure out what to do with RES_SERVICE
//
dwFlags = LUP_RETURN_NAME |
LUP_RETURN_ADDR |
(dwResolution & RES_SERVICE ? LUP_RES_SERVICE : 0);
//
// ready to start this thing going. We ask for the name back
// to handle aliases.
//
#ifdef CHICAGO
error = (*ws2_WSALookupServiceBeginA)(
#else
error = WSALookupServiceBeginA(
#endif
pwsaq,
dwFlags,
&hRnR);
if(error == NO_ERROR)
{
DWORD dwLastNameSpace = NS_ALL;
//
// Get one buffer of stuff back
//
DWORD dwTempSize;
do
{
dwTempSize = dwBufferSize;
#ifdef CHICAGO
error = (*ws2_WSALookupServiceNextA)(
#else
error = WSALookupServiceNextA(
#endif
hRnR,
0,
&dwTempSize,
pwsaq);
if(error == NO_ERROR)
{
//
// got something. See if it is from the same provider.
// If so, this is an alias, otherwise it's a unique
// entry.
//
if((dwLastNameSpace == NS_ALL)
||
(dwLastNameSpace == pwsaq->dwNameSpace)
||
(dwResolution & RES_FIND_MULTIPLE) )
{
//
// use it. Either copy all of the information or
// just the name. Since we always copy the name,
// do that first.
//
if(lpAliasBuffer)
{
DWORD dwLen =
strlen(pwsaq->lpszServiceInstanceName);
if((dwLen + 2) < dwAliasBytesLeft)
{
strcpy(lpAliasBuffer,
pwsaq->lpszServiceInstanceName);
lpAliasBuffer += dwLen + 1;
dwAliasBytesLeft -= dwLen + 1;
}
}
if(dwLastNameSpace != pwsaq->dwNameSpace)
{
//
// Need to copy the addresses as well
//
if(pwsaq->dwNumberOfCsAddrs)
{
CopyCsaddrToUserBuffer(
pwsaq->lpcsaBuffer,
pwsaq->dwNumberOfCsAddrs,
lpCsaddrBuffer,
*lpdwBufferLength,
totalCount,
&addressPointer,
&bytesUsed);
totalCount += pwsaq->dwNumberOfCsAddrs;
}
dwLastNameSpace = pwsaq->dwNameSpace;
}
}
}
else
{
INT err1 = GetLastError();
if((err1 == NO_DATA)
||
(err1 == WSA_E_NO_MORE) )
{
error = NO_ERROR;
}
break;
}
}
while(1);
}
if(hRnR)
{
if(error != NO_ERROR)
{
error = GetLastError();
}
#ifdef CHICAGO
(*ws2_WSALookupServiceEnd)(hRnR);
#else
WSALookupServiceEnd(hRnR);
#endif
SetLastError(error);
}
}
if(lpAliasBuffer)
{
*lpAliasBuffer = 0; // add another NULL
}
//
// free any allocated memory
//
if(pp)
{
FREE_HEAP(pp);
}
if(pwsaq)
{
FREE_HEAP(pwsaq);
}
//
// Return the count of addresses found or a -1, depending on
// whether this succeeded
//
if(error != NO_ERROR)
{
if(error != -1)
{
SetLastError(error);
}
totalCount = -1 ;
}
return(totalCount);
} // DoNameResolution
#endif // OLDXBYY