@deepseek-ai/dsh-win32-process 0.1.2-alpha.5 → 0.1.3-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.i18n.yaml +2 -2
- package/README.md +11 -11
- package/README.zh.md +11 -11
- package/lib/index.js +155 -30
- package/lib/types/abi.d.ts +10 -0
- package/lib/types/ffi.d.ts +14 -2
- package/lib/types/index.d.ts +5 -5
- package/lib/types/process.d.ts +63 -5
- package/package.json +2 -2
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write packages/subprocess/win32-process/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 7a4d12f7fe6ef553113e0f202886fd42e8a313a2
|
|
6
|
+
README.zh.md: 8ebc614d38ea206cba792b90a2f118c028bf0447
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Low-level Win32 process primitives for maintainers implementing or debugging the Windows ACL sandbox."
|
|
2
|
+
description: "Low-level Win32 process primitives for maintainers implementing or debugging the Windows ACL sandbox and ordinary subprocess Job runner."
|
|
3
3
|
kind: "package-library"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
|
|
|
9
9
|
|
|
10
10
|
## Summary
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
This low-level Win32 process library is consumed by the Windows ACL sandbox and the ordinary subprocess Job runner. It owns the repository's one Koffi binding table for reusable process, stdio, and Job Object operations; it is not a Cordis service and does not choose sandbox policy or public child behavior. Read this page when maintaining either native process path or checking its handle-lifetime limits.
|
|
13
13
|
|
|
14
14
|
## Table of Contents
|
|
15
15
|
|
|
@@ -24,16 +24,16 @@ Low-level Win32 process library consumed by the Windows ACL sandbox. It owns the
|
|
|
24
24
|
<a id="behavior"></a>
|
|
25
25
|
## Behavior
|
|
26
26
|
|
|
27
|
-
- **One reusable ABI owner** — `abi.ts` owns the Win32 constants and x64 layout values consumed by
|
|
28
|
-
- **Restricted-token creation** — `RestrictedProcessSpawnOptions` requires the sandbox's primary token and uses `CreateProcessAsUserW`. Piped and inherited-stdio paths share command-line quoting, cwd, the
|
|
27
|
+
- **One reusable ABI owner** — `abi.ts` owns the Win32 constants and x64 layout values consumed by both process paths. `ffi.ts` lazily loads `kernel32.dll` and `advapi32.dll`, verifies `STARTUPINFOW` and `PROCESS_INFORMATION`, exposes typed operations and error formatting, and lets sandbox policy bind its remaining APIs through the same loaded libraries.
|
|
28
|
+
- **Restricted-token creation** — `RestrictedProcessSpawnOptions` requires the sandbox's primary token and uses `CreateProcessAsUserW`. Piped and inherited-stdio paths share command-line quoting, cwd, the restricted-token null-environment policy, checked return values, and handle cleanup.
|
|
29
29
|
- **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.
|
|
30
30
|
- **Inherited-stdio Job primitive** — `spawnInheritedJobProcess()` creates one kill-on-close Job, temporarily marks the current stdio handles inheritable, creates the restricted child suspended, assigns it to the Job, and then resumes its initial thread. Target code cannot run before Job assignment; controlled assignment or resume failures terminate the suspended child or close the assigned Job before releasing every owned handle.
|
|
31
|
-
- **
|
|
31
|
+
- **Ordinary Job runner primitive** — `CurrentTokenProcessSpawnOptions` requires a resolved `applicationName`, the complete target environment, and three runner CRT descriptors dedicated to target stdin, stdout, and stderr. `spawnCurrentTokenJobProcess()` maps those descriptors to OS handles through Node's exported `uv_get_osfhandle()`, rejects invalid results, temporarily marks the handles inheritable, and passes them through `STARTF_USESTDHANDLES`. It sends a sorted UTF-16LE environment block with `CREATE_UNICODE_ENVIRONMENT`, creates the target suspended through `CreateProcessW`, assigns it to an unnamed kill-on-close Job, and resumes it only after assignment. The original command-line argv entry remains unchanged, and the runner can close its carrier descriptors without touching Node's own standard streams.
|
|
32
|
+
- **Ordinary settlement operations** — `pollProcessExit()` publishes direct exit separately, while `isJobEmpty()` reads `QueryInformationJobObject(JobObjectBasicAccountingInformation)` until `ActiveProcesses` reaches zero. Checked Job termination and handle closure keep the runner as the only native owner.
|
|
33
|
+
- **Explicit settlement ownership** — `waitForProcessExit()` waits and closes a sandbox process handle; ordinary runner process polling, Job accounting, and checked Job termination/closure remain separate operations. `drainPipe()` reuses one native count slot while draining, frees it, and closes the pipe read handle. Each caller owns its result composition and returned handles.
|
|
32
34
|
|
|
33
35
|
The Windows ACL sandbox adds SID, DACL, grant, workspace, and public child policy above these primitives.
|
|
34
36
|
|
|
35
|
-
<a id="header-verification"></a>
|
|
36
|
-
|
|
37
37
|
<a id="header-verification"></a>
|
|
38
38
|
## Header verification
|
|
39
39
|
|
|
@@ -43,7 +43,7 @@ The process, stdio, and Job constants plus selected structure sizes and offsets
|
|
|
43
43
|
g++ -std=c++20 -municode -O2 -o abi-probe.exe verify/abi-probe.cpp && ./abi-probe.exe
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
The Koffi `STARTUPINFOW` and `PROCESS_INFORMATION` definitions also assert their 64-bit sizes at module load. The probe remains the evidence for the other recorded offsets and constants.
|
|
46
|
+
The Koffi `STARTUPINFOW` and `PROCESS_INFORMATION` definitions also assert their 64-bit sizes at module load. The probe additionally fixes pointer and handle widths, the Unicode-environment flag, and the basic Job accounting record size and `ActiveProcesses` offset used to determine quiescence; it remains the evidence for the other recorded offsets and constants.
|
|
47
47
|
|
|
48
48
|
<a id="model-experience"></a>
|
|
49
49
|
## Model Experience
|
|
@@ -52,7 +52,7 @@ The Koffi `STARTUPINFOW` and `PROCESS_INFORMATION` definitions also assert their
|
|
|
52
52
|
|
|
53
53
|
#### What the model sees
|
|
54
54
|
|
|
55
|
-
Nothing directly. The package exposes `Win32ProcessBindings` and process primitives to the sandbox, which
|
|
55
|
+
Nothing directly. The package exposes `Win32ProcessBindings`, `CurrentTokenProcessBindings`, and process primitives to the sandbox and ordinary runner, which own all model-visible tools, output, and diagnostics; this package contributes no prompt text or tool schema.
|
|
56
56
|
|
|
57
57
|
#### Token effect
|
|
58
58
|
|
|
@@ -68,8 +68,8 @@ The package contributes no stable request prefix, so it does not invalidate mode
|
|
|
68
68
|
|
|
69
69
|
- **Windows-only native loading** — importing the generic types is portable, but resolving the binding table loads Windows DLLs and fails on other hosts. Cross-platform tests inject a binding table instead of loading native APIs.
|
|
70
70
|
- **No public process service** — the package intentionally does not wrap its primitives in Cordis or Node streams. A consumer must own its policy, async scheduling, output limits, cancellation, and final handle closure.
|
|
71
|
-
- **
|
|
72
|
-
- **
|
|
71
|
+
- **Restricted-token null environment** — the `CreateProcessAsUserW` sandbox primitives pass a null environment block and establish changes through `SetEnvironmentVariableW` first because an explicit block through Koffi fails with `ERROR_INVALID_PARAMETER`. The ordinary `CreateProcessW` runner instead requires a complete target environment and passes a sorted, double-NUL-terminated UTF-16LE block, including `=X:` drive entries, without mutating its own environment.
|
|
72
|
+
- **No standalone process API** — the package exposes the operations current sandbox and ordinary-runner consumers need, but it does not own Node streams, public handles, output policy, cancellation, or durable state.
|
|
73
73
|
- **Create-to-assignment interruption** — the target starts suspended and cannot execute before Job assignment, but an external termination of the runner in the narrow interval between process creation and assignment can leave the suspended target behind. The package does not claim atomic Job attachment.
|
|
74
74
|
- **Header evidence is architecture-specific** — the committed ABI probe and layout constants cover the repository's current 64-bit Windows targets. A new pointer width or incompatible Windows ABI requires updating the probe before support is claimed.
|
|
75
75
|
|
package/README.zh.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "面向实现或排查 Windows ACL
|
|
2
|
+
description: "面向实现或排查 Windows ACL 沙箱与普通子进程 Job runner 的维护者,说明底层 Win32 进程原语。"
|
|
3
3
|
kind: "package-library"
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ kind: "package-library"
|
|
|
9
9
|
|
|
10
10
|
## 概述
|
|
11
11
|
|
|
12
|
-
供 Windows ACL
|
|
12
|
+
供 Windows ACL 沙箱与普通子进程 Job runner 消费的底层 Win32 进程库。它唯一拥有仓库中可复用 process、stdio 与 Job Object 操作的 Koffi 绑定表;它不是 Cordis 服务,也不决定沙箱策略或公共 child 行为。维护任一原生进程路径或检查 handle 生命周期限制时,请阅读本页。
|
|
13
13
|
|
|
14
14
|
## 目录
|
|
15
15
|
|
|
@@ -24,16 +24,16 @@ kind: "package-library"
|
|
|
24
24
|
<a id="behavior"></a>
|
|
25
25
|
## Behavior
|
|
26
26
|
|
|
27
|
-
- **唯一可复用 ABI owner** — `abi.ts`
|
|
28
|
-
- **restricted-token 创建** — `RestrictedProcessSpawnOptions` 要求 sandbox 的 primary token,并使用 `CreateProcessAsUserW`。pipe 与 inherited-stdio 路径共用命令行引用、cwd
|
|
27
|
+
- **唯一可复用 ABI owner** — `abi.ts` 拥有两条 process 路径消费的 Win32 常量与 x64 布局值。`ffi.ts` 懒加载 `kernel32.dll` 与 `advapi32.dll`,核验 `STARTUPINFOW` 和 `PROCESS_INFORMATION`,提供带类型的操作与错误格式化,并让 sandbox policy 通过同一组已加载库绑定剩余 API。
|
|
28
|
+
- **restricted-token 创建** — `RestrictedProcessSpawnOptions` 要求 sandbox 的 primary token,并使用 `CreateProcessAsUserW`。pipe 与 inherited-stdio 路径共用命令行引用、cwd、restricted-token 空环境策略、返回值检查与句柄清理。
|
|
29
29
|
- **管道进程原语** — `spawnPipedProcess()` 创建匿名 stdin/stdout/stderr 管道,立即关闭 stdin,并返回两个读取端;调用方负责等待进程与排空管道。任一局部失败都会关闭该操作已经拥有的句柄,并在各自 Win32 生命周期结束后释放每个 Koffi 输出槽与结构体分配。
|
|
30
30
|
- **继承 stdio 的 Job 原语** — `spawnInheritedJobProcess()` 创建一个 kill-on-close Job,临时把当前 stdio 句柄设为可继承,以 suspended 状态创建 restricted child,把它分配给 Job,再恢复初始线程。目标代码不会在 Job 分配前运行;受控的分配或恢复失败会终止 suspended child,或在释放全部已拥有句柄前关闭已分配的 Job。
|
|
31
|
-
-
|
|
31
|
+
- **ordinary Job runner 原语** — `CurrentTokenProcessSpawnOptions` 要求已解析的 `applicationName`、完整 target 环境,以及三个专用于 target stdin、stdout 与 stderr 的 runner CRT 描述符。`spawnCurrentTokenJobProcess()` 通过 Node 导出的 `uv_get_osfhandle()` 把这些描述符映射为 OS handle,拒绝无效结果,临时把 handle 设为可继承,并通过 `STARTF_USESTDHANDLES` 传入。它使用 `CREATE_UNICODE_ENVIRONMENT` 传入排序后的 UTF-16LE 环境块,再以 suspended 状态通过 `CreateProcessW` 创建 target、把它分配给 unnamed kill-on-close Job,并只在分配后恢复。原始命令行 argv 项保持不变,runner 也可以关闭自己的 carrier 描述符,而不触碰 Node 自身的标准流。
|
|
32
|
+
- **ordinary 停稳操作** — `pollProcessExit()` 单独发布 direct exit,`isJobEmpty()` 则读取 `QueryInformationJobObject(JobObjectBasicAccountingInformation)`,直到 `ActiveProcesses` 归零。带检查的 Job 终止与 handle 关闭使 runner 保持唯一 native owner。
|
|
33
|
+
- **显式结算归属** — `waitForProcessExit()` 等待并关闭 sandbox process handle;ordinary runner 的 process polling、Job accounting 与 checked Job termination/closure 是独立操作。`drainPipe()` 在排空期间复用一个 native count slot,释放该分配并关闭管道读取句柄。每个调用方拥有自己的 result 组合与返回 handle。
|
|
32
34
|
|
|
33
35
|
Windows ACL 沙箱在这些原语上增加 SID、DACL、grant、workspace 与公共 child policy。
|
|
34
36
|
|
|
35
|
-
<a id="header-verification"></a>
|
|
36
|
-
|
|
37
37
|
<a id="header-verification"></a>
|
|
38
38
|
## 头部验证
|
|
39
39
|
|
|
@@ -43,7 +43,7 @@ process、stdio 与 Job 的常量以及选定结构体的大小和偏移由 [`ve
|
|
|
43
43
|
g++ -std=c++20 -municode -O2 -o abi-probe.exe verify/abi-probe.cpp && ./abi-probe.exe
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
Koffi 的 `STARTUPINFOW` 与 `PROCESS_INFORMATION` 定义还会在模块加载时断言各自的 64
|
|
46
|
+
Koffi 的 `STARTUPINFOW` 与 `PROCESS_INFORMATION` 定义还会在模块加载时断言各自的 64 位大小。该探针还固定指针与 handle 宽度、Unicode 环境标志,以及用于判断停稳的基础 Job accounting record 大小与 `ActiveProcesses` 偏移;其余已记录偏移和常量也由该探针提供证据。
|
|
47
47
|
|
|
48
48
|
<a id="model-experience"></a>
|
|
49
49
|
## Model Experience
|
|
@@ -52,7 +52,7 @@ Koffi 的 `STARTUPINFOW` 与 `PROCESS_INFORMATION` 定义还会在模块加载
|
|
|
52
52
|
|
|
53
53
|
#### 模型看到什么
|
|
54
54
|
|
|
55
|
-
没有直接内容。本包向 sandbox 提供 `Win32ProcessBindings`
|
|
55
|
+
没有直接内容。本包向 sandbox 与 ordinary runner 提供 `Win32ProcessBindings`、`CurrentTokenProcessBindings` 与进程原语;两者拥有全部模型可见工具、输出与诊断,本包不贡献提示词或工具 schema。
|
|
56
56
|
|
|
57
57
|
#### Token 影响
|
|
58
58
|
|
|
@@ -68,8 +68,8 @@ Koffi 的 `STARTUPINFOW` 与 `PROCESS_INFORMATION` 定义还会在模块加载
|
|
|
68
68
|
|
|
69
69
|
- **仅在 Windows 原生加载** — 导入通用类型可跨平台进行,但解析绑定表会加载 Windows DLL,并在其他宿主失败。跨平台测试注入绑定表,不加载原生 API。
|
|
70
70
|
- **没有公共进程服务** — 本包刻意不把原语包装成 Cordis 或 Node streams。消费方必须拥有自己的策略、异步调度、输出上限、取消与最终句柄关闭。
|
|
71
|
-
-
|
|
72
|
-
-
|
|
71
|
+
- **restricted-token 空环境** — `CreateProcessAsUserW` sandbox 原语传入空环境块,并先通过 `SetEnvironmentVariableW` 建立改动,因为经 Koffi 传入显式环境块会以 `ERROR_INVALID_PARAMETER` 失败。ordinary `CreateProcessW` runner 则要求完整 target 环境,并传入排序、双 NUL 结尾的 UTF-16LE 块,其中包括 `=X:` 驱动器条目,而不修改自身环境。
|
|
72
|
+
- **没有 standalone process API** — 本包只暴露当前 sandbox 与 ordinary-runner consumer 所需的操作,不拥有 Node streams、公共 handle、output policy、cancellation 或 durable state。
|
|
73
73
|
- **创建到分配之间的中断** — 目标以 suspended 状态启动,不能在 Job 分配前执行,但 runner 若在进程创建到分配之间的极窄区间被外力终止,可能留下 suspended target。本包不声明原子 Job 附加保证。
|
|
74
74
|
- **header 证据限定架构** — 已提交的 ABI probe 与布局常量覆盖仓库当前 64 位 Windows 目标。支持新的指针宽度或不兼容 Windows ABI 前,必须先更新 probe。
|
|
75
75
|
|
package/lib/index.js
CHANGED
|
@@ -142,6 +142,7 @@ function bindingContext() {
|
|
|
142
142
|
function bindings() {
|
|
143
143
|
if (cached !== void 0) return cached;
|
|
144
144
|
const { kernel32, advapi32, bind } = bindingContext();
|
|
145
|
+
const node = koffi.load(null);
|
|
145
146
|
cached = {
|
|
146
147
|
closeHandle: bind(kernel32, "CloseHandle", "int", [PVOID]),
|
|
147
148
|
getLastError: bind(kernel32, "GetLastError", "uint32", []),
|
|
@@ -178,6 +179,18 @@ function bindings() {
|
|
|
178
179
|
koffi.pointer(STARTUPINFOW),
|
|
179
180
|
koffi.pointer(PROCESS_INFORMATION)
|
|
180
181
|
]),
|
|
182
|
+
createProcessW: bind(kernel32, "CreateProcessW", "int", [
|
|
183
|
+
"str16",
|
|
184
|
+
"str16",
|
|
185
|
+
PVOID,
|
|
186
|
+
PVOID,
|
|
187
|
+
"int",
|
|
188
|
+
"uint32",
|
|
189
|
+
PVOID,
|
|
190
|
+
"str16",
|
|
191
|
+
koffi.pointer(STARTUPINFOW),
|
|
192
|
+
koffi.pointer(PROCESS_INFORMATION)
|
|
193
|
+
]),
|
|
181
194
|
readFile: bind(kernel32, "ReadFile", "int", [
|
|
182
195
|
PVOID,
|
|
183
196
|
PVOID,
|
|
@@ -202,10 +215,19 @@ function bindings() {
|
|
|
202
215
|
PVOID,
|
|
203
216
|
"uint32"
|
|
204
217
|
]),
|
|
218
|
+
queryInformationJobObject: bind(kernel32, "QueryInformationJobObject", "int", [
|
|
219
|
+
PVOID,
|
|
220
|
+
"int",
|
|
221
|
+
PVOID,
|
|
222
|
+
"uint32",
|
|
223
|
+
PVOID
|
|
224
|
+
]),
|
|
205
225
|
assignProcessToJobObject: bind(kernel32, "AssignProcessToJobObject", "int", [PVOID, PVOID]),
|
|
206
226
|
resumeThread: bind(kernel32, "ResumeThread", "uint32", [PVOID]),
|
|
207
227
|
terminateProcess: bind(kernel32, "TerminateProcess", "int", [PVOID, "uint32"]),
|
|
208
|
-
|
|
228
|
+
terminateJobObject: bind(kernel32, "TerminateJobObject", "int", [PVOID, "uint32"]),
|
|
229
|
+
getStdHandle: bind(kernel32, "GetStdHandle", PVOID, ["int"]),
|
|
230
|
+
uvGetOsfhandle: node.func("uv_get_osfhandle", PVOID, ["int"])
|
|
209
231
|
};
|
|
210
232
|
return cached;
|
|
211
233
|
}
|
|
@@ -220,6 +242,13 @@ function extendWin32ProcessBindings(create) {
|
|
|
220
242
|
...create(bindingContext())
|
|
221
243
|
};
|
|
222
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Load the generic process binding table without policy-specific extensions.
|
|
247
|
+
* @returns shared Win32 process, stdio, and Job operations.
|
|
248
|
+
*/
|
|
249
|
+
function loadWin32ProcessBindings() {
|
|
250
|
+
return bindings();
|
|
251
|
+
}
|
|
223
252
|
/* v8 ignore stop */
|
|
224
253
|
/**
|
|
225
254
|
* Format a Win32 error code through FormatMessageW.
|
|
@@ -287,6 +316,15 @@ function quoteArg(argument) {
|
|
|
287
316
|
function buildCommandLine(program, args) {
|
|
288
317
|
return [program, ...args].map(quoteArg).join(" ");
|
|
289
318
|
}
|
|
319
|
+
function compareWindowsEnvironmentKeys([left], [right]) {
|
|
320
|
+
const foldedLeft = left.toUpperCase();
|
|
321
|
+
const foldedRight = right.toUpperCase();
|
|
322
|
+
return foldedLeft < foldedRight ? -1 : foldedLeft > foldedRight ? 1 : 0;
|
|
323
|
+
}
|
|
324
|
+
function encodeWindowsEnvironment(env) {
|
|
325
|
+
const strings = Object.entries(env).sort(compareWindowsEnvironmentKeys).map(([key, value]) => `${key}=${value}`);
|
|
326
|
+
return Buffer.from(`${strings.join("\0")}\0\0`, "utf16le");
|
|
327
|
+
}
|
|
290
328
|
function freeNative(pointer) {
|
|
291
329
|
if (pointer !== void 0) koffi.free(pointer);
|
|
292
330
|
}
|
|
@@ -448,38 +486,46 @@ function createKillOnCloseJob(api) {
|
|
|
448
486
|
}
|
|
449
487
|
return job;
|
|
450
488
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
* @returns caller-owned process and Job handles after successful resume.
|
|
456
|
-
* @remarks Node clears stdio handle inheritability at startup through
|
|
457
|
-
* uv_disable_stdio_inheritance. This operation temporarily restores the bits
|
|
458
|
-
* required by STARTF_USESTDHANDLES. Restoring them afterward is best-effort:
|
|
459
|
-
* failure must not replace the already-created child's outcome.
|
|
460
|
-
*/
|
|
461
|
-
function spawnInheritedJobProcess(api, options) {
|
|
462
|
-
const job = createKillOnCloseJob(api);
|
|
463
|
-
const getStdHandle = (selector, label) => {
|
|
489
|
+
const UV_INVALID_OS_FILE_HANDLE = 18446744073709551615n;
|
|
490
|
+
const UV_INVALID_FILE_DESCRIPTOR = 18446744073709551614n;
|
|
491
|
+
function inheritedStandardHandles(api) {
|
|
492
|
+
const get = (selector, label) => {
|
|
464
493
|
const handle = api.getStdHandle(selector);
|
|
465
494
|
if (!isNullPtr(handle)) return handle;
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
495
|
+
throwLastError(api, "GetStdHandle", `null ${label} handle`);
|
|
496
|
+
};
|
|
497
|
+
return {
|
|
498
|
+
stdin: get(-10, "stdin"),
|
|
499
|
+
stdout: get(-11, "stdout"),
|
|
500
|
+
stderr: get(-12, "stderr")
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
function targetCarrierHandles(api, descriptors) {
|
|
504
|
+
const get = (fileDescriptor, label) => {
|
|
505
|
+
const handle = api.uvGetOsfhandle(fileDescriptor);
|
|
506
|
+
if (isNullPtr(handle) || handle === UV_INVALID_OS_FILE_HANDLE || handle === UV_INVALID_FILE_DESCRIPTOR) throw new Error(`uv_get_osfhandle returned an invalid handle for target ${label} fd ${String(fileDescriptor)}`);
|
|
507
|
+
return handle;
|
|
508
|
+
};
|
|
509
|
+
return {
|
|
510
|
+
stdin: get(descriptors.stdin, "stdin"),
|
|
511
|
+
stdout: get(descriptors.stdout, "stdout"),
|
|
512
|
+
stderr: get(descriptors.stderr, "stderr")
|
|
469
513
|
};
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
514
|
+
}
|
|
515
|
+
/** Shared suspended-create, Job-assignment, and resume lifecycle. */
|
|
516
|
+
function spawnJobProcess(api, options, resolveStdio, createName, create) {
|
|
517
|
+
const job = createKillOnCloseJob(api);
|
|
473
518
|
const enabled = [];
|
|
474
519
|
let startupInfo;
|
|
475
520
|
let processInfo;
|
|
476
521
|
let created = 0;
|
|
477
522
|
let createFailureCode = 0;
|
|
478
523
|
try {
|
|
524
|
+
const stdio = resolveStdio();
|
|
479
525
|
for (const [handle, label] of [
|
|
480
|
-
[
|
|
481
|
-
[
|
|
482
|
-
[
|
|
526
|
+
[stdio.stdin, "stdin"],
|
|
527
|
+
[stdio.stdout, "stdout"],
|
|
528
|
+
[stdio.stderr, "stderr"]
|
|
483
529
|
]) {
|
|
484
530
|
if (api.setHandleInformation(handle, 1, 1) === 0) throwLastError(api, "SetHandleInformation", `${label} (enable inherit)`);
|
|
485
531
|
enabled.push(handle);
|
|
@@ -488,12 +534,12 @@ function spawnInheritedJobProcess(api, options) {
|
|
|
488
534
|
encodeStartupInfo(startupInfo, {
|
|
489
535
|
cb: 104,
|
|
490
536
|
dwFlags: 256,
|
|
491
|
-
hStdInput:
|
|
492
|
-
hStdOutput:
|
|
493
|
-
hStdError:
|
|
537
|
+
hStdInput: stdio.stdin,
|
|
538
|
+
hStdOutput: stdio.stdout,
|
|
539
|
+
hStdError: stdio.stderr
|
|
494
540
|
});
|
|
495
541
|
processInfo = allocProcessInfo();
|
|
496
|
-
created =
|
|
542
|
+
created = create(startupInfo, processInfo);
|
|
497
543
|
if (created === 0) createFailureCode = api.getLastError();
|
|
498
544
|
} catch (error) {
|
|
499
545
|
freeNative(processInfo);
|
|
@@ -506,7 +552,7 @@ function spawnInheritedJobProcess(api, options) {
|
|
|
506
552
|
if (created === 0) {
|
|
507
553
|
freeNative(processInfo);
|
|
508
554
|
api.closeHandle(job);
|
|
509
|
-
throwWin32(api,
|
|
555
|
+
throwWin32(api, createName, createFailureCode, `command: ${options.command}, cwd: ${options.cwd}`);
|
|
510
556
|
}
|
|
511
557
|
let info;
|
|
512
558
|
try {
|
|
@@ -519,7 +565,7 @@ function spawnInheritedJobProcess(api, options) {
|
|
|
519
565
|
api.closeHandle(job);
|
|
520
566
|
closeBestEffort(api, info.hThread);
|
|
521
567
|
closeBestEffort(api, info.hProcess);
|
|
522
|
-
throw new Error(
|
|
568
|
+
throw new Error(`${createName} succeeded but returned null process/thread handles (pid ${info.dwProcessId})`);
|
|
523
569
|
}
|
|
524
570
|
if (api.assignProcessToJobObject(job, info.hProcess) === 0) {
|
|
525
571
|
const win32Code = api.getLastError();
|
|
@@ -543,5 +589,84 @@ function spawnInheritedJobProcess(api, options) {
|
|
|
543
589
|
job
|
|
544
590
|
};
|
|
545
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Spawn a restricted-token process suspended, assign its Job, then resume it.
|
|
594
|
+
* @param api - active binding table.
|
|
595
|
+
* @param options - command, cwd, args, and restricted primary token.
|
|
596
|
+
* @returns caller-owned process and Job handles after successful resume.
|
|
597
|
+
* @remarks Node clears stdio handle inheritability at startup through
|
|
598
|
+
* uv_disable_stdio_inheritance. This operation temporarily restores the bits
|
|
599
|
+
* required by STARTF_USESTDHANDLES. Restoring them afterward is best-effort:
|
|
600
|
+
* failure must not replace the already-created child's outcome.
|
|
601
|
+
*/
|
|
602
|
+
function spawnInheritedJobProcess(api, options) {
|
|
603
|
+
const commandLine = buildCommandLine(options.command, options.args);
|
|
604
|
+
return spawnJobProcess(api, options, () => inheritedStandardHandles(api), "CreateProcessAsUserW", (startupInfo, processInfo) => createRestrictedProcess(api, options, commandLine, 4, startupInfo, processInfo));
|
|
605
|
+
}
|
|
606
|
+
/**
|
|
607
|
+
* Spawn an ordinary process suspended, assign its Job, then resume it.
|
|
608
|
+
* @param api - active binding table.
|
|
609
|
+
* @param options - command, cwd, argv, and target carrier descriptors.
|
|
610
|
+
* @returns caller-owned process and Job handles after successful resume.
|
|
611
|
+
*/
|
|
612
|
+
function spawnCurrentTokenJobProcess(api, options) {
|
|
613
|
+
const commandLine = buildCommandLine(options.command, options.args);
|
|
614
|
+
const environment = encodeWindowsEnvironment(options.env);
|
|
615
|
+
return spawnJobProcess(api, options, () => targetCarrierHandles(api, options.stdio), "CreateProcessW", (startupInfo, processInfo) => api.createProcessW(options.applicationName, commandLine, null, null, 1, 1028, environment, options.cwd, startupInfo, processInfo));
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Verify that an unnamed kill-on-close Job can be created and released now.
|
|
619
|
+
* @param api - active binding table.
|
|
620
|
+
*/
|
|
621
|
+
function probeCurrentTokenJobSupport(api) {
|
|
622
|
+
closeHandleChecked(api, createKillOnCloseJob(api), "current-token Job capability probe");
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Poll one process handle without blocking the runner event loop.
|
|
626
|
+
* @param api - active binding table.
|
|
627
|
+
* @param process - caller-owned process handle.
|
|
628
|
+
* @returns the direct exit code when signalled, or undefined while running.
|
|
629
|
+
*/
|
|
630
|
+
function pollProcessExit(api, process) {
|
|
631
|
+
const waitResult = api.waitForSingleObject(process, 0);
|
|
632
|
+
if (waitResult === 258) return void 0;
|
|
633
|
+
if (waitResult === 4294967295) throwLastError(api, "WaitForSingleObject");
|
|
634
|
+
const exitCodeSlot = allocUint32();
|
|
635
|
+
try {
|
|
636
|
+
if (api.getExitCodeProcess(process, exitCodeSlot) === 0) throwLastError(api, "GetExitCodeProcess");
|
|
637
|
+
return decodeUint32(exitCodeSlot);
|
|
638
|
+
} finally {
|
|
639
|
+
koffi.free(exitCodeSlot);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Return whether a Job has no active processes.
|
|
644
|
+
* @param api - active binding table.
|
|
645
|
+
* @param job - caller-owned Job handle.
|
|
646
|
+
* @returns true once the Job reports zero active processes.
|
|
647
|
+
*/
|
|
648
|
+
function isJobEmpty(api, job) {
|
|
649
|
+
const information = Buffer.alloc(48);
|
|
650
|
+
if (api.queryInformationJobObject(job, 1, information, information.length, null) === 0) throwLastError(api, "QueryInformationJobObject", "active process count");
|
|
651
|
+
return information.readUInt32LE(40) === 0;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Terminate every process in a Job.
|
|
655
|
+
* @param api - active binding table.
|
|
656
|
+
* @param job - caller-owned Job handle.
|
|
657
|
+
* @param exitCode - direct Windows exit code assigned to members.
|
|
658
|
+
*/
|
|
659
|
+
function terminateJob(api, job, exitCode) {
|
|
660
|
+
if (api.terminateJobObject(job, exitCode) === 0) throwLastError(api, "TerminateJobObject");
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Close a caller-owned handle and report a labelled Win32 failure.
|
|
664
|
+
* @param api - active binding table.
|
|
665
|
+
* @param handle - handle to close.
|
|
666
|
+
* @param detail - lifecycle label for diagnostics.
|
|
667
|
+
*/
|
|
668
|
+
function closeHandleChecked(api, handle, detail) {
|
|
669
|
+
if (api.closeHandle(handle) === 0) throwLastError(api, "CloseHandle", detail);
|
|
670
|
+
}
|
|
546
671
|
//#endregion
|
|
547
|
-
export { ERROR_INSUFFICIENT_BUFFER, Win32Error, allocPtrSlot, allocUint32, decodePtr, decodeUint32, drainPipe, extendWin32ProcessBindings, isNullPtr, spawnInheritedJobProcess, spawnPipedProcess, throwLastError, throwWin32, waitForProcessExit };
|
|
672
|
+
export { ERROR_INSUFFICIENT_BUFFER, Win32Error, allocPtrSlot, allocUint32, closeHandleChecked, decodePtr, decodeUint32, drainPipe, extendWin32ProcessBindings, isJobEmpty, isNullPtr, loadWin32ProcessBindings, pollProcessExit, probeCurrentTokenJobSupport, spawnCurrentTokenJobProcess, spawnInheritedJobProcess, spawnPipedProcess, terminateJob, throwLastError, throwWin32, waitForProcessExit };
|
package/lib/types/abi.d.ts
CHANGED
|
@@ -5,8 +5,12 @@ export declare const STARTF_USESTDHANDLES = 256;
|
|
|
5
5
|
export declare const HANDLE_FLAG_INHERIT = 1;
|
|
6
6
|
/** Infinite WaitForSingleObject timeout. */
|
|
7
7
|
export declare const INFINITE = 4294967295;
|
|
8
|
+
/** WaitForSingleObject returned because a zero-time probe is not signalled. */
|
|
9
|
+
export declare const WAIT_TIMEOUT = 258;
|
|
8
10
|
/** CreateProcess flag that prevents user code from running before resume. */
|
|
9
11
|
export declare const CREATE_SUSPENDED = 4;
|
|
12
|
+
/** CreateProcess flag selecting a UTF-16 environment block. */
|
|
13
|
+
export declare const CREATE_UNICODE_ENVIRONMENT = 1024;
|
|
10
14
|
/** GetStdHandle selector for standard input. */
|
|
11
15
|
export declare const STD_INPUT_HANDLE = -10;
|
|
12
16
|
/** GetStdHandle selector for standard output. */
|
|
@@ -25,8 +29,14 @@ export declare const ERROR_BROKEN_PIPE = 109;
|
|
|
25
29
|
export declare const ERROR_NO_DATA = 232;
|
|
26
30
|
/** Job limit that terminates every member when the final Job handle closes. */
|
|
27
31
|
export declare const JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 8192;
|
|
32
|
+
/** QueryInformationJobObject class for basic accounting and active-process count. */
|
|
33
|
+
export declare const JobObjectBasicAccountingInformation = 1;
|
|
28
34
|
/** SetInformationJobObject class for JOBOBJECT_EXTENDED_LIMIT_INFORMATION. */
|
|
29
35
|
export declare const JobObjectExtendedLimitInformation = 9;
|
|
36
|
+
/** x64 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION byte size. */
|
|
37
|
+
export declare const JOBOBJECT_BASIC_ACCOUNTING_SIZE = 48;
|
|
38
|
+
/** Byte offset of ActiveProcesses in JOBOBJECT_BASIC_ACCOUNTING_INFORMATION. */
|
|
39
|
+
export declare const JOBOBJECT_BASIC_ACCOUNTING_ACTIVE_PROCESSES_OFFSET = 40;
|
|
30
40
|
/** x64 JOBOBJECT_EXTENDED_LIMIT_INFORMATION byte size. */
|
|
31
41
|
export declare const JOBOBJECT_EXTENDED_LIMIT_SIZE = 144;
|
|
32
42
|
/** Byte offset of BasicLimitInformation.LimitFlags in the extended Job record. */
|
package/lib/types/ffi.d.ts
CHANGED
|
@@ -43,18 +43,25 @@ export interface Win32ProcessBindings {
|
|
|
43
43
|
formatMessageW(flags: number, source: null, messageId: number, languageId: number, buffer: Buffer, size: number, args: null): number;
|
|
44
44
|
createPipe(readHandle: NativePtr, writeHandle: NativePtr, attributes: null, size: number): number;
|
|
45
45
|
setHandleInformation(handle: NativePtr, mask: number, flags: number): number;
|
|
46
|
-
createProcessAsUserW(token: NativePtr, applicationName: null, commandLine: string, processAttributes: null, threadAttributes: null, inheritHandles: number, creationFlags: number, environment: null, currentDirectory: string | null, startupInfo: NativePtr, processInfo: NativePtr): number;
|
|
46
|
+
createProcessAsUserW(token: NativePtr, applicationName: string | null, commandLine: string, processAttributes: null, threadAttributes: null, inheritHandles: number, creationFlags: number, environment: null, currentDirectory: string | null, startupInfo: NativePtr, processInfo: NativePtr): number;
|
|
47
|
+
createProcessW(applicationName: string | null, commandLine: string, processAttributes: null, threadAttributes: null, inheritHandles: number, creationFlags: number, environment: Buffer | null, currentDirectory: string | null, startupInfo: NativePtr, processInfo: NativePtr): number;
|
|
47
48
|
readFile(file: NativePtr, buffer: Buffer, count: number, bytesRead: NativePtr, overlapped: null): number;
|
|
48
49
|
peekNamedPipe(pipe: NativePtr, buffer: null, size: number, bytesRead: NativePtr | null, totalAvail: NativePtr, leftThisMessage: NativePtr | null): number;
|
|
49
50
|
waitForSingleObject(handle: NativePtr, milliseconds: number): number;
|
|
50
51
|
getExitCodeProcess(process: NativePtr, exitCode: NativePtr): number;
|
|
51
52
|
createJobObjectW(attributes: null, name: null): NativePtr;
|
|
52
53
|
setInformationJobObject(job: NativePtr, cls: number, information: Buffer, length: number): number;
|
|
54
|
+
queryInformationJobObject(job: NativePtr, cls: number, information: Buffer, length: number, returnLength: null): number;
|
|
53
55
|
assignProcessToJobObject(job: NativePtr, process: NativePtr): number;
|
|
54
56
|
resumeThread(thread: NativePtr): number;
|
|
55
57
|
terminateProcess(process: NativePtr, exitCode: number): number;
|
|
58
|
+
terminateJobObject(job: NativePtr, exitCode: number): number;
|
|
56
59
|
getStdHandle(stdHandle: number): NativePtr;
|
|
57
60
|
}
|
|
61
|
+
/** Generic Win32 calls plus Node's libuv descriptor-to-handle bridge. */
|
|
62
|
+
export interface CurrentTokenProcessBindings extends Win32ProcessBindings {
|
|
63
|
+
uvGetOsfhandle(fileDescriptor: number): NativePtr | null;
|
|
64
|
+
}
|
|
58
65
|
/** Koffi STARTUPINFOW layout. */
|
|
59
66
|
export declare const STARTUPINFOW: import("koffi").TypeObject;
|
|
60
67
|
/** Koffi PROCESS_INFORMATION layout. */
|
|
@@ -108,7 +115,12 @@ export declare function decodeProcessInfo(processInfo: NativePtr): ProcessInfoOu
|
|
|
108
115
|
* @param create - binds only the caller-specific operations from the shared libraries.
|
|
109
116
|
* @returns generic process bindings combined with the caller-specific operations.
|
|
110
117
|
*/
|
|
111
|
-
export declare function extendWin32ProcessBindings<Extension extends object>(create: (context: Win32BindingContext) => Extension):
|
|
118
|
+
export declare function extendWin32ProcessBindings<Extension extends object>(create: (context: Win32BindingContext) => Extension): CurrentTokenProcessBindings & Extension;
|
|
119
|
+
/**
|
|
120
|
+
* Load the generic process binding table without policy-specific extensions.
|
|
121
|
+
* @returns shared Win32 process, stdio, and Job operations.
|
|
122
|
+
*/
|
|
123
|
+
export declare function loadWin32ProcessBindings(): CurrentTokenProcessBindings;
|
|
112
124
|
/**
|
|
113
125
|
* Format a Win32 error code through FormatMessageW.
|
|
114
126
|
* @param api - active binding table.
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Shared low-level Win32 process, stdio, and Job Object primitives. */
|
|
2
2
|
export { ERROR_INSUFFICIENT_BUFFER } from './abi.ts';
|
|
3
3
|
export * from './errors.ts';
|
|
4
|
-
export { allocPtrSlot, allocUint32, decodePtr, decodeUint32, extendWin32ProcessBindings, isNullPtr, throwLastError, throwWin32, } from './ffi.ts';
|
|
5
|
-
export type { NativePtr, Win32ProcessBindings, } from './ffi.ts';
|
|
6
|
-
export { drainPipe, spawnInheritedJobProcess, spawnPipedProcess, waitForProcessExit, } from './process.ts';
|
|
7
|
-
export type { SpawnedJobProcess, SpawnedPipedProcess, } from './process.ts';
|
|
4
|
+
export { allocPtrSlot, allocUint32, decodePtr, decodeUint32, extendWin32ProcessBindings, isNullPtr, loadWin32ProcessBindings, throwLastError, throwWin32, } from './ffi.ts';
|
|
5
|
+
export type { CurrentTokenProcessBindings, NativePtr, Win32ProcessBindings, } from './ffi.ts';
|
|
6
|
+
export { closeHandleChecked, drainPipe, isJobEmpty, pollProcessExit, probeCurrentTokenJobSupport, spawnInheritedJobProcess, spawnCurrentTokenJobProcess, spawnPipedProcess, terminateJob, waitForProcessExit, } from './process.ts';
|
|
7
|
+
export type { CurrentTokenStdioFileDescriptors, CurrentTokenProcessSpawnOptions, SpawnedJobProcess, SpawnedPipedProcess, } from './process.ts';
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/process.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Typed Win32 process operations over the shared binding table. */
|
|
2
|
-
import type { NativePtr, Win32ProcessBindings } from './ffi.ts';
|
|
2
|
+
import type { CurrentTokenProcessBindings, NativePtr, Win32ProcessBindings } from './ffi.ts';
|
|
3
3
|
/**
|
|
4
4
|
* Quote one argument according to CommandLineToArgvW parsing.
|
|
5
5
|
* @param argument - one argv entry.
|
|
@@ -13,14 +13,31 @@ export declare function quoteArg(argument: string): string;
|
|
|
13
13
|
* @returns joined Win32 command line.
|
|
14
14
|
*/
|
|
15
15
|
export declare function buildCommandLine(program: string, args: readonly string[]): string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/** Executable argv entry passed through CreateProcessAsUserW. */
|
|
16
|
+
interface ProcessSpawnOptions {
|
|
17
|
+
/** Executable argv entry passed through CreateProcess. */
|
|
19
18
|
command: string;
|
|
20
19
|
/** Arguments excluding the executable. */
|
|
21
20
|
args: readonly string[];
|
|
22
21
|
/** Existing child working directory. */
|
|
23
22
|
cwd: string;
|
|
23
|
+
}
|
|
24
|
+
/** Ordinary process creation inputs used by the local Win32 runner. */
|
|
25
|
+
export interface CurrentTokenProcessSpawnOptions extends ProcessSpawnOptions {
|
|
26
|
+
/** Resolved executable path passed separately from the preserved argv entry. */
|
|
27
|
+
applicationName: string;
|
|
28
|
+
/** Complete target environment passed without mutating the runner. */
|
|
29
|
+
env: Readonly<Record<string, string>>;
|
|
30
|
+
/** Runner CRT descriptors carrying target stdin, stdout, and stderr. */
|
|
31
|
+
stdio: CurrentTokenStdioFileDescriptors;
|
|
32
|
+
}
|
|
33
|
+
/** Runner CRT descriptors whose OS handles become the target standard handles. */
|
|
34
|
+
export interface CurrentTokenStdioFileDescriptors {
|
|
35
|
+
stdin: number;
|
|
36
|
+
stdout: number;
|
|
37
|
+
stderr: number;
|
|
38
|
+
}
|
|
39
|
+
/** Restricted-token process creation inputs owned by the Windows ACL sandbox. */
|
|
40
|
+
export interface RestrictedProcessSpawnOptions extends ProcessSpawnOptions {
|
|
24
41
|
/** Restricted primary token supplied by sandbox policy. */
|
|
25
42
|
token: NativePtr;
|
|
26
43
|
}
|
|
@@ -67,7 +84,7 @@ export declare function drainPipe(api: Win32ProcessBindings, handle: NativePtr):
|
|
|
67
84
|
*/
|
|
68
85
|
export declare function waitForProcessExit(api: Win32ProcessBindings, process: NativePtr): number;
|
|
69
86
|
/**
|
|
70
|
-
* Spawn suspended, assign
|
|
87
|
+
* Spawn a restricted-token process suspended, assign its Job, then resume it.
|
|
71
88
|
* @param api - active binding table.
|
|
72
89
|
* @param options - command, cwd, args, and restricted primary token.
|
|
73
90
|
* @returns caller-owned process and Job handles after successful resume.
|
|
@@ -77,4 +94,45 @@ export declare function waitForProcessExit(api: Win32ProcessBindings, process: N
|
|
|
77
94
|
* failure must not replace the already-created child's outcome.
|
|
78
95
|
*/
|
|
79
96
|
export declare function spawnInheritedJobProcess(api: Win32ProcessBindings, options: RestrictedProcessSpawnOptions): SpawnedJobProcess;
|
|
97
|
+
/**
|
|
98
|
+
* Spawn an ordinary process suspended, assign its Job, then resume it.
|
|
99
|
+
* @param api - active binding table.
|
|
100
|
+
* @param options - command, cwd, argv, and target carrier descriptors.
|
|
101
|
+
* @returns caller-owned process and Job handles after successful resume.
|
|
102
|
+
*/
|
|
103
|
+
export declare function spawnCurrentTokenJobProcess(api: CurrentTokenProcessBindings, options: CurrentTokenProcessSpawnOptions): SpawnedJobProcess;
|
|
104
|
+
/**
|
|
105
|
+
* Verify that an unnamed kill-on-close Job can be created and released now.
|
|
106
|
+
* @param api - active binding table.
|
|
107
|
+
*/
|
|
108
|
+
export declare function probeCurrentTokenJobSupport(api: CurrentTokenProcessBindings): void;
|
|
109
|
+
/**
|
|
110
|
+
* Poll one process handle without blocking the runner event loop.
|
|
111
|
+
* @param api - active binding table.
|
|
112
|
+
* @param process - caller-owned process handle.
|
|
113
|
+
* @returns the direct exit code when signalled, or undefined while running.
|
|
114
|
+
*/
|
|
115
|
+
export declare function pollProcessExit(api: Win32ProcessBindings, process: NativePtr): number | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Return whether a Job has no active processes.
|
|
118
|
+
* @param api - active binding table.
|
|
119
|
+
* @param job - caller-owned Job handle.
|
|
120
|
+
* @returns true once the Job reports zero active processes.
|
|
121
|
+
*/
|
|
122
|
+
export declare function isJobEmpty(api: Win32ProcessBindings, job: NativePtr): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Terminate every process in a Job.
|
|
125
|
+
* @param api - active binding table.
|
|
126
|
+
* @param job - caller-owned Job handle.
|
|
127
|
+
* @param exitCode - direct Windows exit code assigned to members.
|
|
128
|
+
*/
|
|
129
|
+
export declare function terminateJob(api: Win32ProcessBindings, job: NativePtr, exitCode: number): void;
|
|
130
|
+
/**
|
|
131
|
+
* Close a caller-owned handle and report a labelled Win32 failure.
|
|
132
|
+
* @param api - active binding table.
|
|
133
|
+
* @param handle - handle to close.
|
|
134
|
+
* @param detail - lifecycle label for diagnostics.
|
|
135
|
+
*/
|
|
136
|
+
export declare function closeHandleChecked(api: Win32ProcessBindings, handle: NativePtr, detail: string): void;
|
|
137
|
+
export {};
|
|
80
138
|
//# sourceMappingURL=process.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-win32-process",
|
|
3
|
-
"description": "
|
|
4
|
-
"version": "0.1.
|
|
3
|
+
"description": "Shared low-level Win32 process, stdio, and Job Object primitives",
|
|
4
|
+
"version": "0.1.3-alpha.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|