Library

system/windows

The Win32 calls the standard library needs.

1 file lib/system/windows/windows.vader 88 exports

Not the CRT: _write would be the shorter road, but it is an emulation layer over these, and going through it means inheriting its buffering and its descriptor table for no gain.

Types

Handle :: CPointer

A Win32 HANDLE: an opaque kernel object, never dereferenced.

Coord :: struct

COORD: a console cell position or size.

Field names are the C ones because a mirror copies BY NAME; the snake_case rule does not reach across the boundary.

Fields

X: i16
No description.
Y: i16
No description.
SmallRect :: struct

SMALL_RECT: an inclusive rectangle of console cells.

Fields

Left: i16
No description.
Top: i16
No description.
Right: i16
No description.
Bottom: i16
No description.
ScreenBufferInfo :: struct

CONSOLE_SCREEN_BUFFER_INFO. Mirrored WHOLE rather than as a prefix: every member but wAttributes is itself a struct, so a prefix would have to stop before the one that matters.

Fields

dwSize: Coord
No description.
dwCursorPosition: Coord
No description.
wAttributes: u16
No description.
srWindow: SmallRect
No description.
dwMaximumWindowSize: Coord
No description.
SecurityAttributes :: struct

SECURITY_ATTRIBUTES, mirrored for the two members a pipe needs.

EVERY member, in order, not a prefix of the useful ones. The interpreter lays a mirror out from its DECLARED fields alone, at natural alignment from zero, so skipping lpSecurityDescriptor put bInheritHandle at 4 where C has it at 16: the callee read a zero, made the pipe non-inheritable, and reported success. Native was unaffected (the shim copies by name) which is exactly what kept it invisible. The offset _Static_assert catches it now.

lpSecurityDescriptor is a u64 because it is RESERVED, never read: it only has to occupy its eight bytes and stay zero, which is the NULL the call wants.

Fields

nLength: u32
No description.
lpSecurityDescriptor: u64
No description.
bInheritHandle: i32
No description.
StartupInfo :: struct

STARTUPINFOA, mirrored for the members a redirected child needs.

EVERY member up to hStdError, for the reason spelled out on SecurityAttributes: eleven precede dwFlags in the real struct, and naming only the useful ones put every one of them at the wrong offset in the interpreter's block.

The reserved ones are machine words that stay zero, which is what CreateProcess expects of a plain console child. cb must be sizeof(STARTUPINFOA) (104 on x86_64) and is the one member the callee validates.

Fields

cb: u32
No description.
lpReserved: u64
No description.
lpDesktop: u64
No description.
lpTitle: u64
No description.
dwX: u32
No description.
dwY: u32
No description.
dwXSize: u32
No description.
dwYSize: u32
No description.
dwXCountChars: u32
No description.
dwYCountChars: u32
No description.
dwFillAttribute: u32
No description.
dwFlags: u32
No description.
wShowWindow: u16
No description.
cbReserved2: u16
No description.
lpReserved2: u64
No description.
hStdInput: Handle
No description.
hStdOutput: Handle
No description.
hStdError: Handle
No description.
ProcessInformation :: struct

PROCESS_INFORMATION: what CreateProcess hands back.

Fields

hProcess: Handle
No description.
hThread: Handle
No description.
dwProcessId: u32
No description.
dwThreadId: u32
No description.

Functions

get_std_handle :: fn(which: u32) -> Handle

GetStdHandle. Returns INVALID_HANDLE_VALUE on failure.

Parameters

whichu32 one of the STD_*_HANDLE selectors.

Returns

Handle the standard device's handle.
get_active_processor_count :: fn(group: u16) -> u32

GetActiveProcessorCount. Logical processors active in group; 0 on failure.

Parameters

groupu16 a processor group, or ALL_PROCESSOR_GROUPS.

Returns

u32
get_module_file_name :: fn(module: CPointer | null, @c_out buf: u16[], size: u32) -> u32

GetModuleFileNameW. Writes the running module's path into buf and returns its length; 0 on failure, or size exactly when it was truncated.

Parameters

moduleCPointer | null null for the running executable.
bufu16[] No description.
sizeu32 No description.

Returns

