38 Commits
Author SHA1 Message Date
mirkobrombin bde0a7b7d0 fix: keep the root of device and UNC paths in GetFullPathNameW
Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: GetFullPathNameW keeps the device and UNC root, with test cases
2026-11-03 12:41:25 +00:00
Raymond Bennett df78d476dc feat: poll sockets through the AFD device, as mio and wepoll do
mio, the I/O layer under Tokio, waits for sockets by opening \Device\Afd
with NtCreateFile and issuing IOCTL_AFD_POLL through NtDeviceIoControlFile,
with the completions delivered to an I/O completion port; wepoll and libuv
do the same. Every Tokio program that touches the network stopped there:
xh, Deno's fetch, Bun.

An AFD endpoint is now a handle that can join a completion port. A poll
reads AFD_POLL_INFO (the timeout, the sockets and the events wanted), waits
in the reactor on the sockets' host descriptors, and finishes as overlapped
I/O does: the output records with the events that occurred (receive,
expedited, send, disconnect, abort, local close, accept, connect failure),
the IO_STATUS_BLOCK, the event, and a packet carrying the APC context. The
native cancels end pending polls as cancelled. WSAIoctl answers
SIO_BASE_HANDLE and the SIO_BSP_HANDLE codes with the socket itself, since
no layered provider sits on it. The structures and codes are the ones those
open-source projects define; Microsoft does not document this interface.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the AFD endpoint, its poll and cancellation, and the base-handle codes
(cherry picked from commit 660a20304054e00ab94afef0322f9dbd0a8cbb8f)
2026-10-30 08:25:32 -07:00
mirkobrombin 7527eeba9b chore: merge pull request #68 from rayzorben/feat/reparse-points 2026-10-30 06:32:59 +00:00
mirkobrombin cdc47e145b chore: merge pull request #66 from rayzorben/fix/duplicate-close-source 2026-10-30 06:32:59 +00:00
mirkobrombin 07dd5ae09d chore: merge pull request #65 from rayzorben/fix/long-path-name 2026-10-30 06:32:59 +00:00
mirkobrombin a020ed0b4d chore: merge pull request #55 from rayzorben/feat/nt-create-file 2026-10-30 06:32:59 +00:00
mirkobrombin abf4cb9c90 chore: merge pull request #48 from rayzorben/fix/set-file-time-access 2026-10-30 06:32:58 +00:00
Raymond Bennett c7f74916cd feat: make, read and remove reparse points through DeviceIoControl
uv makes directory junctions with FSCTL_SET_REPARSE_POINT for its Python
version links, and lsd asks every file for its reparse data with
FSCTL_GET_REPARSE_POINT; both got ERROR_INVALID_FUNCTION.

Reparse points are the host's symbolic links: FSCTL_SET_REPARSE_POINT makes
an empty directory a mount point, or an empty file or directory a symbolic
link, to the target its REPARSE_DATA_BUFFER names; FSCTL_GET_REPARSE_POINT
describes a link (as a mount point when it holds an absolute path to a
directory); FSCTL_DELETE_REPARSE_POINT leaves an empty directory or file.
A file that is no reparse point answers ERROR_NOT_A_REPARSE_POINT. A test
makes a junction, reads a file through it, reads it back and removes it.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the control codes and the test
2026-10-29 00:11:51 -07:00
Raymond Bennett e92c7be65e fix: close the source handle with DUPLICATE_CLOSE_SOURCE whatever else happens
Windows closes the source handle of DuplicateHandle with
DUPLICATE_CLOSE_SOURCE regardless of the outcome. Go starts every child
process that way: it closes the inheritable copies it made with
DuplicateHandle(GetCurrentProcess(), handle, NULL, NULL, 0, FALSE,
DUPLICATE_CLOSE_SOURCE), with no target process at all. Raven refused the
call and kept the handles, so the write ends of the child's output pipes
stayed open in the parent, its readers never saw the end of the output, and
the parent waited forever: go build hung after its first compile, curlie
after curl.

