// Static function that obtains the propagation cookie to be given to the SQL Server to which // the connection is made to, so that the server will enlist the connection in the // distributed transaction. Function returns bool indicating whether the cookie was obtained. public static bool GetTransactionCookie(byte[] dtcAddr, ITransaction transaction, ref UnsafeNativeMethods.ITransactionExport transactionExport, ref byte[] cookie, ref int length) { bool fSuccess = true; Debug.Assert(dtcAddr != null, "GetTransactionCookie: dtcAddr null!"); Debug.Assert(transaction != null, "GetTransactionCookie: transaction null!"); // local UInt32 variables, since the interfaces expect the UInt32 type UInt32 cookieLength = 0; UInt32 dtcLength = (UInt32)dtcAddr.Length; // if the user's transactionExport is null, create one for them! if (null == transactionExport) { // if creation fails, return false so connection will re-obtain DTC and retry if (!CreateTransactionExport(dtcAddr, dtcLength, transaction, ref transactionExport)) { fSuccess = false; } } if (fSuccess) { // obtain the cookie length transactionExport.Export(transaction, ref cookieLength); // If export call failed, kill the instance of transactionExport and return false! // Checked with ShaiwalS, and this is the correct behavior. if (0 == cookieLength) { transactionExport = null; fSuccess = false; } else { // allocate the cookie to be the appropriate length cookie = new byte[(int)cookieLength]; // obtain the cookie transactionExport.GetTransactionCookie(transaction, cookieLength, cookie, ref cookieLength); // set the passed in length - before we were using local UInt32 length = (int)cookieLength; //if (AdapterSwitches.SqlPooling.TraceVerbose) { // Debug.WriteLine("Transaction.GetTransactionCookie(): cookieLength: " + cookieLength.ToString()); // Debug.WriteLine("Transaction.GetTransactionCookie(): cookie: "); // for (int i=0; i<cookieLength; i++) // Debug.Write((cookie[i]).ToString("x2") + " "); // Debug.WriteLine(""); //} } } return(fSuccess); }
private void EnlistNonNullDistributedTransaction(ITransaction transaction) { //if (AdapterSwitches.SqlPooling.TraceVerbose) // Debug.WriteLine("SqlInternalConnection.EnlistDistributedTransaction(): Enlisting connection in distributed transaction..."); if (null == _dtcAddress) { _dtcAddress = _parser.GetDTCAddress(_connectionOptions.ConnectTimeout); } Debug.Assert(_dtcAddress != null, "SqlInternalConnection.EnlistDistributedTransaction(): dtcAddress null, error #1"); byte[] cookie = null; int length = 0; UnsafeNativeMethods.ITransactionExport transactionExport = null; if (null != _transactionExport) { transactionExport = _transactionExport.GetITransactionExport(); } // if the call for the cookie fails, re-obtain the DTCAddress and recall the function if (!Transaction.GetTransactionCookie(_dtcAddress, transaction, ref transactionExport, ref cookie, ref length)) { _dtcAddress = _parser.GetDTCAddress(_connectionOptions.ConnectTimeout); Debug.Assert(_dtcAddress != null, "SqlInternalConnection.Activate(): dtcAddress null, error #2"); if (!Transaction.GetTransactionCookie(_dtcAddress, transaction, ref transactionExport, ref cookie, ref length)) { throw SQL.TransactionEnlistmentError(); } } if (null != transactionExport) { _transactionExport = new TransactionExportWrapper(transactionExport); } else { _transactionExport = null; } // send cookie to server to finish enlistment _parser.PropagateDistributedTransaction(cookie, length, _connectionOptions.ConnectTimeout); }
// Private method that creates a TransactionExport for the passed in DTCAddr. private static bool CreateTransactionExport(byte[] dtcAddr, UInt32 dtcLength, ITransaction transaction, ref UnsafeNativeMethods.ITransactionExport transactionExport) { object transactionExportFactory = null; // UNDONE - when not using pooling - the below cast to IGetDispenser call seems to fail // on the 3rd pooling object. Investigate when time permits. // cast to IGetDispenser, then call GetDispenser to obtain an // ITtransactionExportFactory interface ((UnsafeNativeMethods.IGetDispenser)transaction).GetDispenser(s_transactionExportFactoryGuid, ref transactionExportFactory); // cast to ITransactionExportFactory, then make call to create a ITransactionExport ((UnsafeNativeMethods.ITransactionExportFactory)transactionExportFactory).Create(dtcLength, dtcAddr, ref transactionExport); // if the create call failed, then transactionExport is null and return false! return(null != transactionExport); }
internal UnsafeNativeMethods.ITransactionExport GetITransactionExport() { UnsafeNativeMethods.ITransactionExport value = (UnsafeNativeMethods.ITransactionExport)System.Runtime.Remoting.Services.EnterpriseServicesHelper.WrapIUnknownWithComObject(this.iunknown); GC.KeepAlive(this); return(value); }
internal TransactionExportWrapper(UnsafeNativeMethods.ITransactionExport transactionExport) { this.iunknown = Marshal.GetIUnknownForObject(transactionExport); }