diff --git a/PInvoke/KtmW32/KtmW32.cs b/PInvoke/KtmW32/KtmW32.cs new file mode 100644 index 00000000..b820ada9 --- /dev/null +++ b/PInvoke/KtmW32/KtmW32.cs @@ -0,0 +1,1736 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using static Vanara.PInvoke.Kernel32; + +namespace Vanara.PInvoke +{ + /// Kernel Transaction Manager (KTM) functions and structures. + public static partial class KtmW32 + { + /// An optional enlistment instruction. + [PInvokeData("ktmw32.h", MSDNShortId = "7bc06468-947f-48ec-8e58-20df58ed93bd")] + [Flags] + public enum CreateEnlistmentOptions + { + /// Enlist as a superior transaction manager. + ENLISTMENT_SUPERIOR = 1 + } + + /// Optional attributes for the new RM. + [PInvokeData("ktmw32.h", MSDNShortId = "ad88e478-1dff-4f35-a0e3-6bda8bb45711")] + [Flags] + public enum CreateRMOptions + { + /// Indicates that the RM is volatile, and does not perform recovery. + RESOURCE_MANAGER_VOLATILE = 1, + + /// + RESOURCE_MANAGER_COMMUNICATION = 2 + } + + /// Optional attributes for the new TM. + [PInvokeData("ktmw32.h", MSDNShortId = "f5b7d0c1-9cd0-48fc-8125-d4da040951c4")] + [Flags] + public enum CreateTrxnMgrOptions + { + /// + TRANSACTION_MANAGER_COMMIT_DEFAULT = 0x00000000, + + /// Indicates that the TM is volatile, and does not perform recovery. + TRANSACTION_MANAGER_VOLATILE = 0x00000001, + + /// + TRANSACTION_MANAGER_COMMIT_SYSTEM_VOLUME = 0x00000002, + + /// + TRANSACTION_MANAGER_COMMIT_SYSTEM_HIVES = 0x00000004, + + /// + TRANSACTION_MANAGER_COMMIT_LOWEST = 0x00000008, + + /// + TRANSACTION_MANAGER_CORRUPT_FOR_RECOVERY = 0x00000010, + + /// + TRANSACTION_MANAGER_CORRUPT_FOR_PROGRESS = 0x00000020, + } + + /// Optional transaction instructions. + [PInvokeData("ktmw32.h", MSDNShortId = "578bda35-bd35-4f6d-8366-a4bfb4dbfe42")] + [Flags] + public enum CreateTrxnOptions + { + /// The transaction cannot be distributed. + TRANSACTION_DO_NOT_PROMOTE = 1 + } + + /// KTM defines the following enlistment access masks to be used when opening enlistments. + // https://docs.microsoft.com/en-us/windows/win32/ktm/enlistment-access-masks + [PInvokeData("winnt.h", MSDNShortId = "93773eb7-141a-49f3-9306-ffbda2f4ab9f")] + [Flags] + public enum EnlistmentAccess : uint + { + /// The caller can query KTM for information about the enlistment. + ENLISTMENT_QUERY_INFORMATION = 0x00001, + + /// The caller can set information about the enlistment. + ENLISTMENT_SET_INFORMATION = 0x00002, + + /// The caller can recover an enlistment. + ENLISTMENT_RECOVER = 0x00004, + + /// + /// + /// The caller can complete actions that a resource manager does on behalf of the transaction. The following is a list of actions: + /// + /// + /// CommitComplete + /// PrepareComplete + /// PrePrepareComplete + /// RollbackComplete + /// ReadOnlyEnlistment + /// RollbackEnlistment + /// SinglePhaseReject + /// + /// + ENLISTMENT_SUBORDINATE_RIGHTS = 0x00008, + + /// The caller can enlist in the transaction as a superior transaction manager. + ENLISTMENT_SUPERIOR_RIGHTS = 0x00010, + + /// The caller has the following privileges: STANDARD_RIGHTS_READ and ENLISTMENT_QUERY_INFORMATION. + ENLISTMENT_GENERIC_READ = 0x20001, + + /// The caller has the following privileges: STANDARD_RIGHTS_WRITE, ENLISTMENT_SET_INFORMATION, and ENLISTMENT_RECOVER. + ENLISTMENT_GENERIC_WRITE = 0x2001E, + + /// The caller has the following privileges: STANDARD_RIGHTS_EXECUTE, ENLISTMENT_RECOVER, and ENLISTMENT_SUBORDINATE_RIGHTS. + ENLISTMENT_GENERIC_EXECUTE = 0x2001C, + + /// This value sets all valid bits for an enlistment access value. + ENLISTMENT_ALL_ACCESS = 0xF001F, + } + + /// Lists the different types of notifications that can be received by an enlistment. + // https://docs.microsoft.com/en-us/windows/win32/ktm/notification-mask + [PInvokeData("winnt.h", MSDNShortId = "65db8ba5-193c-439b-8e8c-6cb4a9bd4efd")] + [Flags] + public enum NOTIFICATION_MASK : uint + { + /// A mask that indicates all valid bits for a transaction notification. + TRANSACTION_NOTIFY_MASK = 0x3FFFFFFF, + + /// + /// This notification is called after a client calls CommitTransaction and either no resource manager (RM) supports single-phase + /// commit or a superior transaction manager (TM) calls PrePrepareEnlistment. This notification is received by the RMs indicating + /// that they should complete any work that could cause other RMs to need to enlist in a transaction, such as flushing its cache. + /// After completing these operations the RM must call PrePrepareComplete. To receive this notification the RM must also support + /// TRANSACTION_NOTIFY_PREPARE and TRANSACTION_NOTIFY_COMMIT. + /// + TRANSACTION_NOTIFY_PREPREPARE = 0x00000001, + + /// + /// This notification is called after the TRANSACTION_NOTIFY_PREPREPARE processing is complete. It signals the RM to complete all + /// the work that is associated with this enlistment so that it can guarantee that a commit operation could succeed and an abort + /// operation could also succeed. Typically, the bulk of the work for a transaction is done during the prepare phase. For durable + /// RMs, they must log their state prior to calling the PrepareComplete function. This is the last chance for the RM to request + /// that the transaction be rolled back. + /// + TRANSACTION_NOTIFY_PREPARE = 0x00000002, + + /// + /// This notification signals the RM to complete all the work that is associated with this enlistment. Typically, the RM releases + /// any locks, releases any information necessary to roll back the transaction. The RM must respond by calling the CommitComplete + /// function when it has finished these operations. + /// + TRANSACTION_NOTIFY_COMMIT = 0x00000004, + + /// This notification signals the RM to undo all the work it has done that is associated with the transaction. + TRANSACTION_NOTIFY_ROLLBACK = 0x00000008, + + /// This notification signals to the superior TM that a pre-prepare operation was completed successfully. + TRANSACTION_NOTIFY_PREPREPARE_COMPLETE = 0x00000010, + + /// This notification signals to the superior TM that a prepare operation was completed successfully. + TRANSACTION_NOTIFY_PREPARE_COMPLETE = 0x00000020, + + /// This notification signals to the superior TM that a commit operation was completed successfully. + TRANSACTION_NOTIFY_COMMIT_COMPLETE = 0x00000040, + + /// This notification signals to the superior TM that a rollback operation was completed successfully. + TRANSACTION_NOTIFY_ROLLBACK_COMPLETE = 0x00000080, + + /// + /// This notification signals to RMs that they should recover their state because a transaction outcome must be redelivered. For + /// example, when an RM is recovered, and when there are transactions left in-doubt. This notification is delivered once the + /// in-doubt state is resolved. + /// + TRANSACTION_NOTIFY_RECOVER = 0x00000100, + + /// + /// This notification signals the RM to complete and commit the transaction without using a two-phase commit protocol. If the RM + /// wants to use a two-phase operation, it must respond by calling the SinglePhaseReject function. + /// + TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT = 0x00000200, + + /// KTM is signaling to the superior TM to perform a commit operation. + TRANSACTION_NOTIFY_DELEGATE_COMMIT = 0x00000400, + + /// KTM is signaling to the superior TM to query the status of an in-doubt transaction. + TRANSACTION_NOTIFY_RECOVER_QUERY = 0x00000800, + + /// + /// This notification signals to the superior TM that pre-prepare notifications must be delivered on the specified enlistment. + /// + TRANSACTION_NOTIFY_ENLIST_PREPREPARE = 0x00001000, + + /// This notification indicates that the recovery operation is complete for this RM. + TRANSACTION_NOTIFY_LAST_RECOVER = 0x00002000, + + /// + /// The specified transaction is in an in-doubt state. The RM receives this notification during recovery operations when a + /// transaction has been prepared, but there is no superior transaction manager (TM) available. For example, when a transaction + /// involves a remote TM and that node is unavailable, its node is unavailable, or the local Distributed Transaction Coordinator + /// service is unavailable, the transaction state is in-doubt. + /// + TRANSACTION_NOTIFY_INDOUBT = 0x00004000, + + /// The TM is online and accepting requests. + TRANSACTION_NOTIFY_TM_ONLINE = 0x02000000, + + /// + /// Signals to RMs that there is outcome information available, and that a request for that information should be made. + /// + TRANSACTION_NOTIFY_REQUEST_OUTCOME = 0x20000000, + + /// Reserved. + TRANSACTION_NOTIFY_COMMIT_FINALIZE = 0x40000000, + } + + /// KTM defines the following enlistment access masks to be used when opening a resource manager. + // https://docs.microsoft.com/en-us/windows/win32/ktm/resource-manager-access-masks + [PInvokeData("winnt.h", MSDNShortId = "6b901b73-516d-4f27-b258-3b93a8f9675f")] + [Flags] + public enum ResourceManagerAccess : uint + { + /// The caller can query for the resource manager (RM) information. + RESOURCEMANAGER_QUERY_INFORMATION = 0x0001, + + /// The caller can set the RM information. + RESOURCEMANAGER_SET_INFORMATION = 0x0002, + + /// The caller can recover the specified RM. + RESOURCEMANAGER_RECOVER = 0x0004, + + /// The caller can enlist an RM in a transaction. + RESOURCEMANAGER_ENLIST = 0x0008, + + /// The caller can receive a notification for an RM. + RESOURCEMANAGER_GET_NOTIFICATION = 0x0010, + + /// + RESOURCEMANAGER_REGISTER_PROTOCOL = 0x0020, + + /// + RESOURCEMANAGER_COMPLETE_PROPAGATION = 0x0040, + + /// The caller has the following privileges: STANDARD_RIGHTS_READ, RESOURCEMANAGER_QUERY_INFORMATION, and RESOURCEMANAGER_RECOVER. + RESOURCEMANAGER_GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ | RESOURCEMANAGER_QUERY_INFORMATION | ACCESS_MASK.SYNCHRONIZE, + + /// + /// The caller has the following privileges: STANDARD_RIGHTS_WRITE, RESOURCEMANAGER_SET_INFORMATION, RESOURCEMANAGER_ENLIST, and RESOURCEMANAGER_GET_NOTIFICATION. + /// + RESOURCEMANAGER_GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE | RESOURCEMANAGER_SET_INFORMATION | RESOURCEMANAGER_RECOVER | RESOURCEMANAGER_ENLIST | RESOURCEMANAGER_GET_NOTIFICATION | RESOURCEMANAGER_REGISTER_PROTOCOL | RESOURCEMANAGER_COMPLETE_PROPAGATION | ACCESS_MASK.SYNCHRONIZE, + + /// The caller has the following privileges: STANDARD_RIGHTS_EXECUTE, RESOURCEMANAGER_ENLIST, and RESOURCEMANAGER_GET_NOTIFICATION. + RESOURCEMANAGER_GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE | RESOURCEMANAGER_RECOVER | RESOURCEMANAGER_ENLIST | RESOURCEMANAGER_GET_NOTIFICATION | RESOURCEMANAGER_COMPLETE_PROPAGATION | ACCESS_MASK.SYNCHRONIZE, + + /// The caller has the following privilege: STANDARD_RIGHTS_REQUIRED. + RESOURCEMANAGER_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED | RESOURCEMANAGER_GENERIC_READ | RESOURCEMANAGER_GENERIC_WRITE | RESOURCEMANAGER_GENERIC_EXECUTE, + } + + /// Defines the outcomes (results) that KTM can assign to a transaction. + // https://docs.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-transaction_outcome typedef enum _TRANSACTION_OUTCOME { + // TransactionOutcomeUndetermined, TransactionOutcomeCommitted, TransactionOutcomeAborted } TRANSACTION_OUTCOME; + [PInvokeData("winnt.h", MSDNShortId = "d4315a62-b65f-4744-8084-2317ad39c32c")] + public enum TRANSACTION_OUTCOME + { + /// The transaction has not yet been committed or rolled back. + TransactionOutcomeUndetermined = 1, + + /// The transaction has been committed. + TransactionOutcomeCommitted, + + /// The transaction has been rolled back. + TransactionOutcomeAborted, + } + + /// KTM defines the following transaction access masks to be used when opening a transaction. + /// + /// It is recommended that resource managers, when enlisting in a transaction, specify TRANSACTION_RESOURCE_MANAGER_RIGHTS + /// when opening a transaction. + /// + // https://docs.microsoft.com/en-us/windows/win32/ktm/transaction-access-masks + [PInvokeData("winnt.h", MSDNShortId = "93ef3098-b3cc-4b24-ae82-1c10d937f14f")] + [Flags] + public enum TransactionAccess : uint + { + /// The caller can query transaction information. + TRANSACTION_QUERY_INFORMATION = 0x000001, + + /// The caller can set transaction information. + TRANSACTION_SET_INFORMATION = 0x000002, + + /// The caller can enlist in this transaction. + TRANSACTION_ENLIST = 0x000004, + + /// The caller can commit this transaction. + TRANSACTION_COMMIT = 0x000008, + + /// The caller can roll back this transaction. + TRANSACTION_ROLLBACK = 0x000010, + + /// + /// The caller can propagate this transaction to a superior resource manager, such as the Distributed Transaction Coordinator (DTC). + /// + TRANSACTION_PROPAGATE = 0x000020, + + /// The caller has the following privileges: STANDARD_RIGHTS_READ, TRANSACTION_QUERY_INFORMATION, and SYNCHRONIZE. + TRANSACTION_GENERIC_READ = 0x120001, + + /// + /// The caller has the following privileges: STANDARD_RIGHTS_WRITE, TRANSACTION_SET_INFORMATION, TRANSACTION_COMMIT, + /// TRANSACTION_ENLIST, TRANSACTION_ROLLBACK, TRANSACTION_PROPAGATE, and SYNCHRONIZE. + /// + TRANSACTION_GENERIC_WRITE = 0x12003E, + + /// + /// The caller has the following privileges: STANDARD_RIGHTS_EXECUTE, TRANSACTION_COMMIT, TRANSACTION_ROLLBACK, and SYNCHRONIZE. + /// + TRANSACTION_GENERIC_EXECUTE = 0x120018, + + /// + /// The caller has the following privilege: STANDARD_RIGHTS_REQUIRED, TRANSACTION_GENERIC_READ, TRANSACTION_GENERIC_WRITE, and TRANSACTION_GENERIC_EXECUTE. + /// + TRANSACTION_ALL_ACCESS = 0x12003F, + + /// + /// The caller has the following privileges: TRANSACTION_GENERIC_READ, STANDARD_RIGHTS_WRITE, TRANSACTION_SET_INFORMATION, + /// TRANSACTION_ROLLBACK, TRANSACTION_ENLIST, TRANSACTION_PROPAGATE, and SYNCHRONIZE. + /// + TRANSACTION_RESOURCE_MANAGER_RIGHTS = 0x120037, + } + + /// KTM defines the following enlistment access masks to be used when opening a transaction manager (TM). + // https://docs.microsoft.com/en-us/windows/win32/ktm/transaction-manager-access-masks + [PInvokeData("winnt.h", MSDNShortId = "8f9b9d3d-e7ea-4df2-82b1-2d4c3e0766c0")] + [Flags] + public enum TransactionMgrAccess + { + /// The caller can query information about this TM. + TRANSACTIONMANAGER_QUERY_INFORMATION = 0x00001, + + /// The caller can set information about this TM. + TRANSACTIONMANAGER_SET_INFORMATION = 0x00002, + + /// The caller can recover this TM. + TRANSACTIONMANAGER_RECOVER = 0x00004, + + /// The caller can rename a TM instance. + TRANSACTIONMANAGER_RENAME = 0x00008, + + /// The caller can create a resource manager that is associated with this TM. + TRANSACTIONMANAGER_CREATE_RM = 0x00010, + + /// This value is reserved. + TRANSACTIONMANAGER_BIND_TRANSACTION = 0x00020, + + /// The caller has the following privileges: STANDARD_RIGHTS_READ and TRANSACTIONMANAGER_QUERY_INFORMATION. + TRANSACTIONMANAGER_GENERIC_READ = 0x20001, + + /// + /// The caller has the following privileges: STANDARD_RIGHTS_WRITE, TRANSACTIONMANAGER_SET_INFORMATION, + /// TRANSACTIONMANAGER_RECOVER, TRANSACTIONMANAGER_RENAME, and TRANSACTIONMANAGER_CREATE_RM. + /// + TRANSACTIONMANAGER_GENERIC_WRITE = 0x2001E, + + /// The caller has the following privilege: STANDARD_RIGHTS_EXECUTE. + TRANSACTIONMANAGER_GENERIC_EXECUTE = 0x20000, + + /// This value sets all valid bits for a TM access value. + TRANSACTIONMANAGER_ALL_ACCESS = 0xF003F, + } + + /// + /// Indicates that a resource manager (RM) has finished committing a transaction that was requested by the transaction manager (TM). + /// + /// A handle to the enlistment for which the commit operation is completed. + /// + /// + /// The latest virtual clock value received for this transaction. If you specify NULL, the virtual clock value is not changed. + /// See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-commitcomplete BOOL CommitComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "de3e3a26-3e56-4732-8e7c-945b45593aed")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CommitComplete([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Indicates that a resource manager (RM) has finished committing a transaction that was requested by the transaction manager (TM). + /// + /// A handle to the enlistment for which the commit operation is completed. + /// + /// + /// The latest virtual clock value received for this transaction. If you specify NULL, the virtual clock value is not changed. + /// See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-commitcomplete BOOL CommitComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "de3e3a26-3e56-4732-8e7c-945b45593aed")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CommitComplete([In] HENLISTMENT EnlistmentHandle, [Optional] IntPtr TmVirtualClock); + + /// + /// Commits the transaction associated with this enlistment handle. This function is used by communication resource managers + /// (sometimes called superior transaction managers). + /// + /// A handle to the enlistment to commit. + /// + /// + /// A pointer to the latest virtual clock value received for this enlistment. If you specify NULL, the virtual clock value is + /// not changed. + /// + /// To change the virtual clock value, this value must be greater than the current value returned by a subordinate TM. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-commitenlistment BOOL CommitEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "d1e1043d-2db3-4f05-affc-2d32744baf10")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CommitEnlistment([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Commits the transaction associated with this enlistment handle. This function is used by communication resource managers + /// (sometimes called superior transaction managers). + /// + /// A handle to the enlistment to commit. + /// + /// + /// A pointer to the latest virtual clock value received for this enlistment. If you specify NULL, the virtual clock value is + /// not changed. + /// + /// To change the virtual clock value, this value must be greater than the current value returned by a subordinate TM. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-commitenlistment BOOL CommitEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "d1e1043d-2db3-4f05-affc-2d32744baf10")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CommitEnlistment([In] HENLISTMENT EnlistmentHandle, [Optional] IntPtr TmVirtualClock); + + /// Requests that the specified transaction be committed. + /// + /// A handle to the transaction to be committed. + /// + /// This handle must have been opened with the TRANSACTION_COMMIT access right. For more information, see KTM Security and Access Rights. + /// + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// + /// You can commit any transaction handle that has been opened or created using the TRANSACTION_COMMIT permission; any application + /// can commit a transaction, not just the creator. + /// + /// This function can only be called if the transaction is still active, not prepared, pre-prepared, or rolled back. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-committransaction BOOL CommitTransaction( IN HANDLE + // TransactionHandle ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "17db5e1f-685b-46f0-bac6-dff4c18bb515")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CommitTransaction([In] HTRXN TransactionHandle); + + /// Requests that the specified transaction be committed. + /// + /// A handle to the transaction to be committed. + /// + /// This handle must have been opened with the TRANSACTION_COMMIT access right. For more information, see KTM Security and Access Rights. + /// + /// + /// + /// + /// If the function succeeds, the return value is nonzero. Success means that the function completed synchronously, and the calling + /// application does not need to wait for pending results. + /// + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-committransactionasync BOOL CommitTransactionAsync( IN HANDLE + // TransactionHandle ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "cc0f4314-e216-490b-a49a-14bb850e0762")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool CommitTransactionAsync([In] HTRXN TransactionHandle); + + /// Creates an enlistment, sets its initial state, and opens a handle to the enlistment with the specified access. + /// + /// A pointer to a SECURITY_ATTRIBUTES structure that contains the security attributes for the enlistment manager. Specify + /// NULL to obtain the default attributes. + /// + /// A handle to the resource manager (RM) to enlist. + /// A handle to the transaction in which the RM is enlisting. + /// + /// The notifications this RM is requesting for the TransactionHandle parameter. For a list of valid values, see NOTIFICATION_MASK. + /// + /// + /// Any optional enlistment instructions. + /// + /// + /// Value + /// Meaning + /// + /// + /// ENLISTMENT_SUPERIOR 1 + /// Enlist as a superior transaction manager. + /// + /// + /// + /// + /// A pointer to a user-defined structure used by the RM that is returned when a notification is sent in the TRANSACTION_NOTIFICATION + /// structure. This is typically used to associate a private structure with this specific transaction. + /// + /// + /// If the function succeeds, the return value is a handle to the enlistment. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// + /// Windows Vista: Any attempt to enlist during the pre-prepare phase or later will fail. + /// + /// If you do not specify within your notification mask that you accept a single-phase commit request, KTM always performs a + /// two-phase commit operation. + /// + /// Keep the following notification rules in mind when enlisting in transactions: + /// + /// + /// The RM must always request rollback notification. + /// + /// + /// If the RM requests prepare notification, it must also request commit notification. + /// + /// + /// If the RM requests a single-phase commit operation, it must also specify prepare and commit notifications. + /// + /// + /// + /// The only time an RM is not required to request commit notifications is when it is requesting at least a pair of pre-prepare and + /// rollback notifications. + /// + /// + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-createenlistment HANDLE CreateEnlistment( IN + // LPSECURITY_ATTRIBUTES lpEnlistmentAttributes, IN HANDLE ResourceManagerHandle, IN HANDLE TransactionHandle, IN NOTIFICATION_MASK + // NotificationMask, IN DWORD CreateOptions, IN PVOID EnlistmentKey ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "7bc06468-947f-48ec-8e58-20df58ed93bd")] + public static extern SafeHENLISTMENT CreateEnlistment([In, Optional] SECURITY_ATTRIBUTES lpEnlistmentAttributes, [In] HRESMGR ResourceManagerHandle, [In] HTRXN TransactionHandle, [In] NOTIFICATION_MASK NotificationMask, [In, Optional] CreateEnlistmentOptions CreateOptions, [In, Optional] IntPtr EnlistmentKey); + + /// Creates a new resource manager (RM) object, and associates the RM with a transaction manager (TM). + /// + /// A pointer to a SECURITY_ATTRIBUTES structure that contains the security attributes for the resource manager. Specify NULL + /// to obtain the default attributes. + /// + /// A pointer the resource manager GUID. This parameter is required and must not be NULL. + /// + /// Any optional attributes for the new RM. + /// + /// + /// Value + /// Meaning + /// + /// + /// RESOURCE_MANAGER_VOLATILE + /// Indicates that the RM is volatile, and does not perform recovery. + /// + /// + /// + /// A handle to the TM that will manage the transactions for this RM. + /// A description for this RM. + /// + /// If the function succeeds, the return value is a handle to the RM. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// + /// Immediately after calling this function, you must call RecoverResourceManager. + /// An RM is an endpoint for TM notifications regarding transactions that the RM has enlisted in. + /// + /// RMs are typically persistent, meaning that after a system failure, they must be reopened to perform certain operations. Volatile, + /// or transient, RMs can be created by calling the CreateResourceManager function and by specifying + /// RESOURCE_MANAGER_VOLATILE. Volatile RMs do not perform recovery operations, but do require notifications about a transaction. + /// + /// You can create a volatile RM on a durable TM, but you cannot create a durable RM on a volatile TM. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-createresourcemanager HANDLE CreateResourceManager( IN + // LPSECURITY_ATTRIBUTES lpResourceManagerAttributes, IN LPGUID ResourceManagerId, IN DWORD CreateOptions, IN HANDLE TmHandle, LPWSTR + // Description ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "ad88e478-1dff-4f35-a0e3-6bda8bb45711")] + public static extern SafeHRESMGR CreateResourceManager([In, Optional] SECURITY_ATTRIBUTES lpResourceManagerAttributes, [In] in Guid ResourceManagerId, [In, Optional] CreateRMOptions CreateOptions, [In] HTRXNMGR TmHandle, [MarshalAs(UnmanagedType.LPWStr), Optional] string Description); + + /// Creates a new transaction object. + /// + /// + /// A pointer to a SECURITY_ATTRIBUTES structure that determines whether the returned handle can be inherited by child processes. If + /// this parameter is NULL, the handle cannot be inherited. + /// + /// + /// The lpSecurityDescriptor member of the structure specifies a security descriptor for the new event. If + /// lpTransactionAttributes is NULL, the object gets a default security descriptor. The access control lists (ACL) in the + /// default security descriptor for a transaction come from the primary or impersonation token of the creator. + /// + /// + /// Reserved. Must be zero (0). + /// + /// Any optional transaction instructions. + /// + /// + /// Value + /// Meaning + /// + /// + /// TRANSACTION_DO_NOT_PROMOTE + /// The transaction cannot be distributed. + /// + /// + /// + /// Reserved; specify zero (0). + /// Reserved; specify zero (0). + /// + /// + /// The time-out interval, in milliseconds. If a nonzero value is specified, the transaction will be aborted when the interval + /// elapses if it has not already reached the prepared state. + /// + /// Specify zero (0) or INFINITE to provide an infinite time-out. + /// + /// A user-readable description of the transaction. + /// + /// If the function succeeds, the return value is a handle to the transaction. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// + /// + /// Use the CloseHandle function to close the transaction handle. If the last transaction handle is closed before a client calls the + /// CommitTransaction function with the transaction handle, then KTM rolls back the transaction. + /// + /// + /// If the transaction might need to be promotable to a distributed transaction, then you must grant the Distributed Transaction + /// Coordinator (DTC) access rights to enlist in the transaction. To do this, the lpTransactionAttributes parameter needs to contain + /// an access control entry with the DTC’s SID (S-1-5-80-2818357584-3387065753-4000393942-342927828-138088443) and the + /// TRANSACTION_ENLIST right. For more information, see Distributed Transaction Coordinator and Access Control Components. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-createtransaction HANDLE CreateTransaction( IN + // LPSECURITY_ATTRIBUTES lpTransactionAttributes, IN LPGUID UOW, IN DWORD CreateOptions, IN DWORD IsolationLevel, IN DWORD + // IsolationFlags, IN DWORD Timeout, LPWSTR Description ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "578bda35-bd35-4f6d-8366-a4bfb4dbfe42")] + public static extern SafeHTRXN CreateTransaction([In, Optional] SECURITY_ATTRIBUTES lpTransactionAttributes, [In, Optional] IntPtr UOW, [In, Optional] CreateTrxnOptions CreateOptions, [In, Optional] uint IsolationLevel, [In, Optional] uint IsolationFlags, [In, Optional] uint Timeout, [MarshalAs(UnmanagedType.LPWStr), Optional] string Description); + + /// Creates a new transaction manager (TM) object and returns a handle with the specified access. + /// The transaction SECURITY_ATTRIBUTES (ACLs) for the TM object. + /// + /// The log file stream name. If the stream does not exist in the log, it is created. To create a volatile TM, this parameter must be + /// NULL and CreateOptions must specify TRANSACTION_MANAGER_VOLATILE, this transaction manager is considered volatile. + /// + /// + /// Any optional attributes for the new TM. + /// + /// + /// Value + /// Meaning + /// + /// + /// TRANSACTION_MANAGER_VOLATILE + /// Indicates that the TM is volatile, and does not perform recovery. + /// + /// + /// + /// Reserved; specify zero. + /// + /// If the function succeeds, the return value is a handle to the transaction manager. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// + /// Immediately after calling this function, you must call RecoverTransactionManager. + /// If your transaction manager is volatile, all your resource managers must also be volatile. + /// You must call RecoverTransactionManager after creating a TM in order for the TM to function correctly. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-createtransactionmanager HANDLE CreateTransactionManager( IN + // LPSECURITY_ATTRIBUTES lpTransactionAttributes, LPWSTR LogFileName, IN ULONG CreateOptions, IN ULONG CommitStrength ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "f5b7d0c1-9cd0-48fc-8125-d4da040951c4")] + public static extern SafeHTRXNMGR CreateTransactionManager([In, Optional] SECURITY_ATTRIBUTES lpTransactionAttributes, [MarshalAs(UnmanagedType.LPWStr), Optional] string LogFileName, [In, Optional] CreateTrxnMgrOptions CreateOptions, uint CommitStrength = 0); + + /// Obtains a virtual clock value from a transaction manager. + /// A handle to the transaction manager to obtain a virtual clock value for. + /// The latest virtual clock value for the transaction manager. See LARGE_INTEGER. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-getcurrentclocktransactionmanager BOOL + // GetCurrentClockTransactionManager( IN HANDLE TransactionManagerHandle, OUT PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "21d7c0fa-3a49-43b3-9325-d3dfdabbcb98")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetCurrentClockTransactionManager([In] HTRXNMGR TransactionManagerHandle, out long TmVirtualClock); + + /// Obtains the identifier (ID) for the specified enlistment. + /// A handle to the enlistment. + /// A pointer to a variables that receives the ID of the enlistment. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-getenlistmentid BOOL GetEnlistmentId( IN HANDLE + // EnlistmentHandle, OUT LPGUID EnlistmentId ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "ffd37a2e-6bac-4566-bb15-eafce8a11c3b")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetEnlistmentId([In] HENLISTMENT EnlistmentHandle, out Guid EnlistmentId); + + /// + /// Retrieves an opaque structure of recovery data from KTM. Recovery information is stored in a log on behalf of a resource manager + /// (RM) by calling the SetEnlistmentRecoveryInformation function. After a failure, the RM can use the + /// GetEnlistmentRecoveryInformation function to retrieve the information. + /// + /// A handle to the enlistment. + /// The size of the Buffer parameter, in bytes. + /// A pointer to a buffer that receives the enlistment recovery information. + /// A pointer to a variable that receives the actual number of bytes returned in the Buffer parameter. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// This call cannot be used with volatile transaction managers. + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-getenlistmentrecoveryinformation BOOL + // GetEnlistmentRecoveryInformation( IN HANDLE EnlistmentHandle, IN ULONG BufferSize, OUT PVOID Buffer, OUT PULONG BufferUsed ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "05bfbe81-5f3d-4e32-b4fa-4532227f522e")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetEnlistmentRecoveryInformation([In] HENLISTMENT EnlistmentHandle, [In] uint BufferSize, IntPtr Buffer, out uint BufferUsed); + + /// + /// Requests and receives a notification for a resource manager (RM). This function is used by the RM register to receive + /// notifications when a transaction changes state. + /// + /// A handle to the resource manager. + /// A pointer to a TRANSACTION_NOTIFICATION structure that receives the first available notification. + /// The size of the TransactionNotification buffer, in bytes. + /// + /// The time, in milliseconds, for which the calling application is blocking while waiting for the notification to become available. + /// If no notifications are available when the timeout expires, ERROR_TIMEOUT is returned. + /// + /// + /// A pointer to a variable that receives the actual size of the notification received by the TransactionNotification parameter. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// All resource managers must register to receive TRANSACTION_NOTIFY_PREPREPARE, TRANSACTION_NOTIFY_PREPARE, and + /// TRANSACTION_NOTIFY_COMMIT notifications, even if they subsequently call ReadOnlyEnlistment to mark an enlistment as + /// read-only. Resource managers can support TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT, but they must also support the + /// multi-phase pre-prepare, prepare, and commit notifications. For the list of all notifications that resource managers can receive, + /// see TRANSACTION_NOTIFICATION. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-getnotificationresourcemanager BOOL + // GetNotificationResourceManager( IN HANDLE ResourceManagerHandle, OUT PTRANSACTION_NOTIFICATION TransactionNotification, IN ULONG + // NotificationLength, IN DWORD dwMilliseconds, OUT PULONG ReturnLength ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "d606f960-e843-4478-8ba7-5201f85c44ce")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetNotificationResourceManager([In] HRESMGR ResourceManagerHandle, IntPtr TransactionNotification, [In] uint NotificationLength, [In, Optional] uint dwMilliseconds, out uint ReturnLength); + + /// + /// Requests and receives asynchronous notification for a resource manager (RM). This function is used by the RM register to receive + /// notifications when a transaction changes state. + /// + /// A handle to the resource manager. + /// A pointer to a TRANSACTION_NOTIFICATION structure that receives the first available notification. + /// The size of the TransactionNotification buffer, in bytes. + /// + /// A pointer to a variable that receives the actual size of the notification received by the TransactionNotification parameter. + /// + /// A pointer to an OVERLAPPED structure that is required for asynchronous operation. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// + /// All resource managers must register to receive TRANSACTION_NOTIFY_PREPREPARE, TRANSACTION_NOTIFY_PREPARE, and + /// TRANSACTION_NOTIFY_COMMIT notifications, even if they subsequently call ReadOnlyEnlistment to mark an enlistment as + /// read-only. Resource managers can support TRANSACTION_NOTIFY_SINGLE_PHASE_COMMIT, but they must also support the + /// multi-phase pre-prepare, prepare, and commit notifications. For the list of all notifications that resource managers can receive, + /// see TRANSACTION_NOTIFICATION. + /// + /// + /// Resource managers (RM) may want to call this function more than once to provide multiple buffers for KTM to use when delivering + /// notifications. The number of calls to this function depends on how much load your RM is carrying. + /// + /// This function must be called after the SetResourceManagerCompletionPort function is called. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-getnotificationresourcemanagerasync BOOL + // GetNotificationResourceManagerAsync( IN HANDLE ResourceManagerHandle, OUT PTRANSACTION_NOTIFICATION TransactionNotification, IN + // ULONG TransactionNotificationLength, OUT PULONG ReturnLength, IN LPOVERLAPPED lpOverlapped ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "c83e104b-6cd7-4399-8232-7c2e7b408f1a")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern unsafe bool GetNotificationResourceManagerAsync([In] HRESMGR ResourceManagerHandle, IntPtr TransactionNotification, [In] uint TransactionNotificationLength, out uint ReturnLength, [In] NativeOverlapped* lpOverlapped); + + /// Obtains the identifier (ID) for the specified transaction. + /// A handle to the transaction. + /// A pointer to a variable that receives the ID of the transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-gettransactionid BOOL GetTransactionId( IN HANDLE + // TransactionHandle, OUT LPGUID TransactionId ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "10f4729f-3e6e-469a-8f72-48c29735e7b1")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetTransactionId([In] HTRXN TransactionHandle, out Guid TransactionId); + + /// Returns the requested information about the specified transaction. + /// + /// A handle to the transaction. The handle must have the TRANSACTION_QUERY_INFORMATION permission to retrieve the information. + /// + /// + /// A pointer to a buffer that receives the current outcome of the transaction. If the call to the GetTransactionInformation + /// function is successful, this value will be one of the TRANSACTION_OUTCOME enumeration values. + /// + /// Reserved. + /// Reserved. + /// A pointer to a variable that receives the timeout value, in milliseconds, for this transaction. + /// + /// The size of the Description parameter, in bytes. The buffer length value cannot be longer than the value of MAX_TRANSACTION_DESCRIPTION_LENGTH. + /// + /// A pointer to a buffer that receives the user-defined description of the transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-gettransactioninformation BOOL GetTransactionInformation( IN + // HANDLE TransactionHandle, OUT PDWORD Outcome, OUT PDWORD IsolationLevel, OUT PDWORD IsolationFlags, OUT PDWORD Timeout, DWORD + // BufferLength, LPWSTR Description ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "5ce3c96a-629e-49d0-8ec4-f9bf76af99ac")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetTransactionInformation([In] HTRXN TransactionHandle, out TRANSACTION_OUTCOME Outcome, [Optional] IntPtr IsolationLevel, [Optional] IntPtr IsolationFlags, out uint Timeout, uint BufferLength, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder Description); + + /// Obtains an identifier for the specified transaction manager. + /// A handle to the transaction manager. + /// A pointer to a variable that receives the identifier for the transaction manager. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-gettransactionmanagerid BOOL GetTransactionManagerId( IN + // HANDLE TransactionManagerHandle, OUT LPGUID TransactionManagerId ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "e1aa573d-add9-42b7-8b2b-773dc12aa51b")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetTransactionManagerId([In] HTRXNMGR TransactionManagerHandle, out Guid TransactionManagerId); + + /// Opens an existing enlistment object, and returns a handle to the enlistment. + /// The access requested for this enlistment. See Enlistment Access Masks for a list of valid values. + /// A handle to the resource manager. + /// The enlistment identifier. + /// + /// If the function succeeds, the return value is a handle to the enlistment. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-openenlistment HANDLE OpenEnlistment( IN DWORD + // dwDesiredAccess, IN HANDLE ResourceManagerHandle, IN LPGUID EnlistmentId ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "2c403e22-3feb-415a-b65b-572802764548")] + public static extern SafeHENLISTMENT OpenEnlistment([In] EnlistmentAccess dwDesiredAccess, [In] HRESMGR ResourceManagerHandle, [In] in Guid EnlistmentId); + + /// Opens an existing resource manager (RM). + /// The access requested for the RM. See Resource Manager Access Masks for a list of valid values. + /// A handle to the transaction manager. + /// The identifier for this resource manager. + /// + /// If the function succeeds, the return value is a handle to the resource manager. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// Immediately after calling this function, you must call RecoverResourceManager. + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-openresourcemanager HANDLE OpenResourceManager( IN DWORD + // dwDesiredAccess, IN HANDLE TmHandle, IN LPGUID ResourceManagerId ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "396b586f-c594-4481-b095-862e9058519c")] + public static extern SafeHRESMGR OpenResourceManager([In] ResourceManagerAccess dwDesiredAccess, [In] HTRXNMGR TmHandle, [In] in Guid ResourceManagerId); + + /// Opens an existing transaction. + /// + /// The access to the transaction object. You must have read and write access to work with a transaction. See Transaction Access + /// Masks for a list of valid values. + /// + /// + /// The GUID that identifies the transaction to be opened. This is commonly referred to as a unit of work for the transaction. + /// + /// + /// If the function succeeds, the return value is a handle to the transaction. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// + /// Clients close the transaction handle by using the CloseHandle function. If the last transaction handle is closed without anyone + /// calling the CommitTransaction function on the transaction, then the KTM implicitly rolls back the transaction. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-opentransaction HANDLE OpenTransaction( IN DWORD + // dwDesiredAccess, IN LPGUID TransactionId ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "d95f15e4-d0fd-4665-849d-eecac8fc542b")] + public static extern SafeHTRXN OpenTransaction([In] TransactionAccess dwDesiredAccess, [In] in Guid TransactionId); + + /// Opens an existing transaction manager. + /// The name of the log stream. This stream must exist within a CLFS log file. + /// The access requested. See Transaction Manager Access Masks for a list of valid values. + /// Reserved; specify zero. + /// + /// If the function succeeds, the return value is a handle to the transaction manager. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// + /// Immediately after calling this function, you must call RecoverTransactionManager. + /// + /// The LogFileName must be specified using the NT file format. For example: <drive>:<path>. Do not use the .BLF extension. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-opentransactionmanager HANDLE OpenTransactionManager( LPWSTR + // LogFileName, IN ACCESS_MASK DesiredAccess, IN ULONG OpenOptions ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "6b53609a-b956-441c-b5b5-9a8e6aa489c9")] + public static extern SafeHTRXNMGR OpenTransactionManager([MarshalAs(UnmanagedType.LPWStr)] string LogFileName, [In] TransactionMgrAccess DesiredAccess, uint OpenOptions = 0); + + /// Opens an existing transaction manager. + /// The identifier of the transaction to open. + /// The access requested. See Transaction Manager Access Masks for a list of valid values. + /// Reserved; specify zero. + /// + /// If the function succeeds, the return value is a handle to the transaction manager. + /// + /// If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call the GetLastError function. + /// + /// The following list identifies the possible error codes: + /// + /// Immediately after calling this function, you must call RecoverTransactionManager. + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-opentransactionmanagerbyid HANDLE OpenTransactionManagerById( + // LPGUID TransactionManagerId, IN ACCESS_MASK DesiredAccess, IN ULONG OpenOptions ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "4724383d-8ecf-40cb-8159-15a6d5ddfd1b")] + public static extern SafeHTRXNMGR OpenTransactionManagerById(in Guid TransactionManagerId, [In] TransactionMgrAccess DesiredAccess, uint OpenOptions = 0); + + /// + /// Indicates that the resource manager (RM) has completed all processing necessary to guarantee that a commit or abort operation + /// will succeed for the specified transaction. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received for this prepare complete notification. If you specify NULL, the virtual clock + /// value is not changed. See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-preparecomplete BOOL PrepareComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "47488c70-3409-4544-bcca-3415f91e7194")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrepareComplete([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Indicates that the resource manager (RM) has completed all processing necessary to guarantee that a commit or abort operation + /// will succeed for the specified transaction. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received for this prepare complete notification. If you specify NULL, the virtual clock + /// value is not changed. See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-preparecomplete BOOL PrepareComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "47488c70-3409-4544-bcca-3415f91e7194")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrepareComplete([In] HENLISTMENT EnlistmentHandle, [Optional] IntPtr TmVirtualClock); + + /// + /// Prepares the transaction associated with this enlistment handle. This function is used by communication resource managers + /// (sometimes called superior transaction managers). + /// + /// A handle to the enlistment for which the prepare operation has completed. + /// A pointer to the latest virtual clock value received for this transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-prepareenlistment BOOL PrepareEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "5f1b1eb2-e2f5-4daf-b549-7f0c195414f0")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrepareEnlistment([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Signals that this resource manager has completed its pre-prepare work, so that other resource managers can now begin their + /// prepare operations. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received for this pre-prepare operation. If you specify NULL, the virtual clock value is + /// not changed. See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-prepreparecomplete BOOL PrePrepareComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "b4a70a51-2c49-4626-9fca-9ca6e0d21a53")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrePrepareComplete([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Signals that this resource manager has completed its pre-prepare work, so that other resource managers can now begin their + /// prepare operations. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received for this pre-prepare operation. If you specify NULL, the virtual clock value is + /// not changed. See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-prepreparecomplete BOOL PrePrepareComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "b4a70a51-2c49-4626-9fca-9ca6e0d21a53")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrePrepareComplete([In] HENLISTMENT EnlistmentHandle, [Optional] IntPtr TmVirtualClock); + + /// + /// Pre-prepares the transaction associated with this enlistment handle. This function is used by communication resource managers + /// (sometimes called superior transaction managers). + /// + /// A handle to the enlistment for which the prepare operation has completed. + /// A pointer to the latest virtual clock value received for this transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-preprepareenlistment BOOL PrePrepareEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "7a336267-4bee-4aac-abff-ec112650789a")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool PrePrepareEnlistment([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Requests that the specified enlistment be converted to a read-only enlistment. A read-only enlistment cannot participate in the + /// outcome of the transaction and is not durably recorded for recovery. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received for this enlistment. If you specify NULL, the virtual clock value is not changed. + /// See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// If a resource manager no longer needs to participate in a transaction without rolling back the transaction, it should call + /// ReadOnlyEnlistment prior to closing the enlistment handle. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-readonlyenlistment BOOL ReadOnlyEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "a6411fad-8ad0-4a31-9e09-0c18dd384634")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ReadOnlyEnlistment([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Requests that the specified enlistment be converted to a read-only enlistment. A read-only enlistment cannot participate in the + /// outcome of the transaction and is not durably recorded for recovery. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received for this enlistment. If you specify NULL, the virtual clock value is not changed. + /// See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// If a resource manager no longer needs to participate in a transaction without rolling back the transaction, it should call + /// ReadOnlyEnlistment prior to closing the enlistment handle. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-readonlyenlistment BOOL ReadOnlyEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "a6411fad-8ad0-4a31-9e09-0c18dd384634")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool ReadOnlyEnlistment([In] HENLISTMENT EnlistmentHandle, [Optional] IntPtr TmVirtualClock); + + /// Recovers an enlistment's state. + /// A handle to the enlistment. + /// The key to the enlistment to be recovered. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-recoverenlistment BOOL RecoverEnlistment( IN HANDLE + // EnlistmentHandle, IN PVOID EnlistmentKey ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "5c36732f-bf4f-4071-959e-3359be0b2363")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RecoverEnlistment([In] HENLISTMENT EnlistmentHandle, [In, Optional] IntPtr EnlistmentKey); + + /// Recovers a resource manager's state from its log file. + /// A handle to the resource manager. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-recoverresourcemanager BOOL RecoverResourceManager( IN HANDLE + // ResourceManagerHandle ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "616ff873-c0d0-464e-9b1b-74a426b99abd")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RecoverResourceManager([In] HRESMGR ResourceManagerHandle); + + /// Recovers a transaction manager's state from its log file. + /// A handle to the transaction manager. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// This function must be called after you call CreateTransactionManager. + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-recovertransactionmanager BOOL RecoverTransactionManager( IN + // HANDLE TransactionManagerHandle ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "6f217ebb-3423-41d3-acff-eb21838c9751")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RecoverTransactionManager([In] HTRXNMGR TransactionManagerHandle); + + /// + /// Renames a transaction manager (TM) object. This function can only be used on named TM handles. A new GUID for the TM is + /// selected and can be retrieved using the GetTransactionManagerID function. + /// + /// The name of the log stream. This stream must exist within a CLFS log file. + /// A value that specifies the current name of the TM. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-renametransactionmanager BOOL RenameTransactionManager( LPWSTR + // LogFileName, IN LPGUID ExistingTransactionManagerGuid ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "2767e689-1342-458f-a215-a29d774c0648")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RenameTransactionManager([MarshalAs(UnmanagedType.LPWStr)] string LogFileName, in Guid ExistingTransactionManagerGuid); + + /// Indicates that the resource manager (RM) has successfully completed rolling back a transaction. + /// A handle the enlistment. + /// The latest virtual clock value received for this transaction. See LARGE_INTEGER. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// If the RM was not able to successfully roll back a transaction, the RM should request a full rollback by calling the + /// RollbackTransaction function. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-rollbackcomplete BOOL RollbackComplete( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "c9d53777-eef9-4c60-921d-50b0fbf8d005")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RollbackComplete([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Rolls back the specified transaction that is associated with an enlistment. This function cannot be called for read-only enlistments. + /// + /// A handle to the enlistment. + /// The latest virtual clock value received for this enlistment. See LARGE_INTEGER. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// + /// This function is used by an RM to roll back a transaction in which it is enlisted. All work associated with the transaction is + /// rolled back. + /// + /// Rollbacks are allowed by enlistments at any time before it issues a prepare complete notification. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-rollbackenlistment BOOL RollbackEnlistment( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "e62c0c81-6802-4a76-94bb-617933490e83")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RollbackEnlistment([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// Requests that the specified transaction be rolled back. This function is synchronous. + /// A handle to the transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// + /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function. The following + /// list identifies the possible error codes: + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-rollbacktransaction BOOL RollbackTransaction( IN HANDLE + // TransactionHandle ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "7d3522b8-ddf0-449e-8ab4-09e679ba1f15")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RollbackTransaction([In] HTRXN TransactionHandle); + + /// Requests that the specified transaction be rolled back. This function returns asynchronously. + /// A handle to the transaction. + /// + /// If the function succeeds, the return value is nonzero, and GetLastError returns ERROR_IO_PENDING. + /// + /// If the function fails, the return value is zero. To get extended error information, call the GetLastError function. The following + /// list identifies the possible error codes: + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-rollbacktransactionasync BOOL RollbackTransactionAsync( IN + // HANDLE TransactionHandle ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "df23e5af-c37e-4e60-b160-6ffa8f6a26e3")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RollbackTransactionAsync([In] HTRXN TransactionHandle); + + /// Recovers information only to the specified virtual clock value. + /// A handle to the transaction manager. + /// A pointer to the latest virtual clock value received for this transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-rollforwardtransactionmanager BOOL + // RollforwardTransactionManager( IN HANDLE TransactionManagerHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "13492b74-8707-46bb-93f1-59c3c5ceab6d")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool RollforwardTransactionManager([In] HTRXNMGR TransactionManagerHandle, in long TmVirtualClock); + + /// + /// Sets an opaque, user-defined structure of recovery data from KTM. Recovery information is stored in a log on behalf of a resource + /// manager (RM) by calling SetEnlistmentRecoveryInformation. After a failure, the RM can use GetEnlistmentRecoveryInformation + /// to retrieve the information. + /// + /// A handle to the enlistment. + /// The size of Buffer, in bytes. + /// The recovery information. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// This call cannot be used with volatile transaction managers. + /// + /// The information that is provided by the user may not be durably stored in the log at the completion of this operation, but it + /// will be durably stored by the end of the next commit operation for this enlistment. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-setenlistmentrecoveryinformation BOOL + // SetEnlistmentRecoveryInformation( IN HANDLE EnlistmentHandle, IN ULONG BufferSize, IN PVOID Buffer ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "54e7526f-57f0-40cd-9624-fce0644a0884")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetEnlistmentRecoveryInformation([In] HENLISTMENT EnlistmentHandle, [In] uint BufferSize, [In] IntPtr Buffer); + + /// + /// Associates the specified I/O completion port with the specified resource manager (RM). This port receives all notifications for + /// the RM. + /// + /// A handle to the resource manager. + /// A handle to the I/O completion port. + /// + /// The user-defined identifier. Typically, it is used to associate the receive notification with a specific resource manager. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + /// + /// + /// This function must be used in conjunction with the GetNotificationResourceManagerAsync function, which provides the buffers that + /// KTM uses to deliver notifications asynchronously. These functions provide a different way to receive notifications from KTM. You + /// can use these two functions instead of the GetNotificationResourceManager function. + /// + /// This function must be called before calling GetNotificationResourceManagerAsync. + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-setresourcemanagercompletionport BOOL + // SetResourceManagerCompletionPort( IN HANDLE ResourceManagerHandle, IN HANDLE IoCompletionPortHandle, IN ULONG_PTR CompletionKey ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "219fc899-84ee-474f-9f86-6ebf9c721810")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetResourceManagerCompletionPort([In] HRESMGR ResourceManagerHandle, [In] IntPtr IoCompletionPortHandle, [In] IntPtr CompletionKey); + + /// Sets the transaction information for the specified transaction. + /// + /// A handle to the transaction. The handle must have the TRANSACTION_SET_INFORMATION permission to set the transaction information. + /// + /// Reserved; specify zero. + /// Reserved. + /// The timeout value, in milliseconds, for this transaction. + /// The user-defined description of this transaction. + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is 0 (zero). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-settransactioninformation BOOL SetTransactionInformation( IN + // HANDLE TransactionHandle, IN DWORD IsolationLevel, IN DWORD IsolationFlags, IN DWORD Timeout, LPWSTR Description ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "e33d221b-cd06-4f20-a4b5-407a04362ba0")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetTransactionInformation([In] HTRXN TransactionHandle, [In, Optional] uint IsolationLevel, [In, Optional] uint IsolationFlags, [In, Optional] uint Timeout, [MarshalAs(UnmanagedType.LPWStr), Optional] string Description); + + /// + /// Indicates that the resource manager (RM) is refusing a single-phase request. When a transaction manager (TM) receives this call, + /// it initiates a two-phase commit and sends a prepare request to all enlisted RMs. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received from the single-phase request notification. If you specify NULL, the virtual clock + /// value is not changed. See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-singlephasereject BOOL SinglePhaseReject( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "8cc77686-e130-4b82-b2f5-70121b40e052")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SinglePhaseReject([In] HENLISTMENT EnlistmentHandle, in long TmVirtualClock); + + /// + /// Indicates that the resource manager (RM) is refusing a single-phase request. When a transaction manager (TM) receives this call, + /// it initiates a two-phase commit and sends a prepare request to all enlisted RMs. + /// + /// A handle to the enlistment. + /// + /// + /// The latest virtual clock value received from the single-phase request notification. If you specify NULL, the virtual clock + /// value is not changed. See LARGE_INTEGER. + /// + /// To change the virtual clock value, this value must be greater than the current value returned in the COMMIT notification. + /// + /// + /// If the function succeeds, the return value is nonzero. + /// If the function fails, the return value is zero (0). To get extended error information, call the GetLastError function. + /// The following list identifies the possible error codes: + /// + // https://docs.microsoft.com/en-us/windows/win32/api/ktmw32/nf-ktmw32-singlephasereject BOOL SinglePhaseReject( IN HANDLE + // EnlistmentHandle, IN PLARGE_INTEGER TmVirtualClock ); + [DllImport(Lib.Ktmw32, SetLastError = true, ExactSpelling = true)] + [PInvokeData("ktmw32.h", MSDNShortId = "8cc77686-e130-4b82-b2f5-70121b40e052")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SinglePhaseReject([In] HENLISTMENT EnlistmentHandle, [Optional] IntPtr TmVirtualClock); + + /// Provides a handle to an enlistment. + [StructLayout(LayoutKind.Sequential)] + public struct HENLISTMENT : IKernelHandle + { + private readonly IntPtr handle; + + /// Initializes a new instance of the struct. + /// An object that represents the pre-existing handle to use. + public HENLISTMENT(IntPtr preexistingHandle) => handle = preexistingHandle; + + /// Returns an invalid handle by instantiating a object with . + public static HENLISTMENT NULL => new HENLISTMENT(IntPtr.Zero); + + /// Gets a value indicating whether this instance is a null handle. + public bool IsNull => handle == IntPtr.Zero; + + /// Performs an explicit conversion from to . + /// The handle. + /// The result of the conversion. + public static explicit operator IntPtr(HENLISTMENT h) => h.handle; + + /// Performs an implicit conversion from to . + /// The pointer to a handle. + /// The result of the conversion. + public static implicit operator HENLISTMENT(IntPtr h) => new HENLISTMENT(h); + + /// Implements the operator !=. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator !=(HENLISTMENT h1, HENLISTMENT h2) => !(h1 == h2); + + /// Implements the operator ==. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator ==(HENLISTMENT h1, HENLISTMENT h2) => h1.Equals(h2); + + /// + public override bool Equals(object obj) => obj is HENLISTMENT h ? handle == h.handle : false; + + /// + public override int GetHashCode() => handle.GetHashCode(); + + /// + public IntPtr DangerousGetHandle() => handle; + } + + /// Provides a handle to a resource manager. + [StructLayout(LayoutKind.Sequential)] + public struct HRESMGR : IKernelHandle + { + private readonly IntPtr handle; + + /// Initializes a new instance of the struct. + /// An object that represents the pre-existing handle to use. + public HRESMGR(IntPtr preexistingHandle) => handle = preexistingHandle; + + /// Returns an invalid handle by instantiating a object with . + public static HRESMGR NULL => new HRESMGR(IntPtr.Zero); + + /// Gets a value indicating whether this instance is a null handle. + public bool IsNull => handle == IntPtr.Zero; + + /// Performs an explicit conversion from to . + /// The handle. + /// The result of the conversion. + public static explicit operator IntPtr(HRESMGR h) => h.handle; + + /// Performs an implicit conversion from to . + /// The pointer to a handle. + /// The result of the conversion. + public static implicit operator HRESMGR(IntPtr h) => new HRESMGR(h); + + /// Implements the operator !=. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator !=(HRESMGR h1, HRESMGR h2) => !(h1 == h2); + + /// Implements the operator ==. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator ==(HRESMGR h1, HRESMGR h2) => h1.Equals(h2); + + /// + public override bool Equals(object obj) => obj is HRESMGR h ? handle == h.handle : false; + + /// + public override int GetHashCode() => handle.GetHashCode(); + + /// + public IntPtr DangerousGetHandle() => handle; + } + + /// Provides a handle to a Transaction Manager (TM). + [StructLayout(LayoutKind.Sequential)] + public struct HTRXNMGR : IKernelHandle + { + private readonly IntPtr handle; + + /// Initializes a new instance of the struct. + /// An object that represents the pre-existing handle to use. + public HTRXNMGR(IntPtr preexistingHandle) => handle = preexistingHandle; + + /// Returns an invalid handle by instantiating a object with . + public static HTRXNMGR NULL => new HTRXNMGR(IntPtr.Zero); + + /// Gets a value indicating whether this instance is a null handle. + public bool IsNull => handle == IntPtr.Zero; + + /// Performs an explicit conversion from to . + /// The handle. + /// The result of the conversion. + public static explicit operator IntPtr(HTRXNMGR h) => h.handle; + + /// Performs an implicit conversion from to . + /// The pointer to a handle. + /// The result of the conversion. + public static implicit operator HTRXNMGR(IntPtr h) => new HTRXNMGR(h); + + /// Implements the operator !=. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator !=(HTRXNMGR h1, HTRXNMGR h2) => !(h1 == h2); + + /// Implements the operator ==. + /// The first handle. + /// The second handle. + /// The result of the operator. + public static bool operator ==(HTRXNMGR h1, HTRXNMGR h2) => h1.Equals(h2); + + /// + public override bool Equals(object obj) => obj is HTRXNMGR h ? handle == h.handle : false; + + /// + public override int GetHashCode() => handle.GetHashCode(); + + /// + public IntPtr DangerousGetHandle() => handle; + } + + /// Contains the data that is associated with a transaction notification. + // https://docs.microsoft.com/en-us/windows/win32/api/ktmtypes/ns-ktmtypes-transaction_notification typedef struct + // _TRANSACTION_NOTIFICATION { PVOID TransactionKey; ULONG TransactionNotification; LARGE_INTEGER TmVirtualClock; ULONG + // ArgumentLength; } TRANSACTION_NOTIFICATION, *PTRANSACTION_NOTIFICATION; + [PInvokeData("ktmtypes.h", MSDNShortId = "4f87de9d-a068-4ab9-8f38-b75f20552b1d")] + [StructLayout(LayoutKind.Sequential)] + public struct TRANSACTION_NOTIFICATION + { + /// The user-defined, opaque ID for this transaction. + public IntPtr TransactionKey; + + /// The NOTIFICATION_MASK value for this transaction. + public NOTIFICATION_MASK TransactionNotification; + + /// The latest virtual clock value that is associated with this transaction. See LARGE_INTEGER. + public long TmVirtualClock; + + /// + /// Indicates the number of bytes for the TRANSACTION_NOTIFICATION_RECOVERY_ARGUMENT structure that follow this + /// TRANSACTION_NOTIFICATION structure. + /// + public uint ArgumentLength; + } + + /// Indicates the transaction to be recovered. This structure is sent with a recovery notification. + // https://docs.microsoft.com/en-us/windows/win32/api/ktmtypes/ns-ktmtypes-transaction_notification_recovery_argument typedef struct + // _TRANSACTION_NOTIFICATION_RECOVERY_ARGUMENT { GUID EnlistmentId; UOW UOW; } TRANSACTION_NOTIFICATION_RECOVERY_ARGUMENT, *PTRANSACTION_NOTIFICATION_RECOVERY_ARGUMENT; + [PInvokeData("ktmtypes.h", MSDNShortId = "29a32b89-22d1-4d26-8927-a2051dd5d37a")] + [StructLayout(LayoutKind.Sequential)] + public struct TRANSACTION_NOTIFICATION_RECOVERY_ARGUMENT + { + /// The enlistment identifier. + public Guid EnlistmentId; + + /// The transaction identifier, sometimes called the unit of work. + public Guid UOW; + } + + /// Provides a for that is disposed using . + public class SafeHENLISTMENT : SafeKernelHandle + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHENLISTMENT(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHENLISTMENT() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HENLISTMENT(SafeHENLISTMENT h) => h.handle; + + /// + protected override bool InternalReleaseHandle() => CloseHandle(handle); + } + + /// Provides a for that is disposed using . + public class SafeHRESMGR : SafeKernelHandle + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHRESMGR(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHRESMGR() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HRESMGR(SafeHRESMGR h) => h.handle; + + /// + protected override bool InternalReleaseHandle() => CloseHandle(handle); + } + + /// Provides a for that is disposed using . + public class SafeHTRXN : SafeKernelHandle + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHTRXN(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHTRXN() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HTRXN(SafeHTRXN h) => h.handle; + + /// + protected override bool InternalReleaseHandle() => CloseHandle(handle); + } + + /// Provides a for that is disposed using . + public class SafeHTRXNMGR : SafeKernelHandle + { + /// Initializes a new instance of the class and assigns an existing handle. + /// An object that represents the pre-existing handle to use. + /// + /// to reliably release the handle during the finalization phase; otherwise, (not recommended). + /// + public SafeHTRXNMGR(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } + + /// Initializes a new instance of the class. + private SafeHTRXNMGR() : base() { } + + /// Performs an implicit conversion from to . + /// The safe handle instance. + /// The result of the conversion. + public static implicit operator HTRXNMGR(SafeHTRXNMGR h) => h.handle; + + /// + protected override bool InternalReleaseHandle() => CloseHandle(handle); + } + } +} \ No newline at end of file diff --git a/PInvoke/KtmW32/Vanara.PInvoke.KtmW32.csproj b/PInvoke/KtmW32/Vanara.PInvoke.KtmW32.csproj new file mode 100644 index 00000000..27e763e8 --- /dev/null +++ b/PInvoke/KtmW32/Vanara.PInvoke.KtmW32.csproj @@ -0,0 +1,51 @@ + + + + PInvoke API (methods, structures and constants imported from Windows KtmW32.dll. + Copyright © 2017-2019 + $(AssemblyName) + 3.0.0 + net20;net35;net40;net45;netstandard2.0;netcoreapp2.0;netcoreapp2.1 + Vanara.PInvoke.KtmW32 + $(AssemblyName) + Vanara.PInvoke + David Hall + https://github.com/dahall/vanara + MIT + https://raw.githubusercontent.com/dahall/Vanara/master/docs/icons/Vanara48x48.png + https://github.com/dahall/vanara + Git + pinvoke;vanara;net-extensions;interop;ktmw32;transactions + en-US + true + true + GitHub Community + Vanara + True + + latest + true + ..\..\Vanara.snk + + + true + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PInvoke/Shared/Lib.cs b/PInvoke/Shared/Lib.cs index 90f19ce7..2c146618 100644 --- a/PInvoke/Shared/Lib.cs +++ b/PInvoke/Shared/Lib.cs @@ -42,6 +42,9 @@ /// The kernel base public const string KernelBase = "kernelbase.dll"; + /// The Kernel Transaction Manager (KTM) + public const string Ktmw32 = "ktmw32.dll"; + /// The MPR public const string Mpr = "mpr.dll"; diff --git a/UnitTests/PInvoke/KtmW32/KtmW32.csproj b/UnitTests/PInvoke/KtmW32/KtmW32.csproj new file mode 100644 index 00000000..c3e873dd --- /dev/null +++ b/UnitTests/PInvoke/KtmW32/KtmW32.csproj @@ -0,0 +1,82 @@ + + + + + Debug + AnyCPU + {8BC51B6B-77FA-4571-8E1C-EA75ED4DCD56} + Library + Properties + Vanara.PInvoke.Tests + UnitTest.PInvoke.KtmW32 + v4.7.2 + 512 + latest + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x64 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + x64 + + + + + + + + + + {241f73ee-9298-45c9-b869-a045dff94c03} + Vanara.Core + + + {842d436f-598c-47d7-b5aa-12399f8ccfe9} + Vanara.PInvoke.Kernel32 + + + {c325c0a4-b8cf-442b-b393-c65fc9174045} + Vanara.PInvoke.KtmW32 + + + {a5e519e9-feba-4fe3-93a5-b8269bef72f4} + Vanara.PInvoke.Shared + + + {a96cff10-0967-429a-8700-4a86c97c5603} + Shared + + + + + 3.12.0 + + + 3.13.0 + + + + + \ No newline at end of file diff --git a/UnitTests/PInvoke/KtmW32/KtmW32Tests.cs b/UnitTests/PInvoke/KtmW32/KtmW32Tests.cs new file mode 100644 index 00000000..9e3552cf --- /dev/null +++ b/UnitTests/PInvoke/KtmW32/KtmW32Tests.cs @@ -0,0 +1,163 @@ +using NUnit.Framework; +using System; +using System.Text; +using Vanara.InteropServices; +using static Vanara.PInvoke.Kernel32; +using static Vanara.PInvoke.KtmW32; + +namespace Vanara.PInvoke.Tests +{ + [TestFixture()] + public class KtmW32Tests + { + private const string txnDesc = "MyTransaction"; + + [Test] + public void CommitTransactionAsyncTest() + { + using (var hTR = CreateTransaction(null, default, 0, 0, 0, 0, txnDesc)) + { + Assert.That(hTR, ResultIs.ValidHandle); + Assert.That(CommitTransactionAsync(hTR), ResultIs.Successful); + } + } + + [Test] + public void CommitTransactionTest() + { + using (var hTR = CreateTransaction(null, default, 0, 0, 0, 0, txnDesc)) + { + Assert.That(hTR, ResultIs.ValidHandle); + Assert.That(CommitTransaction(hTR), ResultIs.Successful); + } + } + + [Test] + public unsafe void CreateTMNVTest() + { + using (var tmp = new TempFile(null)) + using (var hTM = CreateTransactionManager(null, tmp.FullName)) + { + Assert.That(hTM, ResultIs.ValidHandle); + + Assert.That(RenameTransactionManager(tmp.FullName, Guid.NewGuid()), ResultIs.Failure); + + Assert.That(RecoverTransactionManager(hTM), ResultIs.Successful); + + using (var hTM2 = OpenTransactionManager(tmp.FullName, TransactionMgrAccess.TRANSACTIONMANAGER_ALL_ACCESS)) + Assert.That(hTM2, ResultIs.ValidHandle); + + var rmId = Guid.NewGuid(); + using (var hRM = CreateResourceManager(null, rmId, 0, hTM, "MyRM")) + { + Assert.That(hRM, ResultIs.ValidHandle); + + Assert.That(RecoverResourceManager(hRM), ResultIs.Successful); + + using (var pTn = new SafeHGlobalHandle(4096)) + Assert.That(GetNotificationResourceManagerAsync(hRM, pTn, pTn.Size, out _, null), ResultIs.Failure); + + using (var hRM2 = OpenResourceManager(ResourceManagerAccess.RESOURCEMANAGER_ALL_ACCESS, hTM, rmId)) + Assert.That(hRM2, ResultIs.ValidHandle); + } + + Assert.That(RollforwardTransactionManager(hTM, 255L), ResultIs.Successful); + } + } + + [Test] + public void CreateTMRMGetInfoTest() + { + using (var hTM = CreateTransactionManager(CreateOptions: CreateTrxnMgrOptions.TRANSACTION_MANAGER_VOLATILE)) + { + Assert.That(hTM, ResultIs.ValidHandle); + + Assert.That(GetCurrentClockTransactionManager(hTM, out var clock), ResultIs.Successful); + TestContext.WriteLine($"TMClock=0x{clock:X}"); + + Assert.That(GetTransactionManagerId(hTM, out var tmguid), ResultIs.Successful); + TestContext.WriteLine($"TMID={tmguid}"); + + using (var hTM2 = OpenTransactionManagerById(tmguid, TransactionMgrAccess.TRANSACTIONMANAGER_ALL_ACCESS)) + Assert.That(hTM2, ResultIs.ValidHandle); + + Assert.That(RecoverTransactionManager(hTM), ResultIs.FailureCode(Win32Error.ERROR_TM_VOLATILE)); + + using (var hRM = CreateResourceManager(null, Guid.Empty, CreateRMOptions.RESOURCE_MANAGER_VOLATILE, hTM, null)) + { + Assert.That(hRM, ResultIs.ValidHandle); + + using (var pTn = new SafeHGlobalHandle(4096)) + Assert.That(GetNotificationResourceManager(hRM, pTn, pTn.Size, 10, out var req), ResultIs.FailureCode(Win32Error.WAIT_TIMEOUT)); + + Assert.That(RecoverResourceManager(hRM), ResultIs.FailureCode(Win32Error.ERROR_TM_VOLATILE)); + } + } + } + + [Test] + public void GetSetTransactionInformationTest() + { + using (var hTR = CreateTransaction(null, default, 0, 0, 0, 0, txnDesc)) + { + Assert.That(hTR, ResultIs.ValidHandle); + + Assert.That(GetTransactionId(hTR, out var trguid), ResultIs.Successful); + TestContext.WriteLine($"TrID={trguid}"); + + using (var hTR2 = OpenTransaction(TransactionAccess.TRANSACTION_ALL_ACCESS, trguid)) + Assert.That(hTR2, ResultIs.ValidHandle); + + var sb = new StringBuilder(255); + Assert.That(GetTransactionInformation(hTR, out var troutcome, default, default, out var trTO, 255, sb), ResultIs.Successful); + TestContext.WriteLine($"TrInf={troutcome}, {trTO}, {sb}"); + + sb.Append("2"); + Assert.That(SetTransactionInformation(hTR, 0, 0, 5000, sb.ToString()), ResultIs.Successful); + } + } + + // Despite hours of trying, I cannot successfully create an enlistment nor find working code on the internet. So, I'm punting and + // just doing non-functional testing for all enlistment functions. -- Sigh -- + [Test] + public void NonFunctionalTest() + { + Assert.That(CommitComplete(HENLISTMENT.NULL), ResultIs.Failure); + Assert.That(CommitEnlistment(HENLISTMENT.NULL), ResultIs.Failure); + Assert.That(CreateEnlistment(null, HRESMGR.NULL, HTRXN.NULL, 0).DangerousGetHandle(), Is.EqualTo((IntPtr)HFILE.INVALID_HANDLE_VALUE)); + Assert.That(GetEnlistmentId(HENLISTMENT.NULL, out _), ResultIs.Failure); + Assert.That(GetEnlistmentRecoveryInformation(HENLISTMENT.NULL, 0, default, out _), ResultIs.Failure); + Assert.That(OpenEnlistment(EnlistmentAccess.ENLISTMENT_ALL_ACCESS, HRESMGR.NULL, Guid.NewGuid()).DangerousGetHandle(), Is.EqualTo((IntPtr)HFILE.INVALID_HANDLE_VALUE)); + Assert.That(PrepareComplete(HENLISTMENT.NULL), ResultIs.Failure); + Assert.That(PrepareEnlistment(HENLISTMENT.NULL, 0L), ResultIs.Failure); + Assert.That(PrePrepareComplete(HENLISTMENT.NULL), ResultIs.Failure); + Assert.That(PrePrepareEnlistment(HENLISTMENT.NULL, 0L), ResultIs.Failure); + Assert.That(ReadOnlyEnlistment(HENLISTMENT.NULL), ResultIs.Failure); + Assert.That(RecoverEnlistment(HENLISTMENT.NULL), ResultIs.Failure); + Assert.That(RollbackComplete(HENLISTMENT.NULL, 0L), ResultIs.Failure); + Assert.That(RollbackEnlistment(HENLISTMENT.NULL, 0L), ResultIs.Failure); + Assert.That(SetEnlistmentRecoveryInformation(HENLISTMENT.NULL, 0, default), ResultIs.Failure); + Assert.That(SinglePhaseReject(HENLISTMENT.NULL), ResultIs.Failure); + } + + [Test] + public void RollbackTransactionAsyncTest() + { + using (var hTR = CreateTransaction(null, default, 0, 0, 0, 0, txnDesc)) + { + Assert.That(hTR, ResultIs.ValidHandle); + Assert.That(RollbackTransactionAsync(hTR), ResultIs.Successful); + } + } + + [Test] + public void RollbackTransactionTest() + { + using (var hTR = CreateTransaction(null, default, 0, 0, 0, 0, txnDesc)) + { + Assert.That(hTR, ResultIs.ValidHandle); + Assert.That(RollbackTransaction(hTR), ResultIs.Successful); + } + } + } +} \ No newline at end of file diff --git a/Vanara.sln b/Vanara.sln index fe67cfd7..e7d1db3c 100644 --- a/Vanara.sln +++ b/Vanara.sln @@ -161,6 +161,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared", "UnitTests\CSharpR EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vanara.PInvoke.Wer", "PInvoke\Wer\Vanara.PInvoke.Wer.csproj", "{FA58DCE9-60A6-4321-982C-37C0DACC371D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vanara.PInvoke.KtmW32", "PInvoke\KtmW32\Vanara.PInvoke.KtmW32.csproj", "{C325C0A4-B8CF-442B-B393-C65FC9174045}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KtmW32", "UnitTests\PInvoke\KtmW32\KtmW32.csproj", "{632795F2-F552-4907-9373-4929CB9ACE09}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug (no Unit Tests)|Any CPU = Debug (no Unit Tests)|Any CPU @@ -521,6 +525,18 @@ Global {FA58DCE9-60A6-4321-982C-37C0DACC371D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FA58DCE9-60A6-4321-982C-37C0DACC371D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FA58DCE9-60A6-4321-982C-37C0DACC371D}.Release|Any CPU.Build.0 = Release|Any CPU + {C325C0A4-B8CF-442B-B393-C65FC9174045}.Debug (no Unit Tests)|Any CPU.ActiveCfg = Debug|Any CPU + {C325C0A4-B8CF-442B-B393-C65FC9174045}.Debug (no Unit Tests)|Any CPU.Build.0 = Debug|Any CPU + {C325C0A4-B8CF-442B-B393-C65FC9174045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C325C0A4-B8CF-442B-B393-C65FC9174045}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C325C0A4-B8CF-442B-B393-C65FC9174045}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C325C0A4-B8CF-442B-B393-C65FC9174045}.Release|Any CPU.Build.0 = Release|Any CPU + {632795F2-F552-4907-9373-4929CB9ACE09}.Debug (no Unit Tests)|Any CPU.ActiveCfg = Debug|Any CPU + {632795F2-F552-4907-9373-4929CB9ACE09}.Debug (no Unit Tests)|Any CPU.Build.0 = Debug|Any CPU + {632795F2-F552-4907-9373-4929CB9ACE09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {632795F2-F552-4907-9373-4929CB9ACE09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {632795F2-F552-4907-9373-4929CB9ACE09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {632795F2-F552-4907-9373-4929CB9ACE09}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -591,6 +607,8 @@ Global {3EDE955E-50DE-4E1D-97E8-31E4E6A83E7D} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} {A96CFF10-0967-429A-8700-4A86C97C5603} = {3EC6B40D-71D3-4E59-A0E0-544EC605FE11} {FA58DCE9-60A6-4321-982C-37C0DACC371D} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} + {C325C0A4-B8CF-442B-B393-C65FC9174045} = {212ABBD0-B724-4CFA-9D6D-E3891547FA90} + {632795F2-F552-4907-9373-4929CB9ACE09} = {385CAD2D-0A5E-4F80-927B-D5499D126B90} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {543FAC75-2AF1-4EF1-9609-B242B63FEED4}