Skip to main content

Crate windows_namespace_request_sys

Crate windows_namespace_request_sys 

Source
Expand description

Owned, marshalable parameter sets for synchronous Win32 namespace calls.

Win32’s namespace and metadata surface – opening, querying, closing – is synchronous-only. A call that blocks on a dead network path blocks the thread that made it, and no overlapped form exists. This crate makes such a call capturable as a value: an owned parameter set built on one thread and executed faithfully on another.

It schedules nothing. It is the catalogue-plus-faithful-execution layer, testable with no ring, no pool, and no async anywhere near it.

§What a request is, and is not

A request carries call parameters. It does not carry the impersonation token or any other thread-scoped state the call runs under – that belongs to windows-thread-ambient-sys, which this crate does not depend on. The two are siblings rather than a stack: a request can be executed with no captured context at all, and a context is useful to work that never opens a file. Whoever owns both pairs them at the submission site.

A request also chooses no delivery model. An opened handle comes back plain and unassociated, because associating it with a completion port irreversibly forecloses IoRing use, and that choice belongs to a layer that knows the handle’s destination.

§Faithful means unaltered

An entry reports the raw Win32 outcome. ERROR_FILE_NOT_FOUND means a missing directory from an open, an empty directory from a first query, and a genuine failure from a later one; only a consumer can tell those apart, so nothing here normalises or reclassifies.

The code is also snapshotted before any cleanup can overwrite it, because GetLastError is volatile thread state that a Drop or a buffer release will happily clobber. That guarantee is a primitive rather than a rule each entry remembers: see outcome.

§A path is copied; a handle is duplicated

Several entries take a handle rather than a path, and a request owns a duplicate of any handle it names. The distinction matters and is easy to get backwards: a path is a value and is copied, while a handle is a reference to a kernel object, so duplicating it shares that object rather than cloning it.

A request is therefore self-contained with respect to lifetime – it cannot be left pointing at a handle its originator closed – and is not isolated with respect to state. Measured: a duplicated handle continues the source’s directory enumeration rather than starting its own, while closing the duplicate leaves the source usable and single-shot metadata queries disturb nothing. An independent traversal needs a fresh open, not a duplicate.

§Scope

One entry per Win32 call; a consumer needing two makes two requests and sequences them itself. The round-one entry list is audited from three real consumers rather than chosen by taste, and its omissions are deliberate and written down. Volume and disk operations are not namespace operations and are in win-volume-sys, not here. See DESIGN-NOTES.md in the crate root.

§Example

Capture the parameters on the submitting thread, where a failure is still the caller’s to see and the process current directory still means what the caller thinks it means, then use them on a worker that saw none of it:

use std::fs;
use std::os::windows::io::AsHandle;
use std::thread;

use windows_namespace_request_sys::{CapturedHandle, OpenFile};
use wtf_string::Wtf16String;

let path = std::env::temp_dir().join(format!("wnrs-doc-{}.tmp", std::process::id()));
fs::write(&path, b"example")?;

// Built here, not on the worker: a relative path is fixed to the process
// current directory now, which is shared mutable state that any thread can
// change in between. This one is absolute, so it is handed over as given.
let text = path.to_str().expect("a temporary path is valid UTF-8");
let request = OpenFile::new(Wtf16String::from(text))?;
assert_eq!(request.win32_path().to_string_lossy(), text);

// An owned duplicate, so the captured parameters cannot be left pointing
// at a handle the caller has since closed.
let file = fs::File::open(&path)?;
let captured = CapturedHandle::capture(file.as_handle())?;
drop(file);

let length = thread::spawn(move || {
    fs::File::from(captured.into_owned_handle()).metadata().map(|m| m.len())
})
.join()
.expect("the worker did not panic")?;

assert_eq!(length, b"example".len() as u64);

Re-exports§

pub use close::CloseFn;
pub use close::CloseRequest;
pub use file_info::QueryFileInformationByHandle;
pub use final_path::FinalPathError;
pub use final_path::FinalPathFlags;
pub use final_path::QueryFinalPath;
pub use full_path::FullPathError;
pub use full_path::ResolveFullPath;
pub use handle::CapturedHandle;
pub use handle::HandleCaptureError;
pub use handle::HandleCaptureFailure;
pub use open::OpenFile;
pub use open_by_id::FileIdentifier;
pub use open_by_id::OpenFileByIdentifier;
pub use outcome::Outcome;
pub use query::FileInformationClass;
pub use query::QueryFileInformation;
pub use reopen::ReOpenFile;
pub use request::ConsumingRequest;
pub use request::Request;
pub use security::AclState;
pub use security::SecurityAttributes;
pub use security::SecurityCaptureError;
pub use security::SecurityCaptureFailure;
pub use security::SecurityDescriptor;
pub use security::SecurityInformation;
pub use volume::QueryVolumeInformation;
pub use volume::VolumeInformation;
pub use watch::ChangeNotification;
pub use watch::NotifyFilter;
pub use watch::WatchDirectory;

Modules§

close
The close entries.
file_info
The GetFileInformationByHandle entry.
final_path
The GetFinalPathNameByHandleW entry.
full_path
The GetFullPathNameW entry.
handle
Owned handle references.
open
The CreateFileW entry.
open_by_id
The OpenFileById entry.
outcome
The faithful-execution contract every entry follows.
query
The GetFileInformationByHandleEx entry.
reopen
The ReOpenFile entry.
request
The seam: what every entry has in common, as a trait.
security
Owned capture of a caller’s lpSecurityAttributes.
volume
The GetVolumeInformationByHandleW entry.
watch
The FindFirstChangeNotificationW entry.

Structs§

AlignedBuf
An owned, zero-initialised buffer whose address is aligned to a boundary the caller chooses.
Win32Error
A raw Win32 error code, exactly as Windows produced it: win_error_codes::Win32Error, which carries a code of 2^31 or more through its io::Error form, where this crate’s own earlier type did not.

Enums§

PathCaptureError
Why a path could not be captured for a request.