|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
stiapi.h
Abstract:
Common RPC related utility functions
Functions Exported:
MIDL_user_allocate() MIDL_user_free() RpcBindHandleForServer() RpcBindHandleFree()
Author:
Vlad Sadovsky (vlads) 26-Jan-1997
Revision History:
26-Jan-1997 VladS created
--*/
#include "cplusinc.h"
#include "sticomm.h"
# include <rpc.h>
# include "apiutil.h"
#include "simstr.h"
/************************************************************
* Functions ************************************************************/
extern "C" { PVOID MIDL_user_allocate(IN size_t size) /*++
Routine Description:
MIDL memory allocation.
Arguments:
size : Memory size requested.
Return Value:
Pointer to the allocated memory block.
--*/ { PVOID pvBlob;
pvBlob = LocalAlloc( LPTR, size);
return( pvBlob );
} // MIDL_user_allocate()
VOID MIDL_user_free(IN PVOID pvBlob) /*++
Routine Description:
MIDL memory free .
Arguments:
pvBlob : Pointer to a memory block that is freed.
Return Value:
None.
--*/ { LocalFree( pvBlob);
return; } // MIDL_user_free()
}
static CHAR szLocalAddress[] = "127.0.0.1";
RPC_STATUS RpcBindHandleOverLocal( OUT handle_t * pBindingHandle, IN LPWSTR pwszInterfaceName ) /*++
This function uses the parameters supplied and generates static binding handle for RPC over LRPC
Arguments: pBindingHandle pointer to location which will contain binding handle on successful return pwszInterfaceName pointer to string containing the interface name
Returns: RPC_STATUS - RPC_S_OK on success Also on success, the binding handle is stored in pBindingHandle. It should freed after usage, using the RpcBindingFree() function.
--*/ { RPC_STATUS rpcStatus; LPTSTR pszBinding = NULL; BOOL fLocalCall = FALSE;
if ( pBindingHandle != NULL) {
*pBindingHandle = NULL; // init the value
}
//
// Compose the binding string for local binding
//
rpcStatus = RpcStringBindingCompose(0, // ObjUuid
(RPC_STRING)STI_LRPC_SEQ, // transport seq
(RPC_STRING)TEXT(""), // NetworkAddr
(RPC_STRING)STI_LRPC_ENDPOINT, // Endpoint
NULL, // Options
(RPC_STRING *)&pszBinding);// StringBinding
if ( rpcStatus == RPC_S_OK ) {
//
// establish the binding handle using string binding.
//
rpcStatus = RpcBindingFromStringBinding((RPC_STRING)pszBinding,pBindingHandle );
if (rpcStatus == RPC_S_OK) { //
// Check that the server we're connecting to has the appropriate credentials.
// For XP CLient, we know the principal name is LocalSystem.
//
CSimpleStringWide cswStiSvcPrincipalName = L"NT Authority\\System";
RPC_SECURITY_QOS RpcSecQos = {0};
RpcSecQos.Version = RPC_C_SECURITY_QOS_VERSION_1; RpcSecQos.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH; RpcSecQos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; RpcSecQos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
rpcStatus = RpcBindingSetAuthInfoExW(*pBindingHandle, (WCHAR*)cswStiSvcPrincipalName.String(), RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, NULL, RPC_C_AUTHZ_NONE, &RpcSecQos); } }
//
// Cleanup and return back.
//
if ( pszBinding != NULL) {
DWORD rpcStatus1 = RpcStringFree((RPC_STRING *)&pszBinding); }
if ( rpcStatus != RPC_S_OK) {
if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
// RPC should have freed the binding handle.
// We will free it now.
DWORD rpcStatus1 = RpcBindingFree(pBindingHandle); *pBindingHandle = NULL; } }
return (rpcStatus);
} // RpcBindHandleOverLocal()
#ifdef STI_REMOTE_BINDING
RPC_STATUS RpcBindHandleOverTcpIp( OUT handle_t * pBindingHandle, IN LPWSTR pwszServerName, IN LPWSTR pwszInterfaceName ) /*++
This function uses the parameters supplied and generates a dynamic end point binding handle for RPC over TCP/IP.
Arguments: pBindingHandle pointer to location which will contain binding handle on successful return pwszServerName pointer to string containing the name of the server to which, this function will obtain a binding. pwszInterfaceName pointer to string containing the interface name
Returns: RPC_STATUS - RPC_S_OK on success Also on success, the binding handle is stored in pBindingHandle. It should freed after usage, using the RpcBindingFree() function.
--*/ { RPC_STATUS rpcStatus; LPSTR pszBindingA = NULL; CHAR szServerA[MAX_PATH]; CHAR szInterfaceA[MAX_PATH]; int cch; BOOL fLocalCall = FALSE;
if ( pBindingHandle != NULL) {
*pBindingHandle = NULL; // init the value
}
*szServerA = '0';
if (pwszServerName ) { cch = WideCharToMultiByte(CP_ACP, 0, pwszServerName, -1, szServerA, sizeof(szServerA)/sizeof(CHAR), NULL,NULL ); }
// If empty server name has been passed - use address of local machine
if (!*szServerA || !lstrcmpi(szServerA,szLocalAddress)) {
fLocalCall = TRUE; lstrcpy(szServerA,szLocalAddress);
}
*szInterfaceA = '0';
if(pwszInterfaceName) cch = WideCharToMultiByte(CP_ACP, 0, pwszInterfaceName, -1, szInterfaceA, sizeof(szInterfaceA)/sizeof(CHAR), NULL,NULL );
//
// Compose the binding string for TCP/IP binding
//
rpcStatus = RpcStringBindingCompose(0, // ObjUuid
"ncacn_ip_tcp", // tcpip seq
szServerA, // NetworkAddr
NULL, // Endpoint
NULL, //L"", // Options
&pszBindingA); // StringBinding
DBGPRINTF( (DBG_CONTEXT, "\nRpcStringBindingCompose(%s, %s) return %s." " Error = %ld\n", "ncacn_ip_tcp", szServerA, pszBindingA, rpcStatus) );
if ( rpcStatus == RPC_S_OK ) {
//
// establish the binding handle using string binding.
//
rpcStatus = RpcBindingFromStringBinding(pszBindingA, pBindingHandle );
DBGPRINTF( (DBG_CONTEXT, "RpcBindingFromStringBinding(%s) return %d." "Binding=%08x\n", pszBindingA, rpcStatus, *pBindingHandle) ); }
if ( (rpcStatus == RPC_S_OK) && !fLocalCall) {
//
// set up the security information
//
rpcStatus = RpcBindingSetAuthInfo(*pBindingHandle, szInterfaceA, // pszPrincipalName
RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_AUTHN_WINNT, NULL, // AuthnIdentity
0 // AuthzSvc
); DBGPRINTF( (DBG_CONTEXT, "RpcBindingSetAuthInfo(%s(Interface=%s), %08x)" " return %d.\n", pszBindingA, szInterfaceA, *pBindingHandle, rpcStatus ) );
}
//
// Cleanup and return back.
//
if ( pszBindingA != NULL) {
DWORD rpcStatus1 = RpcStringFree(&pszBindingA); DBGPRINTF( (DBG_CONTEXT, "RpcStringFreeW() returns %d.", rpcStatus1) );
}
if ( rpcStatus != RPC_S_OK) {
if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
// RPC should have freed the binding handle.
// We will free it now.
DWORD rpcStatus1 = RpcBindingFree(*pBindingHandle); DBGPRINTF( (DBG_CONTEXT, "RpcBindingFree() returns %d.\n", rpcStatus1) ); *pBindingHandle = NULL; } }
return (rpcStatus);
} // RpcBindHandleOverTcpIp()
RPC_STATUS RpcBindHandleOverNamedPipe( OUT handle_t * pBindingHandle, IN LPWSTR pwszServerName, IN LPWSTR pwszEndpoint, IN LPWSTR pwszOptions ) /*++
This function uses the parameters supplied and generates a named pipe binding handle for RPC.
Arguments: pBindingHandle pointer to location which will contain binding handle on successful return pwszServerName pointer to string containing the name of the server to which, this function will obtain a binding. pwszEndpoint pointer to string containing the Named Pipe Endpoint pwszOptions pointer to string containing any additional options for binding.
Returns: RPC_STATUS - RPC_S_OK on success Also on success, the binding handle is stored in pBindingHandle. It should freed after usage, using the RpcBindingFree() function.
--*/ { RPC_STATUS rpcStatus;
LPWSTR pwszBinding = NULL; LPSTR pszBindingA = NULL;
CHAR szServerA[MAX_PATH+2]; CHAR szEndpointA[MAX_PATH]; CHAR szOptionsA[MAX_PATH]; PSTR pszStartServerName;
int cch; BOOL fLocalCall = FALSE;
if ( pBindingHandle != NULL) {
*pBindingHandle = NULL; // init the value
}
*szServerA = '0';
if (pwszServerName ) {
// We are trying to bind over NP transport, so server name should start with leading slashes
if(*pwszServerName == L'\\' && *(pwszServerName+1) == L'\\') { pszStartServerName = szServerA; } else { lstrcpy(szServerA,TEXT("\\\\")); pszStartServerName = szServerA+2; }
cch = WideCharToMultiByte(CP_ACP, 0, pwszServerName, -1, pszStartServerName, sizeof(szServerA)/sizeof(CHAR)-2, NULL,NULL ); }
if (!*szServerA) { return ERROR_INVALID_PARAMETER; }
// Remove extra slashes if there are too many
*szEndpointA = '0';
if(pwszEndpoint) cch = WideCharToMultiByte(CP_ACP, 0, pwszEndpoint, -1, szEndpointA, sizeof(szEndpointA)/sizeof(CHAR), NULL,NULL );
*szOptionsA = '0';
if(pwszOptions) cch = WideCharToMultiByte(CP_ACP, 0, pwszOptions, -1, szOptionsA, sizeof(szOptionsA)/sizeof(CHAR), NULL,NULL );
//
// Compose the binding string for named pipe binding
//
rpcStatus = RpcStringBindingCompose(0, // ObjUuid
"ncacn_np", // prot seq: named pipe
szServerA, // NetworkAddr
szEndpointA, // Endpoint
"", //szOptionsA, // Options
&pszBindingA); // StringBinding
if ( rpcStatus == RPC_S_OK ) {
//
// establish the binding handle using string binding.
//
rpcStatus = RpcBindingFromStringBinding(pszBindingA, pBindingHandle ); }
//
// Cleanup and return back.
//
if ( pwszBinding != NULL) { RpcStringFree(&pszBindingA); }
if ( rpcStatus != RPC_S_OK) {
if ( pBindingHandle != NULL && *pBindingHandle != NULL) {
// RPC should have freed the binding handle.
// We will free it now.
RpcBindingFree(*pBindingHandle); *pBindingHandle = NULL; } }
return (rpcStatus);
} // RpcBindHandleOverNamedPipe()
#endif // STI_REMOTE_BINDING
RPC_STATUS RpcBindHandleForServer( OUT handle_t * pBindingHandle, IN LPWSTR pwszServerName, IN LPWSTR pwszInterfaceName, IN LPWSTR pwszOptions ) /*++
This function uses the parameters supplied and generates a binding handle for RPC.
The transport used is determined dynamically based on following rules.
If server name starts with a leading "\\" (double slash), then attempt RPC binding over NamedPipe.
If server name does not start with leading "\\", then attempt RPC binding over TCPIP.
If TCPIP binding fails, then this function tries binding over NamedPipe.
It is assumed that binding over named pipe uses static end point with the interface name and options as provided.
Arguments: pBindingHandle pointer to location which will contain binding handle on successful return pwszServerName pointer to string containing the name of the server to which, this function will obtain a binding. pwszInterfaceName pointer to string containing the interface name pwszOptions pointer to string containing any additional options for binding.
Returns: RPC_STATUS - RPC_S_OK on success Also on success, the binding handle is stored in pBindingHandle. It should freed after usage, using the RpcBindingFree() function.
--*/ { RPC_STATUS rpcStatus = RPC_S_SERVER_UNAVAILABLE; LPWSTR pwszBinding = NULL;
if ( pBindingHandle != NULL) {
*pBindingHandle = NULL; // init the value
}
//
// STI interfaces are not remotable, so only try binding to local server
//
if ( pwszServerName == NULL || *pwszServerName == L'\0' ) {
rpcStatus = RpcBindHandleOverLocal( pBindingHandle, pwszInterfaceName);
} else { rpcStatus = RPC_S_INVALID_NET_ADDR; }
# ifdef STI_REMOTE_BINDING
#ifdef CHICAGO
//
// On Windows9x if there is no VRedir installed, RPC refuses to bind over
// TCP/IP or NetBIOS. TO resolve this issue server always listens on LRPC
// and if client is requesting local operation ( by passing empty string or NULL)
// as first parameter binding is done over LRPC. Note, that passing non-null IP address
// ( even if it points to local machine, like 127.0.0.1 ) will result in binding over TCP/IP
// and may now work .
//
if ( pwszServerName == NULL || *pwszServerName == L'\0' ) {
rpcStatus = RpcBindHandleOverLocal( pBindingHandle, pwszInterfaceName);
} else {
if ( pwszServerName[0] != L'\\' && pwszServerName[1] != L'\\' ) {
//
// Attempt binding over TCPIP using Dynamic Endpoint.
//
rpcStatus = RpcBindHandleOverTcpIp( pBindingHandle, pwszServerName, pwszInterfaceName);
} else {
rpcStatus = RPC_S_INVALID_NET_ADDR; } } #endif
if ( rpcStatus != RPC_S_OK) {
WCHAR rgchNp[1024];
//
// generate a NamedPipe end point name from the interface name.
// the End point = \PIPE\<InterfaceName>
//
wcscpy( rgchNp, L"\\PIPE\\"); wcscat( rgchNp, pwszInterfaceName);
//
// Attempt binding over static NamedPipe.
//
rpcStatus = RpcBindHandleOverNamedPipe( pBindingHandle, pwszServerName, rgchNp, pwszOptions );
DBGPRINTF(( DBG_CONTEXT, " RpcBindingOverNamedPipe(%S) returns %d. Handle = %08x\n", pwszServerName, rpcStatus, *pBindingHandle));
}
# endif // STI_REMOTE_BINDING
return ( rpcStatus);
} // RpcBindHandleForServer()
RPC_STATUS RpcBindHandleFree(IN OUT handle_t * pBindingHandle) /*++
Description:
This function frees up the binding handle allocated using RpcBindHandleForServer(). It uses RPC Binding Free routing to do this. This function acts just as a thunk so that the alloc/free of RPC contexts are consolidated within this module.
Arguments: pBindingHandle pointer to RPC binding handle that needs to be freed.
Returns: RPC_STATUS - containig the RPC status. RPC_S_OK for success.
--*/ {
return ( RpcBindingFree( pBindingHandle));
} // RpcBindHandleFree()
/************************ End of File ***********************/
|