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§
- Transaction
Context - An owned duplicate of a thread’s current transaction.
- Transaction
Error - A transaction aspect operation failed.
- Transaction
Guard - Holds an installed thread transaction until released.
Enums§
- Transaction
Failure - Why a transaction could not be captured or applied.
Functions§
- capture
- Capture the calling thread’s current transaction.
- install
- Install
capturedon the calling thread until the guard is released. - is_
supported - Whether this system offers the thread-transaction entry points at all.
- with_
applied - Run
operationundercaptured.