u32
get_current_directory :: fn(size: u32, @c_out buf: u16[]) -> u32

GetCurrentDirectoryW. Writes the working directory into buf and returns its length; 0 on failure, or a length >= size when buf is too small.

Parameters

sizeu32 buf's capacity in UTF-16 UNITS, not bytes.
bufu16[] receives the path, NUL-terminated.

Returns

u32
set_current_directory :: fn(path: u16[]) -> i32

SetCurrentDirectoryW. Zero on failure.

Parameters

pathu16[] the new working directory, NUL-terminated UTF-16.

Returns

i32 non-zero on success.
get_temp_path :: fn(size: u32, @c_out buf: u16[]) -> u32

GetTempPathW. Writes the temp directory, trailing backslash included, into buf. Returns its length, 0 on failure, or a length >= size when buf is too small: in both of which cases nothing usable was written.

Parameters

sizeu32 buf's capacity in UTF-16 UNITS, not bytes.
bufu16[] receives the path, NUL-terminated.

Returns

u32 UTF-16 units written, excluding the NUL.
create_directory :: fn(path: u16[], security: CPointer | null) -> bool

CreateDirectoryW. False on failure, ERROR_ALREADY_EXISTS included: the caller re-tests the path rather than reading GetLastError.

Parameters

pathu16[] directory to create.
securityCPointer | null lpSecurityAttributes; null for the default descriptor.

Returns

bool
get_file_attributes_ex :: fn(path: u16[], level: i32, @c_out data: u32[]) -> bool

GetFileAttributesExW. False when the path cannot be queried.

data crosses as the nine DWORDs of a WIN32_FILE_ATTRIBUTE_DATA, which has no padding : ftLastWriteTime is cells 5 (low half) and 6 (high half).

Parameters

pathu16[] the path to query.
leveli32 always GET_FILE_EX_INFO_STANDARD.
datau32[] receives the attribute data ; nine cells at least.

Returns

bool whether the query succeeded.
get_file_attributes :: fn(path: u16[]) -> u32

GetFileAttributesW. INVALID_FILE_ATTRIBUTES when the path cannot be queried, which is how existence is tested, there being no access here.

Parameters

pathu16[] the path to query.

Returns

u32 the attribute bitmask, or INVALID_FILE_ATTRIBUTES.
delete_file :: fn(path: u16[]) -> i32

DeleteFileW. Zero on failure. Refuses a directory outright, which is the behaviour std/io::remove_file promises.

Parameters

pathu16[] the file to delete.

Returns

i32 non-zero on success.
get_last_error :: fn() -> u32

GetLastError. The calling thread's last Win32 error code.

⚠️ Read it IMMEDIATELY after the call that failed: any Win32 call in between may overwrite it.

Returns

u32 the raw Win32 code ; 0 when nothing has failed.
write_file :: fn(h: Handle, buf: u8[], count: u32, @c_out written: u32[], overlapped: CPointer | null) -> bool

WriteFile. False on failure: the caller reads GetLastError.

written is Win32's lpNumberOfBytesWritten, which a synchronous call may NOT pass as null.

written is a one-element array so the count READS BACK, the same shape read_file uses. A @c_pointer scalar would not: the callee writes through it and the value is discarded.

Parameters

hHandle the device handle.
bufu8[] the bytes to write.
countu32 how many of them.
writtenu32[] scratch the callee fills with the byte count; unread.
overlappedCPointer | null always null here: this is the synchronous form.

Returns

bool whether the write succeeded.
multi_byte_to_wide_char :: fn(code_page: u32, flags: u32, src: string, src_len: i32, @c_out dst: u16[], dst_len: i32) -> i32

MultiByteToWideChar. With src_len of -1 the input is read up to its NUL and the terminator is written too, so the result is usable as LPCWSTR.

Parameters

code_pageu32 No description.
flagsu32 No description.
srcstring No description.
src_leni32 No description.
dstu16[] receives the UTF-16 units; may be empty when dst_len is 0.
dst_leni32 dst's capacity in UTF-16 units, or 0 to measure.

Returns

