3.3.4.2.1 Primary

If the sRank parameter is SRANK_PRIMARY, the caller MUST be a primary partner, and the callee MUST be a secondary partner. The session object has already been created on the primary partner, and its state has been set to Connecting.

The secondary partner MUST construct a name object using the host name specified in the pszHostName parameter, the contact identifier (CID) specified in the pszUuidString parameter, and the RPC protocols specified in the grbitComProtocols field of the BIND_INFO_BLOB structure contained in the rguchBlob parameter.

The secondary partner MUST use this name object to check whether an existing session with a matching name object already exists in the session table.

If an existing session object is found (which would occur if the secondary partner initiated the connection through a call to the Poke method or the PokeW method), the secondary partner MUST check the State field of the session object.

  • If the value is set to Connecting, the existing session will be used during the rest of the call.

  • Otherwise, the secondary partner SHOULD return an implementation-specific error code or indicate that the bind was unsuccessful.<23>

If an existing session object is not found, a new session object MUST be created, MUST be initialized with the name object, and added to the session table. Regardless of whether the session object was found or created, the State field of the session object MUST be set to Confirming Connection.

Next, the secondary partner MUST calculate the pBoundVersionSet parameter as follows:

  • The dwLevelOneAccepted member MUST be set to the largest value such that:

    • It is greater than or equal to the larger of the two values:

      • The dwMinLevelOne member of the BindVersionSet parameter

      • The local Minimum Level 1 Version Number ADM element

    • It is less than or equal to the lesser of the two values:

      • The dwMaxLevelOne member of the BindVersionSet parameter

      • The local Maximum Level 1 Version Number ADM element

        If no such value exists, then the function MUST return with the 0x80000172 (E_CM_VERSION_SET_NOTSUPPORTED) error, and the cleanup steps described in the following list MUST be followed.

  • The dwLevelTwoAccepted member MUST be set to the largest value such that:

    • It is greater than or equal to the larger of the two values:

      • The dwMinLevelTwo member of the BindVersionSet parameter

      • The local Minimum Level 2 Version Number ADM element

    • It is less than or equal to the lesser of the two values:

      • The dwMaxLevelTwo member of the BindVersionSet parameter

      • The local Maximum Level 2 Version Number ADM element

        If no such value exists, then the function MUST return with the 0x80000172 (E_CM_VERSION_SET_NOTSUPPORTED) error, and the following cleanup steps MUST be followed:

  • The dwLevelThreeAccepted member MUST be set to the largest value such that:

    • It is greater than or equal to the larger of the two values:

      • The dwMinLevelThree member of the BindVersionSet parameter

      • The local Minimum Level 3 Version Number ADM element

    • It is less than or equal to the lesser of the two values:

      • The dwMaxLevelThree member of the BindVersionSet parameter

      • The local Maximum Level 3 Version Number ADM element

        If no such value exists, then the function MUST return with the 0x80000172 (E_CM_VERSION_SET_NOTSUPPORTED) error, and the following cleanup steps MUST be followed:

The pBoundVersionSet parameter calculated previously contains the maximum protocol versions supported by both partners for the MSDTC Connection Manager: OleTx Transports Protocol implementation, and the level-two and level-three protocol implementations layered on top of that implementation (see also 3.2.1.1). These represent the negotiated protocol versions that MUST be used in the respective protocol communications.

If any of the previously described operations fails, the secondary partner MUST remove the session object from the session table and clean it up. See section 3.2.1.3. After cleaning up the session object, the secondary partner MUST return from this method with an error code (E_CM_VERSION_SET_NOTSUPPORTED or an implementation-specific error).

If the previously described calculations succeed, a copy of the BOUND_VERSION_SET structure MUST also be stored in the Version ADM element of the session object. Once this is done, the secondary partner MUST start the Session Setup timer associated with that session object if it has not already been started. The Session Setup timer will not have been started if the session establishment began with the primary partner. In this case, this method call is the first time that the secondary partner has considered this session.

An RPC binding handle to the primary partner MUST be created and stored in the session object. For binding handles, see [C706]. The secondary partner MUST attempt to call either the BuildContextW method or the BuildContext method on the primary partner using the binding handle stored in the session object. For making calls to a partner, see section 3.4.

To determine whether the primary partner supports BuildContextW, the secondary partner calls BuildContextW on the primary partner and waits for a return value. If the call completes with error code RPC_S_PROCNUM_OUT_OF_RANGE, then the primary partner does not support BuildContextW.

If the primary partner supports the BuildContextW method:

  • If the secondary partner supports the BuildContextW method, then the secondary partner MUST call the BuildContextW method.

  • Otherwise, secondary partner SHOULD call the BuildContext method.<24>

The secondary partner MUST NOT return from the current call to BuildContext or BuildContextW until the nested call to BuildContext or BuildContextW has completed.

If the incoming RPC is authenticated, the secondary partner SHOULD use the authenticated identity of the caller as the server principal name for performing mutual authentication, and then use the secondary partner's identity on the nested call.<25>

If the nested call completes successfully, the secondary partner MUST set the state of the session object to Active, store the received context handle in the associated session object, and cancel the Session Setup timer associated with that session object. It MUST set the contextHandle parameter to a context handle (see [C706]) that identifies the session object, and then return from the method with the S_OK code.

If the nested call completes unsuccessfully, the secondary partner SHOULD behave according to the error code that was returned:

  • If the error code is 0x80000172 (E_CM_VERSION_SET_NOTSUPPORTED), or 0x80000173 (E_CM_S_PROTOCOL_NOT_SUPPORTED), or 0x80000124 (indicating that the Session Setup timer expired), or it retried the nested call for more than the number of times specified in the Session Setup Retry Count ADM element, the secondary partner MUST remove the session object from the session table and clean it up. See section 3.2.1.3. After cleaning up the session object, the secondary partner MUST return the error code to the caller.

  • If the error code is 0x80000123 (E_CM_SERVER_NOT_READY) or 0x000006BB (RPC_S_SERVER_TOO_BUSY), or any other implementation-specific error code, the secondary partner SHOULD retry the nested call for the number of times specified in the Session Setup Retry Count ADM element.