A handle of the calling process is now closed on every return, success or
failure.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the change
(cherry picked from commit 017a3d84a400223f845101adf7864163e80e9981)
2026-10-28 23:44:22 -07:00
Raymond Bennett 59568a9a98 fix: keep the caller's path in GetLongPathNameW, with each component in long form
GetLongPathNameW answered the fully normalised DOS path of the file. Windows
keeps the path as given (relative or absolute, its separators as written)
and replaces each component with its long name. nginx compares the answer
with the path it opened, prefix\conf/nginx.conf by default, and refused its
own configuration file when they differed.

The folders keep no 8.3 names, so each component's long form is the name of
its directory entry, which may differ from the caller's in case.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the change
(cherry picked from commit b1e588fe2e0fbc89f2e5918b1750068b315e335f)
2026-10-28 23:44:22 -07:00
Raymond Bennett 47a47ad7ab feat: list a directory through GetFileInformationByHandleEx
Go's os.ReadDir reads directories with GetFileInformationByHandleEx and
FileIdBothDirectoryInfo or FileFullDirectoryInfo, which failed with
ERROR_INVALID_PARAMETER: Hugo, OpenTofu, rclone, restic, gdu and the go
command itself could not read a directory.

The directory classes (FileIdBothDirectoryInfo, FileFullDirectoryInfo,
FileIdExtdDirectoryInfo and their restarting forms) now read entries as
NtQueryDirectoryFile does, which gains the native classes that carry the
file's identifier (FileIdBothDirectoryInformation,
FileIdFullDirectoryInformation, FileIdExtdDirectoryInformation).
RtlNtStatusToDosError learns the statuses directory reads end with, such as
STATUS_NO_MORE_FILES.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the directory classes and the status translations
2026-10-28 23:30:05 -07:00
Raymond Bennett 023fe78345 feat: open files and directories with NtCreateFile and NtOpenFile
Rust's standard library, uv, Zig and the event loops built on mio call
NtCreateFile and NtOpenFile directly, which Raven did not answer.