i32 units written (or required, when measuring); 0 on failure.
wide_char_to_multi_byte :: fn(code_page: u32, flags: u32, src: u16[], src_len: i32, @c_out dst: u8[], dst_len: i32, default_char: CPointer | null, used_default: CPointer | null) -> i32

WideCharToMultiByte. The two trailing lpDefaultChar / lpUsedDefaultChar arguments must be null for CP_UTF8; Windows fails the call otherwise.

Parameters

code_pageu32 No description.
flagsu32 No description.
srcu16[] No description.
src_leni32 units to read, or -1 for a NUL-terminated input.
dstu8[] No description.
dst_leni32 dst's capacity in bytes, or 0 to measure.
default_charCPointer | null No description.
used_defaultCPointer | null No description.

Returns

i32 bytes written (or required, when measuring); 0 on failure.
create_file_w :: fn(path: u16[], access: u32, share: u32, security: CPointer | null, disposition: u32, flags: u32, template: CPointer | null) -> Handle

CreateFileW. Returns INVALID_HANDLE_VALUE on failure: test it with i64(h) == INVALID_HANDLE, never against null.

Unlike fopen there is no text mode, so nothing ever rewrites a \n.

Parameters

pathu16[] UTF-16, NUL-terminated. Prefix \\?\\ to pass MAX_PATH.
accessu32 No description.
shareu32 No description.
securityCPointer | null lpSecurityAttributes; null for the default descriptor.
dispositionu32 No description.
flagsu32 No description.
templateCPointer | null hTemplateFile; always null here.

Returns

find_first_file :: fn(pattern: u16[], @c_out data: u8[]) -> Handle

FindFirstFileW. The pattern is a directory path with \* appended.

Returns INVALID_HANDLE_VALUE on failure: test it with i64(h) == INVALID_HANDLE, never against null.

Parameters

patternu16[] a NUL-terminated UTF-16 glob, from to_wide.
datau8[] FIND_DATA_BYTES of scratch the callee fills.

Returns

Handle a search handle.
find_next_file :: fn(handle: Handle, @c_out data: u8[]) -> bool

FindNextFileW. False once the search is exhausted.

Parameters

handleHandle the search handle find_first_file returned.
datau8[] the same buffer, refilled.

Returns

bool
find_close :: fn(handle: Handle) -> bool

FindClose. Pairs with find_first_file.

Parameters

handleHandle the search handle.

Returns

bool
find_data_name :: fn(data: u8[]) -> string

The cFileName of a filled WIN32_FIND_DATAW, as a Vader string.

The Windows twin of system/posix::dirent_name, and it exists for the same reason: reading a NAMED member of a C struct is the one step a Vader FFI call cannot take for itself. It has to be a CALL, not a read of the struct: the interpreter has no C layout but resolves an @extern by name out of the running process. It carries the UTF-16 to UTF-8 conversion with it.

The bytes are valid until the next call, which is also cFileName's own contract: find_next_file overwrites it. The shim interns before either.

Parameters

datau8[] the buffer find_first_file filled.

Returns

string the entry name.
get_console_screen_buffer_info :: fn(h: Handle, @c_pointer @c_out info: ScreenBufferInfo) -> bool

GetConsoleScreenBufferInfo. False when the handle is not a console.

srWindow is the VISIBLE window, which is what a width should be measured from: the buffer (dwSize) is often far wider, and wrapping follows what is on screen.

Parameters

hHandle No description.
infoScreenBufferInfo No description.

Returns

bool
peek_named_pipe :: fn(h: Handle, buf: CPointer | null, size: u32, read: CPointer | null, @c_out available: u32[], message: CPointer | null) -> bool

PeekNamedPipe. Reports how many bytes are readable WITHOUT consuming them.

It works on an anonymous pipe too, despite the name, which is what makes it the console-less way to ask "is there input". False when the handle is not a pipe (a console, a redirected file) or the peer closed it; a caller reads that as "go ahead and read", never as "idle".

Parameters

hHandle No description.
bufCPointer | null always null here: we ask for the COUNT, not the bytes.
sizeu32 No description.
readCPointer | null always null, for the same reason.
availableu32[] receives the byte count; a one-element array so it reads back.
messageCPointer | null always null: only a message-mode pipe uses it.

Returns

bool
sleep_ms :: fn(ms: u32) -> void

