/*++ 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 // needed for NTSTATUS #include // needed for nturtl.h #include // needed for windows.h #include // win32 typedefs #include // rpc prototypes #include #include // for wcscpy wcscat #include // 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); }