2888 lines
78 KiB
C++
2888 lines
78 KiB
C++
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||
|
||
Module Name:
|
||
|
||
dcesvr.cxx
|
||
|
||
Abstract:
|
||
|
||
This routine implements the server side DCE runtime APIs. The
|
||
routines in this file are used by server applications only.
|
||
|
||
Author:
|
||
|
||
Michael Montague (mikemon) 13-Nov-1991
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <precomp.hxx>
|
||
#include <wincrypt.h>
|
||
#include <rpcssl.h>
|
||
#include <rpcobj.hxx>
|
||
#include <rpcasync.h>
|
||
#include <hndlsvr.hxx>
|
||
#include <mgmt.h>
|
||
#include <rpccfg.h>
|
||
#include <CharConv.hxx>
|
||
|
||
long GroupIdCounter;
|
||
|
||
RPC_INTERFACE * GlobalManagementInterface;
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcNetworkInqProtseqs (
|
||
OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to obtain a list of the
|
||
rpc protocol sequences supported by this system configuration.
|
||
|
||
Arguments:
|
||
|
||
ProtseqVector - Returns a vector of the rpc protocol sequences
|
||
supported by this system configuration.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The operation completed successfully.
|
||
|
||
RPC_S_NO_PROTSEQS - The current system configuration does not
|
||
support any rpc protocol sequences.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to inquire
|
||
the rpc protocol sequences supported by this system configuration.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(RpcConfigInquireProtocolSequences(FALSE, ProtseqVector));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcObjectInqType (
|
||
IN UUID PAPI * ObjUuid,
|
||
OUT UUID PAPI * TypeUuid OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to obtain the type uuid
|
||
for an object. This routine can also be used to determine whether
|
||
a given object is register with the runtime or not. This is done
|
||
by not specifying the optional type uuid argument.
|
||
|
||
Arguments:
|
||
|
||
ObjUuid - Supplies the object uuid for which we want look up the
|
||
type uuid.
|
||
|
||
TypeUuid - Optionally returns the type uuid of the specified object
|
||
uuid.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The operation completed successfully; the object uuid
|
||
is registered with the runtime or the object inquiry function
|
||
knows the object uuid.
|
||
|
||
RPC_S_OBJECT_NOT_FOUND - The specified object uuid has not been
|
||
registered with the runtime and the object inquiry function
|
||
does not know about the object uuid.
|
||
|
||
--*/
|
||
{
|
||
RPC_UUID OptionalTypeUuid;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (ARGUMENT_PRESENT(TypeUuid))
|
||
{
|
||
return(ObjectInqType(
|
||
(RPC_UUID PAPI *) ObjUuid, (RPC_UUID PAPI *) TypeUuid));
|
||
}
|
||
|
||
return(ObjectInqType(
|
||
(RPC_UUID PAPI *) ObjUuid, &OptionalTypeUuid));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcObjectSetInqFn (
|
||
IN RPC_OBJECT_INQ_FN PAPI * InquiryFn
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A function to be used to determine an object's type is specified
|
||
using this routine.
|
||
|
||
Arguments:
|
||
|
||
InquiryFn - Supplies a pointer to a function which will automatically
|
||
be called when an inquiry is made for the type of object which
|
||
has not yet been registered with the runtime.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - This value will always be returned.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(ObjectSetInqFn(InquiryFn));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcObjectSetType (
|
||
IN UUID PAPI * ObjUuid,
|
||
IN UUID PAPI * TypeUuid OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
An application will call this routine to register an object and its
|
||
type with the runtime.
|
||
|
||
Arguments:
|
||
|
||
ObjUuid - Supplies the object uuid to be registered with the runtime.
|
||
|
||
TypeUuid - Supplies the type of the object being registered. The type
|
||
is registered with the object.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The object uuid (and type uuid with it) were successfully
|
||
registered with the runtime.
|
||
|
||
RPC_S_ALREADY_REGISTERED - The object uuid specified has already
|
||
been registered with the runtime.
|
||
|
||
RPC_S_OUT_OF_MEMORY - There is insufficient memory available to
|
||
register the object with the runtime.
|
||
|
||
RPC_S_INVALID_OBJECT - The object uuid specified is the nil uuid.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(ObjectSetType(
|
||
(RPC_UUID PAPI *) ObjUuid, (RPC_UUID PAPI *) TypeUuid));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcProtseqVectorFree (
|
||
IN OUT RPC_PROTSEQ_VECTOR PAPI * PAPI * ProtseqVector
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The protocol sequence vector obtained by calling RpcNetworkInqProtseqs
|
||
is freed using this routine. Each of the protocol sequences (they
|
||
are represented as strings) and the vector itself are all freed.
|
||
|
||
Arguments:
|
||
|
||
ProtseqVector - Supplies the rpc protocol sequence vector to be freed,
|
||
and returns zero in place of the pointer to the vector.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - This routine always completes successfully.
|
||
|
||
--*/
|
||
{
|
||
unsigned int Index, Count;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if ( *ProtseqVector == 0 )
|
||
{
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
for (Index = 0, Count = (*ProtseqVector)->Count; Index < Count; Index++)
|
||
{
|
||
delete((*ProtseqVector)->Protseq[Index]);
|
||
}
|
||
|
||
delete(*ProtseqVector);
|
||
*ProtseqVector = 0;
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerInqBindings (
|
||
OUT RPC_BINDING_VECTOR PAPI * PAPI * BindingVector
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to obtain a vector of
|
||
binding handles. Each protocol sequence registered with the rpc
|
||
server will be used to create one binding handle.
|
||
|
||
Arguments:
|
||
|
||
BindingVector - Returns the vector of binding handles.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - At least one rpc protocol sequence has been registered
|
||
with the rpc server, and the operation completed successfully.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
|
||
the operation.
|
||
|
||
RPC_S_NO_BINDINGS - No rpc protocol sequences have been successfully
|
||
registered with the rpc server.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
*BindingVector = 0L;
|
||
|
||
return(GlobalRpcServer->InquireBindings(BindingVector));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerInqIf (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN UUID PAPI * MgrTypeUuid, OPTIONAL
|
||
OUT RPC_MGR_EPV PAPI * PAPI * MgrEpv
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will call this routine to obtain the manager
|
||
entry point vector for a given interface and a given type uuid.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Supplies a description of the interface.
|
||
|
||
MgrTypeUuid - Optionally supplies the type uuid of the manager
|
||
entry point vector we want returned. If no manager type uuid
|
||
is specified, then the null uuid is assumed.
|
||
|
||
MgrEpv - Returns the manager entry point vector.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The manager entry point vector has successfully been
|
||
returned.
|
||
|
||
RPC_S_UNKNOWN_MGR_TYPE - The specified type uuid is not registered
|
||
with the interface.
|
||
|
||
RPC_S_UNKNOWN_IF - The specified interface is not registered with
|
||
the rpc server.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(GlobalRpcServer->InquireManagerEpv(
|
||
(RPC_SERVER_INTERFACE PAPI *) IfSpec,
|
||
(RPC_UUID PAPI *) MgrTypeUuid, MgrEpv));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerListen (
|
||
IN unsigned int MinimumCallThreads,
|
||
IN unsigned int MaxCalls,
|
||
IN unsigned int DontWait
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine gets called to start the rpc server listening for remote
|
||
procedure calls. We do not return until RpcMgmtStopServerListening
|
||
is called and all active remote procedure calls complete, or a fatal
|
||
error occurs in the runtime.
|
||
|
||
Arguments:
|
||
|
||
MinimumCallThreads - Supplies the minimum number of threads which
|
||
should be around to service remote procedure calls. A higher
|
||
value for this number will give more responsive service at the
|
||
cost of more threads.
|
||
|
||
MaxCalls - Supplies the maximum number of concurrent calls the rpc
|
||
server is willing to accept. This number must be greater than
|
||
or equal to the largest MaxCalls value specified to the
|
||
RpcServerUse* routines.
|
||
|
||
DontWait - Supplies a flag indicating whether or not to wait until
|
||
RpcMgmtStopServerListening has been called and all calls have
|
||
completed. A non-zero value indicates not to wait.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everything worked as expected. All active remote procedure
|
||
calls have completed. It is now safe to exit this process.
|
||
|
||
RPC_S_ALREADY_LISTENING - Another thread has already called
|
||
RpcServerListen and has not yet returned.
|
||
|
||
RPC_S_NO_PROTSEQS_REGISTERED - No protocol sequences have been
|
||
registered with the rpc server. As a consequence it is
|
||
impossible for the rpc server to receive any remote procedure
|
||
calls, hence, the error code.
|
||
|
||
RPC_S_MAX_CALLS_TOO_SMALL - The supplied value for MaxCalls is smaller
|
||
than the the supplied value for MinimumCallThreads, or the zero
|
||
was supplied for MaxCalls.
|
||
|
||
--*/
|
||
{
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Thread = ThreadSelf();
|
||
if (Thread)
|
||
{
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
}
|
||
|
||
return(GlobalRpcServer->ServerListen(MinimumCallThreads, MaxCalls,
|
||
DontWait));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerRegisterIf (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN UUID PAPI * MgrTypeUuid OPTIONAL,
|
||
IN RPC_MGR_EPV PAPI * MgrEpv OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by server application to register a manager
|
||
entry point vector and optionally an interface. If the interface
|
||
has not been registered, then it will be registered. If it has
|
||
already been registered, the manager entry point vector will be
|
||
added to it under the specified type uuid.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Supplies a description of the interface. This is actually
|
||
a pointer to an opaque data structure which the runtime knows
|
||
how to interpret.
|
||
|
||
MgrTypeUuid - Optionally supplies the type uuid for the specified
|
||
manager entry point vector. If no type uuid is supplied, then
|
||
the null uuid will be used as the type uuid.
|
||
|
||
MgrEpv - Optionally supplies a manager entry point vector corresponding
|
||
to the type uuid. If a manager entry point vector is not supplied,
|
||
then the manager entry point vector in the interface will be
|
||
used.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The specified rpc interface has been successfully
|
||
registered with the rpc server. It is now ready to accept
|
||
remote procedure calls.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to register
|
||
the rpc interface with the rpc server.
|
||
|
||
RPC_S_TYPE_ALREADY_REGISTERED - A manager entry point vector has
|
||
already been registered for the supplied rpc interface and
|
||
manager type UUID.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(GlobalRpcServer->RegisterInterface(
|
||
(RPC_SERVER_INTERFACE PAPI *) IfSpec,
|
||
(RPC_UUID PAPI *) MgrTypeUuid, MgrEpv, 0,
|
||
MAX_IF_CALLS, gMaxRpcSize, 0));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerRegisterIfEx (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN UUID PAPI * MgrTypeUuid,
|
||
IN RPC_MGR_EPV PAPI * MgrEpv,
|
||
IN unsigned int Flags,
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_IF_CALLBACK_FN PAPI *IfCallbackFn
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by server application to register a manager
|
||
entry point vector and an interface. If the interface
|
||
has not been registered, then it will be registered. If it has
|
||
already been registered, the manager entry point vector will be
|
||
added to it under the specified type uuid. If the IF_AUTOLISTEN flag
|
||
has been specified, then the registered interface will be treated as an
|
||
auto-listen interface.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Supplies a description of the interface. This is actually
|
||
a pointer to an opaque data structure which the runtime knows
|
||
how to interpret.
|
||
|
||
MgrTypeUuid - Optionally supplies the type uuid for the specified
|
||
manager entry point vector. If no type uuid is supplied, then
|
||
the null uuid will be used as the type uuid.
|
||
|
||
MgrEpv - Optionally supplies a manager entry point vector corresponding
|
||
to the type uuid. If a manager entry point vector is not supplied,
|
||
then the manager entry point vector in the interface will be
|
||
used.
|
||
|
||
Flags -
|
||
RPC_IF_OLE - the interface is an OLE interface. Calls need to be dispatched
|
||
to procnum 0
|
||
RPC_IF_AUTOLISTEN - the interface is an auto-listen inteface, calls may be
|
||
dispatched on this inteface as soon as it is registered.
|
||
|
||
MaxCalls -
|
||
Maximum number of calls that can be simulaneously dispatched on this interface
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The specified rpc interface has been successfully
|
||
registered with the rpc server. It is now ready to accept
|
||
remote procedure calls.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to register
|
||
the rpc interface with the rpc server.
|
||
|
||
RPC_S_TYPE_ALREADY_REGISTERED - A manager entry point vector has
|
||
already been registered for the supplied rpc interface and
|
||
manager type UUID.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
if (Flags & RPC_IF_OLE)
|
||
{
|
||
Flags |= RPC_IF_AUTOLISTEN ;
|
||
}
|
||
|
||
return(GlobalRpcServer->RegisterInterface(
|
||
(RPC_SERVER_INTERFACE PAPI *) IfSpec,
|
||
(RPC_UUID PAPI *) MgrTypeUuid, MgrEpv, Flags,
|
||
MaxCalls, gMaxRpcSize, IfCallbackFn));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerRegisterIf2 (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN UUID PAPI * MgrTypeUuid,
|
||
IN RPC_MGR_EPV PAPI * MgrEpv,
|
||
IN unsigned int Flags,
|
||
IN unsigned int MaxCalls,
|
||
IN unsigned int MaxRpcSize,
|
||
IN RPC_IF_CALLBACK_FN PAPI *IfCallbackFn
|
||
)
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
if (Flags & RPC_IF_OLE)
|
||
{
|
||
Flags |= RPC_IF_AUTOLISTEN ;
|
||
}
|
||
|
||
return(GlobalRpcServer->RegisterInterface(
|
||
(RPC_SERVER_INTERFACE PAPI *) IfSpec,
|
||
(RPC_UUID PAPI *) MgrTypeUuid, MgrEpv, Flags,
|
||
MaxCalls, MaxRpcSize, IfCallbackFn));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUnregisterIf (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN UUID PAPI * MgrTypeUuid, OPTIONAL
|
||
IN unsigned int WaitForCallsToComplete
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to unregister an interface
|
||
with the rpc server. Depending on what is specified for the manager
|
||
type uuid one or all of the manager entry point vectors will be removed
|
||
from the interface.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Supplies a description of the interface. This is actually
|
||
a pointer to an opaque data structure which the runtime knows
|
||
how to interpret.
|
||
|
||
MgrTypeUuid - Optionally supplies the type uuid of the manager entry
|
||
point vector to be removed. If this argument is not supplied,
|
||
then all manager entry point vectors for this interface will
|
||
be removed.
|
||
|
||
WaitForCallsToComplete - Supplies a flag indicating whether or not
|
||
this routine should wait for all calls to complete using the
|
||
interface and manager being unregistered. A non-zero value
|
||
indicates to wait.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The manager entry point vector(s) are(were) successfully
|
||
removed from the specified interface.
|
||
|
||
RPC_S_UNKNOWN_MGR_TYPE - The specified type uuid is not registered
|
||
with the interface.
|
||
|
||
RPC_S_UNKNOWN_IF - The specified interface is not registered with
|
||
the rpc server.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(GlobalRpcServer->UnregisterIf(
|
||
(RPC_SERVER_INTERFACE PAPI *) IfSpec,
|
||
(RPC_UUID PAPI *) MgrTypeUuid, WaitForCallsToComplete));
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUnregisterIfEx (
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN UUID PAPI * MgrTypeUuid, OPTIONAL
|
||
IN int RundownContextHandles
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Does the same as RpcServerUnregisterIf and in addition to that
|
||
will cleanup all context handles registered by this interface
|
||
provided that the interface is using strict_context_handles. If
|
||
the interface does not use strict context handles, this API will
|
||
return ERROR_INVALID_HANDLE, but the interface will be
|
||
unregistered. Unlike RpcServerUnregisterIf, this API requires the
|
||
IfSpec argument.
|
||
|
||
Arguments:
|
||
|
||
IfSpec - Supplies a description of the interface. This is actually
|
||
a pointer to an opaque data structure which the runtime knows
|
||
how to interpret.
|
||
|
||
MgrTypeUuid - Optionally supplies the type uuid of the manager entry
|
||
point vector to be removed. If this argument is not supplied,
|
||
then all manager entry point vectors for this interface will
|
||
be removed.
|
||
|
||
RundownContextHandles - if TRUE, the context handles belonging to
|
||
this interface will be rundown. If FALSE, only the runtime
|
||
portion of the context handle will be cleaned up, and the
|
||
server portion of the context handle will be left alone.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The manager entry point vector(s) are(were) successfully
|
||
removed from the specified interface.
|
||
|
||
RPC_S_UNKNOWN_MGR_TYPE - The specified type uuid is not registered
|
||
with the interface.
|
||
|
||
RPC_S_UNKNOWN_IF - The specified interface is not registered with
|
||
the rpc server.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS RpcStatus;
|
||
DestroyContextHandleCallbackContext CallbackContext;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (!ARGUMENT_PRESENT(IfSpec))
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
RpcStatus = RpcServerUnregisterIf(IfSpec,
|
||
MgrTypeUuid,
|
||
TRUE // WaitForCallsToComplete
|
||
);
|
||
|
||
if (RpcStatus != RPC_S_OK)
|
||
return RpcStatus;
|
||
|
||
CallbackContext.RpcInterfaceInformation = (RPC_SERVER_INTERFACE *) IfSpec;
|
||
CallbackContext.RundownContextHandles = RundownContextHandles;
|
||
RpcStatus = GlobalRpcServer->EnumerateAndCallEachAddress(
|
||
RPC_SERVER::actDestroyContextHandle,
|
||
&CallbackContext);
|
||
|
||
return RpcStatus;
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseAllProtseqsEx (
|
||
IN unsigned int MaxCalls,
|
||
IN void PAPI * SecurityDescriptor,
|
||
IN PRPC_POLICY Policy
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to add all rpc protocol
|
||
sequences supported by the current operating environment to the
|
||
rpc server. An endpoint will be dynamically selected for each rpc
|
||
protocol sequence. We will inquire the supported rpc protocol
|
||
sequences, and then let the RPC_SERVER class take care of adding
|
||
each one for us.
|
||
|
||
Arguments:
|
||
|
||
MaxCalls - Supplies a lower bound for the number of concurrent
|
||
remote procedure calls the server must be able to handle.
|
||
|
||
SecurityDescriptor - Optionally supplies a security descriptor to
|
||
place on the rpc protocol sequence (address) we are adding to
|
||
the rpc server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - All supported rpc protocol sequences have been added to
|
||
the rpc server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add all of
|
||
the supported rpc protocol sequences to the rpc server.
|
||
|
||
RPC_S_NO_PROTSEQS - The current system configuration does not
|
||
support any rpc protocol sequences.
|
||
|
||
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
||
invalid.
|
||
|
||
--*/
|
||
{
|
||
RPC_PROTSEQ_VECTOR * RpcProtseqVector;
|
||
RPC_STATUS Status;
|
||
unsigned int Index, ValidProtocolSequences = 0;
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Policy->Length < sizeof(RPC_POLICY))
|
||
{
|
||
return RPC_S_INVALID_BOUND ;
|
||
}
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
Status = RpcConfigInquireProtocolSequences(TRUE, &RpcProtseqVector);
|
||
if (Status != RPC_S_OK)
|
||
{
|
||
return(Status);
|
||
}
|
||
|
||
Policy->EndpointFlags |= RPC_C_DONT_FAIL;
|
||
|
||
for (Index = 0; Index < RpcProtseqVector->Count; Index++)
|
||
{
|
||
//
|
||
// Don't include nb protocols, ncadg_mq and ncacn_http
|
||
// in RpcServerUseAllProtseqs().
|
||
//
|
||
if ( (RpcpStringNCompare(RPC_CONST_STRING("ncacn_nb_"),
|
||
RpcProtseqVector->Protseq[Index],
|
||
9) == 0)
|
||
||(RpcpStringNCompare(RPC_CONST_STRING("ncadg_mq"),
|
||
RpcProtseqVector->Protseq[Index],
|
||
8) == 0)
|
||
#if !defined(APPLETALK_ON)
|
||
||(RpcpStringNCompare(RPC_CONST_STRING("ncacn_at_dsp"),
|
||
RpcProtseqVector->Protseq[Index],
|
||
12) == 0)
|
||
#endif
|
||
||(RpcpStringNCompare(RPC_CONST_STRING("ncacn_http"),
|
||
RpcProtseqVector->Protseq[Index],
|
||
10) == 0) )
|
||
{
|
||
continue;
|
||
}
|
||
|
||
Status = GlobalRpcServer->UseRpcProtocolSequence(NULL,
|
||
RpcProtseqVector->Protseq[Index], MaxCalls, 0,
|
||
SecurityDescriptor, Policy->EndpointFlags, Policy->NICFlags);
|
||
if ( Status == RPC_S_OK )
|
||
{
|
||
ValidProtocolSequences += 1;
|
||
}
|
||
else if ( ( Status == RPC_S_OUT_OF_MEMORY )
|
||
|| ( Status == RPC_S_INVALID_SECURITY_DESC )
|
||
|| ( Status == RPC_S_OUT_OF_RESOURCES ) )
|
||
{
|
||
RpcProtseqVectorFree(&RpcProtseqVector);
|
||
return(Status);
|
||
}
|
||
}
|
||
|
||
RpcProtseqVectorFree(&RpcProtseqVector);
|
||
|
||
if ( ValidProtocolSequences == 0 )
|
||
{
|
||
return(Status);
|
||
}
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseAllProtseqs (
|
||
IN unsigned int MaxCalls,
|
||
IN void PAPI * SecurityDescriptor OPTIONAL
|
||
)
|
||
{
|
||
RPC_POLICY Policy ;
|
||
|
||
Policy.Length = sizeof(RPC_POLICY) ;
|
||
Policy.EndpointFlags = 0;
|
||
Policy.NICFlags = 0;
|
||
|
||
return RpcServerUseAllProtseqsEx (MaxCalls, SecurityDescriptor, &Policy) ;
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseAllProtseqsIfEx (
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN void PAPI * SecurityDescriptor,
|
||
IN PRPC_POLICY Policy
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to add all protocol
|
||
sequences and endpoints specified in the header of an IDL file.
|
||
This information (from the IDL file) is specified by the interface
|
||
specification argument.
|
||
|
||
Arguments:
|
||
|
||
MaxCalls - Supplies a lower bound for the number of concurrent
|
||
remote procedure calls the server must be able to handle.
|
||
|
||
IfSpec - Supplies the interface specification from which we
|
||
should extract the rpc protocol sequence and end point
|
||
information to be used.
|
||
|
||
SecurityDescriptor - Optionally supplies a security descriptor to
|
||
place on the rpc protocol sequence (address) we are adding to
|
||
the rpc server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - All of the support rpc protocol sequences (and their
|
||
associated endpoints) have been added to the rpc server.
|
||
|
||
RPC_S_NO_PROTSEQS - None of the specified rpc protocol sequences
|
||
are supported by the rpc server, or no rpc protocol sequences
|
||
were specified.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
|
||
requested rpc protocol sequence to the rpc server.
|
||
|
||
RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
|
||
syntactically invalid.
|
||
|
||
RPC_S_DUPLICATE_ENDPOINT - One of the supplied endpoints has already
|
||
been added to this rpc server.
|
||
|
||
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
||
invalid.
|
||
|
||
--*/
|
||
{
|
||
RPC_SERVER_INTERFACE PAPI * RpcServerInfo;
|
||
unsigned int SupportedProtseqCount = 0;
|
||
unsigned int Index;
|
||
RPC_STATUS Status;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Policy->Length < sizeof(RPC_POLICY))
|
||
{
|
||
return RPC_S_INVALID_BOUND ;
|
||
}
|
||
|
||
RpcServerInfo = (RPC_SERVER_INTERFACE PAPI *) IfSpec;
|
||
|
||
if (RpcServerInfo->RpcProtseqEndpointCount == 0)
|
||
{
|
||
return(RPC_S_NO_PROTSEQS);
|
||
}
|
||
|
||
Policy->EndpointFlags |= RPC_C_DONT_FAIL;
|
||
|
||
for (Index = 0; Index < RpcServerInfo->RpcProtseqEndpointCount;
|
||
Index++)
|
||
{
|
||
Status = RpcServerUseProtseqEpExA(
|
||
RpcServerInfo->RpcProtseqEndpoint[Index].RpcProtocolSequence,
|
||
MaxCalls, RpcServerInfo->RpcProtseqEndpoint[Index].Endpoint,
|
||
SecurityDescriptor, Policy);
|
||
if ( Status == RPC_S_OK )
|
||
{
|
||
SupportedProtseqCount += 1;
|
||
}
|
||
else if ( ( Status == RPC_S_OUT_OF_MEMORY )
|
||
|| ( Status == RPC_S_INVALID_SECURITY_DESC )
|
||
|| ( Status == RPC_S_OUT_OF_RESOURCES ) )
|
||
{
|
||
return(Status);
|
||
}
|
||
}
|
||
|
||
if ( SupportedProtseqCount == 0 )
|
||
{
|
||
if ( Status == RPC_S_PROTSEQ_NOT_SUPPORTED )
|
||
{
|
||
return(RPC_S_NO_PROTSEQS);
|
||
}
|
||
return(Status);
|
||
}
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseAllProtseqsIf (
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN void PAPI * SecurityDescriptor OPTIONAL
|
||
)
|
||
{
|
||
RPC_POLICY Policy ;
|
||
|
||
Policy.Length = sizeof(RPC_POLICY) ;
|
||
Policy.EndpointFlags = 0;
|
||
Policy.NICFlags = 0;
|
||
|
||
return RpcServerUseAllProtseqsIfEx ( MaxCalls, IfSpec, SecurityDescriptor, &Policy) ;
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcServerUseProtseq2 (
|
||
IN unsigned short PAPI *NetworkAddress,
|
||
IN unsigned short PAPI *Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN void PAPI *SecurityDescriptor,
|
||
IN void *pPolicy
|
||
)
|
||
{
|
||
PRPC_POLICY Policy = (PRPC_POLICY) pPolicy;
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
if (Policy->Length < sizeof(RPC_POLICY))
|
||
{
|
||
return RPC_S_INVALID_BOUND ;
|
||
}
|
||
|
||
return(GlobalRpcServer->UseRpcProtocolSequence(NetworkAddress, Protseq, MaxCalls, 0,
|
||
SecurityDescriptor, Policy->EndpointFlags, Policy->NICFlags));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseProtseqEx (
|
||
IN unsigned short PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN void PAPI * SecurityDescriptor,
|
||
IN PRPC_POLICY Policy
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by a server application to add an rpc protocol
|
||
sequence to the rpc server. An endpoint will be dynamically selected
|
||
for this rpc protocol sequence. What we do is to let the RPC_SERVER
|
||
class take care of most of the work.
|
||
|
||
Arguments:
|
||
|
||
Protseq - Supplies the rpc protocol sequence we wish to add. An
|
||
rpc protocol sequence contains two pieces of information we
|
||
are interested in: the rpc protocol (connection, datagram, or
|
||
shared memory) and the transport interface requested.
|
||
|
||
MaxCalls - Supplies a lower bound for the number of concurrent
|
||
remote procedure calls the server must be able to handle.
|
||
|
||
SecurityDescriptor - Optionally supplies a security descriptor to
|
||
place on the rpc protocol sequence (address) we are adding to
|
||
the rpc server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The requested rpc protocol sequence has been added to
|
||
the rpc server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
|
||
requested rpc protocol sequence to the rpc server.
|
||
|
||
RPC_S_PROTSEQ_NOT_SUPPORTED - The specified rpc protocol sequence
|
||
is not supported (but it appears to be valid).
|
||
|
||
RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
|
||
syntactically invalid.
|
||
|
||
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
||
invalid.
|
||
|
||
--*/
|
||
{
|
||
return I_RpcServerUseProtseq2(NULL, Protseq, MaxCalls, SecurityDescriptor, Policy);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseProtseq (
|
||
IN unsigned short PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN void PAPI * SecurityDescriptor OPTIONAL
|
||
)
|
||
{
|
||
RPC_POLICY Policy ;
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Policy.Length = sizeof(RPC_POLICY) ;
|
||
Policy.EndpointFlags = 0;
|
||
Policy.NICFlags = 0;
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
return RpcServerUseProtseqEx(Protseq, MaxCalls, SecurityDescriptor, &Policy) ;
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcServerUseProtseqEp2 (
|
||
IN unsigned short PAPI * NetworkAddress,
|
||
IN unsigned short PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_CHAR PAPI * Endpoint,
|
||
IN void PAPI * SecurityDescriptor,
|
||
IN void *pPolicy
|
||
)
|
||
{
|
||
PRPC_POLICY Policy = (PRPC_POLICY) pPolicy;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Policy->Length < sizeof(RPC_POLICY))
|
||
{
|
||
return RPC_S_INVALID_BOUND ;
|
||
}
|
||
|
||
return(GlobalRpcServer->UseRpcProtocolSequence(NetworkAddress, Protseq, MaxCalls,
|
||
Endpoint, SecurityDescriptor,
|
||
Policy->EndpointFlags, Policy->NICFlags));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseProtseqEpEx (
|
||
IN unsigned short PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN unsigned short PAPI * Endpoint,
|
||
IN void PAPI * SecurityDescriptor,
|
||
IN PRPC_POLICY Policy
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by a server application to add an rpc protocol
|
||
sequence and an endpoint to the rpc server. What we do is to let
|
||
the RPC_SERVER class take care of most of the work.
|
||
|
||
Arguments:
|
||
|
||
Protseq - Supplies the rpc protocol sequence we wish to add. An
|
||
rpc protocol sequence contains two pieces of information we
|
||
are interested in: the rpc protocol (connection, datagram, or
|
||
shared memory) and the transport interface requested.
|
||
|
||
MaxCalls - Supplies a lower bound for the number of concurrent
|
||
remote procedure calls the server must be able to handle.
|
||
|
||
Endpoint - Supplies the endpoint to use for this rpc protocol
|
||
sequence.
|
||
|
||
SecurityDescriptor - Optionally supplies a security descriptor to
|
||
place on the rpc protocol sequence (address) we are adding to
|
||
the rpc server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The requested rpc protocol sequence has been added to
|
||
the rpc server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
|
||
requested rpc protocol sequence to the rpc server.
|
||
|
||
RPC_S_PROTSEQ_NOT_SUPPORTED - The specified rpc protocol sequence
|
||
is not supported (but it appears to be valid).
|
||
|
||
RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
|
||
syntactically invalid.
|
||
|
||
RPC_S_INVALID_ENDPOINT_FORMAT -
|
||
|
||
RPC_S_DUPLICATE_ENDPOINT - The supplied endpoint has already been
|
||
added to this rpc server.
|
||
|
||
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
||
invalid.
|
||
|
||
--*/
|
||
{
|
||
return I_RpcServerUseProtseqEp2 (NULL, Protseq, MaxCalls, Endpoint,
|
||
SecurityDescriptor, (void *) Policy);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseProtseqEp (
|
||
IN RPC_CHAR PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_CHAR PAPI * Endpoint,
|
||
IN void PAPI * SecurityDescriptor
|
||
)
|
||
{
|
||
RPC_POLICY Policy ;
|
||
|
||
Policy.Length = sizeof(RPC_POLICY) ;
|
||
Policy.EndpointFlags = 0;
|
||
Policy.NICFlags = 0;
|
||
|
||
return RpcServerUseProtseqEpEx(Protseq, MaxCalls, Endpoint,
|
||
SecurityDescriptor, &Policy) ;
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseProtseqIfEx (
|
||
IN unsigned short PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN void PAPI * SecurityDescriptor,
|
||
IN PRPC_POLICY Policy
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to one of the protocol
|
||
sequences (and its associated endpoint) specified in the header of
|
||
an IDL file. This information (from the IDL file) is specified by
|
||
the interface specification argument.
|
||
|
||
Arguments:
|
||
|
||
Protseq - Supplies the rpc protocol sequence to be added to
|
||
the rpc server. The list of rpc protocol sequence -- endpoint
|
||
pairs in the interface specification will be searched to find
|
||
the corresponding endpoint.
|
||
|
||
MaxCalls - Supplies a lower bound for the number of concurrent
|
||
remote procedure calls the server must be able to handle.
|
||
|
||
IfSpec - Supplies the interface specification from which we
|
||
should extract the rpc protocol sequence and end point
|
||
information to be used.
|
||
|
||
SecurityDescriptor - Optionally supplies a security descriptor to
|
||
place on the rpc protocol sequence (address) we are adding to
|
||
the rpc server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The requested rpc protocol sequence (and its associated
|
||
endpoint) has been added to the rpc server.
|
||
|
||
RPC_S_PROTSEQ_NOT_SUPPORTED - The supplied rpc protocol sequence
|
||
is not supported by the rpc server.
|
||
|
||
RPC_S_PROTSEQ_NOT_SUPPORTED - The supplied rpc protocol sequence is not
|
||
in the list of rpc protocol sequences in the interface specification.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to add the
|
||
requested rpc protocol sequence to the rpc server.
|
||
|
||
RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is
|
||
syntactically invalid.
|
||
|
||
RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
|
||
invalid.
|
||
|
||
--*/
|
||
{
|
||
RPC_SERVER_INTERFACE PAPI * RpcServerInfo;
|
||
unsigned int Index, EndpointsRegistered = 0;
|
||
RPC_STATUS RpcStatus;
|
||
#ifdef UNICODE
|
||
UNICODE_STRING UnicodeString;
|
||
#endif // UNICODE
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Policy->Length < sizeof(RPC_POLICY))
|
||
{
|
||
return RPC_S_INVALID_BOUND ;
|
||
}
|
||
|
||
|
||
RpcServerInfo = (RPC_SERVER_INTERFACE PAPI *) IfSpec;
|
||
|
||
for (Index = 0; Index < RpcServerInfo->RpcProtseqEndpointCount;
|
||
Index++)
|
||
{
|
||
#ifdef UNICODE
|
||
RpcStatus = AnsiToUnicodeString(
|
||
RpcServerInfo->RpcProtseqEndpoint[Index].RpcProtocolSequence,
|
||
&UnicodeString);
|
||
if (RpcStatus != RPC_S_OK)
|
||
return(RpcStatus);
|
||
if ( RpcpStringCompare(Protseq, UnicodeString.Buffer) == 0 )
|
||
#else // UNICODE
|
||
if ( RpcpStringCompare(Protseq,
|
||
RpcServerInfo->RpcProtseqEndpoint[Index].RpcProtocolSequence)
|
||
== 0 )
|
||
#endif // UNICODE
|
||
{
|
||
#ifdef UNICODE
|
||
RtlFreeUnicodeString(&UnicodeString);
|
||
#endif
|
||
RpcStatus = RpcServerUseProtseqEpExA(
|
||
RpcServerInfo->RpcProtseqEndpoint[ Index].RpcProtocolSequence,
|
||
MaxCalls, RpcServerInfo->RpcProtseqEndpoint[Index].Endpoint,
|
||
SecurityDescriptor, Policy);
|
||
if ( RpcStatus != RPC_S_OK )
|
||
{
|
||
return(RpcStatus);
|
||
}
|
||
EndpointsRegistered += 1;
|
||
}
|
||
#ifdef UNICODE
|
||
else
|
||
{
|
||
RtlFreeUnicodeString(&UnicodeString);
|
||
}
|
||
#endif // UNICODE
|
||
}
|
||
|
||
if ( EndpointsRegistered == 0 )
|
||
{
|
||
return(RPC_S_PROTSEQ_NOT_SUPPORTED);
|
||
}
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerUseProtseqIf (
|
||
IN unsigned short PAPI * Protseq,
|
||
IN unsigned int MaxCalls,
|
||
IN RPC_IF_HANDLE IfSpec,
|
||
IN void PAPI * SecurityDescriptor
|
||
)
|
||
{
|
||
RPC_POLICY Policy ;
|
||
|
||
Policy.Length = sizeof(RPC_POLICY) ;
|
||
Policy.EndpointFlags = 0;
|
||
Policy.NICFlags = 0;
|
||
|
||
return RpcServerUseProtseqIfEx (Protseq, MaxCalls, IfSpec,
|
||
SecurityDescriptor, &Policy) ;
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtStatsVectorFree (
|
||
IN OUT RPC_STATS_VECTOR ** StatsVector
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to free the statistics vector obtained from
|
||
RpcMgmtInqStats.
|
||
|
||
Arguments:
|
||
|
||
StatsVector - Supplies the statistics vector to be freed; on return,
|
||
the pointer this pointer points to will be set to zero.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The operation completed successfully.
|
||
|
||
RPC_S_INVALID_ARG - The specified statistics vectors does not contain
|
||
the address of a statistics vector.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
if (StatsVector == 0)
|
||
return(RPC_S_INVALID_ARG);
|
||
|
||
RpcpFarFree(*StatsVector);
|
||
*StatsVector = 0;
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
|
||
|
||
#define MAX_STATISTICS 4
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtInqStats (
|
||
IN RPC_BINDING_HANDLE Binding,
|
||
OUT RPC_STATS_VECTOR ** Statistics
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to inquire statistics about the server. In
|
||
particular, the statistics consist of the number of remote procedure
|
||
calls received by this server, the number of remote procedure calls
|
||
initiated by this server (callbacks), the number of network packets
|
||
received, and the number of network packets sent.
|
||
|
||
Arguments:
|
||
|
||
Binding - Optionally supplies a binding handle to the server. If this
|
||
argument is not supplied, the local application is queried.
|
||
|
||
Statistics - Returns the statistics vector for this server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everything worked just fine, and you now know the
|
||
statistics for this server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
|
||
the operation.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied binding is not zero.
|
||
|
||
--*/
|
||
{
|
||
unsigned long Status = 0;
|
||
unsigned long Count = MAX_STATISTICS;
|
||
unsigned long StatsVector[MAX_STATISTICS];
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Binding == 0)
|
||
{
|
||
*Statistics = (RPC_STATS_VECTOR *) RpcpFarAllocate(sizeof(RPC_STATS_VECTOR)
|
||
+ 3 * sizeof(unsigned long));
|
||
if (*Statistics == 0)
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
|
||
(*Statistics)->Count = 4;
|
||
GlobalRpcServer->InquireStatistics(*Statistics);
|
||
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
_rpc_mgmt_inq_stats(Binding, &Count, StatsVector, &Status);
|
||
|
||
if ( Status == RPC_S_OK )
|
||
{
|
||
*Statistics = (RPC_STATS_VECTOR __RPC_FAR *) RpcpFarAllocate(
|
||
sizeof(RPC_STATS_VECTOR) + sizeof(unsigned long)
|
||
* (MAX_STATISTICS - 1));
|
||
if ( *Statistics == 0 )
|
||
{
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
|
||
for ((*Statistics)->Count = 0; (*Statistics)->Count < Count
|
||
&& (*Statistics)->Count < MAX_STATISTICS;
|
||
(*Statistics)->Count++)
|
||
{
|
||
(*Statistics)->Stats[(*Statistics)->Count] =
|
||
StatsVector[(*Statistics)->Count];
|
||
}
|
||
}
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtIsServerListening (
|
||
IN RPC_BINDING_HANDLE Binding
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
An application will use this routine to determine whether or not
|
||
the server is listening.
|
||
|
||
Arguments:
|
||
|
||
Binding - Optionally supplies a binding handle to the server. If this
|
||
argument is not supplied, the local application is queried.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The server is listening.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied binding is not zero.
|
||
|
||
RPC_S_NOT_LISTENING - The server is not listening.
|
||
|
||
--*/
|
||
{
|
||
unsigned long Result;
|
||
unsigned long Status = 0;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Binding == 0)
|
||
{
|
||
if (GlobalRpcServer->IsServerListening() == 0)
|
||
return(RPC_S_NOT_LISTENING);
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
Result = _rpc_mgmt_is_server_listening(Binding, &Status);
|
||
|
||
if (Status == RPC_S_OK)
|
||
{
|
||
return((Result == 1) ? RPC_S_OK : RPC_S_NOT_LISTENING);
|
||
}
|
||
if ( (Status == RPC_S_SERVER_UNAVAILABLE)
|
||
|| (Status == RPC_S_SERVER_TOO_BUSY) )
|
||
{
|
||
return (RPC_S_NOT_LISTENING);
|
||
}
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtStopServerListening (
|
||
IN RPC_BINDING_HANDLE Binding
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by an application to stop the rpc server from
|
||
accepting any more remote procedure calls. Currently active remote
|
||
procedure calls are allowed to complete.
|
||
|
||
Arguments:
|
||
|
||
Binding - Optionally supplies a binding handle to the server. If this
|
||
argument is not supplied, the local server is stopped.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The server has been successfully notified that it should
|
||
stop listening for remote procedure calls. No new remote procedure
|
||
calls will be accepted after this routine returns. RpcServerListen
|
||
will return after all active calls have completed.
|
||
|
||
RPC_S_NOT_LISTENING - A thread has not called RpcServerListen (and
|
||
not returned) yet.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (Binding == 0)
|
||
{
|
||
return(GlobalRpcServer->StopServerListening());
|
||
}
|
||
|
||
_rpc_mgmt_stop_server_listening(Binding, (unsigned long *)&Status);
|
||
|
||
return(Status);
|
||
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtWaitServerListen (
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs the wait that RpcServerListen normally performs
|
||
when the DontWait flag is not set. An application must call this
|
||
routine only after RpcServerListen has been called with the DontWait
|
||
flag set. We do not return until RpcMgmtStopServerListening is called
|
||
and all active remote procedure calls complete, or a fatal error occurs
|
||
in the runtime.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everything worked as expected. All active remote procedure
|
||
calls have completed. It is now safe to exit this process.
|
||
|
||
RPC_S_ALREADY_LISTENING - Another thread has already called
|
||
RpcMgmtWaitServerListen and has not yet returned.
|
||
|
||
RPC_S_NOT_LISTENING - RpcServerListen has not yet been called.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(GlobalRpcServer->WaitServerListen());
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcBindingInqDynamicEndpointA (
|
||
IN RPC_BINDING_HANDLE Binding,
|
||
OUT unsigned char PAPI * PAPI * DynamicEndpoint
|
||
)
|
||
{
|
||
#ifdef UNICODE
|
||
return (RPC_S_CANNOT_SUPPORT);
|
||
#else
|
||
USES_CONVERSION;
|
||
CNlDelUnicodeAnsi thunkedDynamicEndpoint;
|
||
RPC_STATUS RpcStatus;
|
||
|
||
RpcStatus = I_RpcBindingInqDynamicEndpointW(Binding, thunkedDynamicEndpoint);
|
||
if (RpcStatus == RPC_S_OK)
|
||
{
|
||
ATTEMPT_CONVERT_W2A_OPTIONAL(thunkedDynamicEndpoint, DynamicEndpoint);
|
||
}
|
||
return RpcStatus;
|
||
#endif
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcBindingInqDynamicEndpointW (
|
||
IN RPC_BINDING_HANDLE Binding,
|
||
OUT unsigned short PAPI * PAPI * DynamicEndpoint
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to inquire the dynamic endpoint from a binding
|
||
handle. The only binding handles which will have dynamic endpoints
|
||
are those which are create from rpc addresses which have dynamic
|
||
endpoints. This routine will be used for one purpose and one purpose
|
||
only: RpcEpRegister and RpcEpRegisterNoReplace need to know which
|
||
binding handles have dynamic endpoints; only binding handles with
|
||
dynamic endpoints get placed into the endpoint mapper database.
|
||
|
||
Arguments:
|
||
|
||
Binding - Supplies the binding handle from which we wish to obtain
|
||
the dynamic endpoint.
|
||
|
||
DynamicEndpoint - Returns a pointer to a string containing the dynamic
|
||
endpoint for this binding handle if it has one; otherwise, it
|
||
will be zero. If a string is return, it must be freed using
|
||
RpcStringFree.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The operation completed successfully. This does not
|
||
indicate whether or not the binding handle has a dynamic endpoint.
|
||
To determine that, you must check whether *DynamicEndpoint is
|
||
equal to zero.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to duplicate
|
||
the dynamic endpoint.
|
||
|
||
RPC_S_INVALID_BINDING - The binding argument does not specify a binding
|
||
handle.
|
||
|
||
--*/
|
||
{
|
||
BINDING_HANDLE * BindingHandle;
|
||
#ifndef UNICODE
|
||
USES_CONVERSION;
|
||
COutDelThunk thunkedDynamicEndpoint;
|
||
RPC_STATUS RpcStatus;
|
||
#endif
|
||
|
||
InitializeIfNecessary();
|
||
|
||
BindingHandle = (BINDING_HANDLE *) Binding;
|
||
if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
|
||
return(RPC_S_INVALID_BINDING);
|
||
|
||
#ifdef UNICODE
|
||
return (BindingHandle->InquireDynamicEndpoint(DynamicEndpoint));
|
||
#else
|
||
RpcStatus = BindingHandle->InquireDynamicEndpoint(thunkedDynamicEndpoint);
|
||
if (RpcStatus == RPC_S_OK)
|
||
{
|
||
ATTEMPT_OUT_THUNK_OPTIONAL(thunkedDynamicEndpoint, DynamicEndpoint);
|
||
}
|
||
return RpcStatus;
|
||
#endif
|
||
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerRegisterAuthInfo (
|
||
IN unsigned short PAPI * ServerPrincName,
|
||
IN unsigned long AuthnSvc,
|
||
IN RPC_AUTH_KEY_RETRIEVAL_FN GetKeyFn, OPTIONAL
|
||
IN void PAPI * Arg OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to indicate to the runtime
|
||
what authentication service to use for authenticating remote procedure
|
||
calls. This routine should be called once for each pair of authentication
|
||
service and principal name which the server wishes to use for
|
||
authentication. In order for an client to be able to talk with an
|
||
authenticated server, the authentication service specified by the client
|
||
must be one of the ones registered by the server. Attempting to
|
||
register the same authentication service and principal name will not
|
||
result in an error.
|
||
|
||
Arguments:
|
||
|
||
ServerPrincName - Supplies the principal name for the server.
|
||
|
||
AuthnSvc - Supplies an authentication service to use when the server
|
||
receives a remote procedure call.
|
||
|
||
GetKeyFn - Optionally supplies a routine to be used when the runtime
|
||
needs an encryption key.
|
||
|
||
Arg - Optionally supplies an argument to be passed to the routine used
|
||
to get keys each time it is called.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - The authentication service and server principal name have
|
||
been registered with the runtime.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
|
||
operation.
|
||
|
||
RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
|
||
not supported.
|
||
|
||
--*/
|
||
{
|
||
THREAD *Thread;
|
||
InitializeIfNecessary();
|
||
|
||
Thread = ThreadSelf();
|
||
if (Thread)
|
||
{
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
}
|
||
|
||
return(GlobalRpcServer->RegisterAuthInformation(ServerPrincName,
|
||
AuthnSvc, GetKeyFn, Arg));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcBindingInqAuthClient (
|
||
IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
|
||
OUT RPC_AUTHZ_HANDLE PAPI * Privs,
|
||
OUT unsigned short PAPI * PAPI * PrincName, OPTIONAL
|
||
OUT unsigned long PAPI * AuthnLevel, OPTIONAL
|
||
OUT unsigned long PAPI * AuthnSvc, OPTIONAL
|
||
OUT unsigned long PAPI * AuthzSvc OPTIONAL
|
||
)
|
||
{
|
||
return RpcBindingInqAuthClientEx( ClientBinding,
|
||
Privs,
|
||
PrincName,
|
||
AuthnLevel,
|
||
AuthnSvc,
|
||
AuthzSvc,
|
||
0
|
||
);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcBindingInqAuthClientEx (
|
||
IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
|
||
OUT RPC_AUTHZ_HANDLE PAPI * Privs,
|
||
OUT unsigned short PAPI * PAPI * ServerPrincName, OPTIONAL
|
||
OUT unsigned long PAPI * AuthnLevel, OPTIONAL
|
||
OUT unsigned long PAPI * AuthnSvc, OPTIONAL
|
||
OUT unsigned long PAPI * AuthzSvc, OPTIONAL
|
||
IN unsigned long Flags
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to obtain the authorization
|
||
information about a client making an authenticated remote procedure
|
||
call.
|
||
|
||
Arguments:
|
||
|
||
ClientBinding - Optionally supplies a binding handle on the server
|
||
side which indicates for which remote procedure call we wish to
|
||
obtain authorization information. If no binding handle is supplied,
|
||
then it is taken to be the remote procedure call currently being
|
||
handled by this server thread.
|
||
|
||
Privs - Returns a handle to the privileges information for the client
|
||
thread which made the remote procedure call.
|
||
|
||
ServerPrincName - Optionally returns the server principal name specified
|
||
by the client application.
|
||
|
||
AuthnLevel - Optionally returns the authentication level requested
|
||
by the client application.
|
||
|
||
AuthnSvc - Optionally returns the authentication service requested by
|
||
the client application.
|
||
|
||
AuthzSvc - Optionally returns the authorization service requested by
|
||
the client application.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - We successfully obtained the requested authentication and
|
||
authorization information.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied binding handle (as the binding
|
||
argument) is not a valid binding handle.
|
||
|
||
RPC_S_WRONG_KIND_OF_BINDING - The binding handle is not a binding handle
|
||
on the server side.
|
||
|
||
RPC_S_BINDING_HAS_NO_AUTH - The remote procedure call is not
|
||
authenticated.
|
||
|
||
RPC_S_NO_CALL_ACTIVE - No binding handle was supplied and there is no
|
||
call active for this server thread.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
|
||
operation.
|
||
|
||
--*/
|
||
{
|
||
SCALL * SCall;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (ARGUMENT_PRESENT(ClientBinding))
|
||
{
|
||
SCall = (SCALL *) ClientBinding;
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
{
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if ( SCall == 0 )
|
||
{
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
}
|
||
|
||
return SCall->InquireAuthClient(Privs,
|
||
ServerPrincName,
|
||
AuthnLevel,
|
||
AuthnSvc,
|
||
AuthzSvc,
|
||
Flags
|
||
);
|
||
}
|
||
|
||
RPCRTAPI
|
||
RPC_STATUS
|
||
RPC_ENTRY
|
||
RpcServerInqCallAttributesW (
|
||
IN RPC_BINDING_HANDLE ClientBinding, OPTIONAL
|
||
IN OUT void *RpcCallAttributes
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
A server application will use this routine to obtain the security context
|
||
attributes for the calling client.
|
||
|
||
Arguments:
|
||
|
||
ClientBinding - Optionally supplies a binding handle on the server
|
||
side which indicates for which remote procedure call we wish to
|
||
obtain authorization information. If no binding handle is supplied,
|
||
then it is taken to be the remote procedure call currently being
|
||
handled by this server thread.
|
||
|
||
RpcCallAttributes - a pointer to
|
||
RPC_CALL_ATTRIBUTES_V1_W structure. The Version
|
||
member must be initialized.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK for success of RPC_S_* /Win32 error code for error. EEInfo is
|
||
supplied. If the function fails, the contents of
|
||
RpcCallAttributes is undefined.
|
||
--*/
|
||
{
|
||
SCALL * SCall;
|
||
RPC_CALL_ATTRIBUTES_V1 *CallAttributes;
|
||
|
||
CallAttributes =
|
||
(RPC_CALL_ATTRIBUTES_V1 *)RpcCallAttributes;
|
||
|
||
if (CallAttributes->Version != 1)
|
||
return ERROR_INVALID_PARAMETER;
|
||
|
||
if (CallAttributes->Flags & RPC_QUERY_SERVER_PRINCIPAL_NAME)
|
||
{
|
||
if ((CallAttributes->ServerPrincipalName == NULL) &&
|
||
(CallAttributes->ServerPrincipalNameBufferLength != 0))
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
}
|
||
|
||
if (CallAttributes->Flags & RPC_QUERY_CLIENT_PRINCIPAL_NAME)
|
||
{
|
||
if ((CallAttributes->ClientPrincipalName == NULL) &&
|
||
(CallAttributes->ClientPrincipalNameBufferLength != 0))
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
}
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (ARGUMENT_PRESENT(ClientBinding))
|
||
{
|
||
SCall = (SCALL *) ClientBinding;
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
{
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if ( SCall == 0 )
|
||
{
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
}
|
||
|
||
return SCall->InquireCallAttributes(CallAttributes);
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcImpersonateClient (
|
||
IN RPC_BINDING_HANDLE ClientBinding OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
Return Values:
|
||
|
||
--*/
|
||
{
|
||
SCALL * SCall;
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
ASSERT(!RpcpCheckHeap());
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
if ( ClientBinding == 0 )
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if (SCall == 0)
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) ClientBinding;
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
|
||
return(SCall->ImpersonateClient());
|
||
}
|
||
|
||
// the handle to the authz.dll. Protected by the global mutex. Once initialized,
|
||
// never uninitialized
|
||
HMODULE AuthzDllHandle = NULL;
|
||
|
||
// pointer to the AuthzInitializeContextFromToken function from authz.dll. Once
|
||
// initialized, never uninitialized
|
||
AuthzInitializeContextFromTokenFnType AuthzInitializeContextFromTokenFn = NULL;
|
||
|
||
// pointer to the AuthzInitializeContextFromSid function from authz.dll. Once
|
||
// initialized, never uninitialized
|
||
AuthzInitializeContextFromSidFnType AuthzInitializeContextFromSidFn = NULL;
|
||
|
||
// pointer to the AuthzInitializeContextFromContext function from authz.dll. Once
|
||
// initialized, never uninitialized
|
||
AuthzInitializeContextFromAuthzContextFnType AuthzInitializeContextFromAuthzContextFn = NULL;
|
||
|
||
// pointer to the AuthzInitializeContextFromToken function from authz.dll. Once
|
||
// initialized, never uninitialized
|
||
AuthzFreeContextFnType AuthzFreeContextFn = NULL;
|
||
|
||
// the dummy resource manager with NULL callbacks for everything. Protected
|
||
// by the global mutex. Once initialized, never uninitialized
|
||
AUTHZ_RESOURCE_MANAGER_HANDLE DummyResourceManager = NULL;
|
||
|
||
typedef struct tagProcLoadArgs
|
||
{
|
||
char *ProcName;
|
||
PVOID *ProcRoutine;
|
||
} ProcLoadArgs;
|
||
|
||
const ProcLoadArgs AuthzProcs[4] = {
|
||
{"AuthzInitializeContextFromToken", (PVOID *)&AuthzInitializeContextFromTokenFn},
|
||
{"AuthzInitializeContextFromAuthzContext", (PVOID *)&AuthzInitializeContextFromAuthzContextFn},
|
||
{"AuthzInitializeContextFromSid", (PVOID *)&AuthzInitializeContextFromSidFn},
|
||
{"AuthzFreeContext", (PVOID *) &AuthzFreeContextFn}
|
||
};
|
||
|
||
RPC_STATUS
|
||
InitializeAuthzSupportIfNecessary (
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Perform initialization required for Authz functions to work. Everybody
|
||
should call that before they use any Authz functionality.
|
||
|
||
Arguments:
|
||
|
||
Return Values:
|
||
RPC_S_OK for success and RPC_S_* for the rest
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status;
|
||
int i;
|
||
|
||
if (AuthzDllHandle)
|
||
return RPC_S_OK;
|
||
|
||
GlobalMutexRequest();
|
||
|
||
if (AuthzDllHandle)
|
||
{
|
||
GlobalMutexClear();
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
AuthzDllHandle = LoadLibrary(L"Authz.dll");
|
||
if (AuthzDllHandle)
|
||
{
|
||
Status = RPC_S_OK;
|
||
for (i = 0; i < (sizeof(AuthzProcs) / sizeof(AuthzProcs[0])); i ++)
|
||
{
|
||
*(AuthzProcs[i].ProcRoutine) = GetProcAddress(AuthzDllHandle,
|
||
AuthzProcs[i].ProcName);
|
||
|
||
if (*(AuthzProcs[i].ProcRoutine) == NULL)
|
||
{
|
||
Status = GetLastError();
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
Status,
|
||
EEInfoDLInitializeAuthzSupportIfNecessary20,
|
||
AuthzProcs[i].ProcName);
|
||
FreeLibrary(AuthzDllHandle);
|
||
AuthzDllHandle = NULL;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Status = GetLastError();
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
Status,
|
||
EEInfoDLInitializeAuthzSupportIfNecessary10,
|
||
L"Authz.dll");
|
||
}
|
||
|
||
GlobalMutexClear();
|
||
|
||
return Status;
|
||
}
|
||
|
||
typedef AUTHZAPI
|
||
BOOL
|
||
(WINAPI *AuthzInitializeResourceManagerFnType) (
|
||
IN DWORD AuthzFlags,
|
||
IN PFN_AUTHZ_DYNAMIC_ACCESS_CHECK pfnAccessCheck OPTIONAL,
|
||
IN PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS pfnComputeDynamicGroups OPTIONAL,
|
||
IN PFN_AUTHZ_FREE_DYNAMIC_GROUPS pfnFreeDynamicGroups OPTIONAL,
|
||
IN PCWSTR szResourceManagerName,
|
||
OUT PAUTHZ_RESOURCE_MANAGER_HANDLE pAuthzResourceManager
|
||
);
|
||
|
||
RPC_STATUS
|
||
CreateDummyResourceManagerIfNecessary (
|
||
void
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Perform initialization of the dummy resource manager. Any function that
|
||
uses the dummy resource manager must call this function beforehand.
|
||
This function must be called after InitializeAuthzSupportIfNecessary
|
||
|
||
Arguments:
|
||
|
||
Return Values:
|
||
RPC_S_OK for success and RPC_S_* for the rest
|
||
|
||
--*/
|
||
{
|
||
AuthzInitializeResourceManagerFnType AuthzInitializeResourceManagerFn;
|
||
RPC_STATUS Status;
|
||
BOOL Result;
|
||
|
||
// this function must be called after InitializeAuthzSupportIfNecessary
|
||
ASSERT(AuthzDllHandle);
|
||
|
||
if (DummyResourceManager)
|
||
return RPC_S_OK;
|
||
|
||
GlobalMutexRequest();
|
||
|
||
if (DummyResourceManager)
|
||
{
|
||
GlobalMutexClear();
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
AuthzInitializeResourceManagerFn
|
||
= (AuthzInitializeResourceManagerFnType) GetProcAddress(AuthzDllHandle,
|
||
"AuthzInitializeResourceManager");
|
||
|
||
if (AuthzInitializeResourceManagerFn == NULL)
|
||
{
|
||
Status = GetLastError();
|
||
RpcpErrorAddRecord(EEInfoGCRuntime,
|
||
Status,
|
||
EEInfoDLCreateDummyResourceManagerIfNecessary10,
|
||
"AuthzInitializeResourceManager");
|
||
}
|
||
else
|
||
{
|
||
Result = AuthzInitializeResourceManagerFn(
|
||
0, // Flags
|
||
NULL, // pfnAccessCheck
|
||
NULL, // pfnComputeDynamicGroups
|
||
NULL, // pfnFreeDynamicGroups
|
||
L"", // Name
|
||
&DummyResourceManager);
|
||
|
||
if (Result == FALSE)
|
||
{
|
||
Status = GetLastError();
|
||
RpcpErrorAddRecord(EEInfoGCAuthz,
|
||
Status,
|
||
EEInfoDLCreateDummyResourceManagerIfNecessary20);
|
||
}
|
||
else
|
||
Status = RPC_S_OK;
|
||
}
|
||
|
||
GlobalMutexClear();
|
||
|
||
return Status;
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcGetAuthorizationContextForClient (
|
||
IN RPC_BINDING_HANDLE ClientBinding OPTIONAL,
|
||
IN BOOL ImpersonateOnReturn,
|
||
IN PVOID Reserved1,
|
||
IN PLARGE_INTEGER pExpirationTime OPTIONAL,
|
||
IN LUID Reserved2,
|
||
IN DWORD Reserved3,
|
||
IN PVOID Reserved4,
|
||
OUT PVOID *pAuthzClientContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Gets an authorization context for the client that can be used
|
||
with Authz functions. The resulting context is owned by the caller
|
||
and must be freed by it.
|
||
|
||
Arguments:
|
||
ImpersonateOnReturn - if TRUE, when we return, we should be impersonating.
|
||
If the function fails, we're not impersonating
|
||
Reserved1 - the resource manager to use (passed to Authz). Must be
|
||
NULL for now
|
||
pExpirationTime - the expiration time to use (passed to Authz)
|
||
Reserved2 - the LUID (passed to Authz). Must be 0 for now.
|
||
Resevred3 - Flags (passed to Authz). Must be 0 for now.
|
||
Reserved4 - DynamicGroupArgs parameter required by Authz (passed to Authz)
|
||
pAuthzClientContext - the authorization context, returned on success.
|
||
Undefined on failure.
|
||
|
||
Return Values:
|
||
RPC_S_OK for success, ERROR_INVALID_PARAMETER for non-null values for
|
||
the Reserved parameters and RPC_S_* / Win32 errors for the rest
|
||
|
||
--*/
|
||
{
|
||
SCALL * SCall;
|
||
THREAD *Thread;
|
||
RPC_STATUS Status;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
ASSERT(!RpcpCheckHeap());
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
if ((Reserved1 != NULL)
|
||
|| (Reserved2.HighPart != 0)
|
||
|| (Reserved2.LowPart != 0)
|
||
|| (Reserved3 != 0)
|
||
|| (Reserved4 != NULL))
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
Status = InitializeAuthzSupportIfNecessary();
|
||
if (Status != RPC_S_OK)
|
||
return Status;
|
||
|
||
Status = CreateDummyResourceManagerIfNecessary();
|
||
if (Status != RPC_S_OK)
|
||
return Status;
|
||
|
||
if ( ClientBinding == 0 )
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if (SCall == 0)
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) ClientBinding;
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
|
||
return(SCall->GetAuthorizationContext(ImpersonateOnReturn,
|
||
DummyResourceManager,
|
||
pExpirationTime,
|
||
Reserved2,
|
||
Reserved3,
|
||
Reserved4,
|
||
(PAUTHZ_CLIENT_CONTEXT_HANDLE)pAuthzClientContext));
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcFreeAuthorizationContext (
|
||
IN OUT PVOID *pAuthzClientContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
Frees an authorization context obtained through
|
||
RpcGetAuthorizationContextForClient
|
||
|
||
Arguments:
|
||
pAuthzClientContext - a pointer to the authorization context to
|
||
be freed. The function will zero-out the freed authorization context
|
||
to prevent accidental re-use in the success case. The authorization
|
||
context won't be touched in case of failure.
|
||
|
||
Return Values:
|
||
RPC_S_OK for success, Win32 errors for the rest
|
||
|
||
--*/
|
||
{
|
||
BOOL Result;
|
||
|
||
Result = AuthzFreeContextFn((AUTHZ_CLIENT_CONTEXT_HANDLE)(*pAuthzClientContext));
|
||
if (Result == FALSE)
|
||
{
|
||
return GetLastError();
|
||
}
|
||
else
|
||
{
|
||
*pAuthzClientContext = NULL;
|
||
return RPC_S_OK;
|
||
}
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcRevertToSelfEx (
|
||
IN RPC_BINDING_HANDLE ClientBinding OPTIONAL
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
SCALL * SCall ;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
ASSERT(!RpcpCheckHeap());
|
||
|
||
if ( ClientBinding == 0 )
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if ( SCall == 0 )
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) ClientBinding;
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
return(RPC_S_INVALID_BINDING);
|
||
|
||
}
|
||
|
||
return(SCall->RevertToSelf());
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcRevertToSelf (
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
|
||
return(RpcRevertToSelfEx((RPC_BINDING_HANDLE) 0));
|
||
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtSetServerStackSize (
|
||
IN unsigned long ThreadStackSize
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
An application will use this routine to specify the stack size for
|
||
each of the threads created by the server to handle remote procedure
|
||
calls.
|
||
|
||
Arguments:
|
||
|
||
ThreadStackSize - Supplies the thread stack size in bytes.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everybody is happy with the stack size.
|
||
|
||
RPC_S_INVALID_ARG - The stack size is either too small, or too large.
|
||
|
||
--*/
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return(SetThreadStackSize(ThreadStackSize));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcBindingIsClientLocal (
|
||
IN RPC_BINDING_HANDLE BindingHandle OPTIONAL,
|
||
OUT unsigned int PAPI * ClientLocalFlag
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine exists for one reason: so that the security system can
|
||
tell if a client is local or remote. The client must be using named
|
||
pipes to talk to the server.
|
||
|
||
Arguments:
|
||
|
||
BindingHandle - Optionally supplies a client binding handle specifing
|
||
which client we want to know if it is local or remote. If this
|
||
parameter is not supplied, then we will determine local/remote for
|
||
the client which made call currently being handled by this server
|
||
thread.
|
||
|
||
ClientLocalFlag - Returns an indication of whether or not the client is
|
||
local (ie. on the same machine as the server). This field will be
|
||
set to a non-zero value to indicate that the client is local;
|
||
otherwise, the client is remote.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - We successfully determined whether or not the client is
|
||
local.
|
||
|
||
RPC_S_NO_CALL_ACTIVE - There is no call active for this server thread.
|
||
|
||
RPC_S_CANNOT_SUPPORT - Only the connection oriented protocol over named
|
||
pipes can support this operation. If the client is using something
|
||
else, other than the connection oriented protocol, this will be
|
||
returned.
|
||
|
||
RPC_S_INVALID_BINDING - The binding argument does not supply a client
|
||
binding handle.
|
||
|
||
--*/
|
||
{
|
||
SCALL *SCall;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if ( BindingHandle == 0 )
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if ( SCall == 0 )
|
||
{
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) BindingHandle;
|
||
if ( SCall->InvalidHandle(SCALL_TYPE) )
|
||
{
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
}
|
||
|
||
return(SCall->IsClientLocal(ClientLocalFlag));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtInqIfIds (
|
||
IN RPC_BINDING_HANDLE Binding,
|
||
OUT RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR * IfIdVector
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to obtain a vector of the interface identifiers of
|
||
the interfaces supported by a server.
|
||
|
||
Arguments:
|
||
|
||
Binding - Optionally supplies a binding handle to the server. If this
|
||
argument is not supplied, the local application is queried.
|
||
|
||
IfIdVector - Returns a vector of the interfaces supported by the server.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everything worked just fine, and you now know the interfaces
|
||
supported by this server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
|
||
the operation.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied binding is not zero.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if ( Binding == 0 )
|
||
{
|
||
return(GlobalRpcServer->InquireInterfaceIds(IfIdVector));
|
||
}
|
||
|
||
*IfIdVector = 0;
|
||
_rpc_mgmt_inq_if_ids(Binding, (rpc_if_id_vector_p_t *) IfIdVector,
|
||
(unsigned long *) &Status);
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcIfIdVectorFree (
|
||
IN OUT RPC_IF_ID_VECTOR __RPC_FAR * __RPC_FAR * IfIdVector
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used to free an interface id vector.
|
||
|
||
Arguments:
|
||
|
||
IfIdVector - Supplies the interface id vector to be freed; on return
|
||
this will be set to zero.
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - This will always be returned.
|
||
|
||
--*/
|
||
{
|
||
unsigned int Count;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
if (!*IfIdVector)
|
||
{
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
for (Count = 0; Count < (*IfIdVector)->Count; Count++)
|
||
{
|
||
if ( (*IfIdVector)->IfId[Count] != 0 )
|
||
{
|
||
RpcpFarFree((*IfIdVector)->IfId[Count]);
|
||
}
|
||
}
|
||
RpcpFarFree(*IfIdVector);
|
||
*IfIdVector = 0;
|
||
return(RPC_S_OK);
|
||
}
|
||
|
||
|
||
|
||
// StringToUnicodeString lives in epmgmt.c
|
||
//
|
||
extern "C" RPC_CHAR *StringToWideCharString(unsigned char *, RPC_STATUS *);
|
||
|
||
#define SERVER_PRINC_NAME_SIZE 256
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcMgmtInqServerPrincName (
|
||
IN RPC_BINDING_HANDLE Binding,
|
||
IN unsigned long AuthnSvc,
|
||
OUT unsigned short __RPC_FAR * __RPC_FAR * ServerPrincName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
Binding - Supplies
|
||
|
||
AuthnSvc - Supplies
|
||
|
||
ServerPrincName - Returns
|
||
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everything worked just fine, and you now know the interfaces
|
||
supported by this server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
|
||
the operation.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied binding is not zero.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status;
|
||
unsigned char *AnsiPrincName;
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Thread = ThreadSelf();
|
||
if (Thread)
|
||
{
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
}
|
||
|
||
if ( Binding == 0 )
|
||
{
|
||
return(GlobalRpcServer->InquirePrincipalName(AuthnSvc, ServerPrincName));
|
||
}
|
||
|
||
AnsiPrincName = new unsigned char[SERVER_PRINC_NAME_SIZE + 1];
|
||
if (AnsiPrincName == 0)
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
|
||
_rpc_mgmt_inq_princ_name(Binding, AuthnSvc, SERVER_PRINC_NAME_SIZE,
|
||
AnsiPrincName, (unsigned long *)&Status);
|
||
|
||
*ServerPrincName = 0;
|
||
|
||
if ( Status == RPC_S_OK )
|
||
{
|
||
|
||
Status = A2WAttachHelper((char *)AnsiPrincName, ServerPrincName);
|
||
|
||
if (Status != RPC_S_OK)
|
||
{
|
||
delete AnsiPrincName;
|
||
ASSERT(Status == RPC_S_OUT_OF_MEMORY);
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
}
|
||
}
|
||
|
||
delete AnsiPrincName;
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcServerInqDefaultPrincName (
|
||
IN unsigned long AuthnSvc,
|
||
OUT unsigned short __RPC_FAR * __RPC_FAR * PrincName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
Arguments:
|
||
|
||
PrincName - Returns
|
||
|
||
|
||
Return Value:
|
||
|
||
RPC_S_OK - Everything worked just fine, and you now know the interfaces
|
||
supported by this server.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
|
||
the operation.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status = RPC_S_OK;
|
||
SECURITY_CREDENTIALS *pCredentials;
|
||
SEC_CHAR * DefaultPrincName = NULL;
|
||
RPC_CHAR *CopyPrincName;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Status = FindServerCredentials(
|
||
NULL,
|
||
NULL,
|
||
AuthnSvc,
|
||
0,
|
||
NULL,
|
||
&pCredentials
|
||
);
|
||
|
||
if (Status != RPC_S_OK) {
|
||
return (Status);
|
||
}
|
||
|
||
Status = pCredentials->InquireDefaultPrincName(&DefaultPrincName);
|
||
if (Status != RPC_S_OK) {
|
||
return (Status);
|
||
}
|
||
|
||
ASSERT(DefaultPrincName);
|
||
|
||
CopyPrincName = DuplicateString((RPC_CHAR *)DefaultPrincName);
|
||
if (CopyPrincName == 0)
|
||
return(RPC_S_OUT_OF_MEMORY);
|
||
|
||
*PrincName = CopyPrincName;
|
||
|
||
return (RPC_S_OK);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
THUNK_FN(RpcServerInqDefaultPrincName) (
|
||
IN unsigned long AuthnSvc,
|
||
OUT THUNK_CHAR **PrincName
|
||
)
|
||
{
|
||
RPC_STATUS RpcStatus;
|
||
USES_CONVERSION;
|
||
COutDelThunk thunkedPrincName;
|
||
|
||
RpcStatus = RpcServerInqDefaultPrincName(AuthnSvc,
|
||
thunkedPrincName);
|
||
|
||
if (RpcStatus != RPC_S_OK)
|
||
{
|
||
return(RpcStatus);
|
||
}
|
||
|
||
ATTEMPT_OUT_THUNK(thunkedPrincName, PrincName);
|
||
|
||
return (RpcStatus);
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
RpcBindingServerFromClient (
|
||
IN RPC_BINDING_HANDLE ClientBinding,
|
||
OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by a server application to convert a client binding
|
||
handle (server side binding handle) into a partially bound server binding
|
||
handle (client side binding handle).
|
||
|
||
Arguments:
|
||
|
||
ClientBinding - Supplies a client binding.
|
||
|
||
ServerBinding - Returns a partially bound server binding handle which
|
||
can be used to get back to the client.
|
||
|
||
Return Values:
|
||
|
||
RPC_S_OK - The client binding handle has been successfully converted into
|
||
a server binding handle.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
|
||
operation.
|
||
|
||
RPC_S_CANNOT_SUPPORT - The requested operation can not be supported.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied client binding is invalid.
|
||
|
||
RPC_S_WRONG_KIND_OF_BINDING - The supplied client binding is not a
|
||
client binding.
|
||
|
||
--*/
|
||
{
|
||
GENERIC_OBJECT * SCall;
|
||
THREAD *Thread;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
if (ARGUMENT_PRESENT(ClientBinding))
|
||
{
|
||
SCall = (GENERIC_OBJECT *) ClientBinding;
|
||
if (SCall->InvalidHandle(CALL_TYPE | BINDING_HANDLE_TYPE))
|
||
{
|
||
*ServerBinding = 0;
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
{
|
||
*ServerBinding = 0;
|
||
return(RPC_S_WRONG_KIND_OF_BINDING);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
SCall = (GENERIC_OBJECT *) RpcpGetThreadContext();
|
||
if ( SCall == 0 )
|
||
{
|
||
*ServerBinding = 0;
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
}
|
||
|
||
return(((SCALL *) SCall)->ConvertToServerBinding(ServerBinding));
|
||
}
|
||
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcServerRegisterForwardFunction(
|
||
IN RPC_FORWARD_FUNCTION __RPC_FAR * pForwardFunction
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
Allows Epmapper to register a function with the runtime
|
||
to allow the runtime to determine the 'forwarding' endpoint
|
||
(that is the local endpoint the server must forward the
|
||
currently received packet to).
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
{
|
||
|
||
InitializeIfNecessary();
|
||
|
||
GlobalRpcServer->RegisterRpcForwardFunction(pForwardFunction);
|
||
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
RPC_ADDRESS_CHANGE_FN * gAddressChangeFn = 0;
|
||
|
||
RPC_ADDRESS_CHANGE_FN * RPC_ENTRY
|
||
I_RpcServerInqAddressChangeFn()
|
||
{
|
||
return gAddressChangeFn;
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcServerSetAddressChangeFn(
|
||
IN RPC_ADDRESS_CHANGE_FN * pAddressChangeFn
|
||
)
|
||
{
|
||
gAddressChangeFn = pAddressChangeFn;
|
||
return RPC_S_OK;
|
||
}
|
||
|
||
RPC_STATUS
|
||
RPC_ENTRY
|
||
I_RpcServerInqLocalConnAddress (
|
||
IN RPC_BINDING_HANDLE Binding,
|
||
IN OUT void *Buffer,
|
||
IN OUT unsigned long *BufferSize,
|
||
OUT unsigned long *AddressFormat
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is used by a server application to inquire about the local
|
||
address on which a call is made.
|
||
|
||
Arguments:
|
||
|
||
Binding - Supplies a valid server binding (SCALL).
|
||
|
||
Buffer - The buffer that will receive the output address
|
||
|
||
BufferSize - the size of the supplied Buffer on input. On output the
|
||
number of bytes written to the buffer. If the buffer is too small
|
||
to receive all the output data, ERROR_MORE_DATA is returned,
|
||
nothing is written to the buffer, and BufferSize is set to
|
||
the size of the buffer needed to return all the data.
|
||
|
||
AddressFormat - a constant indicating the format of the returned address.
|
||
Currently supported are RPC_P_ADDR_FORMAT_TCP_IPV4 and
|
||
RPC_P_ADDR_FORMAT_TCP_IPV6. Undefined on failure.
|
||
|
||
Return Values:
|
||
|
||
RPC_S_OK - success.
|
||
|
||
RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
|
||
operation.
|
||
|
||
RPC_S_INVALID_BINDING - The supplied client binding is invalid.
|
||
|
||
RPC_S_CANNOT_SUPPORT - The local address was inquired for a protocol
|
||
sequence that doesn't support this type of functionality. Currently
|
||
only ncacn_ip_tcp supports it.
|
||
|
||
RPC_S_* or Win32 error for other errors
|
||
--*/
|
||
{
|
||
SCALL *SCall;
|
||
THREAD *Thread;
|
||
RPC_STATUS Status;
|
||
|
||
InitializeIfNecessary();
|
||
|
||
ASSERT(!RpcpCheckHeap());
|
||
|
||
Thread = ThreadSelf();
|
||
if (!Thread)
|
||
return RPC_S_OUT_OF_MEMORY;
|
||
|
||
RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
|
||
|
||
if ( Binding == 0 )
|
||
{
|
||
SCall = (SCALL *) RpcpGetThreadContext();
|
||
if (SCall == 0)
|
||
return(RPC_S_NO_CALL_ACTIVE);
|
||
}
|
||
else
|
||
{
|
||
SCall = (SCALL *) Binding;
|
||
if (SCall->InvalidHandle(SCALL_TYPE))
|
||
return(RPC_S_INVALID_BINDING);
|
||
}
|
||
|
||
return InqLocalConnAddress(
|
||
SCall,
|
||
Buffer,
|
||
BufferSize,
|
||
AddressFormat);
|
||
}
|
||
|
||
RPC_STATUS RPC_ENTRY
|
||
I_RpcServerUnregisterEndpoint (
|
||
IN RPC_CHAR * Protseq,
|
||
IN RPC_CHAR * Endpoint
|
||
)
|
||
{
|
||
InitializeIfNecessary();
|
||
|
||
return GlobalRpcServer->UnregisterEndpoint(Protseq, Endpoint);
|
||
}
|
||
|
||
|
||
int
|
||
InitializeRpcServer (
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will be called once at DLL initialization time. We
|
||
have got to create and initialize the server. This will get it
|
||
all ready to hang protocol sequences (addresses) and interfaces
|
||
from.
|
||
|
||
Return Value:
|
||
|
||
Zero will be returned if everything is initialized correctly;
|
||
otherwise, non-zero will be returned.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS RpcStatus = RPC_S_OK;
|
||
|
||
GlobalRpcServer = new RPC_SERVER(&RpcStatus);
|
||
if ( ( GlobalRpcServer == 0 )
|
||
|| ( RpcStatus != RPC_S_OK ) )
|
||
{
|
||
return(1);
|
||
}
|
||
|
||
GroupIdCounter = GetTickCount();
|
||
|
||
// If we can't create the global management interface
|
||
// don't worry about it; it probably won't be used anyway.
|
||
// When it is used, it should be checked for NULL.
|
||
|
||
GlobalManagementInterface = new RPC_INTERFACE(
|
||
(RPC_SERVER_INTERFACE *)mgmt_ServerIfHandle,
|
||
GlobalRpcServer, 0, MAX_IF_CALLS, gMaxRpcSize, 0, &RpcStatus);
|
||
|
||
if (GlobalManagementInterface)
|
||
{
|
||
GlobalManagementInterface->RegisterTypeManager(0,
|
||
((RPC_SERVER_INTERFACE *)mgmt_ServerIfHandle)->DefaultManagerEpv);
|
||
}
|
||
|
||
return(RpcStatus);
|
||
}
|
||
|
||
|