803 lines
18 KiB
C++
803 lines
18 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (C) Microsoft Corporation, 1992 - 1999
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
nsiclnt.cxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This is the client side NSI service support layer. These are wrappers
|
|||
|
which call the name service provider.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Steven Zeck (stevez) 03/04/92
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include <nsi.h>
|
|||
|
|
|||
|
#include <string.h>
|
|||
|
#include <time.h>
|
|||
|
|
|||
|
|
|||
|
// This structure is used in binding handle select processing.
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
unsigned long Count;
|
|||
|
int IndexMatch[1];
|
|||
|
|
|||
|
} MATCH_VECTOR;
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
I_NsBindingFoundBogus(RPC_BINDING_HANDLE *BindingHandle, DWORD BindId);
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
I_NsClientBindSearch(RPC_BINDING_HANDLE *NsiClntBinding, DWORD *BindId);
|
|||
|
void RPC_ENTRY
|
|||
|
I_NsClientBindDone(RPC_BINDING_HANDLE *NsiClntBinding, DWORD BindId);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingLookupBeginW(
|
|||
|
IN unsigned long EntryNameSyntax,
|
|||
|
IN unsigned short __RPC_FAR * EntryName,
|
|||
|
IN RPC_IF_HANDLE RpcIfHandle,
|
|||
|
IN UUID __RPC_FAR * Object OPTIONAL,
|
|||
|
IN unsigned long BindingMaxCount,
|
|||
|
OUT RPC_NS_HANDLE *LookupContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Query the named server for the requested binding handles. This will
|
|||
|
request a query from name server to be performed and store the results
|
|||
|
to be retrieved with RpcNsBindingLookupNext().
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
EntryNameSyntax - This value describes the type/format of the EntryName.
|
|||
|
|
|||
|
EntryName - Name that this export will be stored in. This is just a
|
|||
|
token that is passed on the the Name Server.
|
|||
|
|
|||
|
RpcIfHandle - The interface that is being exported.
|
|||
|
|
|||
|
Object - the object UUID that you are looking for (or in combination
|
|||
|
with RpcIfHandle).
|
|||
|
|
|||
|
BindingMaxCount - The maxium size of the binding vector to be returned
|
|||
|
to the RpcNsBindingLookupNext function.
|
|||
|
|
|||
|
LookupContext - handle to be used to pass to RpcNsBindingImportNext,
|
|||
|
This is really allocated by RpcNsLookupBinding
|
|||
|
|
|||
|
SearchOptions - used by the auto handle binding routines and Micosoft
|
|||
|
name server.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
RPC_S_OK, RPC_S_NO_MORE_BINDINGS
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
UNSIGNED16 NsiStatus;
|
|||
|
NSI_INTERFACE_ID_T NilIfOnWire, __RPC_FAR *IfPtr;
|
|||
|
RPC_BINDING_HANDLE NsiClntBinding = NULL;
|
|||
|
DWORD BindId = 0;
|
|||
|
|
|||
|
if (RpcIfHandle == NULL)
|
|||
|
{
|
|||
|
IfPtr = &NilIfOnWire;
|
|||
|
memset(IfPtr, 0, sizeof(NSI_INTERFACE_ID_T));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
IfPtr = (NSI_INTERFACE_ID_T __RPC_FAR *)
|
|||
|
&((PRPC_CLIENT_INTERFACE)RpcIfHandle)->InterfaceId;
|
|||
|
}
|
|||
|
|
|||
|
while ((status = I_NsClientBindSearch(&NsiClntBinding, &BindId)) == RPC_S_OK)
|
|||
|
{
|
|||
|
|
|||
|
// Provide the default entry name if there is none.
|
|||
|
|
|||
|
if ((! EntryName || *EntryName == 0) && DefaultName)
|
|||
|
{
|
|||
|
EntryName = &(*DefaultName);
|
|||
|
EntryNameSyntax = DefaultSyntax;
|
|||
|
}
|
|||
|
else if (! EntryNameSyntax)
|
|||
|
EntryNameSyntax = DefaultSyntax;
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
nsi_binding_lookup_begin(NsiClntBinding, EntryNameSyntax, EntryName,
|
|||
|
IfPtr,
|
|||
|
(NSI_UUID_P_T) Object, BindingMaxCount, 0,
|
|||
|
LookupContext, &NsiStatus);
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
*LookupContext = 0;
|
|||
|
NsiStatus = MapException(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
status = NsiMapStatus(NsiStatus);
|
|||
|
|
|||
|
if (NsiStatus != NSI_S_NAME_SERVICE_UNAVAILABLE)
|
|||
|
break;
|
|||
|
|
|||
|
I_NsBindingFoundBogus(&NsiClntBinding, BindId);
|
|||
|
}
|
|||
|
|
|||
|
I_NsClientBindDone(&NsiClntBinding, BindId);
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingLookupNext(
|
|||
|
IN RPC_NS_HANDLE LookupContext,
|
|||
|
OUT RPC_BINDING_VECTOR **BindingVector
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieve the next group of bindings queryed from RpcNsBindingLookupBegin().
|
|||
|
Arguments:
|
|||
|
|
|||
|
LookupContext - handle to allocated by RpcNsBindingLookupBegin()
|
|||
|
|
|||
|
BindingVector - returns a pointer to a binding vector.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
RPC_S_OK, RPC_S_NO_MORE_BINDINGS, RPC_S_OUT_OF_MEMORY,
|
|||
|
nsi_binding_lookup_next()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
UNSIGNED16 NsiStatus;
|
|||
|
NSI_BINDING_VECTOR_T * NsiBindingVector;
|
|||
|
RPC_BINDING_HANDLE Handle;
|
|||
|
unsigned int HandleValide, Index;
|
|||
|
|
|||
|
NsiBindingVector = 0;
|
|||
|
*BindingVector = 0;
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
nsi_binding_lookup_next((NSI_NS_HANDLE_T *) LookupContext,
|
|||
|
&NsiBindingVector, &NsiStatus);
|
|||
|
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
NsiStatus = MapException(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
if (NsiStatus)
|
|||
|
return(NsiMapStatus(NsiStatus));
|
|||
|
|
|||
|
// Convert the string bindings to binding handles. This done by
|
|||
|
// replacing the StringBinding with RPC_BINDING_HANDLE to a
|
|||
|
// RPC_BINDING_VECTOR allocated by the runtime.
|
|||
|
|
|||
|
*BindingVector = (RPC_BINDING_VECTOR *) I_RpcAllocate((unsigned int) (
|
|||
|
sizeof(RPC_BINDING_VECTOR) - sizeof(RPC_BINDING_HANDLE) +
|
|||
|
sizeof(RPC_BINDING_HANDLE) * NsiBindingVector->count));
|
|||
|
|
|||
|
if (! *BindingVector)
|
|||
|
return(RPC_S_OUT_OF_MEMORY);
|
|||
|
|
|||
|
for (Index = 0, HandleValide = 0;
|
|||
|
Index < NsiBindingVector->count; Index++)
|
|||
|
{
|
|||
|
Handle = 0;
|
|||
|
|
|||
|
if (!UnicodeToRtString(NsiBindingVector->binding[Index].string))
|
|||
|
status = RpcBindingFromStringBinding(
|
|||
|
(RT_CHAR *)NsiBindingVector->binding[Index].string, &Handle);
|
|||
|
|
|||
|
|
|||
|
if (!status && NsiBindingVector->binding[Index].entry_name)
|
|||
|
{
|
|||
|
if (!UnicodeToRtString( NsiBindingVector->binding[Index].entry_name))
|
|||
|
{
|
|||
|
#ifdef NTENV
|
|||
|
status = I_RpcNsBindingSetEntryNameW(Handle,
|
|||
|
#else
|
|||
|
status = I_RpcNsBindingSetEntryName(Handle,
|
|||
|
#endif
|
|||
|
NsiBindingVector->binding[Index].entry_name_syntax,
|
|||
|
(RT_CHAR *)NsiBindingVector->binding[Index].entry_name);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (NsiBindingVector->binding[Index].entry_name)
|
|||
|
I_RpcFree(NsiBindingVector->binding[Index].entry_name);
|
|||
|
|
|||
|
I_RpcFree(NsiBindingVector->binding[Index].string);
|
|||
|
|
|||
|
// only copy the handle to the output if the Binding was OK.
|
|||
|
|
|||
|
if (! status)
|
|||
|
(*BindingVector)->BindingH[HandleValide++] = Handle;
|
|||
|
}
|
|||
|
|
|||
|
(*BindingVector)->Count = HandleValide;
|
|||
|
|
|||
|
I_RpcFree(NsiBindingVector);
|
|||
|
|
|||
|
return((HandleValide > 0)? RPC_S_OK: RPC_S_NO_MORE_BINDINGS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingLookupDone(
|
|||
|
OUT RPC_NS_HANDLE *LookupContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Close the context opened with RpcNsBindingLookupBegin();
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LookupContext - context handle to close
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
nsi_binding_lookup_done()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNSIGNED16 NsiStatus = NSI_S_OK;
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
nsi_binding_lookup_done((NSI_NS_HANDLE_T *) LookupContext, &NsiStatus);
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
NsiStatus = MapException(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
// RpcBindingFree(&NsiClntBinding);
|
|||
|
*LookupContext = 0;
|
|||
|
|
|||
|
return(NsiMapStatus(NsiStatus));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingImportBeginW(
|
|||
|
IN unsigned long EntryNameSyntax,
|
|||
|
IN unsigned short __RPC_FAR * EntryName,
|
|||
|
IN RPC_IF_HANDLE RpcIfHandle,
|
|||
|
IN UUID __RPC_FAR * Object OPTIONAL,
|
|||
|
OUT RPC_NS_HANDLE *ImportContextOut
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Query the named server for the requested binding handles. This function
|
|||
|
is implemented in terms of RpcNsLookupBinding.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
EntryNameSyntax - This value describes the type/format of the EntryName.
|
|||
|
|
|||
|
EntryName - Name that this export will be stored in. This is just a
|
|||
|
token that is passed on the the Name Server.
|
|||
|
|
|||
|
RpcIfHandle - The interface that is being exported.
|
|||
|
|
|||
|
Object - the object UUID that you are looking for (or in combination
|
|||
|
with RpcIfHandle).
|
|||
|
|
|||
|
ImportContext - handle to be used to pass to RpcNsBindingImportNext,
|
|||
|
This is really allocated by RpcNsLookupBinding
|
|||
|
|
|||
|
SearchOptions - used by the auto handle binding routines and Micosoft
|
|||
|
name server.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
|
|||
|
RpcNsBindingLookupBegin(), RPC_S_OUT_OF_MEMORY, RPS_S_OK
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
RPC_NS_HANDLE LookupContext;
|
|||
|
PRPC_IMPORT_CONTEXT_P ImportContext;
|
|||
|
const int BindingVectorSize = 10;
|
|||
|
|
|||
|
*ImportContextOut = 0;
|
|||
|
|
|||
|
status = RpcNsBindingLookupBeginW(EntryNameSyntax, EntryName,
|
|||
|
RpcIfHandle, Object, BindingVectorSize, &LookupContext);
|
|||
|
|
|||
|
if (status)
|
|||
|
return(status);
|
|||
|
|
|||
|
// Allocate an import context which contains a lookup context,
|
|||
|
// a StringBinding vector and an index to the current StringBinding
|
|||
|
// in the vector.
|
|||
|
|
|||
|
if (!(ImportContext = (PRPC_IMPORT_CONTEXT_P)
|
|||
|
I_RpcAllocate(sizeof(RPC_IMPORT_CONTEXT_P))) )
|
|||
|
|
|||
|
return(RPC_S_OUT_OF_MEMORY);
|
|||
|
|
|||
|
ImportContext->LookupContext = LookupContext;
|
|||
|
ImportContext->Bindings = 0;
|
|||
|
|
|||
|
*ImportContextOut = ImportContext;
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingImportNext(
|
|||
|
IN RPC_NS_HANDLE ImportContextIn,
|
|||
|
OUT RPC_BINDING_HANDLE __RPC_FAR * RpcBinding
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Get the next StringBinding in the Import StringBinding vector. If
|
|||
|
the vector is empty, call RpcNsBindingLookupBegin() to get a new
|
|||
|
vector.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ImportContext - handle to be used get a new string binding vector from
|
|||
|
RpcNsBindingLookupNext()
|
|||
|
|
|||
|
RpcBinding - place to return a binding. This Binding Handle ownership
|
|||
|
passes to caller.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
RPC_S_OK, RpcNsBindingLookupNext()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
PRPC_IMPORT_CONTEXT_P ImportContext;
|
|||
|
|
|||
|
ImportContext = (PRPC_IMPORT_CONTEXT_P) ImportContextIn;
|
|||
|
|
|||
|
if (!ImportContext)
|
|||
|
return(RPC_S_NO_CONTEXT_AVAILABLE);
|
|||
|
|
|||
|
if (ImportContext->Bindings)
|
|||
|
{
|
|||
|
status = RpcNsBindingSelect(ImportContext->Bindings, RpcBinding);
|
|||
|
|
|||
|
if (status == RPC_S_OK)
|
|||
|
return(RPC_S_OK);
|
|||
|
|
|||
|
if (status != RPC_S_NO_MORE_BINDINGS)
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
// The vector was empty or there were no more entris. Get another vector.
|
|||
|
|
|||
|
if (ImportContext->Bindings)
|
|||
|
RpcBindingVectorFree(&ImportContext->Bindings);
|
|||
|
|
|||
|
status = RpcNsBindingLookupNext(ImportContext->LookupContext,
|
|||
|
&ImportContext->Bindings);
|
|||
|
|
|||
|
if (status)
|
|||
|
return(status);
|
|||
|
|
|||
|
return(RpcNsBindingSelect(ImportContext->Bindings, RpcBinding));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingImportDone(
|
|||
|
IN RPC_NS_HANDLE *ImportContextIn
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Close an Import Context handle when done. Free up the current
|
|||
|
Bindings vector, LookupContext and ImportContext structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ImportContext - handle to close.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
RPC_S_OK, RpcNsBindingLookupDone()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS status;
|
|||
|
PRPC_IMPORT_CONTEXT_P ImportContext;
|
|||
|
|
|||
|
ImportContext = (PRPC_IMPORT_CONTEXT_P) *ImportContextIn;
|
|||
|
|
|||
|
if (! ImportContext)
|
|||
|
return(RPC_S_OK);
|
|||
|
|
|||
|
if (ImportContext->Bindings)
|
|||
|
RpcBindingVectorFree(&ImportContext->Bindings);
|
|||
|
|
|||
|
status = RpcNsBindingLookupDone(&ImportContext->LookupContext);
|
|||
|
|
|||
|
I_RpcFree (ImportContext);
|
|||
|
*ImportContextIn = 0;
|
|||
|
|
|||
|
return(status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsMgmtHandleSetExpAge(
|
|||
|
IN RPC_NS_HANDLE NsHandle,
|
|||
|
IN unsigned long ExpirationAge
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Set the maxium age that a cached entry will be returned in reponse
|
|||
|
to a name service inquirary transaction.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NsHandle - context handle created with one of the RpcNs*Begin APIs
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
nsi_mgmt_handle_set_exp_age()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UNSIGNED16 NsiStatus;
|
|||
|
RPC_NS_HANDLE LookupContext =
|
|||
|
((PRPC_IMPORT_CONTEXT_P)NsHandle)->LookupContext;
|
|||
|
|
|||
|
|
|||
|
RpcTryExcept
|
|||
|
{
|
|||
|
nsi_mgmt_handle_set_exp_age(LookupContext, ExpirationAge, &NsiStatus);
|
|||
|
}
|
|||
|
RpcExcept(1)
|
|||
|
{
|
|||
|
NsiStatus = MapException(RpcExceptionCode());
|
|||
|
}
|
|||
|
RpcEndExcept
|
|||
|
|
|||
|
return(NsiMapStatus(NsiStatus));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define isLocalName(NetWorkAddress) (1) //BUGBUG
|
|||
|
|
|||
|
|
|||
|
static RPC_STATUS
|
|||
|
GetMatchingProtocols(
|
|||
|
IN RPC_BINDING_VECTOR *BindingVector,
|
|||
|
OUT MATCH_VECTOR *MatchVector,
|
|||
|
IN char * SearchProtocol, OPTIONAL
|
|||
|
IN int fLocalOnly
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Construct a match binding vector with protocols that we are interested in.
|
|||
|
PERF: When we know how to parse NetWorkAddress to know when it is
|
|||
|
a local name, we should select those first
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BindingVector - vector of binding handles to select from.
|
|||
|
|
|||
|
MatchVector - place to put the results.
|
|||
|
|
|||
|
SearchProtocol - Protocol we are looking for. A Nil matches everything.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
The number of protocols that we matched in the match vector.
|
|||
|
|
|||
|
RPC_S_OK, RpcBindingToStringBinding(), RpcStringBindingParse()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
RPC_STATUS Status;
|
|||
|
unsigned int Index;
|
|||
|
RT_CHAR * StringBinding, *ProtocolSeq, *NetAddress;
|
|||
|
int fProtocolsMatched;
|
|||
|
|
|||
|
MatchVector->Count = 0;
|
|||
|
|
|||
|
for (Index = 0; Index < BindingVector->Count; Index++)
|
|||
|
{
|
|||
|
if (!BindingVector->BindingH[Index])
|
|||
|
continue;
|
|||
|
|
|||
|
// Convert the binding handle to a string and then extract
|
|||
|
// the fields we are interested in.
|
|||
|
|
|||
|
if (Status = RpcBindingToStringBinding(
|
|||
|
BindingVector->BindingH[Index], &StringBinding))
|
|||
|
|
|||
|
return (Status);
|
|||
|
|
|||
|
if (Status = RpcStringBindingParse(StringBinding, 0,
|
|||
|
&ProtocolSeq, &NetAddress, 0, 0))
|
|||
|
|
|||
|
return (Status);
|
|||
|
|
|||
|
fProtocolsMatched = 1;
|
|||
|
|
|||
|
if (SearchProtocol)
|
|||
|
{
|
|||
|
char * STmp = SearchProtocol;
|
|||
|
|
|||
|
for (RT_CHAR *pT = ProtocolSeq; *pT &&
|
|||
|
(char) *pT++ == *STmp++; ) ;
|
|||
|
|
|||
|
if (*STmp)
|
|||
|
fProtocolsMatched = 0;
|
|||
|
}
|
|||
|
|
|||
|
// If we are looking for a local name only and the matched
|
|||
|
// protocol isn't local, throw this one out.
|
|||
|
|
|||
|
if (fLocalOnly && !isLocalName(NetAddress))
|
|||
|
fProtocolsMatched = 0;
|
|||
|
|
|||
|
|
|||
|
// Return all the strings to the RPC runtime.
|
|||
|
|
|||
|
if (Status = RpcStringFree(&ProtocolSeq))
|
|||
|
return(Status);
|
|||
|
|
|||
|
if (Status = RpcStringFree(&NetAddress))
|
|||
|
return(Status);
|
|||
|
|
|||
|
if (Status = RpcStringFree(&StringBinding))
|
|||
|
return(Status);
|
|||
|
|
|||
|
if (! fProtocolsMatched)
|
|||
|
continue;
|
|||
|
|
|||
|
|
|||
|
// A match is recorded as an index into the original vector.
|
|||
|
|
|||
|
MatchVector->IndexMatch[MatchVector->Count++] = Index;
|
|||
|
}
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int
|
|||
|
RandomNumber(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Yet another pseudo-random number generator.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
New random number, in the range 0..32767.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
static long holdrand;
|
|||
|
static int fInitialized = 0;
|
|||
|
|
|||
|
// Start with a different seed everytime.
|
|||
|
|
|||
|
if (!fInitialized)
|
|||
|
{
|
|||
|
fInitialized = 1;
|
|||
|
// holdrand = clock();
|
|||
|
}
|
|||
|
|
|||
|
return( (int) (holdrand = (long) ( (holdrand * 214013L + 2531011L)
|
|||
|
>> 16 & 0x7fff ) ));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingSelect(
|
|||
|
IN OUT RPC_BINDING_VECTOR *BindingVector,
|
|||
|
OUT RPC_BINDING_HANDLE __RPC_FAR * RpcBinding
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function will select a Binding handle from a vector of binding
|
|||
|
handles. Since we know a little bit about our binding handles, we
|
|||
|
will chose the more effiecent types of handles first. We select
|
|||
|
groups of bindings unordered via a random number generator.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BindingVector - vector of binding handles to select from
|
|||
|
|
|||
|
RpcBinding - place to return the binding handle. The ownership of
|
|||
|
the handle passes to the caller.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
RPC_S_OK, RPC_S_OUT_OF_MEMORY, RPC_S_NO_MORE_BINDINGS, GetMatchingProtocols()
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
static char * PreferredProtocol[] =
|
|||
|
{
|
|||
|
"ncalrpc",
|
|||
|
"ncacn_np",
|
|||
|
0
|
|||
|
};
|
|||
|
int CountPreferredProtocol = sizeof(PreferredProtocol) / sizeof(void *);
|
|||
|
|
|||
|
RPC_STATUS Status;
|
|||
|
MATCH_VECTOR *MatchVector;
|
|||
|
int IndexSelected;
|
|||
|
int ProtocolIndex;
|
|||
|
int fLocalOnly;
|
|||
|
|
|||
|
*RpcBinding = 0;
|
|||
|
|
|||
|
MatchVector = (MATCH_VECTOR *) I_RpcAllocate((unsigned int)
|
|||
|
(sizeof(MATCH_VECTOR) + sizeof(int) * BindingVector->Count));
|
|||
|
|
|||
|
if (!MatchVector)
|
|||
|
return(RPC_S_OUT_OF_MEMORY);
|
|||
|
|
|||
|
// For all the protocols returned, first try the local ones, then
|
|||
|
// the remote.
|
|||
|
|
|||
|
for (fLocalOnly = 1; fLocalOnly >= 0; fLocalOnly--)
|
|||
|
{
|
|||
|
for (ProtocolIndex = 0; ProtocolIndex < CountPreferredProtocol;
|
|||
|
ProtocolIndex++)
|
|||
|
{
|
|||
|
|
|||
|
// First, get the perferred protocols into a match vector.
|
|||
|
// The match vector has a range from 0..number of matching protocols.
|
|||
|
// We need this so we know what range to generate a random number.
|
|||
|
|
|||
|
if (Status = GetMatchingProtocols(BindingVector, MatchVector,
|
|||
|
PreferredProtocol[ProtocolIndex], fLocalOnly))
|
|||
|
|
|||
|
return(Status);
|
|||
|
|
|||
|
// If we found any, select one and return it.
|
|||
|
|
|||
|
if (MatchVector->Count)
|
|||
|
{
|
|||
|
IndexSelected = MatchVector->
|
|||
|
IndexMatch[RandomNumber() % MatchVector->Count];
|
|||
|
|
|||
|
*RpcBinding = BindingVector->BindingH[IndexSelected];
|
|||
|
|
|||
|
// Remove selected one from binding vector.
|
|||
|
|
|||
|
BindingVector->BindingH[IndexSelected] = 0;
|
|||
|
I_RpcFree (MatchVector);
|
|||
|
|
|||
|
return(RPC_S_OK);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
I_RpcFree (MatchVector);
|
|||
|
|
|||
|
return(RPC_S_NO_MORE_BINDINGS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingLookupBeginA(
|
|||
|
IN unsigned long EntryNameSyntax,
|
|||
|
IN unsigned char __RPC_FAR * EntryName,
|
|||
|
IN RPC_IF_HANDLE RpcIfSpec,
|
|||
|
IN UUID __RPC_FAR * ObjUuid OPTIONAL,
|
|||
|
IN unsigned long BindingMaxCount,
|
|||
|
OUT RPC_NS_HANDLE *LookupContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is an ASCII wrapper to the UNICODE version of the API. It
|
|||
|
converts all char * -> short * strings and calls the UNICODE version.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
WIDE_STRING EntryNameW(EntryName);
|
|||
|
|
|||
|
if (EntryNameW.OutOfMemory())
|
|||
|
return(RPC_S_OUT_OF_MEMORY);
|
|||
|
|
|||
|
return(RpcNsBindingLookupBeginW(EntryNameSyntax, &EntryNameW,
|
|||
|
RpcIfSpec, ObjUuid, BindingMaxCount, LookupContext));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
RPC_STATUS RPC_ENTRY
|
|||
|
RpcNsBindingImportBeginA(
|
|||
|
IN unsigned long EntryNameSyntax,
|
|||
|
IN unsigned char __RPC_FAR * EntryName,
|
|||
|
IN RPC_IF_HANDLE RpcIfSpec,
|
|||
|
IN UUID __RPC_FAR * ObjUuid OPTIONAL,
|
|||
|
OUT RPC_NS_HANDLE *ImportContext
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is an ASCII wrapper to the UNICODE version of the API. It
|
|||
|
converts all char * -> short * strings and calls the UNICODE version.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
WIDE_STRING EntryNameW(EntryName);
|
|||
|
|
|||
|
if (EntryNameW.OutOfMemory())
|
|||
|
return(RPC_S_OUT_OF_MEMORY);
|
|||
|
|
|||
|
return(RpcNsBindingImportBeginW(EntryNameSyntax, &EntryNameW,
|
|||
|
RpcIfSpec, ObjUuid, ImportContext));
|
|||
|
}
|