| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- /** Windows CRT startup descriptors for a Node payload with one inherited control pipe. */
- import type { NativePtr, Win32ProcessBindings } from './ffi.ts'
- /** Native stdio handles plus the single additional descriptor selected by the launcher. */
- export interface InheritedControlStdio {
- stdin: NativePtr
- stdout: NativePtr
- stderr: NativePtr
- control: { fileDescriptor: 7; handle: NativePtr }
- }
- const HANDLE_BYTES = 8
- const INVALID_HANDLE = 0xffff_ffff_ffff_ffffn
- const FOPEN = 0x01
- const FPIPE = 0x08
- const FDEV = 0x40
- const FILE_TYPE_CHAR = 2
- const FILE_TYPE_PIPE = 3
- /**
- * Encode the CRT's descriptor table before the child runtime allocates descriptors.
- * Supported Windows targets use 64-bit handles. Empty slots remain closed, and the
- * backing Buffer must remain alive until CreateProcess returns.
- * @param api - native file-type inspection for inherited handles.
- * @param stdio - standard handles and the provider-owned fd-7 control pipe.
- * @returns descriptor count, flag bytes, and handle values for STARTUPINFO's reserved CRT fields.
- */
- export function inheritedControlStdio(api: Pick<Win32ProcessBindings, 'getFileType'>, stdio: InheritedControlStdio): Buffer {
- const count = stdio.control.fileDescriptor + 1
- const handleOffset = 4 + count
- const bytes = Buffer.alloc(handleOffset + count * HANDLE_BYTES)
- bytes.writeUInt32LE(count, 0)
- for (let index = 0; index < count; index++) {
- bytes.writeBigUInt64LE(INVALID_HANDLE, handleOffset + index * HANDLE_BYTES)
- }
- const entries = [[0, stdio.stdin], [1, stdio.stdout], [2, stdio.stderr], [stdio.control.fileDescriptor, stdio.control.handle]] as const
- for (const [fd, handle] of entries) {
- const kind = api.getFileType(handle)
- if (fd === stdio.control.fileDescriptor && kind !== FILE_TYPE_PIPE) {
- throw new Error('subprocess control descriptor is not a Windows pipe')
- }
- bytes[4 + fd] = FOPEN | (kind === FILE_TYPE_PIPE ? FPIPE : kind === FILE_TYPE_CHAR ? FDEV : 0)
- bytes.writeBigUInt64LE(handle, handleOffset + fd * HANDLE_BYTES)
- }
- return bytes
- }
|