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
7.0 KiB
280 lines
7.0 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);
|
|
}
|