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.
992 lines
22 KiB
992 lines
22 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
NspMisc.c
|
|
|
|
Abstract:
|
|
|
|
This module contains misc support routines for loading
|
|
Name Space providers.
|
|
|
|
Author:
|
|
|
|
David Treadwell (davidtr) 22-Apr-1994
|
|
|
|
Revision History:
|
|
|
|
25-May-1994 ChuckC Split off from nspgaddr.c.
|
|
|
|
--*/
|
|
|
|
#if defined(CHICAGO)
|
|
#undef UNICODE
|
|
#else
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
#endif
|
|
|
|
#include "winsockp.h"
|
|
#include <nspmisc.h>
|
|
#include <stdlib.h>
|
|
|
|
#if defined(CHICAGO)
|
|
PTSTR
|
|
KludgeMultiSz(
|
|
HKEY hkey,
|
|
LPDWORD lpdwLength
|
|
);
|
|
#endif // CHICAGO
|
|
|
|
|
|
BOOL NspInitialized = FALSE;
|
|
|
|
LIST_ENTRY NameSpaceListHead;
|
|
|
|
PDWORD DefaultExclusions;
|
|
DWORD DefaultExclusionCount;
|
|
|
|
|
|
|
|
INT
|
|
InitializeNsp (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes internal structures for the NSP APIs.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
INT - NO_ERROR if initialization was successful, or a Windows error
|
|
code if the NSP could not be initialized.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT error;
|
|
PTSTR providerList;
|
|
DWORD providerCount;
|
|
|
|
//
|
|
// While holding the global lock, check whether we are actually
|
|
// initialized. We must do this with the global lock held so that
|
|
// we synchronize between multiple threads simultaneously making RNR
|
|
// calls.
|
|
//
|
|
|
|
SockAcquireGlobalLockExclusive( );
|
|
|
|
if ( NspInitialized ) {
|
|
SockReleaseGlobalLock( );
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Initialize global variables.
|
|
//
|
|
|
|
InitializeListHead( &NameSpaceListHead );
|
|
|
|
//
|
|
// Read the list of name spaces excluded from default resolutions.
|
|
//
|
|
|
|
error = ReadDefaultExclusions( );
|
|
if ( error != NO_ERROR ) {
|
|
SockReleaseGlobalLock( );
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// Get the list of network provider DLLs from the registry.
|
|
//
|
|
|
|
error = GetProviderList( &providerList, &providerCount );
|
|
if ( error != NO_ERROR ) {
|
|
SockReleaseGlobalLock( );
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// For each network provider, check if it can act as a name space
|
|
// provider and if so load the provider DLL. It is OK if the load
|
|
// of a single DLL fails as long as at least one DLL successfully
|
|
// loads.
|
|
//
|
|
// LoadNspDll() loads all the name spaces exported by the provider
|
|
// and places them in the global list in order of priority.
|
|
//
|
|
|
|
for ( ; providerCount > 0; providerCount-- ) {
|
|
|
|
LoadNspDll( providerList );
|
|
|
|
providerList += _tcslen( providerList ) + 1;
|
|
}
|
|
|
|
//
|
|
// If no name spaces loaded, fail.
|
|
//
|
|
|
|
if ( IsListEmpty( &NameSpaceListHead ) ) {
|
|
SockReleaseGlobalLock( );
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
NspInitialized = TRUE;
|
|
|
|
SockReleaseGlobalLock( );
|
|
|
|
return NO_ERROR;
|
|
|
|
} // InitializeNsp
|
|
|
|
|
|
INT
|
|
GetProviderList (
|
|
OUT PTSTR *ProviderList,
|
|
OUT PDWORD ProviderCount
|
|
)
|
|
{
|
|
INT error;
|
|
DWORD providerListLength;
|
|
HKEY providerOrderKey;
|
|
DWORD type;
|
|
PTSTR lpTmp, lpEnd;
|
|
|
|
//
|
|
// Open the key that stores the list network providers.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
PROVIDER_ORDER_KEY_NAME,
|
|
0,
|
|
KEY_READ,
|
|
&providerOrderKey
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
return error;
|
|
}
|
|
|
|
#if defined(CHICAGO)
|
|
*ProviderList = KludgeMultiSz( providerOrderKey, &providerListLength );
|
|
|
|
if( *ProviderList == NULL )
|
|
{
|
|
error = (INT)GetLastError();
|
|
RegCloseKey( providerOrderKey );
|
|
return error;
|
|
}
|
|
#else // !CHICAGO
|
|
//
|
|
// Determine the size of the provider list. We need this so that we
|
|
// can allocate enough memory to hold it.
|
|
//
|
|
|
|
providerListLength = 0;
|
|
|
|
error = RegQueryValueEx(
|
|
providerOrderKey,
|
|
TEXT("ProviderOrder"),
|
|
NULL,
|
|
&type,
|
|
NULL,
|
|
&providerListLength
|
|
);
|
|
if ( error != ERROR_MORE_DATA && error != NO_ERROR ) {
|
|
RegCloseKey( providerOrderKey );
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// Allocate enough memory to hold the provider list.
|
|
// Add a bit more for safety.
|
|
//
|
|
|
|
*ProviderList = ALLOCATE_HEAP( providerListLength + 16 );
|
|
if ( *ProviderList == NULL ) {
|
|
RegCloseKey( providerOrderKey );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
memset(*ProviderList,
|
|
0,
|
|
providerListLength+16) ;
|
|
|
|
//
|
|
// Get the list of providers from the registry.
|
|
//
|
|
|
|
error = RegQueryValueEx(
|
|
providerOrderKey,
|
|
TEXT("ProviderOrder"),
|
|
NULL,
|
|
&type,
|
|
(PVOID)*ProviderList,
|
|
&providerListLength
|
|
);
|
|
|
|
RegCloseKey( providerOrderKey );
|
|
|
|
if ( error != NO_ERROR ) {
|
|
FREE_HEAP( *ProviderList );
|
|
return error;
|
|
}
|
|
#endif // CHICAGO
|
|
|
|
//
|
|
// Figure out how many providers there are. Take care of simple
|
|
// case first.
|
|
//
|
|
|
|
*ProviderCount = 0 ;
|
|
lpTmp = *ProviderList ;
|
|
lpEnd = *ProviderList + providerListLength ;
|
|
|
|
if ( *lpTmp == 0 )
|
|
{
|
|
return NO_ERROR ;
|
|
}
|
|
|
|
//
|
|
// for all strings in the multi sz
|
|
//
|
|
do
|
|
{
|
|
*ProviderCount += 1 ;
|
|
|
|
//
|
|
// get to end of this string
|
|
//
|
|
while ((lpTmp < lpEnd) && *lpTmp)
|
|
{
|
|
lpTmp++ ;
|
|
}
|
|
|
|
//
|
|
// if no more, quit. this should not happen unless we got bad
|
|
// data that is not a multi sz. but better to play it safe than
|
|
// blow up.
|
|
//
|
|
if (lpTmp >= lpEnd)
|
|
break ;
|
|
|
|
//
|
|
// check for second NULL terminator
|
|
//
|
|
lpTmp++ ;
|
|
if ((lpTmp >= lpEnd) || !*lpTmp)
|
|
break ;
|
|
|
|
} while (TRUE) ;
|
|
|
|
return NO_ERROR;
|
|
|
|
} // GetProviderList
|
|
|
|
|
|
INT
|
|
LoadNspDll (
|
|
IN PTSTR ProviderName
|
|
)
|
|
{
|
|
INT error;
|
|
HKEY providerKey;
|
|
DWORD type;
|
|
DWORD class;
|
|
DWORD entryLength;
|
|
PTSTR providerDllName;
|
|
PTSTR providerDllExpandedName;
|
|
DWORD providerDllExpandedNameLength;
|
|
HANDLE providerDllHandle;
|
|
LPLOAD_NAME_SPACE_PROC loadNameSpaceProc;
|
|
PNS_ROUTINE nsRoutine;
|
|
DWORD nspVersion;
|
|
DWORD nameSpaceCount;
|
|
PTSTR providerKeyName;
|
|
|
|
//
|
|
// Allocate space to hold the provider key name.
|
|
//
|
|
|
|
providerKeyName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(TCHAR) );
|
|
if ( providerKeyName == NULL ) {
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Build the name of the network provider's information key.
|
|
//
|
|
|
|
_tcscpy( providerKeyName, REG_SERVICES_ROOT );
|
|
_tcscat( providerKeyName, ProviderName );
|
|
_tcscat( providerKeyName, TEXT("\\ServiceProvider") );
|
|
|
|
//
|
|
// Open the root key that holds subkeys for each of the network
|
|
// providers.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
providerKeyName,
|
|
0,
|
|
KEY_READ,
|
|
&providerKey
|
|
);
|
|
FREE_HEAP( providerKeyName );
|
|
if ( error != NO_ERROR ) {
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// Determine the class of the provider DLL. If the WN_SERVICE_CLASS
|
|
// bit is not set, then we're not interested in this provider.
|
|
//
|
|
|
|
entryLength = sizeof(class);
|
|
|
|
error = RegQueryValueEx(
|
|
providerKey,
|
|
TEXT("Class"),
|
|
NULL,
|
|
&type,
|
|
(PVOID)&class,
|
|
&entryLength
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
RegCloseKey( providerKey );
|
|
return error;
|
|
}
|
|
|
|
if ( (class & WN_SERVICE_CLASS) == 0 ) {
|
|
RegCloseKey( providerKey );
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
//
|
|
// The provider is an NSP, so we'll need to actually load this DLL.
|
|
// First determine the name of the DLL. Allocate some memory to
|
|
// hold the name and expanded name.
|
|
//
|
|
|
|
providerDllName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(TCHAR) );
|
|
if ( providerDllName == NULL ) {
|
|
RegCloseKey( providerKey );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
providerDllExpandedName = ALLOCATE_HEAP( DOS_MAX_PATH_LENGTH*sizeof(TCHAR) );
|
|
if ( providerDllExpandedName == NULL ) {
|
|
RegCloseKey( providerKey );
|
|
FREE_HEAP( providerDllName );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Get the name of the provider DLL.
|
|
//
|
|
|
|
entryLength = DOS_MAX_PATH_LENGTH*sizeof(TCHAR);
|
|
|
|
error = RegQueryValueEx(
|
|
providerKey,
|
|
TEXT("ProviderPath"),
|
|
NULL,
|
|
&type,
|
|
(PVOID)providerDllName,
|
|
&entryLength
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
FREE_HEAP( providerDllName );
|
|
FREE_HEAP( providerDllExpandedName );
|
|
RegCloseKey( providerKey );
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// Expand the name of the DLL, converting environment variables to
|
|
// their corresponding strings.
|
|
//
|
|
|
|
providerDllExpandedNameLength = ExpandEnvironmentStrings(
|
|
providerDllName,
|
|
providerDllExpandedName,
|
|
DOS_MAX_PATH_LENGTH*sizeof(TCHAR)
|
|
);
|
|
FREE_HEAP( providerDllName );
|
|
|
|
//
|
|
// Load the provider DLL so that we can get at it's entry points.
|
|
//
|
|
|
|
providerDllHandle = LoadLibrary( providerDllExpandedName );
|
|
|
|
FREE_HEAP( providerDllExpandedName );
|
|
RegCloseKey( providerKey );
|
|
|
|
if ( providerDllHandle == NULL ) {
|
|
return GetLastError( );;
|
|
}
|
|
|
|
//
|
|
// Get the address of the load name spaces procedure.
|
|
//
|
|
|
|
loadNameSpaceProc = (LPLOAD_NAME_SPACE_PROC)
|
|
GetProcAddress( providerDllHandle, "NPLoadNameSpaces" );
|
|
|
|
if ( loadNameSpaceProc == NULL ) {
|
|
FreeLibrary( providerDllHandle );
|
|
return GetLastError( );
|
|
}
|
|
|
|
//
|
|
// Call the load name spaces procedure to determine the buffer size
|
|
// we'll need.
|
|
//
|
|
|
|
nspVersion = NSP_VERSION;
|
|
|
|
(VOID)loadNameSpaceProc( &nspVersion, NULL, &entryLength );
|
|
|
|
//
|
|
// If the DLL does not support at least our version of the NSP
|
|
// interface, fail.
|
|
//
|
|
|
|
if ( nspVersion < NSP_VERSION ) {
|
|
FreeLibrary( providerDllHandle );
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Allocate some space to hold return information from the load name
|
|
// spaces procedure.
|
|
//
|
|
|
|
nsRoutine = ALLOCATE_HEAP( entryLength );
|
|
if ( nsRoutine == NULL ) {
|
|
FreeLibrary( providerDllHandle );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Call the load name spaces procedure with correct values to actually
|
|
// load all the name spaces and associated information.
|
|
//
|
|
|
|
nspVersion = NSP_VERSION;
|
|
|
|
nameSpaceCount = loadNameSpaceProc( &nspVersion, nsRoutine, &entryLength );
|
|
if ( nameSpaceCount <= 0 ) {
|
|
FreeLibrary( providerDllHandle );
|
|
FREE_HEAP( nsRoutine );
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// For each name space, allocate and initialize an information
|
|
// structure with pertinent information and place the structure
|
|
// on our global list.
|
|
//
|
|
|
|
for ( ; nameSpaceCount != 0; nameSpaceCount--, nsRoutine++ ) {
|
|
|
|
PNAME_SPACE_INFO nameSpaceInfo;
|
|
DWORD i;
|
|
|
|
//
|
|
// Allocate the structure. If the allocation fails, ignore the
|
|
// failure. There isn't anything intelligent that we can do
|
|
// about it, and an allocation failure this small should be
|
|
// extremely rare.
|
|
//
|
|
|
|
nameSpaceInfo = ALLOCATE_HEAP( sizeof(*nameSpaceInfo) );
|
|
if ( nameSpaceInfo == NULL ) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Store the DLL handle in this structure, then NULL out the
|
|
// handle value so that only the first name space for a specific
|
|
// DLL really stires the DLL handle. We use this handle to
|
|
// correctly free NSP DLLs.
|
|
//
|
|
|
|
nameSpaceInfo->ProviderDllHandle = providerDllHandle;
|
|
providerDllHandle = NULL;
|
|
|
|
//
|
|
// Fill in other information on the name space provider.
|
|
// Note the assumption about consecutive numbering. Ie. if
|
|
// 2 functions are returned, we assume they are for Index 0
|
|
// and Index 1.
|
|
//
|
|
|
|
nameSpaceInfo->GetAddrByNameProc = (LPGET_ADDR_BY_NAME_PROC)
|
|
((nsRoutine->dwFunctionCount > NSPAPI_GET_ADDRESS_BY_NAME) ?
|
|
nsRoutine->alpfnFunctions[NSPAPI_GET_ADDRESS_BY_NAME] :
|
|
NULL) ;
|
|
|
|
nameSpaceInfo->GetServiceProc = (LPGET_SERVICE_PROC)
|
|
((nsRoutine->dwFunctionCount > NSPAPI_GET_SERVICE) ?
|
|
nsRoutine->alpfnFunctions[NSPAPI_GET_SERVICE] :
|
|
NULL) ;
|
|
|
|
nameSpaceInfo->SetServiceProc = (LPSET_SERVICE_PROC)
|
|
((nsRoutine->dwFunctionCount > NSPAPI_SET_SERVICE) ?
|
|
nsRoutine->alpfnFunctions[NSPAPI_SET_SERVICE] :
|
|
NULL) ;
|
|
|
|
nameSpaceInfo->FunctionCount = nsRoutine->dwFunctionCount;
|
|
nameSpaceInfo->Priority = nsRoutine->dwPriority;
|
|
nameSpaceInfo->NameSpace = nsRoutine->dwNameSpace;
|
|
|
|
//
|
|
// Determine whether this name space should be excluded from
|
|
// default searches.
|
|
//
|
|
|
|
nameSpaceInfo->EnabledByDefault = TRUE;
|
|
|
|
for ( i = 0; i < DefaultExclusionCount; i++ ) {
|
|
if ( nameSpaceInfo->NameSpace == DefaultExclusions[i] ) {
|
|
nameSpaceInfo->EnabledByDefault = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Place the name space on our global list in order of it's
|
|
// priority value.
|
|
//
|
|
|
|
InsertNameSpace( nameSpaceInfo );
|
|
}
|
|
|
|
return NO_ERROR;
|
|
|
|
} // LoadNspDll
|
|
|
|
|
|
VOID
|
|
InsertNameSpace (
|
|
IN PNAME_SPACE_INFO NameSpace
|
|
)
|
|
{
|
|
PLIST_ENTRY listEntry;
|
|
PNAME_SPACE_INFO testNameSpace;
|
|
|
|
//
|
|
// Walk the global list of name spaces until we either reach the end
|
|
// or reach a name space with a higher priority value than the one
|
|
// we're inserting.
|
|
//
|
|
|
|
for ( listEntry = NameSpaceListHead.Flink;
|
|
listEntry != &NameSpaceListHead;
|
|
listEntry = listEntry->Flink ) {
|
|
|
|
testNameSpace = CONTAINING_RECORD(
|
|
listEntry,
|
|
NAME_SPACE_INFO,
|
|
NameSpaceListEntry
|
|
);
|
|
|
|
if ( testNameSpace->Priority > NameSpace->Priority ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Insert the name space just before the one we found.
|
|
//
|
|
|
|
InsertTailList( listEntry, &NameSpace->NameSpaceListEntry );
|
|
|
|
return;
|
|
|
|
} // InsertNameSpace
|
|
|
|
|
|
INT
|
|
ReadDefaultExclusions (
|
|
VOID
|
|
)
|
|
{
|
|
INT error;
|
|
DWORD exclusionsListLength;
|
|
HKEY providerOrderKey;
|
|
DWORD type;
|
|
PTSTR exclusionsList;
|
|
DWORD i;
|
|
PTCHAR w;
|
|
|
|
//
|
|
// Initialize the default exclusion count to 0. For many errors, we
|
|
// will assume that no providers are excluded from default searches.
|
|
//
|
|
|
|
DefaultExclusions = NULL;
|
|
DefaultExclusionCount = 0;
|
|
|
|
//
|
|
// Open the key that stores the list network providers.
|
|
//
|
|
|
|
error = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
EXCLUDED_PROVIDERS_KEY_NAME,
|
|
0,
|
|
KEY_READ,
|
|
&providerOrderKey
|
|
);
|
|
if ( error != NO_ERROR ) {
|
|
return error;
|
|
}
|
|
|
|
#if defined(CHICAGO)
|
|
exclusionsList = KludgeMultiSz( providerOrderKey, &exclusionsListLength );
|
|
|
|
if( exclusionsList == NULL )
|
|
{
|
|
error = (INT)GetLastError();
|
|
RegCloseKey( providerOrderKey );
|
|
return error;
|
|
}
|
|
#else // !CHICAGO
|
|
//
|
|
// Determine the size of the provider list. We need this so that we
|
|
// can allocate enough memory to hold it.
|
|
//
|
|
|
|
exclusionsListLength = 0;
|
|
|
|
error = RegQueryValueEx(
|
|
providerOrderKey,
|
|
TEXT("ExcludedProviders"),
|
|
NULL,
|
|
&type,
|
|
NULL,
|
|
&exclusionsListLength
|
|
);
|
|
if ( error != ERROR_MORE_DATA && error != NO_ERROR ) {
|
|
RegCloseKey( providerOrderKey );
|
|
return NO_ERROR;
|
|
}
|
|
|
|
//
|
|
// Allocate enough memory to hold the provider list.
|
|
//
|
|
|
|
exclusionsList = ALLOCATE_HEAP( exclusionsListLength );
|
|
if ( exclusionsList == NULL ) {
|
|
RegCloseKey( providerOrderKey );
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//
|
|
// Get the list of providers from the registry.
|
|
//
|
|
|
|
error = RegQueryValueEx(
|
|
providerOrderKey,
|
|
TEXT("ExcludedProviders"),
|
|
NULL,
|
|
&type,
|
|
(PVOID)exclusionsList,
|
|
&exclusionsListLength
|
|
);
|
|
|
|
RegCloseKey( providerOrderKey );
|
|
|
|
if ( error != NO_ERROR ) {
|
|
FREE_HEAP( exclusionsList );
|
|
return error;
|
|
}
|
|
#endif // CHICAGO
|
|
|
|
//
|
|
// Count the number of providers which are excluded from default
|
|
// searches.
|
|
//
|
|
|
|
DefaultExclusionCount = 0;
|
|
|
|
for ( w = exclusionsList; *w != L'\0'; w += _tcslen( w ) + 1 ) {
|
|
DefaultExclusionCount++;
|
|
}
|
|
|
|
//
|
|
// Allocate space for the exclusions array.
|
|
//
|
|
|
|
DefaultExclusions = ALLOCATE_HEAP( sizeof(DWORD) * (DefaultExclusionCount+1) );
|
|
if ( DefaultExclusions == NULL ) {
|
|
FREE_HEAP( exclusionsList );
|
|
}
|
|
|
|
//
|
|
// Convert the REG_MULTI_SZ from the registry into an array of DWORDs.
|
|
//
|
|
|
|
for ( i = 0, w = exclusionsList; *w != L'\0'; i++, w += _tcslen( w ) + 1 ) {
|
|
TCHAR *end;
|
|
DefaultExclusions[i] = _tcstol( w, &end, 0 );
|
|
}
|
|
|
|
DefaultExclusions[DefaultExclusionCount] = 0;
|
|
|
|
FREE_HEAP( exclusionsList );
|
|
|
|
return NO_ERROR;
|
|
|
|
} // ReadDefaultExclusions
|
|
|
|
|
|
BOOL
|
|
IsValidNameSpace (
|
|
IN DWORD dwNameSpaces,
|
|
IN PNAME_SPACE_INFO NameSpace
|
|
)
|
|
{
|
|
|
|
//
|
|
// If the request is for the default name spaces, this one is valid
|
|
// as long as it is enabled.
|
|
//
|
|
|
|
if ( dwNameSpaces == NS_DEFAULT ) {
|
|
|
|
if ( NameSpace->EnabledByDefault ) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The request is for a specific name space. It is only valid if
|
|
// this is the same name space.
|
|
//
|
|
|
|
if ( dwNameSpaces == NameSpace->NameSpace ) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
|
|
} // IsValidNameSpace
|
|
|
|
|
|
BOOL
|
|
GuidEqual (
|
|
IN LPGUID Guid1,
|
|
IN LPGUID Guid2
|
|
)
|
|
{
|
|
//
|
|
// Check if two GUIDs are equal in every respect.
|
|
//
|
|
|
|
if ( Guid1->Data1 == Guid2->Data1 &&
|
|
Guid1->Data2 == Guid2->Data2 &&
|
|
Guid1->Data3 == Guid2->Data3 &&
|
|
Guid1->Data4[0] == Guid2->Data4[0] &&
|
|
Guid1->Data4[1] == Guid2->Data4[1] &&
|
|
Guid1->Data4[2] == Guid2->Data4[2] &&
|
|
Guid1->Data4[3] == Guid2->Data4[3] &&
|
|
Guid1->Data4[4] == Guid2->Data4[4] &&
|
|
Guid1->Data4[5] == Guid2->Data4[5] &&
|
|
Guid1->Data4[6] == Guid2->Data4[6] &&
|
|
Guid1->Data4[7] == Guid2->Data4[7] ) {
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
} // CompareGuids
|
|
|
|
#if defined(CHICAGO)
|
|
|
|
//
|
|
// Chicago does not support the REG_MULTI_SZ registry value. As
|
|
// a hack (er, workaround), we'll create *keys* in the registry
|
|
// in place of REG_MULTI_SZ *values*. We'll then use the names
|
|
// of any values under the key as the REG_MULTI_SZ entries. So,
|
|
// instead of this:
|
|
//
|
|
// ..\Control\ServiceProvider
|
|
// ProviderOrder = REG_MULTI_SZ "MSTCP"
|
|
// "NWLINK"
|
|
// "FOOBAR"
|
|
//
|
|
// We'll use this:
|
|
//
|
|
// ..\Control\Service\Provider\ProviderOrder
|
|
// MSTCP = REG_SZ ""
|
|
// NWLINK = REG_SZ ""
|
|
// FOOBAR = REG_SZ ""
|
|
//
|
|
// This function takes an open registry key handle, enumerates
|
|
// the names of values contained within the key, and constructs
|
|
// a REG_MULTI_SZ string from the value names.
|
|
//
|
|
// Note that this function is not multithread safe; if another
|
|
// thread (or process) creates or deletes values under the
|
|
// specified key, the results are indeterminate.
|
|
//
|
|
// This function returns NULL on error. It returns non-NULL
|
|
// on success, even if the resulting REG_MULTI_SZ is empty.
|
|
//
|
|
PTSTR
|
|
KludgeMultiSz(
|
|
HKEY hkey,
|
|
LPDWORD lpdwLength
|
|
)
|
|
{
|
|
LONG err;
|
|
DWORD iValue;
|
|
DWORD cchTotal;
|
|
DWORD cchValue;
|
|
char szValue[MAX_PATH];
|
|
LPSTR lpMultiSz;
|
|
LPSTR lpTmp;
|
|
LPSTR lpEnd;
|
|
|
|
//
|
|
// Enumerate the values and total up the lengths.
|
|
//
|
|
|
|
iValue = 0;
|
|
cchTotal = 0;
|
|
|
|
for( ; ; )
|
|
{
|
|
cchValue = sizeof(szValue);
|
|
|
|
err = RegEnumValue( hkey,
|
|
iValue,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if( err != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add the length of the value's name, plus one
|
|
// for the terminator.
|
|
//
|
|
|
|
cchTotal += strlen( szValue ) + 1;
|
|
|
|
//
|
|
// Advance to next value.
|
|
//
|
|
|
|
iValue++;
|
|
}
|
|
|
|
//
|
|
// Add one for the final terminating NULL.
|
|
//
|
|
|
|
cchTotal++;
|
|
*lpdwLength = cchTotal;
|
|
|
|
//
|
|
// Allocate the MULTI_SZ buffer.
|
|
//
|
|
|
|
lpMultiSz = ALLOCATE_HEAP( cchTotal );
|
|
|
|
if( lpMultiSz == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
memset( lpMultiSz, 0, cchTotal );
|
|
|
|
//
|
|
// Enumerate the values and append to the buffer.
|
|
//
|
|
|
|
iValue = 0;
|
|
lpTmp = lpMultiSz;
|
|
lpEnd = lpMultiSz + cchTotal;
|
|
|
|
for( ; ; )
|
|
{
|
|
cchValue = sizeof(szValue);
|
|
|
|
err = RegEnumValue( hkey,
|
|
iValue,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if( err != NO_ERROR )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Compute the length of the value name (including
|
|
// the terminating NULL).
|
|
//
|
|
|
|
cchValue = strlen( szValue ) + 1;
|
|
|
|
//
|
|
// Determine if there is room in the array, taking into
|
|
// account the second NULL that terminates the string list.
|
|
//
|
|
|
|
if( ( lpTmp + cchValue + 1 ) > lpEnd )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Append the value name.
|
|
//
|
|
|
|
strcpy( lpTmp, szValue );
|
|
lpTmp += cchValue;
|
|
|
|
//
|
|
// Advance to next value.
|
|
//
|
|
|
|
iValue++;
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
return (PTSTR)lpMultiSz;
|
|
|
|
} // KludgeMultiSzBecauseChicagoIsSoLame (the original name, left for posterity)
|
|
#endif
|