Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

280 lines
6.7 KiB

/*++
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
#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.
--*/
{
NTSTATUS Status;
RPC_STATUS RpcStatus;
LPWSTR StringBinding;
LPWSTR Endpoint;
WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD bufLen;
LPWSTR AllocatedServerName = NULL;
LPWSTR UncServerName = NULL;
*pBindingHandle = NULL;
if ( ServerName != NULL ) {
DWORD ServerNameLength = wcslen(ServerName);
//
// Canonicalize the server name
//
if ( ServerName[0] == L'\0' ) {
ServerName = NULL;
UncServerName = NULL;
} else if ( ServerName[0] == L'\\' && ServerName[1] == L'\\' ) {
UncServerName = ServerName;
ServerName += 2;
ServerNameLength -= 2;
if ( ServerNameLength == 0 ) {
Status = STATUS_INVALID_COMPUTER_NAME;
goto Cleanup;
}
} else {
AllocatedServerName = LocalAlloc( 0, (ServerNameLength+2+1) * sizeof(WCHAR) );
if ( AllocatedServerName == NULL ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
AllocatedServerName[0] = L'\\';
AllocatedServerName[1] = L'\\';
RtlCopyMemory( &AllocatedServerName[2],
ServerName,
(ServerNameLength+1) * sizeof(WCHAR) );
UncServerName = AllocatedServerName;
}
//
// If the passed in computer name is the netbios name of this machine,
// drop the computer name so we can avoid the overhead of the redir/server/authentication.
//
if ( ServerName != NULL && ServerNameLength <= MAX_COMPUTERNAME_LENGTH ) {
bufLen = MAX_COMPUTERNAME_LENGTH + 1;
if (GetComputerNameW( ComputerName, &bufLen )) {
if ( ServerNameLength == bufLen &&
_wcsnicmp( ComputerName, ServerName, ServerNameLength) == 0 ) {
ServerName = NULL;
UncServerName = NULL;
}
}
}
//
// If the passed in computer name is the DNS host name of this machine,
// drop the computer name so we can avoid the overhead of the redir/server/authentication.
//
if ( ServerName != NULL ) {
LPWSTR DnsHostName;
//
// Further canonicalize the ServerName.
//
if ( ServerName[ServerNameLength-1] == L'.' ) {
ServerNameLength -= 1;
}
DnsHostName = LocalAlloc( 0, (MAX_PATH+1) * sizeof(WCHAR));
if ( DnsHostName == NULL) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
bufLen = MAX_PATH + 1;
if ( GetComputerNameExW(
ComputerNameDnsFullyQualified,
DnsHostName,
&bufLen ) ) {
if ( ServerNameLength == bufLen &&
_wcsnicmp( DnsHostName, ServerName, ServerNameLength) == 0 ) {
ServerName = NULL;
UncServerName = NULL;
}
}
LocalFree( DnsHostName );
}
}
// 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) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
wcscpy(Endpoint,NT_PIPE_PREFIX_W);
wcscat(Endpoint,ServiceName);
RpcStatus = RpcStringBindingComposeW(0, L"ncacn_np", UncServerName,
Endpoint, NetworkOptions, &StringBinding);
LocalFree(Endpoint);
if ( RpcStatus != RPC_S_OK ) {
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
//
// Get an actual binding handle.
//
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 ) {
Status = STATUS_INVALID_COMPUTER_NAME;
} else {
Status = STATUS_NO_MEMORY;
}
goto Cleanup;
}
Status = STATUS_SUCCESS;
Cleanup:
if ( AllocatedServerName != NULL ) {
LocalFree( AllocatedServerName );
}
return Status;
}
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);
}