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.
1821 lines
49 KiB
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
|