/*++ Copyright (c) 1991 Microsoft Corporation Module Name: dcecmisc.cxx Abstract: This module contains the code implementing miscellaneous DCE RPC runtime APIs. In particular, this includes the following APIs: RpcIfInqId, RpcNetworkIsProtseqValid, RpcMgmtInqComTimeout, RpcMgmtSetComTimeout, RpcMgmtSetCancelTimeout, and DceErrorInqText. Author: Michael Montague (mikemon) 11-Nov-1991 Revision History: --*/ #include <precomp.hxx> #include <rpctran.h> #ifdef NTENV unsigned long RecvWindow = 0; unsigned long SendWindow = 0; #endif RPC_STATUS RPC_ENTRY RpcIfInqId ( IN RPC_IF_HANDLE RpcIfHandle, OUT RPC_IF_ID PAPI * RpcIfId ) /*++ Routine Description: The routine is used by an application to obtain the interface identification part of an interface specification. This is a really simple API since the RpcIfHandle points to the interface information, so all we have got to do is cast RpcIfHandle and copy some stuff. Arguments: RpcIfHandle - Supplies a handle to the interface specification. RpcIfId - Returns the interface identification part of the interface specification. Return Value: RPC_S_OK - The operation completed successfully. --*/ { RPC_CLIENT_INTERFACE PAPI * RpcInterfaceInformation; InitializeIfNecessary(); RpcInterfaceInformation = (RPC_CLIENT_INTERFACE PAPI *) RpcIfHandle; RpcpMemoryCopy(&(RpcIfId->Uuid), &(RpcInterfaceInformation->InterfaceId.SyntaxGUID),sizeof(UUID)); RpcIfId->VersMajor = RpcInterfaceInformation->InterfaceId.SyntaxVersion.MajorVersion; RpcIfId->VersMinor = RpcInterfaceInformation->InterfaceId.SyntaxVersion.MinorVersion; return(RPC_S_OK); } RPC_STATUS RPC_ENTRY RpcNetworkIsProtseqValidW ( IN RPC_CHAR PAPI * Protseq ) /*++ Routine Description: An application program will use this API to determine if an rpc protocol sequence is supported by the current system. Arguments: Protseq - Supplies an rpc protocol sequence to be check to see if it is supported. Return Value: RPC_S_OK - The specified rpc protocol sequence is support. RPC_S_PROTSEQ_NOT_SUPPORTED - The specified rpc protocol sequence is not supported (but it appears to be valid). RPC_S_INVALID_RPC_PROTSEQ - The specified rpc protocol sequence is invalid. --*/ { InitializeIfNecessary(); return(IsRpcProtocolSequenceSupported(Protseq)); } RPC_STATUS RPC_ENTRY RpcMgmtInqComTimeout ( IN RPC_BINDING_HANDLE Binding, OUT unsigned int PAPI * Timeout ) /*++ Routine Description: This routine is used to obtain the communications timeout from a binding handle. Arguments: Binding - Supplies a binding handle from which to inquire the communication timeout. Timeout - Returns the communications timeout in the binding handle. Return Value: RPC_S_OK - The operation completed successfully. RPC_S_INVALID_BINDING - The specified binding is not a client side binding handle. --*/ { BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); *Timeout = BindingHandle->InqComTimeout(); return(RPC_S_OK); } RPC_STATUS RPC_ENTRY RpcMgmtSetComTimeout ( IN RPC_BINDING_HANDLE Binding, IN unsigned int Timeout ) /*++ Routine Description: An application will use this routine to set the communications timeout for a binding handle. The timeout value specifies the relative amount of time that should be spent to establish a binding to the server before giving up. Arguments: Binding - Supplies the binding handle for which the communications timeout value will be set. Timeout - Supplies the communications timeout value to set in the binding handle. Return Value: RPC_S_OK - The operation completed successfully. RPC_S_INVALID_BINDING - The specified binding is not a client side binding handle. RPC_S_INVALID_TIMEOUT - The specified timeout value is invalid. --*/ { BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->SetComTimeout(Timeout)); } RPC_STATUS RPC_ENTRY I_RpcIfInqTransferSyntaxes ( IN RPC_IF_HANDLE RpcIfHandle, OUT RPC_TRANSFER_SYNTAX PAPI * TransferSyntaxes, IN unsigned int TransferSyntaxSize, OUT unsigned int PAPI * TransferSyntaxCount ) /*++ Routine Description: This routine will be used to obtain the transfer syntaxes support by an interface. A description of the interface is supplied via the interface handle. Arguments: RpcIfHandle - Supplies a reference to the interface from which we want to inquire the transfer syntaxes. TransferSyntaxes - Returns a copy of the transfer syntaxes support by the interface. TransferSyntaxSize - Supplies the number of RPC_TRANSFER_SYNTAX records which can fit in the transfer syntaxes buffer. TransferSyntaxCount - Returns the number of transfer syntaxes supported by the interface. This value will always be returned, whether or not an error occurs. Return Value: RPC_S_OK - We copied the transfer syntaxes into the buffer successfully. RPC_S_BUFFER_TOO_SMALL - The supplies transfer syntaxes buffer is too small; the transfer syntax count parameter will return the minimum size required. --*/ { RPC_CLIENT_INTERFACE PAPI * RpcInterfaceInformation; *TransferSyntaxCount = 1; if (TransferSyntaxSize < 1) return(RPC_S_BUFFER_TOO_SMALL); RpcInterfaceInformation = (RPC_CLIENT_INTERFACE PAPI *) RpcIfHandle; RpcpMemoryCopy(&(TransferSyntaxes->Uuid), &(RpcInterfaceInformation->TransferSyntax.SyntaxGUID), sizeof(UUID)); TransferSyntaxes->VersMajor = RpcInterfaceInformation->TransferSyntax.SyntaxVersion.MajorVersion; TransferSyntaxes->VersMinor = RpcInterfaceInformation->TransferSyntax.SyntaxVersion.MinorVersion; return(RPC_S_OK); } RPC_STATUS RPC_ENTRY RpcMgmtEnableIdleCleanup ( void ) /*++ Routine Description: An application will use this routine to enable cleanup of idle resources. For the connection oriented protocol module, a connection must be idle for five minutes before it is cleaned up. Return Value: RPC_S_OK - Cleanup of idle resources has been enabled. RPC_S_OUT_OF_THREADS - Insufficient threads are available to be able to perform this operation. RPC_S_OUT_OF_RESOURCES - Insufficient resources are available to be able to perform this operation. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to be able to perform this operation. --*/ { InitializeIfNecessary(); return(EnableGarbageCollection()); } #if !defined(DOS) && !defined(MAC) RPC_STATUS RPC_ENTRY DceErrorInqTextA ( IN RPC_STATUS RpcStatus, OUT unsigned char __RPC_FAR * ErrorText ) /*++ Routine Description: The supplied status code is converted into a text message if possible. Arguments: RpcStatus - Supplies the status code to convert. ErrorText - Returns a character string containing the text message for the status code. Return Value: RPC_S_OK - The supplied status codes has successfully been converted into a text message. RPC_S_INVALID_ARG - The supplied value is not a valid status code. --*/ { if ( FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, RpcStatus, 0, (char *)ErrorText, DCE_C_ERROR_STRING_LEN, 0) == 0 ) { if ( FormatMessageA( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, RPC_S_NOT_RPC_ERROR, 0, (char *)ErrorText, DCE_C_ERROR_STRING_LEN, 0 ) == 0 ) { *ErrorText = '\0'; return(RPC_S_INVALID_ARG); } } return(RPC_S_OK); } RPC_STATUS RPC_ENTRY DceErrorInqTextW ( IN RPC_STATUS RpcStatus, OUT unsigned short __RPC_FAR * ErrorText ) /*++ Routine Description: The supplied status code is converted into a text message if possible. Arguments: RpcStatus - Supplies the status code to convert. ErrorText - Returns a character string containing the text message for the status code. Return Value: RPC_S_OK - The supplied status codes has successfully been converted into a text message. RPC_S_INVALID_ARG - The supplied value is not a valid status code. --*/ { if ( FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, RpcStatus, 0, ErrorText, DCE_C_ERROR_STRING_LEN * sizeof(RPC_CHAR), 0) == 0 ) { if ( FormatMessageW( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, 0, RPC_S_NOT_RPC_ERROR, 0, ErrorText, DCE_C_ERROR_STRING_LEN * sizeof(RPC_CHAR),0 ) == 0 ) { *ErrorText = 0; return(RPC_S_INVALID_ARG); } } return(RPC_S_OK); } #endif // !DOS #if defined(NTENV) || defined(WIN96) #define CANCEL_TIMEOUT_SHIFT (16) long ThreadGetRpcCancelTimeout( ) { THREAD * ThreadInfo = RpcpGetThreadPointer(); if ( (long)ThreadInfo == 0 ) { // // ASSERT(Client Side Thread && SetCancelTO not called) // return (RPC_C_CANCEL_INFINITE_TIMEOUT); } if ( (long)ThreadInfo & HIGHBITSET ) { // // ASSERT(CLIENT Side Thread && ! ServerSideThread && SetCancelTO called) // return (((long)ThreadInfo & ~HIGHBITSET) >> CANCEL_TIMEOUT_SHIFT ); } // // ASSERT(Server Side Thread .. ); // return (ThreadInfo->CancelTimeout); } #endif // NTDEV || WIN96 #ifdef NTENV RPC_STATUS RPC_ENTRY I_RpcConnectionInqSockBuffSize( OUT unsigned long __RPC_FAR * RecvBuffSize, OUT unsigned long __RPC_FAR * SendBuffSize ) { RequestGlobalMutex(); *RecvBuffSize = RecvWindow; *SendBuffSize = SendWindow; ClearGlobalMutex(); return (RPC_S_OK); } RPC_STATUS RPC_ENTRY I_RpcConnectionSetSockBuffSize( IN unsigned long RecvBuffSize, IN unsigned long SendBuffSize ) { if (RecvBuffSize > 0xFFFF) { RecvBuffSize = 0xFFFF; } if (SendBuffSize > 0xFFFF) { SendBuffSize = 0xFFFF; } RequestGlobalMutex(); RecvWindow = RecvBuffSize; SendWindow = SendBuffSize; ClearGlobalMutex(); return (RPC_S_OK); } void RPC_ENTRY I_RpcConnectionInqSockBuffSize2( OUT unsigned long __RPC_FAR * RecvWindowSize ) { *RecvWindowSize = RecvWindow; } #endif // NTENV RPC_STATUS RPC_ENTRY RpcMgmtBindingSetParameter ( IN RPC_BINDING_HANDLE Binding, IN unsigned Parameter, IN unsigned long Value ) { BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->SetConnectionParameter(Parameter, Value)); } RPC_STATUS RPC_ENTRY RpcMgmtBindingInqParameter ( IN RPC_BINDING_HANDLE Binding, IN unsigned Parameter, IN unsigned long __RPC_FAR * Value ) { BINDING_HANDLE * BindingHandle; InitializeIfNecessary(); BindingHandle = (BINDING_HANDLE *) Binding; if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE)) return(RPC_S_INVALID_BINDING); return(BindingHandle->InqConnectionParameter(Parameter, Value)); } RPC_STATUS RPC_ENTRY RpcMgmtSetParameter ( IN unsigned Parameter, IN unsigned long Value ) /*++ Routine Description: This fn changes connection parameters for the whole process. Unrecognized parameter constants are ignored. Arguments: Parameter - a constant representing the parameter to change Value - new value for the parameter Return Value: RPC_S_OK - all is well --*/ { switch (Parameter) { case RPC_C_PARM_BUFFER_LENGTH: { if (Value) { ::DefaultConnectionBufferLength = (unsigned) Value; } else { ::DefaultConnectionBufferLength = DEFAULT_CONNECTION_BUFFER_LENGTH; } break; } case RPC_C_PARM_MAX_PACKET_LENGTH: { if (Value) { ::DefaultMaxDatagramLength = (unsigned) Value; } else { ::DefaultMaxDatagramLength = DEFAULT_MAX_DATAGRAM_LENGTH; } break; } } return RPC_S_OK; } RPC_STATUS RPC_ENTRY RpcMgmtInqParameter ( IN unsigned Parameter, IN unsigned long __RPC_FAR * Value ) /*++ Routine Description: This fn examines connection parameters for the process. Arguments: Parameter - a constant representing the parameter to see Value - pointer where the value is copied Return Value: RPC_S_OK - all is well RPC_S_INVALID_ARG - unknown or inapplicable parm constant --*/ { switch (Parameter) { case RPC_C_PARM_BUFFER_LENGTH: { *Value = ::DefaultConnectionBufferLength; return RPC_S_OK; } case RPC_C_PARM_MAX_PACKET_LENGTH: { *Value = ::DefaultMaxDatagramLength; return RPC_S_OK; } default: { return RPC_S_INVALID_ARG; } } }