/*++ Copyright (C) Microsoft Corporation, 1992 - 1999 Module Name: autohand.cxx Abstract: This module implements the autohandle functions call by the compiler generated stubs. Author: Steven Zeck (stevez) 03/10/92 Kamen Moutafov (KamenM) Feb 2000 - add support for multiple transfer syntaxes --*/ #include #include #ifdef __cplusplus extern "C" { #endif #include #include #ifdef __cplusplus } #endif typedef RPC_STATUS (RPC_ENTRY *RPC_BIND) ( IN PRPC_MESSAGE Message ); RPC_STATUS RpcpNsGetBuffer( IN PRPC_MESSAGE Message, RPC_BIND BindFn ); // Interface can be only RPC_CLIENT_INTERFACE inline BOOL DoesInterfaceSupportMultipleTransferSyntaxes(void *Interface) { // the client and server interface have the same layout - we can just // use one of them RPC_CLIENT_INTERFACE *ClientInterface = (RPC_CLIENT_INTERFACE *)Interface; if (ClientInterface->Length == NT351_INTERFACE_SIZE) return FALSE; return (ClientInterface->Flags & RPCFLG_HAS_MULTI_SYNTAXES); } RPC_STATUS RPC_ENTRY I_RpcNsGetBuffer( IN PRPC_MESSAGE Message ) /*++ Routine Description: Auto bind to a given interface. Arguments: Message - describes the interface that we want to auto bind to. Returns: RPC_S_OK, RPC_S_CALL_FAILED_DNE, I_RpcGetBuffer() --*/ { if (!DoesInterfaceSupportMultipleTransferSyntaxes(Message->RpcInterfaceInformation)) Message->ImportContext = 0; return RpcpNsGetBuffer(Message, I_RpcGetBuffer); } extern "C" { RPC_STATUS RPC_ENTRY I_RpcNsNegotiateTransferSyntax( IN PRPC_MESSAGE Message ); }; // extern "C" RPC_STATUS RPC_ENTRY I_RpcNsNegotiateTransferSyntax( IN PRPC_MESSAGE Message ) /*++ Routine Description: Auto bind to a given interface. Arguments: Message - describes the interface that we want to auto bind to. Returns: RPC_S_OK, RPC_S_CALL_FAILED_DNE, I_RpcGetBuffer() --*/ { Message->ImportContext = 0; return RpcpNsGetBuffer(Message, I_RpcNegotiateTransferSyntax); } RPC_STATUS RpcpNsGetBuffer( IN PRPC_MESSAGE Message, RPC_BIND BindFn ) /*++ Routine Description: Auto bind to a given interface. Arguments: Message - describes the interface that we want to auto bind to. Returns: RPC_S_OK or error --*/ { RPC_STATUS status; PRPC_IMPORT_CONTEXT_P Import; int fSetAge = 0; // If there already is a handle, use it directly. if (Message->Handle) return(BindFn(Message)); Message->ImportContext = 0; for (int cTry = 0; cTry < 2; cTry++) { status = RpcNsBindingImportBegin(RPC_C_NS_SYNTAX_DEFAULT, 0, Message->RpcInterfaceInformation, 0, &Message->ImportContext); Import = (PRPC_IMPORT_CONTEXT_P) Message->ImportContext; if (status) break; // This will cause some Zecky Magic // Also note that naively one might move this ExpAge to // after the first lookup failed time- that is a bobo if (fSetAge) status = RpcNsMgmtHandleSetExpAge (Message->ImportContext, 0); // If we found no bindings last time, tell the locator // to look on the net. // For each handle returned by import, try using it with I_RpcGetBuffer // function until success or no more import handles. while(RpcNsBindingImportNext(Import, &Import->ProposedHandle) == RPC_S_OK) { Message->Handle = Import->ProposedHandle; if (BindFn(Message) == RPC_S_OK) return(RPC_S_OK); RpcBindingFree(&Import->ProposedHandle); } fSetAge = 1; RpcNsBindingImportDone(&Message->ImportContext); } if (status == RPC_S_NAME_SERVICE_UNAVAILABLE || status == RPC_S_OUT_OF_MEMORY || status == RPC_S_OUT_OF_RESOURCES) return(status); return(RPC_S_CALL_FAILED_DNE); } RPC_STATUS RPC_ENTRY I_RpcNsSendReceive( IN PRPC_MESSAGE Message, OUT RPC_BINDING_HANDLE * Handle ) /*++ Routine Description: Make a call on a RPC server. If the call fails continue looking for servers to bind to. This is only needed for protocols which don't allocate the connection at I_RpcGetBuffer time. Arguments: Message - describes the interface that we want to Call. The ImportContext field contains the active lookup handle, if any. Handle - returns the binding handle used on the successfull call. Returns: RPC_S_CALL_FAILED_DNE, I_RpcSendReceive() --*/ { RPC_STATUS status; PRPC_IMPORT_CONTEXT_P Import; Import = (PRPC_IMPORT_CONTEXT_P) Message->ImportContext; while ((status = I_RpcSendReceive(Message)) != RPC_S_OK && Import) { RpcBindingFree(&Import->ProposedHandle); // The call failed, try the next binding handle while(RpcNsBindingImportNext(Import, &Import->ProposedHandle) == RPC_S_OK) { Message->Handle = Import->ProposedHandle; I_RpcReBindBuffer(Message); continue; } I_RpcFreeBuffer(Message); status = RPC_S_CALL_FAILED_DNE; } if (Import) { *Handle = Import->ProposedHandle; RpcNsBindingImportDone(&Message->ImportContext); } if (status) *Handle = 0; return(status); } void RPC_ENTRY I_RpcNsRaiseException( IN PRPC_MESSAGE Message, IN RPC_STATUS Status ) /*++ Routine Description: Raise an Exception for an autobind interface. We simply cleanup any open import context and raise the exception. Arguments: Message - continas the import context, if any. --*/ { RpcNsBindingImportDone(&Message->ImportContext); RpcRaiseException(Status); } // BUG BUG implement this is the runtime. RPC_STATUS RPC_ENTRY I_RpcReBindBuffer( IN PRPC_MESSAGE Message ) { (void __RPC_FAR *) Message; RpcRaiseException(RPC_S_INTERNAL_ERROR); return(0); }