mirror of
https://github.com/stablyai/orca.git
synced 2026-09-27 08:02:35 +00:00
refactor(windows): vendor the registry addon as @orca/windows-registry
windows-native-registry@3.2.2 was last published in 2023 by a single maintainer. Orca called two of its exports, both read-only, so the whole dependency is replaced by a local N-API addon under native/. The vendored addon is read-only by construction: setValue, createKey and deleteKey are gone, so RegDeleteTreeW no longer ships in the app. Two upstream defects are also fixed rather than carried over — the name/data scratch buffers were file-scope statics that concurrent reads would scribble over, and createKey/deleteKey called .c_str() on a temporary. Build wiring keeps the existing shape: still an optionalDependency gated to win32, still excluded from pnpm's allowBuilds so only Orca's own Windows rebuild runs node-gyp for it, still copied into the packaged resources. The CI native caches now key on the vendored sources so an addon.cc edit cannot restore a stale .node.
This commit is contained in:
@@ -150,9 +150,9 @@ runs:
|
||||
with:
|
||||
path: |
|
||||
node_modules/.pnpm/node-pty@*/node_modules/node-pty/build
|
||||
node_modules/.pnpm/windows-native-registry@*/node_modules/windows-native-registry/build
|
||||
node_modules/.pnpm/@orca+windows-registry@*/node_modules/@orca/windows-registry/build
|
||||
node_modules/.pnpm/@vscode+windows-process-tree@*/node_modules/@vscode/windows-process-tree/build
|
||||
key: native-modules-${{ runner.os }}-${{ steps.native-cache-scope.outputs.scope }}-${{ runner.arch }}-${{ inputs.native-runtime }}-node${{ steps.requested-node.outputs.node-version || steps.default-node.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch') }}
|
||||
key: native-modules-${{ runner.os }}-${{ steps.native-cache-scope.outputs.scope }}-${{ runner.arch }}-${{ inputs.native-runtime }}-node${{ steps.requested-node.outputs.node-version || steps.default-node.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json') }}
|
||||
|
||||
- name: Restore compiled native modules without saving
|
||||
id: native-cache-restore-only
|
||||
@@ -161,9 +161,9 @@ runs:
|
||||
with:
|
||||
path: |
|
||||
node_modules/.pnpm/node-pty@*/node_modules/node-pty/build
|
||||
node_modules/.pnpm/windows-native-registry@*/node_modules/windows-native-registry/build
|
||||
node_modules/.pnpm/@orca+windows-registry@*/node_modules/@orca/windows-registry/build
|
||||
node_modules/.pnpm/@vscode+windows-process-tree@*/node_modules/@vscode/windows-process-tree/build
|
||||
key: native-modules-${{ runner.os }}-${{ steps.native-cache-scope.outputs.scope }}-${{ runner.arch }}-${{ inputs.native-runtime }}-node${{ steps.requested-node.outputs.node-version || steps.default-node.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch') }}
|
||||
key: native-modules-${{ runner.os }}-${{ steps.native-cache-scope.outputs.scope }}-${{ runner.arch }}-${{ inputs.native-runtime }}-node${{ steps.requested-node.outputs.node-version || steps.default-node.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json') }}
|
||||
|
||||
# pnpm's bundled gyp_main.py is not executable on fresh Linux runners.
|
||||
- name: Use external node-gyp
|
||||
|
||||
@@ -829,9 +829,9 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
node_modules/.pnpm/node-pty@*/node_modules/node-pty/build
|
||||
node_modules/.pnpm/windows-native-registry@*/node_modules/windows-native-registry/build
|
||||
node_modules/.pnpm/@orca+windows-registry@*/node_modules/@orca/windows-registry/build
|
||||
node_modules/.pnpm/@vscode+windows-process-tree@*/node_modules/@vscode/windows-process-tree/build
|
||||
key: native-modules-${{ runner.os }}-${{ steps.deps.outputs.native-cache-scope }}-${{ runner.arch }}-node-node${{ steps.deps.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch') }}
|
||||
key: native-modules-${{ runner.os }}-${{ steps.deps.outputs.native-cache-scope }}-${{ runner.arch }}-node-node${{ steps.deps.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json') }}
|
||||
|
||||
# vitest runs here directly rather than through `pnpm test`, so the addon
|
||||
# assertions only hold once install-node-dependencies has rebuilt natives.
|
||||
@@ -897,9 +897,9 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
node_modules/.pnpm/node-pty@*/node_modules/node-pty/build
|
||||
node_modules/.pnpm/windows-native-registry@*/node_modules/windows-native-registry/build
|
||||
node_modules/.pnpm/@orca+windows-registry@*/node_modules/@orca/windows-registry/build
|
||||
node_modules/.pnpm/@vscode+windows-process-tree@*/node_modules/@vscode/windows-process-tree/build
|
||||
key: native-modules-${{ runner.os }}-${{ steps.deps.outputs.native-cache-scope }}-${{ runner.arch }}-electron-node${{ steps.deps.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch') }}
|
||||
key: native-modules-${{ runner.os }}-${{ steps.deps.outputs.native-cache-scope }}-${{ runner.arch }}-electron-node${{ steps.deps.outputs.node-version }}-${{ hashFiles('pnpm-lock.yaml', '.github/actions/install-node-dependencies/action.yml', 'config/scripts/ensure-native-runtime.mjs', 'config/scripts/rebuild-native-deps.mjs', 'config/patches/node-pty@1.1.0.patch', 'config/patches/@vscode__windows-process-tree@0.8.0.patch', 'native/windows-registry/src/addon.cc', 'native/windows-registry/binding.gyp', 'native/windows-registry/package.json') }}
|
||||
|
||||
- name: Prepare Electron native runtime
|
||||
run: node config/scripts/ensure-native-runtime.mjs --runtime=electron
|
||||
|
||||
@@ -35,7 +35,7 @@ const PACKAGED_RUNTIME_PACKAGE_ROOTS = [
|
||||
]
|
||||
const WINDOWS_PACKAGED_RUNTIME_PACKAGE_ROOTS = [
|
||||
'@vscode/windows-process-tree',
|
||||
'windows-native-registry'
|
||||
'@orca/windows-registry'
|
||||
]
|
||||
|
||||
const NODE_PTY_PREBUILD_PREFIX_BY_PLATFORM = {
|
||||
|
||||
@@ -22,7 +22,7 @@ const runtime = readRuntimeArg()
|
||||
const NATIVE_MODULES = [
|
||||
'node-pty',
|
||||
...(process.platform === 'win32'
|
||||
? ['windows-native-registry', '@vscode/windows-process-tree']
|
||||
? ['@orca/windows-registry', '@vscode/windows-process-tree']
|
||||
: [])
|
||||
]
|
||||
const NODE_PTY_CONPTY_RUNTIME_FILES = ['conpty.dll', 'OpenConsole.exe']
|
||||
@@ -275,7 +275,7 @@ function loadNativeModule(moduleName) {
|
||||
}
|
||||
return
|
||||
}
|
||||
if (moduleName === 'windows-native-registry') {
|
||||
if (moduleName === '@orca/windows-registry') {
|
||||
const registry = require(moduleName)
|
||||
// Why: the package defers loading its .node addon until the first registry call.
|
||||
registry.getRegistryKey(registry.HK.CU, 'Environment')
|
||||
|
||||
@@ -87,7 +87,7 @@ describe('ensure-native-runtime', () => {
|
||||
const log = readFileSync(logPath, 'utf8')
|
||||
expect(log.match(/pnpm exec node-gyp rebuild\n/g)).toHaveLength(2)
|
||||
expect(log).toContain(join('node_modules', 'node-pty'))
|
||||
expect(log).toContain(join('node_modules', 'windows-native-registry'))
|
||||
expect(log).toContain(join('node_modules', '@orca', 'windows-registry'))
|
||||
} finally {
|
||||
rmSync(projectDir, { recursive: true, force: true })
|
||||
}
|
||||
@@ -299,11 +299,11 @@ function writeFakeWindowsRegistry(projectDir, { requiresMarker = false } = {}) {
|
||||
if (process.platform !== 'win32') {
|
||||
return
|
||||
}
|
||||
const registryDir = join(projectDir, 'node_modules', 'windows-native-registry')
|
||||
const registryDir = join(projectDir, 'node_modules', '@orca', 'windows-registry')
|
||||
mkdirSync(registryDir, { recursive: true })
|
||||
writeFileSync(
|
||||
join(registryDir, 'package.json'),
|
||||
'{"name":"windows-native-registry","version":"3.2.2","main":"index.js"}\n'
|
||||
'{"name":"@orca/windows-registry","version":"1.0.0","main":"index.js"}\n'
|
||||
)
|
||||
const markerGate = requiresMarker
|
||||
? `if (!require('node:fs').existsSync(process.env.ORCA_NATIVE_TEST_MARKER)) { throw new Error('registry ABI mismatch sentinel') }`
|
||||
|
||||
@@ -19,24 +19,20 @@ describe('Electron runtime package contract', () => {
|
||||
})
|
||||
|
||||
it('keeps the native Windows registry addon optional and platform-gated', () => {
|
||||
const rebuildScript = readFileSync(
|
||||
join(projectDir, 'config/scripts/rebuild-native-deps.mjs'),
|
||||
'utf8'
|
||||
const rebuildScript = readProject('config/scripts/rebuild-native-deps.mjs')
|
||||
const ensureScript = readProject('config/scripts/ensure-native-runtime.mjs')
|
||||
expect(packageJson.optionalDependencies['@orca/windows-registry']).toBe(
|
||||
'file:./native/windows-registry'
|
||||
)
|
||||
const ensureScript = readFileSync(
|
||||
join(projectDir, 'config/scripts/ensure-native-runtime.mjs'),
|
||||
'utf8'
|
||||
)
|
||||
expect(packageJson.optionalDependencies['windows-native-registry']).toBe('3.2.2')
|
||||
// Why: pnpm installs optional target architectures on every host; the root
|
||||
// Windows-only rebuild owns this addon so macOS/Linux never run node-gyp for it.
|
||||
expect(pnpmWorkspace.allowBuilds['windows-native-registry']).toBe(false)
|
||||
expect(pnpmWorkspace.allowBuilds['@orca/windows-registry']).toBe(false)
|
||||
// Why assert the guard and the member separately: the list now carries more
|
||||
// than one addon, so pinning the whole literal only tested its formatting.
|
||||
expect(rebuildScript).toContain("rebuildPlatform === 'win32'")
|
||||
expect(rebuildScript).toContain("'windows-native-registry'")
|
||||
expect(rebuildScript).toContain("'@orca/windows-registry'")
|
||||
expect(ensureScript).toContain("process.platform === 'win32'")
|
||||
expect(ensureScript).toContain("'windows-native-registry'")
|
||||
expect(ensureScript).toContain("'@orca/windows-registry'")
|
||||
const packageTargets = {
|
||||
win32: createPackagedRuntimeNodeModuleResources('win32'),
|
||||
darwin: createPackagedRuntimeNodeModuleResources('darwin'),
|
||||
@@ -44,14 +40,14 @@ describe('Electron runtime package contract', () => {
|
||||
}
|
||||
expect(packageTargets.win32).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ to: join('node_modules', 'windows-native-registry') }),
|
||||
expect.objectContaining({ to: join('node_modules', '@orca', 'windows-registry') }),
|
||||
expect.objectContaining({ to: join('node_modules', 'node-addon-api') })
|
||||
])
|
||||
)
|
||||
for (const platform of ['darwin', 'linux']) {
|
||||
expect(packageTargets[platform]).not.toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ to: join('node_modules', 'windows-native-registry') })
|
||||
expect.objectContaining({ to: join('node_modules', '@orca', 'windows-registry') })
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ describe('PR workflow parallelism', () => {
|
||||
expect(cacheStep.with.key).toContain('config/scripts/ensure-native-runtime.mjs')
|
||||
expect(cacheStep.with.key).toContain('config/scripts/rebuild-native-deps.mjs')
|
||||
expect(cacheStep.with.path).toContain('node-pty@*/node_modules/node-pty/build')
|
||||
expect(cacheStep.with.path).toContain('windows-native-registry@')
|
||||
expect(cacheStep.with.path).toContain('@orca+windows-registry@')
|
||||
expect(cacheStep.with.path).toContain('@vscode+windows-process-tree@')
|
||||
expect(cacheStep.with['restore-keys']).toBeUndefined()
|
||||
}
|
||||
|
||||
@@ -239,9 +239,9 @@ describe('rebuild-native-deps patched node-pty rebuild', () => {
|
||||
})
|
||||
|
||||
expect(result.status, result.stderr).toBe(0)
|
||||
expect(result.stdout).toContain('Rebuilding failed native modules: windows-native-registry')
|
||||
expect(result.stdout).toContain('Rebuilding failed native modules: @orca/windows-registry')
|
||||
const rebuildCall = JSON.parse(readFileSync(rebuildLogPath, 'utf8').trim())
|
||||
expect(rebuildCall.onlyModules).toEqual(['windows-native-registry'])
|
||||
expect(rebuildCall.onlyModules).toEqual(['@orca/windows-registry'])
|
||||
} finally {
|
||||
removeTreeSync(projectDir)
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ exports.loadNativeModule = function loadNativeModule(nativeName) {
|
||||
}
|
||||
|
||||
export function writeFakeWindowsRegistry(projectDir) {
|
||||
const registryDir = join(projectDir, 'node_modules', 'windows-native-registry')
|
||||
const registryDir = join(projectDir, 'node_modules', '@orca', 'windows-registry')
|
||||
mkdirSync(registryDir, { recursive: true })
|
||||
writeFileSync(
|
||||
join(registryDir, 'index.js'),
|
||||
|
||||
@@ -76,9 +76,7 @@ if (ignoreModules.length > 0) {
|
||||
const NATIVE_MODULES = [
|
||||
'node-pty',
|
||||
'cpu-features',
|
||||
...(rebuildPlatform === 'win32'
|
||||
? ['windows-native-registry', '@vscode/windows-process-tree']
|
||||
: [])
|
||||
...(rebuildPlatform === 'win32' ? ['@orca/windows-registry', '@vscode/windows-process-tree'] : [])
|
||||
]
|
||||
const onlyModules = NATIVE_MODULES.filter((m) => !ignoreModules.includes(m))
|
||||
const forceRebuild =
|
||||
@@ -542,7 +540,7 @@ if (failures.length > 0) {
|
||||
}
|
||||
|
||||
function loadNativeModule(moduleName) {
|
||||
if (moduleName === 'windows-native-registry') {
|
||||
if (moduleName === '@orca/windows-registry') {
|
||||
const registry = projectRequire(moduleName)
|
||||
// Why: the package defers loading its .node addon until the first registry call.
|
||||
registry.getRegistryKey(registry.HK.CU, 'Environment')
|
||||
|
||||
@@ -504,7 +504,7 @@ miss exactly the detached, reparented descendants the trackers exist to find
|
||||
## Packaging
|
||||
|
||||
The addon is Windows-only, so it follows the same contract as
|
||||
`windows-native-registry` (asserted by
|
||||
`@orca/windows-registry` (asserted by
|
||||
`config/scripts/package-electron-runtime-contract.test.mjs`):
|
||||
|
||||
- an `optionalDependency`, so a macOS/Linux install tolerates its absence;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"targets": [
|
||||
{
|
||||
"target_name": "orca_windows_registry",
|
||||
"sources": ["src/addon.cc"],
|
||||
"libraries": ["advapi32.lib"],
|
||||
"include_dirs": ["<!@(node -p \"require('node-addon-api').include\")"],
|
||||
"defines": ["NAPI_DISABLE_CPP_EXCEPTIONS", "UNICODE", "_UNICODE"],
|
||||
"msvs_settings": {
|
||||
"VCCLCompilerTool": { "ExceptionHandling": 0 }
|
||||
},
|
||||
"conditions": [
|
||||
["OS!='win'", { "sources": [] , "type": "none" }]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
/** Registry root handles. Orca reads HKCU and HKLM; the rest are here to keep the enum faithful. */
|
||||
export declare const HK: {
|
||||
readonly CR: 0x80000000
|
||||
readonly CU: 0x80000001
|
||||
readonly LM: 0x80000002
|
||||
readonly U: 0x80000003
|
||||
readonly PD: 0x80000004
|
||||
readonly CC: 0x80000005
|
||||
readonly DD: 0x80000006
|
||||
}
|
||||
|
||||
export type RegistryValue = {
|
||||
name: string
|
||||
type: number
|
||||
value?: string | number | number[] | string[]
|
||||
}
|
||||
|
||||
/** Every value under `path`, keyed by value name. Null when the key cannot be opened or read. */
|
||||
export declare function getRegistryKey(
|
||||
root: number,
|
||||
path: string
|
||||
): Record<string, RegistryValue> | null
|
||||
@@ -0,0 +1,35 @@
|
||||
'use strict'
|
||||
|
||||
// Why lazy: non-Windows installs never build the addon, so requiring it at module load would
|
||||
// break any import of this package on macOS/Linux — including test collection.
|
||||
let addon = null
|
||||
function getAddon() {
|
||||
if (!addon) {
|
||||
addon = require('./build/Release/orca_windows_registry.node')
|
||||
}
|
||||
return addon
|
||||
}
|
||||
|
||||
const HK = {
|
||||
CR: 0x80000000,
|
||||
CU: 0x80000001,
|
||||
LM: 0x80000002,
|
||||
U: 0x80000003,
|
||||
PD: 0x80000004,
|
||||
CC: 0x80000005,
|
||||
DD: 0x80000006
|
||||
}
|
||||
|
||||
function getRegistryKey(root, path) {
|
||||
const values = getAddon().getKey(root, path)
|
||||
if (!values) {
|
||||
return null
|
||||
}
|
||||
const byName = {}
|
||||
for (const value of values) {
|
||||
byName[value.name] = value
|
||||
}
|
||||
return byName
|
||||
}
|
||||
|
||||
module.exports = { HK, getRegistryKey }
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@orca/windows-registry",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Read-only Windows registry value enumeration for Orca",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"binding.gyp",
|
||||
"src"
|
||||
],
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"dependencies": {
|
||||
"node-addon-api": "^8.5.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// Read-only Windows registry value enumeration for Orca.
|
||||
//
|
||||
// Vendored from windows-native-registry@3.2.2 (MIT, Eugene Pankov), reduced to the one
|
||||
// entry point Orca calls. The upstream write surface (setValue/createKey/deleteKey) is
|
||||
// deliberately absent: Orca only ever reads, and shipping RegDeleteTreeW in the app is
|
||||
// capability we have no use for.
|
||||
//
|
||||
// Two upstream defects are fixed here rather than carried over:
|
||||
// - the name/data scratch buffers were file-scope statics, so two concurrent reads
|
||||
// scribbled over each other; they are per-call locals now (heap for the 1 MB data
|
||||
// buffer, which is too large for a thread's stack).
|
||||
// - createKey/deleteKey called .c_str() on a temporary Utf16Value(); that use-after-free
|
||||
// left with the write surface.
|
||||
|
||||
#include <napi.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
// Registry value names cap at 32767 wide chars; data at 1 MB, matching upstream's ceiling.
|
||||
constexpr DWORD kNameMax = 32767;
|
||||
constexpr DWORD kDataMax = 1024 * 1024;
|
||||
|
||||
Napi::Value GetKey(const Napi::CallbackInfo& info) {
|
||||
auto env = info.Env();
|
||||
if (info.Length() < 2 || !info[0].IsNumber() || !info[1].IsString()) {
|
||||
Napi::TypeError::New(env, "getKey(root: number, path: string)").ThrowAsJavaScriptException();
|
||||
return env.Null();
|
||||
}
|
||||
|
||||
auto root = reinterpret_cast<HKEY>(static_cast<intptr_t>(info[0].As<Napi::Number>().Int64Value()));
|
||||
auto path = info[1].As<Napi::String>().Utf16Value();
|
||||
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExW(root, reinterpret_cast<LPCWSTR>(path.c_str()), 0, KEY_READ, &key) !=
|
||||
ERROR_SUCCESS) {
|
||||
return env.Null();
|
||||
}
|
||||
|
||||
// +2 on data so the two-wide-char terminator below always lands inside the buffer.
|
||||
std::vector<WCHAR> name(kNameMax);
|
||||
auto data = std::make_unique<BYTE[]>(kDataMax + 2);
|
||||
|
||||
auto values = Napi::Array::New(env);
|
||||
DWORD index = 0;
|
||||
|
||||
while (true) {
|
||||
DWORD nameLength = kNameMax - 1;
|
||||
DWORD dataLength = kDataMax - 1;
|
||||
DWORD valueType = 0;
|
||||
|
||||
LSTATUS error = RegEnumValueW(key, index, name.data(), &nameLength, nullptr, &valueType,
|
||||
data.get(), &dataLength);
|
||||
if (error != ERROR_SUCCESS) {
|
||||
if (error == ERROR_NO_MORE_ITEMS) {
|
||||
break;
|
||||
}
|
||||
RegCloseKey(key);
|
||||
return env.Null();
|
||||
}
|
||||
|
||||
auto entry = Napi::Object::New(env);
|
||||
entry.Set("name", Napi::String::New(env, reinterpret_cast<char16_t*>(name.data())));
|
||||
entry.Set("type", Napi::Number::New(env, static_cast<uint32_t>(valueType)));
|
||||
|
||||
if (valueType == REG_SZ || valueType == REG_EXPAND_SZ) {
|
||||
// RegEnumValueW does not guarantee a terminator when the stored value lacks one.
|
||||
data[dataLength] = 0;
|
||||
data[dataLength + 1] = 0;
|
||||
entry.Set("value", Napi::String::New(env, reinterpret_cast<char16_t*>(data.get())));
|
||||
} else if (valueType == REG_DWORD) {
|
||||
DWORD dword = 0;
|
||||
if (dataLength >= sizeof(DWORD)) {
|
||||
memcpy(&dword, data.get(), sizeof(DWORD));
|
||||
}
|
||||
entry.Set("value", Napi::Number::New(env, static_cast<uint32_t>(dword)));
|
||||
} else if (valueType == REG_BINARY) {
|
||||
auto bytes = Napi::Array::New(env, dataLength);
|
||||
for (DWORD i = 0; i < dataLength; i++) {
|
||||
bytes.Set(i, Napi::Number::New(env, static_cast<uint32_t>(data[i])));
|
||||
}
|
||||
entry.Set("value", bytes);
|
||||
} else if (valueType == REG_MULTI_SZ) {
|
||||
data[dataLength] = 0;
|
||||
data[dataLength + 1] = 0;
|
||||
auto parts = Napi::Array::New(env);
|
||||
DWORD pos = 0;
|
||||
uint32_t partIndex = 0;
|
||||
// dataLength includes the trailing empty string's terminator; stop before it.
|
||||
while (dataLength >= 2 && pos < dataLength - 2) {
|
||||
auto part = Napi::String::New(env, reinterpret_cast<char16_t*>(data.get() + pos));
|
||||
parts.Set(partIndex++, part);
|
||||
pos += static_cast<DWORD>((part.Utf16Value().length() + 1) * 2);
|
||||
}
|
||||
entry.Set("value", parts);
|
||||
}
|
||||
|
||||
values.Set(index++, entry);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
return values;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
||||
exports.Set("getKey", Napi::Function::New(env, GetKey));
|
||||
return exports;
|
||||
}
|
||||
|
||||
NODE_API_MODULE(orca_windows_registry, Init)
|
||||
+2
-2
@@ -295,13 +295,13 @@
|
||||
"zustand": "^5.0.14"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@orca/windows-registry": "file:./native/windows-registry",
|
||||
"@vscode/windows-process-tree": "0.8.0",
|
||||
"sherpa-onnx-darwin-arm64": "1.12.37",
|
||||
"sherpa-onnx-darwin-x64": "1.12.37",
|
||||
"sherpa-onnx-linux-arm64": "1.12.37",
|
||||
"sherpa-onnx-linux-x64": "1.12.37",
|
||||
"sherpa-onnx-win-x64": "1.12.37",
|
||||
"windows-native-registry": "3.2.2"
|
||||
"sherpa-onnx-win-x64": "1.12.37"
|
||||
},
|
||||
"lint-staged": {
|
||||
"{*.{ts,tsx,js,jsx,mjs,mts,cts},!(cloud)/**/*.{ts,tsx,js,jsx,mjs,mts,cts}}": [
|
||||
|
||||
Generated
+20
-34
@@ -508,6 +508,9 @@ importers:
|
||||
specifier: ^5.0.14
|
||||
version: 5.0.14(@types/react@19.2.17)(react@19.2.8)(use-sync-external-store@1.6.0(react@19.2.8))
|
||||
optionalDependencies:
|
||||
'@orca/windows-registry':
|
||||
specifier: file:./native/windows-registry
|
||||
version: file:native/windows-registry
|
||||
'@vscode/windows-process-tree':
|
||||
specifier: 0.8.0
|
||||
version: 0.8.0(patch_hash=e66202cc623996d02040c93449eb9ae353fddadf426cb53202a59ee710ee6fe7)
|
||||
@@ -526,9 +529,6 @@ importers:
|
||||
sherpa-onnx-win-x64:
|
||||
specifier: 1.12.37
|
||||
version: 1.12.37
|
||||
windows-native-registry:
|
||||
specifier: 3.2.2
|
||||
version: 3.2.2
|
||||
|
||||
packages:
|
||||
|
||||
@@ -1323,6 +1323,10 @@ packages:
|
||||
resolution: {integrity: sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
'@orca/windows-registry@file:native/windows-registry':
|
||||
resolution: {directory: native/windows-registry, type: directory}
|
||||
os: [win32]
|
||||
|
||||
'@oxc-parser/binding-android-arm-eabi@0.141.0':
|
||||
resolution: {integrity: sha512-jk7086MFvR/T4DG9IY7MKBVt1PMxvSZoz/TvnifodvS0pjghVwJHRttnAExhlwdMOgHv1TmLdENnbNpYk2zjvA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -5571,9 +5575,6 @@ packages:
|
||||
resolution: {integrity: sha512-vLBWCKb+7LWsX+TbfzWOkw0W81m377tyx3hOweBTjO43CXZnRGS1/JPWs20fr0PgZyDXk6ROYrylsEycK8raDA==}
|
||||
engines: {node: '>=22.12.0'}
|
||||
|
||||
node-addon-api@4.3.0:
|
||||
resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==}
|
||||
|
||||
node-addon-api@7.1.0:
|
||||
resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==}
|
||||
engines: {node: ^16 || ^18 || >= 20}
|
||||
@@ -5581,6 +5582,10 @@ packages:
|
||||
node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
|
||||
node-addon-api@8.9.2:
|
||||
resolution: {integrity: sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==}
|
||||
engines: {node: ^18 || ^20 || >= 21}
|
||||
|
||||
node-api-version@0.2.1:
|
||||
resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==}
|
||||
|
||||
@@ -6595,16 +6600,9 @@ packages:
|
||||
resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
||||
tldts-core@7.4.10:
|
||||
resolution: {integrity: sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==}
|
||||
|
||||
tldts-core@7.4.12:
|
||||
resolution: {integrity: sha512-nYNzS2WRf4QJmjzFFgAxLOBjyBxAGRbCy9PVBPaglcYyYajh40VBn+v5Ngr96ZMc7oM0+aCJdtQnNejvdBnXMQ==}
|
||||
|
||||
tldts@7.4.10:
|
||||
resolution: {integrity: sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==}
|
||||
hasBin: true
|
||||
|
||||
tldts@7.4.12:
|
||||
resolution: {integrity: sha512-WylhSDKVeYnWXL3a+vKTaOxjnOeEGw938hImY8zoRWJjRRK/Jp1K+IihBzIONpUmW4e3WmXT6q5FW6vlESVZCA==}
|
||||
hasBin: true
|
||||
@@ -6897,10 +6895,6 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
windows-native-registry@3.2.2:
|
||||
resolution: {integrity: sha512-yg1ZnuzUExn+Uq3cODB23Ju15URw0F/sRrSpjavVhHMi46s6Pcukp4+PtumoELmefoeHarCgci0XV34COpuYkw==}
|
||||
os: [win32]
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -7878,6 +7872,11 @@ snapshots:
|
||||
'@opentelemetry/api@1.9.1':
|
||||
optional: true
|
||||
|
||||
'@orca/windows-registry@file:native/windows-registry':
|
||||
dependencies:
|
||||
node-addon-api: 8.9.2
|
||||
optional: true
|
||||
|
||||
'@oxc-parser/binding-android-arm-eabi@0.141.0':
|
||||
optional: true
|
||||
|
||||
@@ -12244,14 +12243,14 @@ snapshots:
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
|
||||
node-addon-api@4.3.0:
|
||||
optional: true
|
||||
|
||||
node-addon-api@7.1.0:
|
||||
optional: true
|
||||
|
||||
node-addon-api@7.1.1: {}
|
||||
|
||||
node-addon-api@8.9.2:
|
||||
optional: true
|
||||
|
||||
node-api-version@0.2.1:
|
||||
dependencies:
|
||||
semver: 7.8.1
|
||||
@@ -13481,16 +13480,8 @@ snapshots:
|
||||
|
||||
tinyrainbow@3.1.0: {}
|
||||
|
||||
tldts-core@7.4.10:
|
||||
optional: true
|
||||
|
||||
tldts-core@7.4.12: {}
|
||||
|
||||
tldts@7.4.10:
|
||||
dependencies:
|
||||
tldts-core: 7.4.10
|
||||
optional: true
|
||||
|
||||
tldts@7.4.12:
|
||||
dependencies:
|
||||
tldts-core: 7.4.12
|
||||
@@ -13509,7 +13500,7 @@ snapshots:
|
||||
|
||||
tough-cookie@6.0.2:
|
||||
dependencies:
|
||||
tldts: 7.4.10
|
||||
tldts: 7.4.12
|
||||
optional: true
|
||||
|
||||
trim-lines@3.0.1: {}
|
||||
@@ -13776,11 +13767,6 @@ snapshots:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
windows-native-registry@3.2.2:
|
||||
dependencies:
|
||||
node-addon-api: 4.3.0
|
||||
optional: true
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ allowBuilds:
|
||||
node-pty: true
|
||||
sherpa-onnx: true
|
||||
ssh2: false
|
||||
windows-native-registry: false
|
||||
"@orca/windows-registry": false
|
||||
|
||||
overrides:
|
||||
monaco-editor>dompurify: 3.4.14
|
||||
|
||||
@@ -21,5 +21,5 @@ const requireFromMain = createRequire(__filename)
|
||||
|
||||
export function loadWindowsNativeRegistry(): WindowsNativeRegistryModule {
|
||||
// Why: non-Windows installs omit this optional dependency, so never resolve it at module load.
|
||||
return requireFromMain('windows-native-registry') as WindowsNativeRegistryModule
|
||||
return requireFromMain('@orca/windows-registry') as WindowsNativeRegistryModule
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user