Sleep. Milliseconds, and it is the only wait Win32 offers without a handle.

Parameters

msu32 No description.
create_pipe :: fn(@c_out read_end: u64[], @c_out write_end: u64[], @c_pointer attrs: SecurityAttributes, size: u32) -> bool

CreatePipe.

The two ends are separate HANDLE* out-parameters, not one struct, so each is its own one-word buffer. Read the handle back with ptr_at.

Parameters

read_endu64[] a one-word buffer receiving the read end.
write_endu64[] a one-word buffer receiving the write end.
attrsSecurityAttributes a SecurityAttributes with bInheritHandle set.
sizeu32 suggested buffer size; 0 for the default.

Returns

bool
ptr_at :: fn(base: u64[], i: i64) -> Handle

The i-th pointer-sized word of a lent buffer, as a handle.

CPointer cannot be built from an integer (T3010) and a lent array yields integers, so a HANDLE an out-parameter wrote is otherwise unreachable.

Parameters

baseu64[] the buffer the callee filled.
ii64 the word index.

Returns

set_handle_information :: fn(h: Handle, mask: u32, flags: u32) -> bool

SetHandleInformation. Used to CLEAR the inherit flag on a pipe's read end.

The pipe is created inheritable so the child receives its write end; without this the child (and every sibling launched after it) also receives the READ ends, which are the parent's alone.

Parameters

hHandle the handle to adjust.
masku32 which flags to touch, HANDLE_FLAG_INHERIT here.
flagsu32 their new value; 0 to clear.

Returns

bool
create_process :: fn(application: CPointer | null, @c_out command_line: u8[], proc_attrs: CPointer | null, thread_attrs: CPointer | null, inherit: bool, flags: u32, environment: CPointer | null, directory: CPointer | null, @c_pointer startup: StartupInfo, @c_pointer @c_out info: ProcessInformation) -> bool

CreateProcessA. Launches command_line, inheriting the handles named in startup.

The ANSI form: the argument vector is one command line by then, and the wide form would need it widened for nothing the child can see.

Parameters

applicationCPointer | null null: the program is the first word of the line.
command_lineu8[] the whole command line, which the callee MODIFIES.
proc_attrsCPointer | null null.
thread_attrsCPointer | null null.
inheritbool true, so the child receives the pipe ends.
flagsu32 0.
environmentCPointer | null null: inherit the parent's.
directoryCPointer | null null: inherit the parent's.
startupStartupInfo the redirected handles.
infoProcessInformation filled with the child's handles and ids.

Returns

bool
wait_for_single_object :: fn(h: Handle, timeout_ms: u32) -> u32

WaitForSingleObject. WAIT_OBJECT_0 once the process has exited.

Parameters

hHandle the process handle.
timeout_msu32 0 to poll without waiting, INFINITE to wait for the exit.

Returns

u32
get_exit_code_process :: fn(h: Handle, @c_out code: u32[]) -> bool

GetExitCodeProcess.

Parameters

hHandle the process handle.
codeu32[] a one-element array receiving the status.

Returns

bool
terminate_process :: fn(h: Handle, code: u32) -> bool

TerminateProcess.

Parameters

hHandle the process handle.
codeu32 the exit status to report for the killed child.

Returns

bool
get_console_mode :: fn(h: Handle, @c_out mode: u32[]) -> bool

GetConsoleMode. False when the handle is not a console, which is also how a caller tests for one, a redirected stream having no mode to read.

Parameters

hHandle No description.
modeu32[] receives the current mode; a one-element array so it reads back.

Returns

bool
set_console_mode :: fn(h: Handle, mode: u32) -> bool

SetConsoleMode. False on failure: an old console refusing a mode bit it does not know, which is what tells a caller ANSI is unavailable.

Parameters

hHandle No description.
modeu32 No description.

Returns

bool
write_console_w :: fn(h: Handle, text: u16[], count: u32, @c_out written: u32[], reserved: CPointer | null) -> bool

WriteConsoleW: UTF-16 text to a console, which renders it whatever its code page. False on failure, and on a handle that is not a console.

Parameters

