diff options
Diffstat (limited to 'private/rpcutil')
-rw-r--r-- | private/rpcutil/client.c | 182 | ||||
-rw-r--r-- | private/rpcutil/makefile | 6 | ||||
-rw-r--r-- | private/rpcutil/midluser.c | 208 | ||||
-rw-r--r-- | private/rpcutil/server.c | 694 | ||||
-rw-r--r-- | private/rpcutil/sources | 43 |
5 files changed, 1133 insertions, 0 deletions
diff --git a/private/rpcutil/client.c b/private/rpcutil/client.c new file mode 100644 index 000000000..6359c06d1 --- /dev/null +++ b/private/rpcutil/client.c @@ -0,0 +1,182 @@ +/*++ + +Copyright (c) 1990-92 Microsoft Corporation + +Module Name: + + client.c + +Abstract: + + This file contains commonly used client-side RPC control functions. + +Author: + + Dan Lafferty danl 06-Feb-1991 + +Environment: + + User Mode - Win32 + +Revision History: + + 06-Feb-1991 danl + Created + 26-Apr-1991 JohnRo + Split out MIDL user (allocate,free) so linker doesn't get confused. + Deleted tabs. + 03-July-1991 JimK + Copied from LM specific file. + 27-Feb-1992 JohnRo + Fixed heap trashing bug in RpcpBindRpc(). + +--*/ + +// These must be included first: +#include <nt.h> // needed for NTSTATUS +#include <ntrtl.h> // needed for nturtl.h +#include <nturtl.h> // needed for windows.h +#include <windows.h> // win32 typedefs +#include <rpc.h> // rpc prototypes +#include <ntrpcp.h> + +#include <stdlib.h> // for wcscpy wcscat +#include <tstr.h> // WCSSIZE + + +// BUGBUG - Change these when RPC uses Win32 APIs for named pipes. +// +#define LOCAL_NMPIPE_NAME TEXT("\\Device\\Namedpipe\\") +#define REMOTE_NMPIPE_NAME TEXT("\\Device\\LanmanRedirector\\") + +#define NT_PIPE_PREFIX TEXT("\\PIPE\\") +#define NT_PIPE_PREFIX_W L"\\PIPE\\" + + + +NTSTATUS +RpcpBindRpc( + IN LPWSTR ServerName, + IN LPWSTR ServiceName, + IN LPWSTR NetworkOptions, + OUT RPC_BINDING_HANDLE * pBindingHandle + ) + +/*++ + +Routine Description: + + Binds to the RPC server if possible. + +Arguments: + + ServerName - Name of server to bind with. + + ServiceName - Name of service to bind with. + + pBindingHandle - Location where binding handle is to be placed + +Return Value: + + STATUS_SUCCESS - The binding has been successfully completed. + + STATUS_INVALID_COMPUTER_NAME - The ServerName syntax is invalid. + + STATUS_NO_MEMORY - There is not sufficient memory available to the + caller to perform the binding. + +--*/ + +{ + RPC_STATUS RpcStatus; + LPWSTR StringBinding; + LPWSTR Endpoint; + WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; + LPWSTR NewServerName = NULL; + DWORD bufLen = MAX_COMPUTERNAME_LENGTH + 1; + + *pBindingHandle = NULL; + + if (ServerName != NULL) { + if (GetComputerNameW(ComputerName,&bufLen)) { + if ((_wcsicmp(ComputerName,ServerName) == 0) || + ((ServerName[0] == '\\') && + (ServerName[1] == '\\') && + (_wcsicmp(ComputerName,&(ServerName[2]))==0))) { + NewServerName = NULL; + } + else { + NewServerName = ServerName; + } + } + } + + // We need to concatenate \pipe\ to the front of the service + // name. + + Endpoint = (LPWSTR)LocalAlloc( + 0, + sizeof(NT_PIPE_PREFIX_W) + WCSSIZE(ServiceName)); + if (Endpoint == 0) { + return(STATUS_NO_MEMORY); + } + wcscpy(Endpoint,NT_PIPE_PREFIX_W); + wcscat(Endpoint,ServiceName); + + RpcStatus = RpcStringBindingComposeW(0, L"ncacn_np", NewServerName, + Endpoint, NetworkOptions, &StringBinding); + LocalFree(Endpoint); + + if ( RpcStatus != RPC_S_OK ) { + return( STATUS_NO_MEMORY ); + } + + RpcStatus = RpcBindingFromStringBindingW(StringBinding, pBindingHandle); + RpcStringFreeW(&StringBinding); + if ( RpcStatus != RPC_S_OK ) { + *pBindingHandle = NULL; + if ( (RpcStatus == RPC_S_INVALID_ENDPOINT_FORMAT) + || (RpcStatus == RPC_S_INVALID_NET_ADDR) ) { + + return( STATUS_INVALID_COMPUTER_NAME ); + } + return(STATUS_NO_MEMORY); + } + return(STATUS_SUCCESS); +} + + +NTSTATUS +RpcpUnbindRpc( + IN RPC_BINDING_HANDLE BindingHandle + ) + +/*++ + +Routine Description: + + Unbinds from the RPC interface. + If we decide to cache bindings, this routine will do something more + interesting. + +Arguments: + + BindingHandle - This points to the binding handle that is to be closed. + + +Return Value: + + + STATUS_SUCCESS - the unbinding was successful. + +--*/ +{ + RPC_STATUS RpcStatus; + + if (BindingHandle != NULL) { + RpcStatus = RpcBindingFree(&BindingHandle); + ASSERT(RpcStatus == RPC_S_OK); + } + + return(STATUS_SUCCESS); +} diff --git a/private/rpcutil/makefile b/private/rpcutil/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/rpcutil/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/rpcutil/midluser.c b/private/rpcutil/midluser.c new file mode 100644 index 000000000..4350b683d --- /dev/null +++ b/private/rpcutil/midluser.c @@ -0,0 +1,208 @@ +/*++ + +Copyright (c) 1990,91 Microsoft Corporation + +Module Name: + + MidlUser.c + +Abstract: + + This file contains common functions and utilities that the API + DLLs can use in making remote calls. This includes the + MIDL_USER_ALLOCATE functions. + +Author: + + Dan Lafferty danl 06-Feb-1991 + +Environment: + + User Mode - Win32 + +Revision History: + + 06-Feb-1991 danl + Created + 25-Apr-1991 JohnRo + Split out MIDL user (allocate,free) into seperate source file, so + linker doesn't get confused. + 03-July-1991 JimK + Moved to a common directory so services available to more than just + LM code. + 03-Dec-1991 JohnRo + Added MIDL_user_reallocate and MIDL_user_size APIs. (These are so we + create the NetApiBufferAllocate, NetApiBufferReallocate, and + NetApiBufferSize APIs.) + Also check alignment of allocated data. + +--*/ + +// These must be included first: +#include <nt.h> +#include <ntrtl.h> // needed for nturtl.h +#include <nturtl.h> // needed for windows.h +#include <windows.h> // win32 typedefs +#include <rpc.h> // rpc prototypes + +// These may be included in any order: +#include <align.h> // POINTER_IS_ALIGNED(), ALIGN_WORST. +#include <ntrpcp.h> // MIDL_user_allocate(), MIDL_user_free(). + +#include <winbase.h> // LocalAlloc + + +#define LOCAL_ALLOCATION_FLAGS LMEM_ZEROINIT + + +PVOID +MIDL_user_allocate ( + IN unsigned int NumBytes + ) + +/*++ + +Routine Description: + + Allocates storage for RPC transactions. The RPC stubs will either call + MIDL_user_allocate when it needs to un-marshall data into a buffer + that the user must free. RPC servers will use MIDL_user_allocate to + allocate storage that the RPC server stub will free after marshalling + the data. + +Arguments: + + NumBytes - The number of bytes to allocate. + +Return Value: + + none + +Note: + + +--*/ + +{ + LPVOID NewPointer; + + NewPointer = LocalAlloc( + LOCAL_ALLOCATION_FLAGS, + NumBytes); + + ASSERT( POINTER_IS_ALIGNED( NewPointer, ALIGN_WORST) ); + + return (NewPointer); + +} // MIDL_user_allocate + + + +VOID +MIDL_user_free ( + IN void *MemPointer + ) + +/*++ + +Routine Description: + + Frees storage used in RPC transactions. The RPC client can call this + function to free buffer space that was allocated by the RPC client + stub when un-marshalling data that is to be returned to the client. + The Client calls MIDL_user_free when it is finished with the data and + desires to free up the storage. + The RPC server stub calls MIDL_user_free when it has completed + marshalling server data that is to be passed back to the client. + +Arguments: + + MemPointer - This points to the memory block that is to be released. + +Return Value: + + none. + +Note: + + +--*/ +{ + ASSERT( POINTER_IS_ALIGNED( MemPointer, ALIGN_WORST) ); + (void) LocalFree(MemPointer); + +} // MIDL_user_free + +void * +MIDL_user_reallocate( + IN void * OldPointer OPTIONAL, + IN unsigned long NewByteCount + ) +{ + LPVOID NewPointer; // may be NULL. + + ASSERT( POINTER_IS_ALIGNED( OldPointer, ALIGN_WORST) ); + + + // Special cases: something into nothing, or nothing into something. + if (OldPointer == NULL) { + + NewPointer = LocalAlloc( + LOCAL_ALLOCATION_FLAGS, + NewByteCount); + + } else if (NewByteCount == 0) { + + (void) LocalFree( OldPointer ); + NewPointer = NULL; + + } else { // must be realloc of something to something else. + + HANDLE hOldMem; + HANDLE hNewMem; // handle for new (may = old handle) + + hOldMem = LocalHandle( (LPSTR) OldPointer); + ASSERT(hOldMem != NULL); + + hNewMem = LocalReAlloc( + hOldMem, // old handle + NewByteCount, // new size in bytes + LOCAL_ALLOCATION_FLAGS | // flags + LMEM_MOVEABLE); // (motion okay) + if (hNewMem == NULL) { + // BUGBUG: call GetLastError, could be out of memory or error. + return (NULL); + } + NewPointer = (LPVOID) hNewMem; + + } // must be realloc of something to something else + + ASSERT( POINTER_IS_ALIGNED( NewPointer, ALIGN_WORST) ); + + return (NewPointer); + +} // MIDL_user_reallocate + + +unsigned long +MIDL_user_size( + IN void * Pointer + ) +{ + DWORD ByteCount; + HANDLE hMemory; + + ASSERT( Pointer != NULL ); + ASSERT( POINTER_IS_ALIGNED( Pointer, ALIGN_WORST ) ); + + hMemory = LocalHandle( (LPSTR) Pointer ); + ASSERT( hMemory != NULL ); + + ByteCount = LocalSize( hMemory ); + + ASSERT( ByteCount > 0 ); + + return (ByteCount); + +} // MIDL_user_size + diff --git a/private/rpcutil/server.c b/private/rpcutil/server.c new file mode 100644 index 000000000..f20a48227 --- /dev/null +++ b/private/rpcutil/server.c @@ -0,0 +1,694 @@ +/*++ + +Copyright (c) 1990,91 Microsoft Corporation + +Module Name: + + RpcServ.c + +Abstract: + + This file contains commonly used server-side RPC functions, + such as starting and stoping RPC servers. + +Author: + + Dan Lafferty danl 09-May-1991 + +Environment: + + User Mode - Win32 + +Revision History: + + 09-May-1991 Danl + Created + + 03-July-1991 JimK + Copied from a net-specific file. + + 18-Feb-1992 Danl + Added support for multiple endpoints & interfaces per server. + + 10-Nov-1993 Danl + Wait for RPC calls to complete before returning from + RpcServerUnregisterIf. Also, do a WaitServerListen after + calling StopServerListen (when the last server shuts down). + Now this is similar to RpcServer functions in netlib. + + 29-Jun-1995 RichardW + Read an alternative ACL from a key in the registry, if one exists. + This ACL is used to protect the named pipe. + +--*/ + +// +// INCLUDES +// + +// These must be included first: +#include <nt.h> // DbgPrint +#include <ntrtl.h> // DbgPrint +#include <windef.h> // win32 typedefs +#include <rpc.h> // rpc prototypes +#include <ntrpcp.h> +#include <nturtl.h> // needed for winbase.h +#include <winbase.h> // LocalAlloc + +// These may be included in any order: +#include <stdlib.h> // for wcscpy wcscat +#include <tstr.h> // WCSSIZE + +#define NT_PIPE_PREFIX_W L"\\PIPE\\" +#define NT_PIPE_SD_PREFIX_W L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SecurePipeServers\\" + +static +PWSTR RpcpSecurablePipes[] = { + L"eventlog" // Eventlog server + }; + +// +// GLOBALS +// + + static CRITICAL_SECTION RpcpCriticalSection; + static DWORD RpcpNumInstances; + + + +DWORD +RpcpInitRpcServer( + 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); +} + +NTSTATUS +RpcpReadSDFromRegistry( + IN LPWSTR InterfaceName, + OUT PSECURITY_DESCRIPTOR * pSDToUse) +/*++ + +Routine Description: + + This function checks the registry in the magic place to see if an extra + ACL has been defined for the pipe being passed in. If there is one, it + is translated to a NP acl, then returned. If there isn't one, or if + something goes wrong, an NULL acl is returned. + +Arguments: + + InterfaceName name of the pipe to check for, e.g. winreg, etc. + + pSDToUse returned a pointer to the security decriptor to use. + +Return Value: + + STATUS_SUCCESS, + STATUS_NO_MEMORY, + Possible other errors from registry apis. + + +--*/ +{ + HANDLE hKey; + OBJECT_ATTRIBUTES ObjAttr; + UNICODE_STRING UniString; + PWSTR PipeKey; + NTSTATUS Status; + PSECURITY_DESCRIPTOR pSD; + ULONG cbNeeded; + ACL_SIZE_INFORMATION AclSize; + ULONG AceIndex; + ACCESS_MASK NewMask; + PACCESS_ALLOWED_ACE pAce; + PACL pAcl; + BOOLEAN DaclPresent; + BOOLEAN DaclDefaulted; + UNICODE_STRING Interface; + UNICODE_STRING Allowed; + ULONG i; + BOOLEAN PipeNameOk; + PSECURITY_DESCRIPTOR pNewSD; + PACL pNewAcl; + + *pSDToUse = NULL; + + RtlInitUnicodeString( &Interface, InterfaceName ); + + PipeNameOk = FALSE; + + for ( i = 0 ; i < sizeof( RpcpSecurablePipes ) / sizeof(PWSTR) ; i++ ) + { + RtlInitUnicodeString( &Allowed, RpcpSecurablePipes[i] ); + + if ( RtlCompareUnicodeString( &Allowed, &Interface, TRUE ) == 0 ) + { + PipeNameOk = TRUE; + break; + } + } + + if ( PipeNameOk ) + { + + PipeKey = RtlAllocateHeap(RtlProcessHeap(), 0, + sizeof(NT_PIPE_SD_PREFIX_W) + WCSSIZE(InterfaceName) ); + + if (!PipeKey) + { + return(STATUS_NO_MEMORY); + } + + wcscpy(PipeKey, NT_PIPE_SD_PREFIX_W); + wcscat(PipeKey, InterfaceName); + + RtlInitUnicodeString(&UniString, PipeKey); + + InitializeObjectAttributes( &ObjAttr, + &UniString, + OBJ_CASE_INSENSITIVE, + NULL, NULL); + + Status = NtOpenKey( &hKey, + KEY_READ, + &ObjAttr); + + RtlFreeHeap(RtlProcessHeap(), 0, PipeKey); + + } + else + { + // + // This is not one of the interfaces that we allow to be secured + // in this fashion. Fake and error, + // + + Status = STATUS_OBJECT_NAME_NOT_FOUND ; + } + + // + // In general, most times we won't find this key + // + + if (!NT_SUCCESS(Status)) + { + if ((Status == STATUS_OBJECT_NAME_NOT_FOUND) || + (Status == STATUS_OBJECT_PATH_NOT_FOUND) ) + { + pSD = RtlAllocateHeap(RtlProcessHeap(), 0, + sizeof(SECURITY_DESCRIPTOR) ); + if (pSD) + { + InitializeSecurityDescriptor( pSD, + SECURITY_DESCRIPTOR_REVISION ); + + if (SetSecurityDescriptorDacl ( + pSD, + TRUE, // Dacl present + NULL, // NULL Dacl + FALSE // Not defaulted + ) ) + { + *pSDToUse = pSD; + return(STATUS_SUCCESS); + } + + RtlFreeHeap(RtlProcessHeap(), 0, pSD); + + } + return(STATUS_NO_MEMORY); + } + + return(Status); + + } + + // + // Son of a gun, someone has established security for this pipe. + // + + pSD = NULL; + + cbNeeded = 0; + Status = NtQuerySecurityObject( + hKey, + DACL_SECURITY_INFORMATION, + NULL, + 0, + &cbNeeded ); + + if (Status == STATUS_BUFFER_TOO_SMALL) + { + pSD = RtlAllocateHeap(RtlProcessHeap(), 0, cbNeeded); + if (pSD) + { + Status = NtQuerySecurityObject( + hKey, + DACL_SECURITY_INFORMATION, + pSD, + cbNeeded, + &cbNeeded ); + + // + // One way or the other, we are done with the key handle + // + + NtClose(hKey); + + if (NT_SUCCESS(Status)) + { + // + // Now, the tricky part. There is no 1-1 mapping of Key + // permissions to Pipe permissions. So, we do it here. + // We walk the DACL, and examine each ACE. We build a new + // access mask for each ACE, and set the flags as follows: + // + // if (KEY_READ) GENERIC_READ + // if (KEY_WRITE) GENERIC_WRITE + // + + Status = RtlGetDaclSecurityDescriptor( + pSD, + &DaclPresent, + &pAcl, + &DaclDefaulted); + + + // + // If this failed, or there is no DACL present, then + // we're in trouble. + // + + if (!NT_SUCCESS(Status) || !DaclPresent) + { + goto GetSDFromKey_BadAcl; + } + + + Status = RtlQueryInformationAcl(pAcl, + &AclSize, + sizeof(AclSize), + AclSizeInformation); + + if (!NT_SUCCESS(Status)) + { + goto GetSDFromKey_BadAcl; + } + + for (AceIndex = 0; AceIndex < AclSize.AceCount ; AceIndex++ ) + { + NewMask = 0; + Status = RtlGetAce( pAcl, + AceIndex, + & pAce); + + // + // We don't care what kind of ACE it is, since we + // are just mapping the access types, and the access + // mask is always at a constant position. + // + + if (NT_SUCCESS(Status)) + { + if ((pAce->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) && + (pAce->Header.AceType != ACCESS_DENIED_ACE_TYPE)) + { + // + // Must be an audit or random ACE type. Skip it. + // + + continue; + + } + + + if (pAce->Mask & KEY_READ) + { + NewMask |= GENERIC_READ; + } + + if (pAce->Mask & KEY_WRITE) + { + NewMask |= GENERIC_WRITE; + } + + pAce->Mask = NewMask; + } + else + { + // + // Panic: Bad ACL? + // + + goto GetSDFromKey_BadAcl; + } + + } + + // + // BUGBUG: RPC does not understand self-relative SDs, so + // we have to turn this into an absolute for them to turn + // back into a self relative. + // + + pNewSD = RtlAllocateHeap(RtlProcessHeap(), 0, cbNeeded); + if (!pNewSD) + { + goto GetSDFromKey_BadAcl; + } + + InitializeSecurityDescriptor( pNewSD, + SECURITY_DESCRIPTOR_REVISION); + + pNewAcl = (PACL) (((PUCHAR) pNewSD) + + sizeof(SECURITY_DESCRIPTOR) ); + + RtlCopyMemory(pNewAcl, pAcl, AclSize.AclBytesInUse); + + SetSecurityDescriptorDacl(pNewSD, TRUE, pNewAcl, FALSE); + + RtlFreeHeap(RtlProcessHeap(), 0, pSD); + + *pSDToUse = pNewSD; + return(Status); + } + } + return(STATUS_NO_MEMORY); + } + else + { + // + // Failed to read SD: + // + + NtClose(hKey); + + +GetSDFromKey_BadAcl: + + // + // Free the SD that we have allocated + // + + if (pSD) + { + RtlFreeHeap(RtlProcessHeap(), 0, pSD); + } + + // + // Key exists, but there is no security descriptor, or it is unreadable + // for whatever reason. + // + + pSD = RtlAllocateHeap(RtlProcessHeap(), 0, + sizeof(SECURITY_DESCRIPTOR) ); + if (pSD) + { + InitializeSecurityDescriptor( pSD, + SECURITY_DESCRIPTOR_REVISION ); + + if (SetSecurityDescriptorDacl ( + pSD, + TRUE, // Dacl present + NULL, // NULL Dacl + FALSE // Not defaulted + ) ) + { + *pSDToUse = pSD; + return(STATUS_SUCCESS); + } + + } + return(STATUS_NO_MEMORY); + + } + + +} + + +NTSTATUS +RpcpAddInterface( + IN LPWSTR 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 - points to the name of the interface. + + InterfaceSpecification - Supplies the interface handle for the + interface which we wish to add. + +Return Value: + + NT_SUCCESS - Indicates the server was successfully started. + + STATUS_NO_MEMORY - An attempt to allocate memory has failed. + + Other - Status values that may be returned by: + + RpcServerRegisterIf() + RpcServerUseProtseqEp() + + , or any RPC error codes, or any windows error codes that + can be returned by LocalAlloc. + +--*/ +{ + RPC_STATUS RpcStatus; + LPWSTR Endpoint = NULL; + + PSECURITY_DESCRIPTOR SecurityDescriptor = NULL; + BOOL Bool; + NTSTATUS Status; + + // We need to concatenate \pipe\ to the front of the interface name. + + Endpoint = (LPWSTR)LocalAlloc(LMEM_FIXED, sizeof(NT_PIPE_PREFIX_W) + WCSSIZE(InterfaceName)); + if (Endpoint == 0) { + return(STATUS_NO_MEMORY); + } + wcscpy(Endpoint, NT_PIPE_PREFIX_W ); + wcscat(Endpoint,InterfaceName); + + // + // 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 should copy the security descriptor, + // Since it currently doesn't, simply allocate it for now and + // leave it around forever. + // + + Status = RpcpReadSDFromRegistry(InterfaceName, &SecurityDescriptor); + if (!NT_SUCCESS(Status)) + { + return(Status); + } + + // Ignore the second argument for now. + + RpcStatus = RpcServerUseProtseqEpW(L"ncacn_np", 10, Endpoint, SecurityDescriptor); + + // If RpcpStartRpcServer and then RpcpStopRpcServer have already + // been called, the endpoint will have already been added but not + // removed (because there is no way to do it). If the endpoint is + // already there, it is ok. + + if ( (RpcStatus != RPC_S_OK) + && (RpcStatus != RPC_S_DUPLICATE_ENDPOINT)) { + +#if DBG + DbgPrint("RpcServerUseProtseqW failed! rpcstatus = %u\n",RpcStatus); +#endif + goto CleanExit; + } + + RpcStatus = RpcServerRegisterIf(InterfaceSpecification, 0, 0); + +CleanExit: + if ( Endpoint != NULL ) { + LocalFree(Endpoint); + } + if ( SecurityDescriptor != NULL) { + LocalFree(SecurityDescriptor); + } + + return( I_RpcMapWin32Status(RpcStatus) ); +} + + +NTSTATUS +RpcpStartRpcServer( + IN LPWSTR 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 - points to the name of the interface. + + InterfaceSpecification - Supplies the interface handle for the + interface which we wish to add. + +Return Value: + + NT_SUCCESS - Indicates the server was successfully started. + + STATUS_NO_MEMORY - An attempt to allocate memory has failed. + + Other - Status values that may be returned by: + + RpcServerRegisterIf() + RpcServerUseProtseqEp() + + , or any RPC error codes, or any windows error codes that + can be returned by LocalAlloc. + +--*/ +{ + RPC_STATUS RpcStatus; + + EnterCriticalSection(&RpcpCriticalSection); + + RpcStatus = RpcpAddInterface( InterfaceName, + InterfaceSpecification ); + + if ( RpcStatus != RPC_S_OK ) { + LeaveCriticalSection(&RpcpCriticalSection); + return( I_RpcMapWin32Status(RpcStatus) ); + } + + RpcpNumInstances++; + + if (RpcpNumInstances == 1) { + + + // The first argument specifies the minimum number of threads to + // be created to handle calls; the second argument specifies the + // maximum number of concurrent calls allowed. The last argument + // indicates not to wait. + + RpcStatus = RpcServerListen(1,12345, 1); + if ( RpcStatus == RPC_S_ALREADY_LISTENING ) { + RpcStatus = RPC_S_OK; + } + } + + LeaveCriticalSection(&RpcpCriticalSection); + return( I_RpcMapWin32Status(RpcStatus) ); +} + + +NTSTATUS +RpcpDeleteInterface( + IN RPC_IF_HANDLE InterfaceSpecification + ) + +/*++ + +Routine Description: + + Deletes the interface. This is likely + to be caused by an invalid handle. If an attempt to add the same + interface or address again, then an error will be generated at that + time. + +Arguments: + + InterfaceSpecification - A handle for the interface that is to be removed. + +Return Value: + + NERR_Success, or any RPC error codes that can be returned from + RpcServerUnregisterIf. + +--*/ +{ + RPC_STATUS RpcStatus; + + RpcStatus = RpcServerUnregisterIf(InterfaceSpecification, 0, 1); + + return( I_RpcMapWin32Status(RpcStatus) ); +} + + +NTSTATUS +RpcpStopRpcServer( + IN RPC_IF_HANDLE InterfaceSpecification + ) + +/*++ + +Routine Description: + + Deletes the interface. This is likely + to be caused by an invalid handle. If an attempt to add the same + interface or address again, then an error will be generated at that + time. + +Arguments: + + InterfaceSpecification - A handle for the interface that is to be removed. + +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( I_RpcMapWin32Status(RpcStatus) ); +} diff --git a/private/rpcutil/sources b/private/rpcutil/sources new file mode 100644 index 000000000..9a36e7f63 --- /dev/null +++ b/private/rpcutil/sources @@ -0,0 +1,43 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Jim Kelly (JimK) 3-July-1991 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=rpcutil +MINORCOMP=_ + +TARGETNAME=rpcutil +TARGETPATH=$(BASEDIR)\public\sdk\lib +TARGETTYPE=LIBRARY + +INCLUDES=..\inc + + + +SOURCES=midluser.c \ + client.c \ + server.c + +C_DEFINES=-DRPC_NO_WINDOWS_H +UMTYPE=nt +UMTEST= +OPTIONAL_UMTEST= |