diff --git a/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.i18n.yaml b/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.i18n.yaml index 1eda0cef7b..02bb27c70f 100644 --- a/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.i18n.yaml +++ b/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.md -2026-08-19-shared-win32-process-primitives.md: 58bbd5a2ae44caf85dfca144d99efabb063243e2 -2026-08-19-shared-win32-process-primitives.zh.md: 5c4e63979412fbb617094ad1745f4a8318b49237 +2026-08-19-shared-win32-process-primitives.md: 8e5878ff23a49d9f0fbc4e62b9e3e6bccf5fe4ed +2026-08-19-shared-win32-process-primitives.zh.md: 90ca5b21227136febafa946d20acbe59630436fd diff --git a/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.md b/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.md index 58bbd5a2ae..8e5878ff23 100644 --- a/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.md +++ b/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.md @@ -14,13 +14,13 @@ The Windows ACL sandbox owns restricted-token, SID, DACL, grant, and workspace p The Windows ACL sandbox remains the only owner of restricted-token creation, SID and DACL policy, grants, writable-path decisions, temporary-directory policy, and the public sandbox child result. It extends the shared binding context with policy-specific APIs, supplies the primary token, combines pipe drains and waits, and closes the caller-owned Job at its lifecycle boundary. -Every native allocation and HANDLE has one owner. A process operation frees its Koffi out-parameters and closes every pipe, thread, process, or Job handle acquired before a failure. Successful pipe creation returns the process plus stdout/stderr read handles to the sandbox. Inherited-stdio creation puts the kill-on-close Job in `STARTUPINFOEXW`, so a successfully created suspended child is already Job-owned before resume; attribute, creation, or resume failure therefore has one deterministic cleanup owner. The sandbox owns returned process, pipe, and Job handles until wait or disposal. +Every native allocation and HANDLE has one owner. A process operation frees its Koffi out-parameters and closes every pipe, thread, process, or Job handle acquired before a failure. Successful pipe creation returns the process plus stdout/stderr read handles to the sandbox. Inherited-stdio creation puts the kill-on-close Job in `STARTUPINFOEXW`, so the child is already Job-owned before any user code can run; attribute or creation failure therefore has one deterministic cleanup owner. The sandbox owns returned process, pipe, and Job handles until wait or disposal. The package exports only operations used by the sandbox production path. Ordinary `CreateProcessW`, exact `applicationName`, parent-stdio release, and whole-Job settlement remain absent until an ordinary process consumer needs them. The package is a library, not a Cordis service or a public Windows SDK. ## Verification -The shared suite covers x64 ABI values, command-line quoting, binding extension, pipe EOF and drain allocation reuse, restricted-token process creation, atomic suspended Job attachment before resume, wait and exit-code reads, native allocation release, and every acquired-resource failure set. Sandbox tests retain restricted-token, fail-closed, pipe/inherit, result, and disposal composition without duplicating the low-level matrix. Native Windows checks compile both header probes and run the migrated sandbox paths; Wine supplies the emulated Windows package and composition signal. +The shared suite covers x64 ABI values, command-line quoting, binding extension, pipe EOF and drain allocation reuse, restricted-token process creation, atomic Job attachment during creation, wait and exit-code reads, native allocation release, and every acquired-resource failure set. Sandbox tests retain restricted-token, fail-closed, pipe/inherit, result, and disposal composition without duplicating the low-level matrix. Native Windows checks compile both header probes and run the migrated sandbox paths; Wine supplies the emulated Windows package and composition signal. ## Alternatives considered diff --git a/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.zh.md b/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.zh.md index 5c4e639794..90ca5b2122 100644 --- a/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.zh.md +++ b/.agents/notes/implemented/architecture/2026-08-19-shared-win32-process-primitives.zh.md @@ -14,13 +14,13 @@ Windows ACL sandbox 拥有 restricted token、SID、DACL、grant 与 workspace p Windows ACL sandbox 继续唯一拥有 restricted-token 创建、SID 与 DACL policy、grants、可写路径裁定、临时目录 policy 和公共 sandbox child result。它通过共享 binding context 扩展 policy-specific API,提供 primary token,组合 pipe drain 与 wait,并在自己的生命周期边界关闭调用方拥有的 Job。 -每项 native allocation 与 HANDLE 都只有一个 owner。process operation 会释放 Koffi out-parameter,并在失败前关闭已经取得的每个 pipe、thread、process 或 Job handle。pipe 创建成功时,把 process 与 stdout/stderr read handles 返回给 sandbox。inherited-stdio 创建会把 kill-on-close Job 放进 `STARTUPINFOEXW`,因此成功创建的 suspended child 在 resume 前已经归属 Job;attribute、创建或 resume 失败都有唯一且确定的 cleanup owner。sandbox 在 wait 或 disposal 前拥有返回的 process、pipe 与 Job handles。 +每项 native allocation 与 HANDLE 都只有一个 owner。process operation 会释放 Koffi out-parameter,并在失败前关闭已经取得的每个 pipe、thread、process 或 Job handle。pipe 创建成功时,把 process 与 stdout/stderr read handles 返回给 sandbox。inherited-stdio 创建会把 kill-on-close Job 放进 `STARTUPINFOEXW`,因此 child 在任何用户代码运行前已经归属 Job;attribute 或创建失败都有唯一且确定的 cleanup owner。sandbox 在 wait 或 disposal 前拥有返回的 process、pipe 与 Job handles。 该包只导出 sandbox 生产路径已使用的操作。ordinary `CreateProcessW`、精确 `applicationName`、parent-stdio release 与 whole-Job settlement 在 ordinary process consumer 出现前保持缺席。该包是 library,不是 Cordis service 或公共 Windows SDK。 ## Verification -shared suite 覆盖 x64 ABI 值、命令行引用、binding extension、pipe EOF 与 drain allocation 复用、restricted-token process 创建、resume 前的原子 suspended Job 附加、wait 与 exit-code 读取、native allocation 释放,以及每组已取得资源的失败闭集。sandbox 测试保留 restricted-token、fail-closed、pipe/inherit、result 与 disposal 组合行为,不重复低层矩阵。Windows native 检查会编译两份 header probe 并运行迁移后的 sandbox 路径;Wine 提供模拟 Windows package 与组合信号。 +shared suite 覆盖 x64 ABI 值、命令行引用、binding extension、pipe EOF 与 drain allocation 复用、restricted-token process 创建、创建时的原子 Job 附加、wait 与 exit-code 读取、native allocation 释放,以及每组已取得资源的失败闭集。sandbox 测试保留 restricted-token、fail-closed、pipe/inherit、result 与 disposal 组合行为,不重复低层矩阵。Windows native 检查会编译两份 header probe 并运行迁移后的 sandbox 路径;Wine 提供模拟 Windows package 与组合信号。 ## Alternatives considered diff --git a/packages/sandbox/sandbox-windows-acl/src/spawn.ts b/packages/sandbox/sandbox-windows-acl/src/spawn.ts index a36b0253c4..3336a309f1 100644 --- a/packages/sandbox/sandbox-windows-acl/src/spawn.ts +++ b/packages/sandbox/sandbox-windows-acl/src/spawn.ts @@ -39,7 +39,7 @@ export function spawnSandboxed( * @param api - ACL/token binding table. * @param token - restricted primary token. * @param options - command, args, and working directory. - * @returns process and Job handles after assignment and resume. + * @returns process and Job handles after atomic attachment during creation. */ export function spawnSandboxedInherited( api: Win32Bindings, diff --git a/packages/sandbox/sandbox-windows-acl/tests/index-failure-paths.spec.ts b/packages/sandbox/sandbox-windows-acl/tests/index-failure-paths.spec.ts index 4f0957ea65..a8834a8c61 100644 --- a/packages/sandbox/sandbox-windows-acl/tests/index-failure-paths.spec.ts +++ b/packages/sandbox/sandbox-windows-acl/tests/index-failure-paths.spec.ts @@ -154,7 +154,6 @@ function happyStubs(): HappyStubs { }) const updateProcThreadAttribute = vi.fn(() => 1) const deleteProcThreadAttributeList = vi.fn() - const resumeThread = vi.fn(() => 0) const getStdHandle = vi.fn(() => fresh()) const localFree = vi.fn(() => 0n) const closeHandle = vi.fn(() => 1) @@ -169,7 +168,7 @@ function happyStubs(): HappyStubs { setTokenInformation, createPipe, setHandleInformation, createProcessAsUserW, peekNamedPipe, readFile, waitForSingleObject, getExitCodeProcess, createJobObjectW, setInformationJobObject, initializeProcThreadAttributeList, updateProcThreadAttribute, - deleteProcThreadAttributeList, resumeThread, getStdHandle, + deleteProcThreadAttributeList, getStdHandle, localFree, closeHandle, getLastError, formatMessageW, } as unknown as Win32Bindings return { diff --git a/packages/subprocess/win32-process/README.i18n.yaml b/packages/subprocess/win32-process/README.i18n.yaml index 909e34fecb..4fdca725f6 100644 --- a/packages/subprocess/win32-process/README.i18n.yaml +++ b/packages/subprocess/win32-process/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/subprocess/win32-process/README.md -README.md: 53064791de5375cd05008509db4f9d27beec3dc3 -README.zh.md: f5c6bc8334908241b5e6a2332f79e3d3808f6469 +README.md: 601c095ea48fbf46f151ee69ad2e485881dcb4af +README.zh.md: 53a55ef58a404c52ded1d417ba4fa516a3092783 diff --git a/packages/subprocess/win32-process/README.md b/packages/subprocess/win32-process/README.md index 53064791de..601c095ea4 100644 --- a/packages/subprocess/win32-process/README.md +++ b/packages/subprocess/win32-process/README.md @@ -9,7 +9,7 @@ Low-level Win32 process library consumed by the Windows ACL sandbox. It owns the - **One reusable ABI owner** — `abi.ts` owns the Win32 constants and x64 layout values consumed by the sandbox process paths. `ffi.ts` lazily loads `kernel32.dll` and `advapi32.dll`, verifies `STARTUPINFOW`, `STARTUPINFOEXW`, and `PROCESS_INFORMATION`, exposes typed operations and error formatting, and lets sandbox policy bind its remaining APIs through the same loaded libraries. - **Restricted-token creation** — `RestrictedProcessSpawnOptions` requires the sandbox's primary token and uses `CreateProcessAsUserW`. Piped and inherited-stdio paths share command-line quoting, cwd, the inherited environment block, checked return values, and handle cleanup. - **Piped process primitive** — `spawnPipedProcess()` creates anonymous stdin/stdout/stderr pipes, closes stdin immediately, returns the two read ends, and leaves process waiting and pipe draining to the caller. Every partial failure closes the handles already owned by the operation, and every Koffi out-parameter or struct allocation is freed after its Win32 lifetime. -- **Inherited-stdio Job primitive** — `spawnInheritedJobProcess()` creates one kill-on-close Job, temporarily marks the current stdio handles inheritable, attaches that Job through `STARTUPINFOEXW`, creates the restricted child suspended and already Job-owned, restores the parent handle flags, and resumes the child. Attribute setup, creation, or resume failure closes every owned resource; no successful process creation can leave an unowned suspended child. +- **Inherited-stdio Job primitive** — `spawnInheritedJobProcess()` creates one kill-on-close Job, temporarily marks the current stdio handles inheritable, and attaches that Job through `STARTUPINFOEXW` while creating the restricted child. The child is Job-owned before any user code can run; attribute setup or creation failure closes every owned resource, and no successful process creation can leave an unowned child. - **Explicit settlement ownership** — `waitForProcessExit()` waits and closes the process handle; `drainPipe()` reuses one fixed native out-parameter set while draining and frees it before closing the pipe read handle; `closeHandleChecked()` closes a caller-owned Job or other handle and reports a labelled Win32 error. The sandbox decides when these operations compose into public child settlement and disposal. The Windows ACL sandbox adds SID, DACL, grant, workspace, and public child policy above these primitives. diff --git a/packages/subprocess/win32-process/README.zh.md b/packages/subprocess/win32-process/README.zh.md index f5c6bc8334..53a55ef58a 100644 --- a/packages/subprocess/win32-process/README.zh.md +++ b/packages/subprocess/win32-process/README.zh.md @@ -9,7 +9,7 @@ - **唯一可复用 ABI owner** — `abi.ts` 拥有 sandbox process 路径消费的 Win32 常量与 x64 布局值。`ffi.ts` 懒加载 `kernel32.dll` 与 `advapi32.dll`,核验 `STARTUPINFOW`、`STARTUPINFOEXW` 和 `PROCESS_INFORMATION`,提供带类型的操作与错误格式化,并让 sandbox policy 通过同一组已加载库绑定剩余 API。 - **restricted-token 创建** — `RestrictedProcessSpawnOptions` 要求 sandbox 的 primary token,并使用 `CreateProcessAsUserW`。pipe 与 inherited-stdio 路径共用命令行引用、cwd、继承环境块、返回值检查与句柄清理。 - **管道进程原语** — `spawnPipedProcess()` 创建匿名 stdin/stdout/stderr 管道,立即关闭 stdin,并返回两个读取端;调用方负责等待进程与排空管道。任一局部失败都会关闭该操作已经拥有的句柄,并在各自 Win32 生命周期结束后释放每个 Koffi 输出槽与结构体分配。 -- **继承 stdio 的 Job 原语** — `spawnInheritedJobProcess()` 创建一个 kill-on-close Job,临时把当前 stdio 句柄设为可继承,通过 `STARTUPINFOEXW` 附加该 Job,以 suspended 且已经归属 Job 的状态创建 restricted child,恢复父进程句柄标志,再 resume child。attribute 设置、创建或 resume 失败都会关闭全部已拥有资源;成功创建进程后不会留下无 owner 的 suspended child。 +- **继承 stdio 的 Job 原语** — `spawnInheritedJobProcess()` 创建一个 kill-on-close Job,临时把当前 stdio 句柄设为可继承,并在创建 restricted child 时通过 `STARTUPINFOEXW` 附加该 Job。child 会在任何用户代码运行前归属 Job;attribute 设置或创建失败都会关闭全部已拥有资源,成功创建进程后不会留下无 owner 的 child。 - **显式结算归属** — `waitForProcessExit()` 等待并关闭进程句柄;`drainPipe()` 在排空期间复用一组固定原生输出槽,并在关闭管道读取句柄前释放这些槽;`closeHandleChecked()` 关闭调用方拥有的 Job 或其他句柄,并报告带操作标签的 Win32 错误。sandbox 决定这些操作何时组成公共 child 的结算与 dispose。 Windows ACL 沙箱在这些原语上增加 SID、DACL、grant、workspace 与公共 child policy。 diff --git a/packages/subprocess/win32-process/src/abi.ts b/packages/subprocess/win32-process/src/abi.ts index 168879bf65..9409e9025b 100644 --- a/packages/subprocess/win32-process/src/abi.ts +++ b/packages/subprocess/win32-process/src/abi.ts @@ -6,8 +6,6 @@ export const STARTF_USESTDHANDLES = 0x00000100 export const HANDLE_FLAG_INHERIT = 0x1 /** Infinite WaitForSingleObject timeout. */ export const INFINITE = 0xFFFFFFFF -/** CreateProcess flag that prevents user code from running before resume. */ -export const CREATE_SUSPENDED = 0x4 /** CreateProcess flag selecting STARTUPINFOEXW and its process attributes. */ export const EXTENDED_STARTUPINFO_PRESENT = 0x00080000 /** Process-thread attribute that assigns the new process to a caller-supplied Job atomically. */ diff --git a/packages/subprocess/win32-process/src/ffi.ts b/packages/subprocess/win32-process/src/ffi.ts index b22f096bfc..4abea75c5e 100644 --- a/packages/subprocess/win32-process/src/ffi.ts +++ b/packages/subprocess/win32-process/src/ffi.ts @@ -108,7 +108,6 @@ export interface Win32ProcessBindings { ): number waitForSingleObject(handle: NativePtr, milliseconds: number): number getExitCodeProcess(process: NativePtr, exitCode: NativePtr): number - resumeThread(thread: NativePtr): number createJobObjectW(attributes: null, name: null): NativePtr setInformationJobObject(job: NativePtr, cls: number, information: Buffer, length: number): number terminateProcess(process: NativePtr, exitCode: number): number @@ -269,7 +268,6 @@ function bindings(): Win32ProcessBindings { ]), waitForSingleObject: bind(kernel32, 'WaitForSingleObject', 'uint32', [PVOID, 'uint32']), getExitCodeProcess: bind(kernel32, 'GetExitCodeProcess', 'int', [PVOID, koffi.pointer('uint32')]), - resumeThread: bind(kernel32, 'ResumeThread', 'uint32', [PVOID]), createJobObjectW: bind(kernel32, 'CreateJobObjectW', PVOID, [PVOID, 'str16']), setInformationJobObject: bind(kernel32, 'SetInformationJobObject', 'int', [PVOID, 'int', PVOID, 'uint32']), terminateProcess: bind(kernel32, 'TerminateProcess', 'int', [PVOID, 'uint32']), diff --git a/packages/subprocess/win32-process/src/process.ts b/packages/subprocess/win32-process/src/process.ts index ff5d7a9386..7404ccb4ba 100644 --- a/packages/subprocess/win32-process/src/process.ts +++ b/packages/subprocess/win32-process/src/process.ts @@ -78,7 +78,7 @@ export interface SpawnedPipedProcess { stderrRead: NativePtr } -/** Suspended-created child atomically attached to one caller-owned kill-on-close Job. */ +/** Child atomically attached to one caller-owned kill-on-close Job during creation. */ export interface SpawnedJobProcess { /** Direct child process id. */ pid: number @@ -311,10 +311,10 @@ function createKillOnCloseJob(api: Win32ProcessBindings): NativePtr { } /** - * Spawn suspended and atomically attached to a kill-on-close Job, then resume. + * Spawn atomically attached to a kill-on-close Job. * @param api - active binding table. * @param options - command, cwd, args, and restricted primary token. - * @returns caller-owned process and Job handles after successful resume. + * @returns caller-owned process and Job handles after successful creation. */ export function spawnInheritedJobProcess( api: Win32ProcessBindings, @@ -358,7 +358,7 @@ export function spawnInheritedJobProcess( api, options, buildCommandLine(options.command, options.args), - abi.CREATE_SUSPENDED | abi.EXTENDED_STARTUPINFO_PRESENT, + abi.EXTENDED_STARTUPINFO_PRESENT, startupInfo.pointer, processInfo, ) @@ -395,13 +395,6 @@ export function spawnInheritedJobProcess( closeBestEffort(api, info.hProcess) throw new Error(`CreateProcessAsUserW succeeded but returned null process/thread handles (pid ${info.dwProcessId})`) } - if (api.resumeThread(info.hThread) === 0xFFFFFFFF) { - const win32Code = api.getLastError() - closeBestEffort(api, info.hThread) - closeBestEffort(api, info.hProcess) - api.closeHandle(job) - throwWin32(api, 'ResumeThread', win32Code, `pid ${info.dwProcessId}`) - } closeBestEffort(api, info.hThread) return { pid: info.dwProcessId, process: info.hProcess, job } } diff --git a/packages/subprocess/win32-process/tests/process-allocation-failure.spec.ts b/packages/subprocess/win32-process/tests/process-allocation-failure.spec.ts index b850292b6a..f9e115e8d0 100644 --- a/packages/subprocess/win32-process/tests/process-allocation-failure.spec.ts +++ b/packages/subprocess/win32-process/tests/process-allocation-failure.spec.ts @@ -75,7 +75,6 @@ describe('spawnInheritedJobProcess allocation cleanup', () => { }) return 1 }), - resumeThread: vi.fn(() => 1), closeHandle: vi.fn(() => 1), getLastError: vi.fn(() => 5), formatMessageW: vi.fn(() => 0), diff --git a/packages/subprocess/win32-process/tests/process-failure-paths.spec.ts b/packages/subprocess/win32-process/tests/process-failure-paths.spec.ts index 917974a868..93a501c197 100644 --- a/packages/subprocess/win32-process/tests/process-failure-paths.spec.ts +++ b/packages/subprocess/win32-process/tests/process-failure-paths.spec.ts @@ -61,40 +61,6 @@ function pipeFailureApi(): { api: Win32ProcessBindings; closed: bigint[]; closeH return { api, closed, closeHandle } } -/** The stub the ResumeThread failure branch needs: everything succeeds until ResumeThread returns 0xFFFFFFFF. */ -function resumeFailureApi(): { - api: Win32ProcessBindings - closed: bigint[] - closeHandle: ReturnType -} { - const closed: bigint[] = [] - let std = 50n - const closeHandle = vi.fn((handle: NativePtr) => { - closed.push(handle) - return 1 - }) - const resumeThread = vi.fn(() => 0xFFFFFFFF) - const api = { - createJobObjectW: vi.fn(() => 100n), - setInformationJobObject: vi.fn(() => 1), - getStdHandle: vi.fn(() => std++), - setHandleInformation: vi.fn(() => 1), - createProcessAsUserW: vi.fn(( - _token: unknown, _app: unknown, _cmd: unknown, _pa: unknown, _ta: unknown, - _inherit: unknown, _flags: unknown, _env: unknown, _cwd: unknown, _si: unknown, processInfo: NativePtr, - ) => { - koffi.encode(processInfo, PROCESS_INFORMATION, { hProcess: 200n, hThread: 201n, dwProcessId: 1234, dwThreadId: 5678 }) - return 1 - }), - ...jobAttributeStubs(), - resumeThread, - getLastError: vi.fn(() => 5), - closeHandle, - formatMessageW: vi.fn(() => 0), - } as unknown as Win32ProcessBindings - return { api, closed, closeHandle } -} - describe('spawn failure paths close their handles', () => { // A dummy token value; the stubbed spawn never reads it. const token = 1n as NativePtr @@ -114,23 +80,6 @@ describe('spawn failure paths close their handles', () => { expect(closed).toEqual([1n, 2n, 3n, 4n, 5n, 6n]) }) - it('closes thread, process, and kill-on-close job before throwing when ResumeThread fails', () => { - const { api, closed, closeHandle } = resumeFailureApi() - let caught: unknown - try { - spawnInheritedJobProcess(api, { command: 'probe.exe', args: [], cwd: 'C:\\', token }) - } catch (error) { - caught = error - } - expect(caught).toBeInstanceOf(Win32Error) - expect((caught as Win32Error).api).toBe('ResumeThread') - expect((caught as Win32Error).win32Code).toBe(5) - // thread, process, job — closing the job triggers kill-on-close so the - // suspended child dies instead of hanging until this process exits. - expect(closeHandle).toHaveBeenCalledTimes(3) - expect(closed).toEqual([201n, 200n, 100n]) - }) - }) /** The stub the pipe-happy path needs: CreatePipe fills both out slots with fresh handles. */ @@ -257,7 +206,6 @@ describe('spawnInheritedJobProcess failure paths', () => { return 1 }), ...jobAttributeStubs(), - resumeThread: vi.fn(() => 0), getLastError: vi.fn(() => 5), closeHandle, formatMessageW: vi.fn(() => 0), diff --git a/packages/subprocess/win32-process/tests/process.spec.ts b/packages/subprocess/win32-process/tests/process.spec.ts index b729c5d651..c734d13013 100644 --- a/packages/subprocess/win32-process/tests/process.spec.ts +++ b/packages/subprocess/win32-process/tests/process.spec.ts @@ -8,7 +8,6 @@ import { spawnPipedProcess, } from '../src/index.ts' import { - CREATE_SUSPENDED, EXTENDED_STARTUPINFO_PRESENT, POINTER_SIZE, PROC_THREAD_ATTRIBUTE_JOB_LIST, @@ -68,7 +67,6 @@ function inheritedApi(overrides: Partial = {}): { initializeProcThreadAttributeList, updateProcThreadAttribute, deleteProcThreadAttributeList: vi.fn(() => { events.push('attribute-delete') }), - resumeThread: vi.fn(() => { events.push('resume'); return 1 }), terminateProcess: vi.fn(() => 1), closeHandle: vi.fn((handle: NativePtr) => { events.push(`close:${handle}`); return 1 }), getLastError: vi.fn(() => 5), @@ -89,7 +87,7 @@ function inheritedApi(overrides: Partial = {}): { describe('spawnInheritedJobProcess', () => { const token = 70n as NativePtr - it('attaches a restricted suspended child to the Job inside CreateProcessAsUserW', () => { + it('attaches a restricted child to the Job inside CreateProcessAsUserW', () => { const { api, events, @@ -107,7 +105,6 @@ describe('spawnInheritedJobProcess', () => { expect(child).toEqual({ pid: 1234, process: 60n, job: 50n }) expect(events.indexOf('attach-job')).toBeLessThan(events.indexOf('create')) expect(events.indexOf('attribute-delete')).toBeGreaterThan(events.indexOf('create')) - expect(events.indexOf('resume')).toBeGreaterThan(events.indexOf('create')) expect(initializeProcThreadAttributeList).toHaveBeenNthCalledWith(1, null, 1, 0, expect.anything()) expect(initializeProcThreadAttributeList).toHaveBeenNthCalledWith(2, expect.any(Buffer), 1, 0, expect.anything()) expect(updateProcThreadAttribute).toHaveBeenCalledWith( @@ -127,7 +124,7 @@ describe('spawnInheritedJobProcess', () => { null, null, 1, - CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT, + EXTENDED_STARTUPINFO_PRESENT, null, 'C:\\work', expect.anything(), diff --git a/packages/subprocess/win32-process/verify/abi-probe.cpp b/packages/subprocess/win32-process/verify/abi-probe.cpp index 0b0911ea93..50452bd514 100644 --- a/packages/subprocess/win32-process/verify/abi-probe.cpp +++ b/packages/subprocess/win32-process/verify/abi-probe.cpp @@ -19,7 +19,6 @@ int wmain() P(offsetof(PROCESS_INFORMATION, hProcess)); P(offsetof(PROCESS_INFORMATION, hThread)); P(offsetof(PROCESS_INFORMATION, dwProcessId)); - P(CREATE_SUSPENDED); P(EXTENDED_STARTUPINFO_PRESENT); P(PROC_THREAD_ATTRIBUTE_JOB_LIST); P(STARTF_USESTDHANDLES); @@ -42,7 +41,6 @@ int wmain() static_assert(sizeof(STARTUPINFOEXW) == 112, "STARTUPINFOEXW size"); static_assert(offsetof(STARTUPINFOEXW, lpAttributeList) == 104, "STARTUPINFOEXW attribute offset"); static_assert(sizeof(PROCESS_INFORMATION) == 24, "PROCESS_INFORMATION size"); - static_assert(CREATE_SUSPENDED == 0x4, "create suspended"); static_assert(EXTENDED_STARTUPINFO_PRESENT == 0x00080000, "extended startup flag"); static_assert(PROC_THREAD_ATTRIBUTE_JOB_LIST == 0x0002000D, "Job-list attribute"); static_assert(STARTF_USESTDHANDLES == 0x100, "std handles flag");