Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

288 lines
6.8 KiB

/*++
Copyright (c) 1990-1993 Microsoft Corporation
Module Name:
RpcServ.c
Abstract:
This file contains routines for starting and stoping RPC servers.
NetpInitRpcServer
NetpStartRpcServer
NetpStopRpcServer
Author:
Dan Lafferty danl 09-May-1991
Environment:
User Mode - Win32
Revision History:
26-May-1993 Danl
Added call to RpcMgmtWaitServerListen when shutting down the last
RPC server in the process. This fixes the problem where if we
shut down all the RPC services in lmsvcs.exe (but the process stays
up due to other services), and then start them up again, all calls
to those RPC interfaces would return RPC_SERVER_BUSY.
18-May-1993 Danl
Changed RpcServerUnregisterIf so that it waits for outstanding RPC
calls to complete.
29-Jan-1993 Danl
Free memory allocated for Endpoint and Security Descriptor. Also,
fix it so StartListen() is only called if RpcServerRegisterIf()
succeeeds.
23-Oct-1991 Danl
Added Critical Section Locks and made sure the instance count gets
incremented. Added NetpInitRpcServer().
09-May-1991 Danl
Created
--*/
//
// INCLUDES
//
// These must be included first:
#include <nt.h> // DbgPrint
#include <ntrtl.h> // DbgPrint
#include <windef.h> // win32 typedefs
#include <lmcons.h> // NET_API_STATUS
#include <rpc.h> // rpc prototypes
#include <netlib.h>
#include <rpcutil.h>
#include <nturtl.h> // needed for winbase.h
#include <winbase.h> // LocalAlloc
// These may be included in any order:
#include <ntrtl.h> // DbgPrint
#include <lmerr.h> // NetError codes
#include <rpcutil.h> // MIDL_user_allocate(), MIDL_user_free().
#include <string.h> // for strcpy strcat strlen memcmp
#include <tstring.h> // for STRCPY STRCAT STRLEN memcmp
#include <debuglib.h> // IF_DEBUG
#include <netdebug.h> // FORMAT_NTSTATUS, NetpKdPrint(()).
//
// GLOBALS
//
static CRITICAL_SECTION RpcpCriticalSection;
static DWORD RpcpNumInstances;
NET_API_STATUS
NetpInitRpcServer(
VOID
)
/*++
Routine Description:
This function initializes the critical section used to protect the
global server handle and instance count.
Arguments:
none
Return Value:
none
--*/
{
InitializeCriticalSection(&RpcpCriticalSection);
RpcpNumInstances = 0;
return(0);
}
NET_API_STATUS
NetpStartRpcServer(
IN LPTSTR InterfaceName,
IN RPC_IF_HANDLE InterfaceSpecification
)
/*++
Routine Description:
Starts an RPC Server, adds the address (or port/pipe), and adds the
interface (dispatch table).
Arguments:
InterfaceName - This is a pointer to a character string that identifies
the interface.
InterfaceSpecification - Supplies a description of the interface to
be added.
Return Value:
NERR_Success, or any RPC error codes, or any windows error codes that
can be returned by LocalAlloc.
--*/
{
RPC_STATUS RpcStatus;
LPTSTR Endpoint=NULL;
DWORD status;
PSECURITY_DESCRIPTOR SecurityDescriptor=NULL;
BOOLEAN Bool;
Endpoint = (LPTSTR)LocalAlloc(0, STRSIZE(InterfaceName) + STRSIZE(NT_PIPE_PREFIX));
if (Endpoint == 0) {
status = GetLastError();
IF_DEBUG(RPC) {
NetpKdPrint(("NetpStartRpcServer:LocalAlloc Failure %ld\n",status));
}
return(status);
}
STRCPY(Endpoint, NT_PIPE_PREFIX);
STRCAT(Endpoint, InterfaceName);
IF_DEBUG(RPC) {
NetpKdPrint(("Creating Interface: %s\n", Endpoint));
}
//
// All code from this point on must goto a CleanExit prior to returning.
//
EnterCriticalSection(&RpcpCriticalSection);
IF_DEBUG(RPC) {
NetpKdPrint(("[NetpStartRpcServer]Adding Address & Interface...\n"));
}
//
// Croft up a security descriptor that will grant everyone
// all access to the object (basically, no security)
//
// We do this by putting in a NULL Dacl.
//
// BUGBUG: rpc doesn't know how to copy a security descriptor,
// so just allocate this and leave it around for the time being.
// We need to fix this before we ship.
//
SecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc(
LMEM_FIXED,
sizeof( SECURITY_DESCRIPTOR ));
if (SecurityDescriptor == NULL) {
RpcStatus = RPC_S_OUT_OF_MEMORY;
goto CleanExit;
}
InitializeSecurityDescriptor( SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
Bool =
SetSecurityDescriptorDacl (
SecurityDescriptor,
TRUE, // Dacl present
NULL, // NULL Dacl
FALSE // Not defaulted
);
ASSERT( Bool );
RpcStatus = RpcServerUseProtseqEp(
TEXT("ncacn_np"),
10,
Endpoint,
SecurityDescriptor);
if ((RpcStatus != RPC_S_OK) && (RpcStatus != RPC_S_DUPLICATE_ENDPOINT)) {
IF_DEBUG(RPC) {
NetpKdPrint(("RpcServerUseProtseqA failed! rpcstatus = %u\n",RpcStatus));
}
goto CleanExit;
}
RpcStatus = RpcServerRegisterIf(InterfaceSpecification, 0, 0);
if (RpcStatus != RPC_S_OK) {
IF_DEBUG(RPC) {
NetpKdPrint(("RpcServerRegisterIf failed! rpcstatus = %u\n",RpcStatus));
}
goto CleanExit;
}
RpcpNumInstances++;
if (RpcpNumInstances == 1) {
RpcStatus = RpcServerListen(1, 12345, 1);
if ( RpcStatus == RPC_S_ALREADY_LISTENING ) {
RpcStatus = RPC_S_OK;
}
}
CleanExit:
LeaveCriticalSection(&RpcpCriticalSection);
if (Endpoint != NULL) {
LocalFree(Endpoint);
}
if (SecurityDescriptor != NULL) {
LocalFree(SecurityDescriptor);
}
return NetpRpcStatusToApiStatus(RpcStatus);
}
NET_API_STATUS
NetpStopRpcServer(
IN RPC_IF_HANDLE InterfaceSpecification
)
/*++
Routine Description:
Deletes the interface.
Arguments:
InterfaceSpecification - Supplies a description of the interface to
be deleted.
Return Value:
NERR_Success, or any RPC error codes that can be returned from
RpcServerUnregisterIf.
--*/
{
RPC_STATUS RpcStatus;
RpcStatus = RpcServerUnregisterIf(InterfaceSpecification, 0, 1);
EnterCriticalSection(&RpcpCriticalSection);
RpcpNumInstances--;
if (RpcpNumInstances == 0) {
RpcMgmtStopServerListening(0);
RpcMgmtWaitServerListen();
}
LeaveCriticalSection(&RpcpCriticalSection);
return NetpRpcStatusToApiStatus(RpcStatus);
}