The object name becomes a Win32 path (\??\ and \DosDevices\ names, UNC
names, and names relative to an open directory), and the disposition and
create options become CreateFileW's: FILE_DIRECTORY_FILE and
FILE_NON_DIRECTORY_FILE check what was opened, a directory is created first
for FILE_CREATE or FILE_OPEN_IF, synchronous options decide whether the
handle is overlapped, and the write-through, sequential, random-access,
no-buffering, delete-on-close and reparse-point options become the matching
flags. The IO_STATUS_BLOCK reports FILE_OPENED, FILE_CREATED,
FILE_OVERWRITTEN or FILE_SUPERSEDED, and errors come back as the NTSTATUS
values the Win32 errors stand for.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the handlers, from the NtCreateFile and NtOpenFile documentation
(cherry picked from commit 1482289fad28953e3df44449973cd9ea168f7d5e)
2026-10-28 23:17:41 -07:00
Raymond Bennett f135e5790f fix: let SetFileTime use a handle opened for FILE_WRITE_ATTRIBUTES
SetFileTime required a handle opened for writing. Windows asks for
FILE_WRITE_ATTRIBUTES, which Go's os.Chtimes opens with, on directories
too; restic could not open its cache.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: the access check
(cherry picked from commit 85edfabfd7522823d6612700a9ca3f90bafc2c9b)
2026-10-28 23:14:32 -07:00
mirkobrombin 3ec88b9e6b fix: start the console on the OEM code page and show WriteFile text in it 2026-10-28 16:23:32 +00:00
Ray Bennett 4699a741c1 feat: give console programs the terminal as their console (#31)
* feat: give console programs the terminal as their console

A standard handle that is a terminal, and CONIN$, CONOUT$ and CON, now act as a console: modes map to terminal settings,
reads and writes convert between UTF-16 and the terminal's UTF-8, terminal input becomes key events, and Ctrl+C runs the
control handlers. Files and pipes still fail the console functions, as on Windows.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: Wrote the console functions over the terminal, their pty test and the guest test program from the public console API documentation.

* test: let the console client run by hand, saying which step failed

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: Made the exact size and cursor checks optional and gave each step an instruction and a failure number.

* feat: follow the console cursor through the output instead of asking the terminal

Programs that redraw their command line read and move the cursor on every key; asking the terminal each time was slow, and
wrong on terminals that never answer. The terminal is now asked only when the position may be stale.

Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: Wrote the cursor tracker, WriteConsoleOutputCharacter, ScrollConsoleScreenBuffer, the resize events and their tests.
2026-10-28 17:11:25 +01:00
mirkobrombin 6eba6ce686 feat: accept short names on file systems that keep none 2026-10-27 19:42:09 +00:00
mirkobrombin 5d7fd5b471 feat: add CreateFile2, host symbolic links and inheritable file handles 2026-10-27 13:42:09 +00:00
mirkobrombin d4adc44e8d feat: give an SSH client's dialogs double clicks, split buttons and drop-down lists 2026-10-27 01:17:41 +00:00
mirkobrombin 44a593867c feat: run an SSH client's terminal and file transfer windows 2026-10-26 23:13:38 +00:00
mirkobrombin 3bfea32812 feat: fold strings and describe the volume of an open file 2026-10-26 14:17:44 +00:00
mirkobrombin 0a0fe4be89 feat: add shared Windows process state and parallel guest execution 2026-10-24 16:24:23 +00:00
Mirko Brombin 98503c2c88 feat: serve what framework setups run: unquoted program paths, read-only folders, service settings, counter names and bounded formatting 2026-10-03 10:22:11 +00:00
Mirko Brombin f4509d0c1f feat: implement the Windows APIs that .NET programs and their installers call 2026-09-23 00:12:56 +00:00
Mirko Brombin 1074a7e5be feat: add snapshot the prefix before installations, restore it with one command, and carry out what installers leave for a restart 2026-09-21 19:09:11 +00:00
Mirko Brombin f1171c6e0c feat: report the drive that shows the host's files as a remote one 2026-09-21 14:17:07 +00:00
Mirko Brombin 192cb89e53 feat: answer DecryptFile for files that are never encrypted and keep the inherit and close-source flags of 32-bit handle copies 2026-09-21 07:18:00 +00:00
Mirko Brombin 8cdec79f0e feat: answer NtReadFile, NtWriteFile, FSCTL_PIPE_LISTEN and NtCancelIoFile on pipes with the caller's event and IO_STATUS_BLOCK 2026-09-21 06:06:44 +00:00
Mirko Brombin 45a72d4974 feat: add lock ranges of files opened only for reading through a writable description, as Windows allows exclusive locks there 2026-09-21 06:00:50 +02:00
Mirko Brombin eda064950b feat: add place 32-bit allocations in free low gaps and serve completion-routine file I/O, PathCch calls and dependencies beside a library loaded by path 2026-09-20 07:03:09 +00:00
Mirko Brombin ead54d6b10 feat: run Google Chrome with NT object queries, COM apartments, file completion ports and SDDL descriptors 2026-09-03 21:44:05 +02:00
Mirko Brombin 26fbeabc78 feat: run Steam's web UI with cross-process handles, per-thread message queues, socket events and process identity 2026-09-03 16:48:12 +02:00
Mirko Brombin 66087052d8 feat: run Chromium's helper processes with DirectWrite, named pipes, jobs, inherited handles and shared sections 2026-09-03 06:06:54 +02:00
Mirko Brombin a7256dafac feat: run the Steam installer to Finish with child processes, shell links and sockets 2026-09-03 01:15:07 +02:00
Mirko Brombin f5cd92f4c8 feat: give 32-bit programs the registry, shell folder, INI write, token and file services an installer needs 2026-09-02 23:23:20 +02:00
Mirko Brombin 9aa1a31984 feat: honour append-only file access and measure input latency 2026-08-01 23:08:29 +02:00
Mirko Brombin 7cbba82228 feat: resolve C runtime contracts for dependency DLLs and grow the C runtime for DXVK 2026-08-01 09:39:19 +02:00
Mirko Brombin aa5cbc8f90 feat: add standard input reads, byte range locks, file size query and offset transfers for synchronous handles 2026-08-01 03:28:17 +02:00
Mirko Brombin efc6104b5b feat: add kernel32 services, guest threads and structured exceptions for PE64 processes 2026-07-31 21:45:18 +02:00