windows-nt/Source/XPSP1/NT/printscan/wia/common/stirt/rpcutil.cpp
2020-09-26 16:20:57 +08:00

683 lines
18 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 ***********************/