hHandle a console output handle.
textu16[] the UTF-16 units to write.
countu32 how many of them.
writtenu32[] scratch the callee fills with the units written; unread.
reservedCPointer | null always null.

Returns

bool whether the write succeeded.
read_console_w :: fn(h: Handle, @c_out text: u16[], count: u32, @c_out read: u32[], control: CPointer | null) -> bool

ReadConsoleW: what was typed at a console, as UTF-16 whatever its code page. False on failure, and on a handle that is not a console.

Parameters

hHandle a console input handle.
textu16[] receives the UTF-16 units.
countu32 text's capacity in units.
readu32[] receives how many units were read.
controlCPointer | null always null: no early wake-up on a control character.

Returns

bool whether the read succeeded.
flush_console_input_buffer :: fn(h: Handle) -> bool

FlushConsoleInputBuffer: drop what was typed at the console h and not read yet. False on failure.

Parameters

hHandle No description.

Returns

bool
read_file :: fn(h: Handle, @c_out buf: u8[], count: u32, @c_out read: u32[], overlapped: CPointer | null) -> bool

ReadFile. False on failure; a synchronous read returning true with read short of count has reached end of file.

Parameters

hHandle No description.
bufu8[] No description.
countu32 No description.
readu32[] receives the byte count; a one-element array so it reads back: Win32 forbids null here on a synchronous call.
overlappedCPointer | null always null: this is the synchronous form.

Returns

bool
get_file_type :: fn(h: Handle) -> u32

GetFileType. FILE_TYPE_DISK for a file on disk, whose size says how much a read will find; another value for a pipe, a console or a device.

Parameters

hHandle No description.

Returns

u32
get_file_size_ex :: fn(h: Handle, @c_out size: i64[]) -> bool

GetFileSizeEx. False on failure.

Parameters

hHandle No description.
sizei64[] receives the size in bytes; a one-element array so it reads back.

Returns

bool
get_final_path_name_by_handle_w :: fn(h: Handle, @c_out buf: u16[], size: u32, flags: u32) -> u32

GetFinalPathNameByHandleW. Writes the path of the file h names, links followed and NUL-terminated, into buf.

Parameters

hHandle No description.
bufu16[] No description.
sizeu32 buf's capacity in UTF-16 UNITS, not bytes.
flagsu32 VOLUME_NAME_DOS for a path that starts with a drive letter, behind the \\?\ prefix.

Returns

u32 UTF-16 units written, excluding the NUL; 0 on failure, more than size (the capacity needed) when buf is too small.
close_handle :: fn(h: Handle) -> bool

CloseHandle. False on failure, which a caller that is done with the file has nothing to do about.

Parameters

hHandle No description.

Returns

bool
get_system_time_precise_as_file_time :: fn(@c_out ft: i64[]) -> void

GetSystemTimePreciseAsFileTime. Fills ft with 100-ns ticks since 1601.

Parameters

fti64[] No description.
query_performance_counter :: fn(@c_out counter: i64[]) -> bool

QueryPerformanceCounter. Fills counter; false on failure.

Parameters

counteri64[] No description.

Returns

bool
query_performance_frequency :: fn(@c_out freq: i64[]) -> bool

QueryPerformanceFrequency. Fills freq with counts per second; false on failure.

Parameters

freqi64[] No description.

Returns

bool

Constants

STD_OUTPUT_HANDLE: u32: 0xFFFF_FFF5

nStdHandle selectors. DWORD is unsigned, so the negative constants are written in their two's-complement form.

STD_ERROR_HANDLE: u32: 0xFFFF_FFF4

See STD_OUTPUT_HANDLE.

STD_INPUT_HANDLE: u32: 0xFFFF_FFF6

See STD_OUTPUT_HANDLE.

ALL_PROCESSOR_GROUPS: u16: 0xFFFF

ALL_PROCESSOR_GROUPS: asks GetActiveProcessorCount for every group, not just the caller's (a group holds at most 64 processors).

FILE_ATTRIBUTE_DIRECTORY: u32: 0x10

FILE_ATTRIBUTE_DIRECTORY: set when the entry is a directory.

INVALID_FILE_ATTRIBUTES: u32: 0xFFFF_FFFF

What GetFileAttributesW returns for a path it cannot query.

