Files
CipherTalk/electron/workers/decryptWorker.js
T

89 lines
3.1 KiB
JavaScript

const { parentPort, workerData } = require('worker_threads')
const path = require('path')
const fs = require('fs')
const koffi = require('koffi')
// 从 workerData 获取 DLL 路径
const { dllPath } = workerData
if (!dllPath || !fs.existsSync(dllPath)) {
parentPort?.postMessage({ type: 'error', error: 'DLL path not found: ' + dllPath })
process.exit(1)
}
try {
// 加载 DLL
const lib = koffi.load(dllPath)
// 定义回调类型
const ProgressCallback = koffi.proto('void ProgressCallback(int current, int total)')
// 绑定函数 (这里使用同步版本,因为 Worker 本身就是独立的线程)
const Wcdb_DecryptDatabaseWithProgress = lib.func('int Wcdb_DecryptDatabaseWithProgress(const char* inputPath, const char* outputPath, const char* hexKey, ProgressCallback* callback)')
const Wcdb_GetLastErrorMsg = lib.func('int Wcdb_GetLastErrorMsg(char* buffer, int size)')
// 监听主线程消息
parentPort?.on('message', (message) => {
if (message.type === 'decrypt') {
const { id, inputPath, outputPath, hexKey } = message
try {
// 确保输出目录存在
const outputDir = path.dirname(outputPath)
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true })
}
// 定义进度回调 (带节流,每 100ms 更新一次)
let lastUpdate = 0
const onProgress = koffi.register((current, total) => {
const now = Date.now()
if (now - lastUpdate > 100 || current === total || current === 1) {
lastUpdate = now
parentPort?.postMessage({
type: 'progress',
id,
current,
total
})
}
}, koffi.pointer(ProgressCallback))
// 执行解密
const result = Wcdb_DecryptDatabaseWithProgress(inputPath, outputPath, hexKey, onProgress)
// 注销回调以释放资源
koffi.unregister(onProgress)
if (result === 0) {
parentPort?.postMessage({ type: 'success', id })
} else {
// 获取错误信息
const buffer = Buffer.alloc(512)
Wcdb_GetLastErrorMsg(buffer, 512)
const errorMsg = buffer.toString('utf8').replace(/\0+$/, '')
parentPort?.postMessage({
type: 'error',
id,
error: errorMsg || `ErrorCode: ${result}`
})
}
} catch (err) {
parentPort?.postMessage({
type: 'error',
id,
error: String(err)
})
}
}
})
// 通知主线程 Worker 已就绪
parentPort?.postMessage({ type: 'ready' })
} catch (err) {
parentPort?.postMessage({ type: 'error', error: String(err) })
}