Skip to main content

Module transaction

Module transaction 

Source
Expand description

The TxF transaction aspect.

A thread may carry a current transaction, and CreateFileW and its relatives silently join it. Remoting such a call to a worker that carries no transaction would therefore perform it outside the caller’s transaction – quietly, and with no error to notice.

§The documented entry points do not exist as exports

ktmw32.h documents GetCurrentTransaction and SetCurrentTransaction, and MSDN names Ktmw32.dll as their library. Neither is exported from it – verified against the export table of the shipping DLL, which offers CreateTransaction, CommitTransaction, RollbackTransaction and their neighbours but nothing named CurrentTransaction. The header declares them as FORCEINLINE wrappers, so a C caller links nothing; what actually carries the operation is RtlGetCurrentTransaction / RtlSetCurrentTransaction in ntdll.dll, and that is what this module binds.

Two consequences worth stating plainly rather than discovering later. The aspect depends on an Rtl-prefixed ntdll export rather than a documented Win32 one – unavoidable, since no documented export exists, but it is a weaker footing than the rest of this crate and the reason binding is lazy and failure is a typed Unsupported rather than a link error. And RtlSetCurrentTransaction returns BOOLEAN, a single byte, not the four-byte BOOL its documented wrapper returns; reading it as BOOL would test three bytes of whatever happened to be in the register.

Binding is lazy so that a consumer which never captures a transaction pays nothing and, on a system where the symbols are absent, gets a typed failure instead of a process that will not start. The module handle is deliberately never freed: it is a process-lifetime binding resolved at most once, and unloading it while another thread is inside a call would be a use-after-free for no benefit.

§The hazard this aspect cannot remove

A transaction handle is a reference to a shared kernel object, so capturing one does not give the worker a private transaction: the caller may commit or roll it back while the worker is still inside it. Owning a duplicate fixes only the lifetime problem – the request cannot be left holding a closed handle – and not the state problem. Sequencing that is the consumer’s responsibility and cannot be enforced here.

TxF is also deprecated by Microsoft. That is a reason to keep this aspect optional and out of any minimal capture set, not a reason to omit it: a caller using transacted NTFS today still needs its work remoted correctly.

§Example

use windows_thread_ambient_sys::Captured;
use windows_thread_ambient_sys::transaction;

// An ordinary thread carries no transaction. That is an *answer*, not a
// failure, so it is `Absent` rather than an error.
let captured = transaction::capture()?;
assert!(matches!(captured, Captured::Absent));

// Applying `Absent` installs "no transaction" rather than leaving the
// running thread's own alone -- the caller asked, and the answer was none,
// so a worker that happened to carry one must not enlist this work in it.
let value = transaction::with_applied(&captured, || 42)?;
assert_eq!(value, 42);

Structs§

TransactionContext
An owned duplicate of a thread’s current transaction.
TransactionError
A transaction aspect operation failed.
TransactionGuard
Holds an installed thread transaction until released.

Enums§

TransactionFailure
Why a transaction could not be captured or applied.

Functions§

capture
Capture the calling thread’s current transaction.
install
Install captured on the calling thread until the guard is released.
is_supported
Whether this system offers the thread-transaction entry points at all.
with_applied
Run operation under captured.