summaryrefslogtreecommitdiffstats
path: root/private/rpcutil
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/rpcutil
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/rpcutil')
-rw-r--r--private/rpcutil/client.c182
-rw-r--r--private/rpcutil/makefile6
-rw-r--r--private/rpcutil/midluser.c208
-rw-r--r--private/rpcutil/server.c694
-rw-r--r--private/rpcutil/sources43
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=