1597 lines
35 KiB
C++
1597 lines
35 KiB
C++
/*++
|
||
|
||
Copyright (c) 1994 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
isrpc.cxx
|
||
|
||
Abstract:
|
||
|
||
Contains ISRPC class implementation.
|
||
|
||
Author:
|
||
|
||
Murali R. Krishnan 11-Dec-1995
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
/************************************************************
|
||
* Include Headers
|
||
************************************************************/
|
||
|
||
#ifndef dllexp
|
||
#define dllexp __declspec( dllexport )
|
||
#endif
|
||
|
||
//
|
||
// System include files.
|
||
//
|
||
|
||
#include "smtpinc.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
|
||
#include <windows.h>
|
||
#include <winsock2.h>
|
||
#include <lm.h>
|
||
|
||
#include <stdio.h>
|
||
#include <stdarg.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <tchar.h>
|
||
|
||
#ifdef __cplusplus
|
||
} // extern "C"
|
||
#endif // __cplusplus
|
||
|
||
#include <isrpc.hxx>
|
||
|
||
|
||
/************************************************************
|
||
* Functions
|
||
************************************************************/
|
||
|
||
|
||
DWORD
|
||
InetinfoStartRpcServerListen(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function starts RpcServerListen for this process. The first
|
||
service that is calling this function will actually start the
|
||
RpcServerListen, subsequent calls are just noted down in num count.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
RPC_STATUS Status = RPC_S_OK;
|
||
Status = RpcServerListen(
|
||
1, // minimum num threads.
|
||
RPC_C_LISTEN_MAX_CALLS_DEFAULT, // max concurrent calls.
|
||
TRUE ); // don't wait
|
||
|
||
return( Status );
|
||
}
|
||
|
||
|
||
DWORD
|
||
InetinfoStopRpcServerListen(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
RPC_STATUS Status = RPC_S_OK;
|
||
|
||
Status = RpcMgmtStopServerListening(0);
|
||
|
||
//
|
||
// wait for all RPC threads to go away.
|
||
//
|
||
|
||
if( Status == RPC_S_OK) {
|
||
Status = RpcMgmtWaitServerListen();
|
||
}
|
||
|
||
return( Status );
|
||
}
|
||
|
||
|
||
ISRPC::ISRPC(IN LPCTSTR pszServiceName)
|
||
/*++
|
||
|
||
This function constructs a new ISRPC object, initializing the
|
||
members to proper state.
|
||
Always the ISRPC members will use RPC_C_AUTHN_WINNT.
|
||
|
||
Arguments:
|
||
|
||
pszServiceName - pointer to string containing the name of the service
|
||
dwServiceAuthId - DWORD containing the service Authentication Identifier.
|
||
|
||
Returns:
|
||
A valid initialized ISRPC object on success.
|
||
|
||
--*/
|
||
: m_dwProtocols ( 0),
|
||
m_fInterfaceAdded ( FALSE),
|
||
m_fEpRegistered ( FALSE),
|
||
m_fServerStarted ( FALSE),
|
||
m_hRpcInterface ( NULL),
|
||
m_pszServiceName ( pszServiceName),
|
||
m_pBindingVector ( NULL)
|
||
{
|
||
//DBG_REQUIRE( SetSecurityDescriptor() == NO_ERROR);
|
||
SetSecurityDescriptor();
|
||
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" Created new ISRPC object for %s at %08x\n",
|
||
m_pszServiceName, this));
|
||
}
|
||
#endif
|
||
} // ISRPC::ISRPC()
|
||
|
||
|
||
|
||
|
||
ISRPC::~ISRPC(VOID)
|
||
/*++
|
||
|
||
This function cleans up the ISRPC object and releases any dynamic memory or
|
||
state associated with this object.
|
||
|
||
--*/
|
||
{
|
||
|
||
CleanupData();
|
||
Cleanup();
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" Destroyed ISRPC object for %s at %08x\n",
|
||
m_pszServiceName, this));
|
||
}
|
||
#endif
|
||
} // ISRPC::~ISRPC()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::CleanupData(VOID)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function cleans up the ISRPC object.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" ISRPC(%08x)::Cleaning up for %s\n",
|
||
m_pszServiceName));
|
||
}
|
||
#endif
|
||
if ( m_fServerStarted) {
|
||
|
||
rpcStatus = StopServer( );
|
||
}
|
||
|
||
//DBG_ASSERT( rpcStatus == RPC_S_OK);
|
||
|
||
rpcStatus = UnRegisterInterface();
|
||
|
||
m_dwProtocols = 0;
|
||
m_hRpcInterface = NULL;
|
||
|
||
return (rpcStatus);
|
||
} // ISRPC::CleanupData()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::RegisterInterface( IN RPC_IF_HANDLE hRpcInterface)
|
||
/*++
|
||
|
||
This function registers the RPC inteface in the object.
|
||
If there is already a valid instance present in the object,
|
||
this function fails and returns error.
|
||
If this is the new interface specified, the function registers the
|
||
interface both for dynamic and static bindings.
|
||
|
||
Should be called after calling AddProtocol() and before StartServer()
|
||
|
||
Arguments:
|
||
hRpcInteface - RPC inteface handle.
|
||
|
||
Returns:
|
||
Win32 Error Code - NO_ERROR on success.
|
||
|
||
--*/
|
||
{
|
||
DWORD dwError = NO_ERROR;
|
||
|
||
if ( m_dwProtocols == 0) {
|
||
|
||
// No protocol added. Return failure.
|
||
return ( ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
if ( m_hRpcInterface != NULL) {
|
||
|
||
dwError = ( RPC_S_DUPLICATE_ENDPOINT);
|
||
} else {
|
||
|
||
//
|
||
// since there is no duplicate, just set the new value and return.
|
||
//
|
||
|
||
if ( hRpcInterface == NULL) {
|
||
|
||
dwError = ERROR_INVALID_PARAMETER;
|
||
} else {
|
||
|
||
m_hRpcInterface = hRpcInterface;
|
||
}
|
||
}
|
||
|
||
|
||
if ( dwError == RPC_S_OK) {
|
||
|
||
dwError = RpcServerRegisterIf(m_hRpcInterface,
|
||
0, // MgrUuid
|
||
0 // MgrEpv (Entry Point Vector)
|
||
);
|
||
|
||
if ( dwError == RPC_S_OK ) {
|
||
|
||
m_fInterfaceAdded = TRUE;
|
||
|
||
//
|
||
// Establish the dynamic bindings if any.
|
||
//
|
||
|
||
if ( (m_dwProtocols & (ISRPC_OVER_TCPIP | ISRPC_OVER_SPX)) != 0) {
|
||
|
||
dwError = RpcServerInqBindings( &m_pBindingVector);
|
||
|
||
if ( dwError == RPC_S_OK) {
|
||
|
||
//DBG_ASSERT( m_pBindingVector != NULL);
|
||
|
||
dwError = RpcEpRegister(m_hRpcInterface,
|
||
m_pBindingVector,
|
||
NULL,
|
||
(unsigned char *) "" );
|
||
|
||
if ( dwError == RPC_S_OK) {
|
||
|
||
m_fEpRegistered = TRUE;
|
||
}
|
||
} // Ep registering
|
||
} // dynamic bindings
|
||
} // registration successful
|
||
}
|
||
|
||
#if 0
|
||
IF_DEBUG(DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "ISRPC(%08x)::RegisterInterface(%08x)"
|
||
" returns %ld\n",
|
||
this, hRpcInterface, dwError));
|
||
}
|
||
#endif
|
||
return ( dwError);
|
||
|
||
} // ISRPC::RegisterInterface()
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::UnRegisterInterface( VOID)
|
||
/*++
|
||
|
||
This function unregisters the RPC inteface in the object.
|
||
|
||
Should be called after after StopServer() and before cleanup.
|
||
|
||
Arguments:
|
||
None
|
||
|
||
Returns:
|
||
Win32 Error Code - NO_ERROR on success.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
if ( m_fEpRegistered) {
|
||
|
||
//DBG_ASSERT( m_hRpcInterface != NULL && m_pBindingVector != NULL);
|
||
rpcStatus = RpcEpUnregister(m_hRpcInterface,
|
||
m_pBindingVector,
|
||
NULL // pUuidVector
|
||
);
|
||
//_ASSERT( rpcStatus == RPC_S_OK);
|
||
m_fEpRegistered = FALSE;
|
||
}
|
||
|
||
if ( m_pBindingVector != NULL) {
|
||
|
||
rpcStatus = RpcBindingVectorFree( &m_pBindingVector);
|
||
//_ASSERT( rpcStatus == RPC_S_OK);
|
||
m_pBindingVector = NULL;
|
||
}
|
||
|
||
if ( m_fInterfaceAdded != NULL) {
|
||
|
||
rpcStatus = RpcServerUnregisterIf(m_hRpcInterface,
|
||
NULL, // MgrUuid
|
||
TRUE // wait for calls to complete
|
||
);
|
||
//_ASSERT(rpcStatus == RPC_S_OK);
|
||
m_fInterfaceAdded = FALSE;
|
||
}
|
||
return ( rpcStatus);
|
||
|
||
} // ISRPC::UnRegisterInterface()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::AddProtocol( IN DWORD Protocol)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function adds another protocol to the binding list.
|
||
|
||
Arguments:
|
||
|
||
protocol - protocol binding opcode.
|
||
|
||
fDynamic - Boolean indicating if the call should do dynamic or static
|
||
RPC binding for the protocol specified.
|
||
|
||
Return Value:
|
||
|
||
RPC error code.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
if ( Protocol & ISRPC_OVER_LPC ) {
|
||
|
||
// Currently we only support static binding
|
||
rpcStatus = BindOverLpc( FALSE);
|
||
}
|
||
|
||
#ifndef CHICAGO
|
||
|
||
//
|
||
// Enable all remote bindings
|
||
//
|
||
|
||
if ( rpcStatus == RPC_S_OK ) {
|
||
|
||
if ( Protocol & ISRPC_OVER_TCPIP ) {
|
||
|
||
// Currently we only support dynamic binding
|
||
rpcStatus = BindOverTcp( TRUE);
|
||
}
|
||
|
||
if ( rpcStatus == RPC_S_OK && Protocol & ISRPC_OVER_NP ) {
|
||
|
||
// Currently we only support static binding
|
||
rpcStatus = BindOverNamedPipe( FALSE);
|
||
}
|
||
|
||
if ( rpcStatus == RPC_S_OK && Protocol & ISRPC_OVER_SPX ) {
|
||
|
||
// Currently we only support dynamic binding
|
||
rpcStatus = BindOverSpx( TRUE);
|
||
}
|
||
}
|
||
|
||
#else // CHICAGO
|
||
rpcStatus = RPC_S_OK;
|
||
|
||
if ( Protocol & ISRPC_OVER_TCPIP ) {
|
||
|
||
// Currently we only support dynamic binding
|
||
rpcStatus = BindOverTcp( TRUE);
|
||
}
|
||
|
||
if ( Protocol & ISRPC_OVER_NB ) {
|
||
|
||
// Currently we only support dynamic binding
|
||
// Ignore status for NB for now
|
||
(VOID)BindOverNetBios(TRUE);
|
||
}
|
||
#endif // CHICAGO
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"ISRPC(%08x)::AddProtocol(%08x) returns %ld.\n",
|
||
this, Protocol, rpcStatus ));
|
||
}
|
||
#endif
|
||
return( rpcStatus );
|
||
|
||
} // ISRPC::AddProtocol()
|
||
|
||
DWORD
|
||
ISRPC::RemoveProtocol(IN DWORD Protocol)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function removes a protocol from the binding list.
|
||
|
||
Arguments:
|
||
|
||
protocol - protocol binding opcode.
|
||
|
||
Return Value:
|
||
|
||
RPC error code.
|
||
|
||
Note:
|
||
As a side effect, this function removes the dynamic endpoing on
|
||
TCPIP when SPX binding is removed and vice-versa.
|
||
|
||
--*/
|
||
{
|
||
#if 0
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" ISRPC(%08x)::RemoveProtocol(%s) is not implemented\n",
|
||
this, m_pszServiceName));
|
||
DBG_ASSERT( FALSE);
|
||
#endif
|
||
return ( ERROR_CALL_NOT_IMPLEMENTED);
|
||
} // ISRPC::RemoveProtocol()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::StartServer(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function start RPC server.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
RPC error code.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus;
|
||
|
||
//
|
||
// add the interface.
|
||
//
|
||
|
||
if ( m_hRpcInterface == NULL) {
|
||
|
||
return (ERROR_INVALID_PARAMETER);
|
||
}
|
||
|
||
//
|
||
// start rpc server.
|
||
//
|
||
|
||
#ifndef SERVICE_AS_EXE
|
||
|
||
rpcStatus = InetinfoStartRpcServerListen();
|
||
|
||
#else
|
||
|
||
rpcStatus = RpcServerListen(
|
||
1, // minimum num threads.
|
||
1, // max concurrent calls.
|
||
TRUE ); // don't wait
|
||
|
||
#endif // SERVICE_AS_EXE
|
||
|
||
if ( rpcStatus == RPC_S_OK ) {
|
||
m_fServerStarted = TRUE;
|
||
}
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "ISRPC(%08x)::StartServer(%s) returns %ld\n",
|
||
this, m_pszServiceName, rpcStatus));
|
||
}
|
||
#endif
|
||
return( rpcStatus );
|
||
|
||
} // ISRPC::StartServer()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::StopServer(
|
||
VOID
|
||
)
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
if( m_fServerStarted ) {
|
||
|
||
#ifndef SERVICE_AS_EXE
|
||
|
||
rpcStatus = InetinfoStopRpcServerListen();
|
||
#else
|
||
|
||
//
|
||
// stop server listen.
|
||
//
|
||
|
||
rpcStatus = RpcMgmtStopServerListening(0);
|
||
|
||
//
|
||
// wait for all RPC threads to go away.
|
||
//
|
||
|
||
if( rpcStatus == RPC_S_OK) {
|
||
|
||
rpcStatus = RpcMgmtWaitServerListen();
|
||
}
|
||
|
||
#endif // SERVICE_AS_EXE
|
||
|
||
m_fServerStarted = FALSE;
|
||
}
|
||
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"ISRPC(%08x)::StopServer( %s) returns %d\n",
|
||
this, m_pszServiceName, rpcStatus));
|
||
}
|
||
#endif
|
||
|
||
return ( rpcStatus);
|
||
} // ISRPC::StopServer()
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::EnumBindingStrings(
|
||
IN OUT LPINET_BINDINGS pBindings
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function enumurates the binding strings of the protocols
|
||
bound to the server.
|
||
|
||
Arguments:
|
||
|
||
pBindings : pointer to a binding strings structure. The caller
|
||
should call FreeBindingStrings member function to free the string
|
||
after use.
|
||
|
||
Return Value:
|
||
|
||
Windows Error Code;
|
||
|
||
--*/
|
||
{
|
||
DWORD dwError;
|
||
RPC_BINDING_VECTOR * pBindingVector = NULL;
|
||
LPINET_BIND_INFO pBindingsInfo;
|
||
DWORD dwCount = 0;
|
||
DWORD i;
|
||
|
||
//
|
||
// query RPC for RPC_BINDING_VECTORS.
|
||
//
|
||
|
||
dwError = RpcServerInqBindings( &pBindingVector );
|
||
|
||
if( dwError != NO_ERROR ) {
|
||
|
||
goto Cleanup;
|
||
}
|
||
|
||
//DBG_ASSERT( pBindingVector->Count > 0 );
|
||
|
||
//
|
||
// alloc memory for INET_RPC_BINDING_STRINGS.
|
||
//
|
||
|
||
pBindingsInfo = (LPINET_BIND_INFO)
|
||
LocalAlloc( GPTR, sizeof(INET_BIND_INFO) * pBindingVector->Count );
|
||
|
||
if( pBindingsInfo == NULL ) {
|
||
|
||
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// convert binding handle to binding vectors.
|
||
//
|
||
|
||
pBindings->NumBindings = 0;
|
||
pBindings->BindingsInfo = pBindingsInfo;
|
||
|
||
for( i = 0; i < pBindingVector->Count; i++ ) {
|
||
|
||
LPSTR BindingString;
|
||
|
||
BindingString = NULL;
|
||
dwError = RpcBindingToStringBindingA(pBindingVector->BindingH[i],
|
||
(LPBYTE *)&BindingString );
|
||
|
||
if( dwError != NO_ERROR ) {
|
||
goto Cleanup;
|
||
}
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
DBGPRINTF(( DBG_CONTEXT, "Binding Handle[%d] = %08x. String = %s\n",
|
||
i, pBindingVector->BindingH[i], BindingString));
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// check to we get only our named-pipe endpoint.
|
||
//
|
||
|
||
if( strstr( BindingString, "ncacn_np" ) != NULL ) {
|
||
|
||
//
|
||
// found a named-pipe binding string.
|
||
//
|
||
|
||
if( strstr(BindingString,
|
||
m_pszServiceName ) == NULL ) {
|
||
|
||
//
|
||
// found a non service named-pipe entry.
|
||
// ignore it.
|
||
//
|
||
|
||
RpcStringFreeA( (LPBYTE *)&BindingString );
|
||
|
||
} else {
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
DBGPRINTF(( DBG_CONTEXT, "Binding String Chosen = %s\n",
|
||
BindingString));
|
||
}
|
||
#endif
|
||
pBindings->BindingsInfo[dwCount].Length =
|
||
(strlen(BindingString) + 1) * sizeof(CHAR);
|
||
pBindings->BindingsInfo[dwCount].BindData = BindingString;
|
||
dwCount++;
|
||
}
|
||
}
|
||
|
||
} // for
|
||
|
||
dwError = NO_ERROR;
|
||
pBindings->NumBindings = dwCount;
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "Binding Vectors chosen"
|
||
" Service = %s, NumBindings = %d of Total = %d\n",
|
||
m_pszServiceName, dwCount, pBindingVector->Count));
|
||
}
|
||
#endif
|
||
Cleanup:
|
||
|
||
if( pBindingVector != NULL ) {
|
||
|
||
DWORD LocalError;
|
||
LocalError = RpcBindingVectorFree( &pBindingVector );
|
||
//DBG_ASSERT( LocalError == NO_ERROR );
|
||
}
|
||
|
||
if( dwError != NO_ERROR ) {
|
||
FreeBindingStrings( pBindings );
|
||
pBindings->NumBindings = 0;
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
"ISRPC(%08x)::EnumBindingStrings(%s) failed, %ld.",
|
||
this, m_pszServiceName, dwError ));
|
||
}
|
||
#endif
|
||
}
|
||
|
||
return( dwError );
|
||
|
||
} // ISRPC::EnumBindingStrings()
|
||
|
||
|
||
|
||
|
||
VOID
|
||
ISRPC::FreeBindingStrings(
|
||
IN OUT LPINET_BINDINGS pInetBindings
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function deletes a binding vector that was returned by the
|
||
EnumBindingStrings member function.
|
||
|
||
Arguments:
|
||
|
||
pBindings : pointer to a binding vector.
|
||
|
||
Return Value:
|
||
|
||
Windows Error Code;
|
||
|
||
--*/
|
||
{
|
||
DWORD dwError;
|
||
DWORD i;
|
||
|
||
|
||
//
|
||
// free binding strings.
|
||
//
|
||
|
||
for( i = 0; i < pInetBindings->NumBindings; i++) {
|
||
dwError = RpcStringFreeA( ((LPBYTE *)&pInetBindings
|
||
->BindingsInfo[i].BindData ));
|
||
//DBG_ASSERT( dwError == NO_ERROR );
|
||
}
|
||
|
||
pInetBindings->NumBindings = 0;
|
||
|
||
//
|
||
// free bindings info array.
|
||
//
|
||
|
||
if( pInetBindings->BindingsInfo != NULL ) {
|
||
LocalFree( (HANDLE)pInetBindings->BindingsInfo );
|
||
pInetBindings->BindingsInfo = NULL;
|
||
}
|
||
|
||
return;
|
||
|
||
} // ISRPC::FreeBindingStrings()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::BindOverTcp(IN BOOL fDynamic)
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
//DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_TCPIP) == 0);
|
||
|
||
if ( !fDynamic) {
|
||
|
||
rpcStatus = ( ERROR_CALL_NOT_IMPLEMENTED);
|
||
|
||
} else {
|
||
|
||
rpcStatus = ( ISRPC::DynamicBindOverTcp());
|
||
}
|
||
|
||
if ( rpcStatus == RPC_S_OK) {
|
||
|
||
m_dwProtocols |= ISRPC_OVER_TCPIP;
|
||
}
|
||
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "(%08x)::BindOverTcp(%s) returns %d\n",
|
||
this, m_pszServiceName, rpcStatus));
|
||
}
|
||
#endif
|
||
return ( rpcStatus);
|
||
} // ISRPC::BindOverTcpIp()
|
||
|
||
#ifdef CHICAGO
|
||
DWORD
|
||
ISRPC::BindOverNetBios(IN BOOL fDynamic)
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
//DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_NB) == 0);
|
||
|
||
if ( !fDynamic) {
|
||
|
||
return ( ERROR_CALL_NOT_IMPLEMENTED);
|
||
}
|
||
|
||
// We will use Dynamic endpoint for the NetBios binding.
|
||
|
||
rpcStatus =
|
||
RpcServerUseProtseqW(
|
||
L"ncacn_nb_ipx", // protocol string.
|
||
ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
|
||
&sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
|
||
|
||
rpcStatus =
|
||
RpcServerUseProtseqW(
|
||
L"ncacn_nb_tcp", // protocol string.
|
||
ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
|
||
&sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
|
||
|
||
switch (rpcStatus) {
|
||
|
||
case RPC_S_OK:
|
||
|
||
//
|
||
// set the protocol bit.
|
||
//
|
||
|
||
m_dwProtocols |= ISRPC_OVER_NB;
|
||
break;
|
||
|
||
case RPC_S_DUPLICATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "(%08x) ncacn_nb is already added for %s\n",
|
||
// this,
|
||
// m_pszServiceName));
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
case RPC_S_PROTSEQ_NOT_SUPPORTED:
|
||
case RPC_S_CANT_CREATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "(%08x) ncacn_nb is not supported for %s (%ld).\n",
|
||
// this, m_pszServiceName, rpcStatus ));
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
} // switch()
|
||
|
||
//
|
||
// if the security support provider is not enabled, do so.
|
||
//
|
||
|
||
if( rpcStatus == RPC_S_OK && !IsSecurityEnabled() ) {
|
||
|
||
rpcStatus = AddSecurity();
|
||
|
||
}
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "(%08x)::BindOverNetBios(%s) returns %d\n",
|
||
this, m_pszServiceName, rpcStatus));
|
||
}
|
||
#endif
|
||
return ( rpcStatus);
|
||
} // ISRPC::BindOverNetBios()
|
||
#endif // CHICAGO
|
||
|
||
DWORD
|
||
ISRPC::BindOverNamedPipe(IN BOOL fDynamic)
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
//DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_NP) == 0);
|
||
|
||
|
||
//
|
||
// On Named Pipe, we support only static bindings. No dynamic Binding.
|
||
//
|
||
|
||
if ( fDynamic) {
|
||
|
||
return ( ERROR_CALL_NOT_IMPLEMENTED);
|
||
}
|
||
|
||
if( (m_dwProtocols & ISRPC_OVER_NP) == 0 ) {
|
||
|
||
WCHAR rgchNp[1024];
|
||
|
||
wsprintfW( rgchNp,
|
||
#ifdef UNICODE
|
||
L"%ws%s"
|
||
#else
|
||
L"%ws%S"
|
||
#endif // UNICODE
|
||
,
|
||
ISRPC_NAMED_PIPE_PREFIX_W,
|
||
m_pszServiceName);
|
||
|
||
//
|
||
// Establish a static Named pipe binding.
|
||
//
|
||
|
||
rpcStatus =
|
||
RpcServerUseProtseqEpW(
|
||
L"ncacn_np", // protocol string.
|
||
ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
|
||
rgchNp, // end point!
|
||
&sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
|
||
|
||
switch (rpcStatus) {
|
||
|
||
case RPC_S_OK:
|
||
|
||
//
|
||
// set the protocol bit.
|
||
//
|
||
m_dwProtocols |= ISRPC_OVER_NP;
|
||
break;
|
||
|
||
case RPC_S_DUPLICATE_ENDPOINT:
|
||
|
||
//
|
||
// Ignore the duplicate end point error
|
||
//
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "(%08x) ncacn_np is already added for %s\n",
|
||
// this,
|
||
// m_pszServiceName));
|
||
m_dwProtocols |= ISRPC_OVER_NP;
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
case RPC_S_PROTSEQ_NOT_SUPPORTED:
|
||
case RPC_S_CANT_CREATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "(%08x) ncacn_np is not supported for %s (%ld).\n",
|
||
// this, m_pszServiceName, rpcStatus ));
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
} // switch()
|
||
}
|
||
|
||
return ( rpcStatus);
|
||
|
||
} // ISRPC::BindOverNamedPipe()
|
||
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::BindOverLpc(IN BOOL fDynamic)
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
//DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_LPC) == 0);
|
||
|
||
|
||
//
|
||
// On LPC, we support only static bindings. No dynamic Binding.
|
||
//
|
||
|
||
if ( fDynamic) {
|
||
|
||
return ( ERROR_CALL_NOT_IMPLEMENTED);
|
||
}
|
||
|
||
if( (m_dwProtocols & ISRPC_OVER_LPC) == 0 ) {
|
||
|
||
WCHAR rgchLpc[1024];
|
||
|
||
// LPC Endpoint string is: <InterfaceName>_LPC
|
||
wsprintfW( rgchLpc,
|
||
#ifdef UNICODE
|
||
L"%s_%ws"
|
||
#else
|
||
L"%S_%ws"
|
||
#endif // UNICODE
|
||
,
|
||
m_pszServiceName,
|
||
ISRPC_LPC_NAME_SUFFIX_W);
|
||
|
||
//
|
||
// Establish a static Lpc binding.
|
||
//
|
||
|
||
rpcStatus =
|
||
RpcServerUseProtseqEpW(
|
||
L"ncalrpc", // protocol string.
|
||
ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
|
||
rgchLpc, // end point!
|
||
&sm_sid[ACL_INDEX_ALLOW_ALL] ); // security
|
||
switch (rpcStatus) {
|
||
|
||
case RPC_S_OK:
|
||
|
||
//
|
||
// set the protocol bit.
|
||
//
|
||
m_dwProtocols |= ISRPC_OVER_LPC;
|
||
break;
|
||
|
||
case RPC_S_DUPLICATE_ENDPOINT:
|
||
|
||
//
|
||
// Ignore the duplicate end point error
|
||
//
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "(%08x) ncalrpc is already added for %s\n",
|
||
// this,
|
||
// m_pszServiceName));
|
||
m_dwProtocols |= ISRPC_OVER_LPC;
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
case RPC_S_PROTSEQ_NOT_SUPPORTED:
|
||
case RPC_S_CANT_CREATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "(%08x) ncalrpc is not supported for %s (%ld).\n",
|
||
// this, m_pszServiceName, rpcStatus ));
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
} // switch()
|
||
}
|
||
|
||
return ( rpcStatus);
|
||
|
||
} // ISRPC::BindOverLpc()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::BindOverSpx(IN BOOL fDynamic)
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
//DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_SPX) == 0);
|
||
|
||
if ( !fDynamic) {
|
||
|
||
rpcStatus = ( ERROR_CALL_NOT_IMPLEMENTED);
|
||
|
||
} else {
|
||
|
||
rpcStatus = ISRPC::DynamicBindOverSpx();
|
||
}
|
||
|
||
if ( rpcStatus == RPC_S_OK) {
|
||
|
||
m_dwProtocols |= ISRPC_OVER_SPX;
|
||
}
|
||
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "(%08x)::BindOverSpx(%s) returns %d\n",
|
||
this, m_pszServiceName, rpcStatus));
|
||
}
|
||
#endif
|
||
|
||
return ( rpcStatus);
|
||
} // ISRPC::BindOverSpx()
|
||
|
||
|
||
# if DBG
|
||
|
||
VOID
|
||
ISRPC::Print(VOID) const
|
||
{
|
||
#if 0
|
||
DBGPRINTF(( DBG_CONTEXT,
|
||
" ISRPC(%08x). SvcName=%s\n"
|
||
" Protocols = %d.\n"
|
||
" RPC Interface = %08x. Binding Vector = %08x\n"
|
||
" InterfaceAdded = %d.\n"
|
||
" EpRegistered = %d. ServerStarted = %d.\n"
|
||
,
|
||
this, m_pszServiceName,
|
||
m_dwProtocols,
|
||
m_hRpcInterface, m_pBindingVector,
|
||
m_fInterfaceAdded,
|
||
m_fEpRegistered, m_fServerStarted
|
||
));
|
||
#endif
|
||
|
||
} // ISRPC::Print()
|
||
|
||
# endif // DBG
|
||
|
||
|
||
|
||
/******************************
|
||
* STATIC Member Definitions
|
||
******************************/
|
||
|
||
DWORD ISRPC::sm_dwProtocols = 0;
|
||
|
||
SECURITY_DESCRIPTOR ISRPC::sm_sid[2];
|
||
BOOL ISRPC::sm_fSecurityEnabled = FALSE;
|
||
|
||
|
||
DWORD
|
||
ISRPC::Initialize(VOID)
|
||
{
|
||
sm_dwProtocols = 0;
|
||
|
||
return SetSecurityDescriptor();
|
||
|
||
} // ISRPC::Initialize()
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::Cleanup(VOID)
|
||
{
|
||
//
|
||
// Free up the security descriptor
|
||
//
|
||
|
||
if (sm_sid[0].Dacl)
|
||
delete [] (BYTE *) (sm_sid[0].Dacl);
|
||
if (sm_sid[1].Dacl)
|
||
delete [] (BYTE *) (sm_sid[1].Dacl);
|
||
|
||
ZeroMemory( (PVOID) &sm_sid, sizeof(sm_sid));
|
||
|
||
//
|
||
// For now nothing to do. Just a place holder.
|
||
//
|
||
|
||
return ( NO_ERROR);
|
||
|
||
} // ISRPC::Cleanup()
|
||
|
||
|
||
DWORD
|
||
ISRPC::DynamicBindOverTcp(VOID)
|
||
/*++
|
||
This static function (ISRPC member) establishes a dynamic endpoing
|
||
RPC binding over TCP/IP, using a run-time library call to RPC.
|
||
RPC run-time library allows one to create as many dynamic end points
|
||
as one wishes. So we maintain external state and control the number
|
||
of end points created to 1.
|
||
|
||
Arguments:
|
||
None
|
||
|
||
Returns:
|
||
RPC status - RPC_S_OK for success.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
if( (sm_dwProtocols & ISRPC_OVER_TCPIP) == 0 ) {
|
||
|
||
//
|
||
// Not already present. Add dynamic endpoint over TCP/IP
|
||
//
|
||
|
||
rpcStatus =
|
||
RpcServerUseProtseqW(
|
||
L"ncacn_ip_tcp", // protocol string.
|
||
ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
|
||
&sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
|
||
|
||
switch (rpcStatus) {
|
||
|
||
case RPC_S_OK:
|
||
|
||
//
|
||
// set the protocol bit.
|
||
//
|
||
|
||
sm_dwProtocols |= ISRPC_OVER_TCPIP;
|
||
break;
|
||
|
||
case RPC_S_DUPLICATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "ncacn_ip_tcp is already added.\n"));
|
||
sm_dwProtocols |= ISRPC_OVER_TCPIP;
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
case RPC_S_PROTSEQ_NOT_SUPPORTED:
|
||
case RPC_S_CANT_CREATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "ncacn_ip_tcp is not supported. Error = %ld\n",
|
||
// rpcStatus));
|
||
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
} // switch()
|
||
|
||
//
|
||
// if the security support provider is not enabled, do so.
|
||
//
|
||
|
||
if( rpcStatus == RPC_S_OK && !IsSecurityEnabled() ) {
|
||
|
||
rpcStatus = AddSecurity();
|
||
|
||
}
|
||
}
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "DynamicBindOverTcp() returns %d\n",
|
||
rpcStatus));
|
||
}
|
||
#endif
|
||
return ( rpcStatus);
|
||
|
||
} // ISRPC::DynamicBindOverTcp()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::DynamicBindOverSpx(VOID)
|
||
/*++
|
||
This static function (ISRPC member) establishes a dynamic endpoing
|
||
RPC binding over SPX, using a run-time library call to RPC.
|
||
RPC run-time library allows one to create as many dynamic end points
|
||
as one wishes. So we maintain external state and control the number
|
||
of end points created to 1.
|
||
|
||
Arguments:
|
||
None
|
||
|
||
Returns:
|
||
RPC status - RPC_S_OK for success.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus = RPC_S_OK;
|
||
|
||
if( (sm_dwProtocols & ISRPC_OVER_SPX) == 0 ) {
|
||
|
||
// Use dynamic end point for the server.
|
||
rpcStatus =
|
||
RpcServerUseProtseqW(
|
||
L"ncacn_spx", // protocol string.
|
||
ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
|
||
&sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
|
||
|
||
switch (rpcStatus) {
|
||
|
||
case RPC_S_OK:
|
||
|
||
//
|
||
// set the protocol bit.
|
||
//
|
||
sm_dwProtocols |= ISRPC_OVER_SPX;
|
||
break;
|
||
|
||
case RPC_S_DUPLICATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "ncacn_spx is already added.\n"
|
||
// ));
|
||
sm_dwProtocols |= ISRPC_OVER_SPX;
|
||
rpcStatus = RPC_S_OK;
|
||
break;
|
||
|
||
case RPC_S_PROTSEQ_NOT_SUPPORTED:
|
||
case RPC_S_CANT_CREATE_ENDPOINT:
|
||
|
||
//DBGPRINTF(( DBG_CONTEXT,
|
||
// "ncacn_spx is not supported. Error (%ld).\n",
|
||
// rpcStatus ));
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
} // switch()
|
||
|
||
//
|
||
// if the security support provider is not enabled, do so.
|
||
//
|
||
|
||
if( rpcStatus == RPC_S_OK && !IsSecurityEnabled()) {
|
||
|
||
rpcStatus = AddSecurity();
|
||
}
|
||
}
|
||
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "DynamicBindOverSpx() returns %d\n",
|
||
rpcStatus));
|
||
}
|
||
#endif
|
||
|
||
return ( rpcStatus);
|
||
|
||
} // ISRPC::DynamicBindOverSpx()
|
||
|
||
|
||
//----------------------------------------------------------------
|
||
// Description:
|
||
// Initializes a SECURITY_DESCRIPTOR to allow access to all
|
||
// ("World").
|
||
// Arguments:
|
||
// pSd Pass in a pointer to the SECURITY_DESCRIPTOR
|
||
// bAdminOnly: TRUE: allow admin, FALSE: allow everyone
|
||
// Returns:
|
||
// ERROR_SUCCESS if initialization proceeded successfully.
|
||
// Win32 error if some failure occurred.
|
||
//----------------------------------------------------------------
|
||
DWORD InitializeSmtpSecurityDescriptor (PSECURITY_DESCRIPTOR pSd, BOOL bAdminOnly)
|
||
{
|
||
DWORD dwErr = ERROR_SUCCESS;
|
||
PSID pSidWorld = NULL;
|
||
PSID pSidAdmins = NULL;
|
||
PSID pSid2Allow = NULL;
|
||
SID_IDENTIFIER_AUTHORITY sidWorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
||
SID_IDENTIFIER_AUTHORITY sidNtAuthority = SECURITY_NT_AUTHORITY;
|
||
ACL *pAcl = NULL;
|
||
DWORD dwAclSize = 0;
|
||
|
||
_ASSERT (pSd);
|
||
|
||
if (!AllocateAndInitializeSid (
|
||
&sidWorldAuthority,
|
||
1,
|
||
SECURITY_WORLD_RID,
|
||
0,0,0,0,0,0,0,
|
||
&pSidWorld)){
|
||
|
||
dwErr = GetLastError ();
|
||
goto Exit;
|
||
}
|
||
|
||
if ( !bAdminOnly ) pSid2Allow = pSidWorld;
|
||
else
|
||
{
|
||
if (!AllocateAndInitializeSid( &sidNtAuthority,
|
||
2,
|
||
SECURITY_BUILTIN_DOMAIN_RID,
|
||
DOMAIN_ALIAS_RID_ADMINS,
|
||
0,0,0,0,0,0,
|
||
&pSidAdmins ) )
|
||
{
|
||
dwErr = GetLastError ();
|
||
goto Exit;
|
||
}
|
||
pSid2Allow = pSidAdmins;
|
||
}
|
||
dwAclSize = sizeof (ACL) + // Length of ACL
|
||
(sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD)) + // Length of ACE #1
|
||
GetLengthSid (pSid2Allow) + // Length of SID for ACE #1
|
||
(sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD)) + // Length of ACE #2
|
||
GetLengthSid (pSidWorld); // Length of SID for ACE #2
|
||
|
||
pAcl = (PACL) new BYTE [dwAclSize];
|
||
if (!pAcl) {
|
||
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
||
goto Exit;
|
||
}
|
||
|
||
if (!InitializeAcl (
|
||
pAcl,
|
||
dwAclSize,
|
||
ACL_REVISION)) {
|
||
|
||
dwErr = GetLastError ();
|
||
goto Exit;
|
||
}
|
||
|
||
if (!AddAccessDeniedAce (pAcl, ACL_REVISION, WRITE_DAC | WRITE_OWNER, pSidWorld) ||
|
||
!AddAccessAllowedAce (pAcl, ACL_REVISION, GENERIC_ALL, pSid2Allow)) {
|
||
|
||
dwErr = GetLastError ();
|
||
goto Exit;
|
||
}
|
||
|
||
if (!SetSecurityDescriptorDacl (pSd, TRUE, pAcl, FALSE)) {
|
||
dwErr = GetLastError ();
|
||
goto Exit;
|
||
}
|
||
|
||
pAcl = NULL; // Now pAcl is set on pSd... and will be deleted as pSd->Dacl
|
||
|
||
Exit:
|
||
if (pSidWorld)
|
||
FreeSid (pSidWorld);
|
||
if (pSidAdmins)
|
||
FreeSid (pSidAdmins);
|
||
|
||
if (pAcl)
|
||
delete [] pAcl;
|
||
|
||
return dwErr;
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::SetSecurityDescriptor( VOID)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function builds the security descriptor used by RPC module.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Windows error code.
|
||
|
||
--*/
|
||
{
|
||
DWORD dwError = NO_ERROR;
|
||
|
||
if (!InitializeSecurityDescriptor (&sm_sid[0], SECURITY_DESCRIPTOR_REVISION) ||
|
||
!InitializeSecurityDescriptor (&sm_sid[1], SECURITY_DESCRIPTOR_REVISION)) {
|
||
// return directly, don't go to Exit and try to free the Dacl
|
||
return GetLastError();
|
||
}
|
||
//
|
||
// build a security descriptor that will grant everyone
|
||
// all access to the object --- this is done by setting a
|
||
// "World" DACL in the SECURITY_DESCRIPTOR.
|
||
//
|
||
|
||
dwError = InitializeSmtpSecurityDescriptor(&sm_sid[ACL_INDEX_ALLOW_ALL], false);
|
||
if (dwError!=ERROR_SUCCESS) goto Exit;
|
||
|
||
dwError = InitializeSmtpSecurityDescriptor(&sm_sid[ACL_INDEX_ALLOW_ADMIN], true);
|
||
if (dwError!=ERROR_SUCCESS) goto Exit;
|
||
|
||
|
||
Exit:
|
||
|
||
if (dwError != ERROR_SUCCESS) {
|
||
//
|
||
// free up security discriptor memory and set it to NULL.
|
||
//
|
||
if (sm_sid[0].Dacl)
|
||
delete [] (BYTE*) sm_sid[0].Dacl;
|
||
if (sm_sid[1].Dacl)
|
||
delete [] (BYTE*) sm_sid[1].Dacl;
|
||
memset( (PVOID ) &sm_sid, 0, sizeof(sm_sid));
|
||
}
|
||
|
||
return( dwError );
|
||
|
||
} // ISRPC::SetSecurityDescriptor()
|
||
|
||
|
||
|
||
|
||
DWORD
|
||
ISRPC::AddSecurity(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This member function adds security support provider over RPC.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Windows error code.
|
||
|
||
--*/
|
||
{
|
||
DWORD rpcStatus;
|
||
|
||
//
|
||
// Register for authentication using WinNT.
|
||
//
|
||
|
||
rpcStatus = RpcServerRegisterAuthInfo(
|
||
(unsigned char * ) NULL, // app name to security provider
|
||
RPC_C_AUTHN_WINNT, // Auth package ID.
|
||
NULL, // RPC_C_AUTHN_WINNT ==> NULL
|
||
NULL // args ptr for authn function.
|
||
);
|
||
|
||
if ( rpcStatus == RPC_S_OK) {
|
||
|
||
sm_fSecurityEnabled = TRUE;
|
||
}
|
||
|
||
#if 0
|
||
IF_DEBUG( DLL_RPC) {
|
||
|
||
DBGPRINTF(( DBG_CONTEXT, "AddSecurity() returns Error %u\n",
|
||
rpcStatus));
|
||
}
|
||
#endif
|
||
|
||
return (rpcStatus);
|
||
} // ISRPC::AddSecurity()
|