GET_FILE_EX_INFO_STANDARD: i32: 0

GetFileExInfoStandard, the GET_FILEEX_INFO_LEVELS that fills a WIN32_FILE_ATTRIBUTE_DATA.

ERROR_FILE_NOT_FOUND: u32: 2

Win32 error codes std/io classifies. Unlike errno these are stable across Windows versions, so they are plain literals.

ERROR_PATH_NOT_FOUND: u32: 3
ERROR_ACCESS_DENIED: u32: 5
ERROR_INVALID_HANDLE: u32: 6
ERROR_FILE_EXISTS: u32: 80
ERROR_BROKEN_PIPE: u32: 109
ERROR_DISK_FULL: u32: 112
ERROR_DIR_NOT_EMPTY: u32: 145
ERROR_ALREADY_EXISTS: u32: 183
CP_UTF8: u32: 65001

CP_UTF8: the code page identifier for UTF-8.

INVALID_HANDLE: i64: -1

INVALID_HANDLE_VALUE, as the integer i64(handle) yields. Win32 reports a failed CreateFileW with this and NOT with NULL, which is why the handle is tested through i64 rather than a CPointer | null.

GENERIC_READ: u32: 0x8000_0000

dwDesiredAccess bits.

GENERIC_WRITE: u32: 0x4000_0000

See GENERIC_READ.

FILE_SHARE_READ: u32: 0x1

dwShareMode: let other readers in while we hold the file.

FILE_SHARE_WRITE: u32: 0x2

See FILE_SHARE_READ.

FILE_SHARE_DELETE: u32: 0x4

See FILE_SHARE_READ: let a rename or a delete in too.

CREATE_ALWAYS: u32: 2

dwCreationDisposition: truncate an existing file, create it otherwise.

OPEN_EXISTING: u32: 3

See CREATE_ALWAYS: open only what already exists.

FILE_ATTRIBUTE_NORMAL: u32: 0x80

dwFlagsAndAttributes: no special semantics.

FILE_FLAG_BACKUP_SEMANTICS: u32: 0x0200_0000

dwFlagsAndAttributes: open a directory as well as a file.

FIND_DATA_BYTES: i64: 1024

Bytes to reserve for a WIN32_FIND_DATAW.

An OPAQUE buffer: Vader never looks inside it, FindFirstFileW fills it and find_data_name reads the one member a listing needs. Nothing checks this number (the callee writes sizeof(WIN32_FIND_DATAW) bytes whatever it says) so it is taken HIGH on purpose. The real size is 592 on x86_64 (measured against the mingw headers, and it is 320 for the ANSI twin); over-reserving wastes a few hundred bytes on the stack, under-reserving corrupts.

⚠️ Do NOT narrow this to what one toolchain reports.

STARTF_USESTDHANDLES: u32: 0x0100

STARTF_USESTDHANDLES: hStdInput / hStdOutput / hStdError are used.

WAIT_OBJECT_0: u32: 0

WAIT_OBJECT_0: the object is signalled, i.e. the process has exited.

INFINITE: u32: 0xFFFF_FFFF

INFINITE: a wait with no timeout.

HANDLE_FLAG_INHERIT: u32: 1

HANDLE_FLAG_INHERIT.

ENABLE_PROCESSED_INPUT: u32: 0x0001

Console INPUT mode bits raw mode turns off (line buffering, echo, and the translation of Ctrl-C into a signal) plus the one it turns on, so escape sequences arrive as bytes.

ENABLE_LINE_INPUT: u32: 0x0002
ENABLE_ECHO_INPUT: u32: 0x0004
ENABLE_VIRTUAL_TERMINAL_INPUT: u32: 0x0200
ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32: 0x0004

Bit enabling ANSI escape interpretation on a console output handle. Only with it set do escapes render rather than print literally.

FILE_TYPE_DISK: u32: 0x0001

What get_file_type answers for a file on disk.

VOLUME_NAME_DOS: u32: 0x0

See get_final_path_name_by_handle_w: a volume named by its drive letter.

Written by vader doc. Icons: Codicons, CC BY 4.0. Fonts: Atkinson Hyperlegible, JetBrains Mono, OFL.