|
| 1 | +const path = require('path'); |
| 2 | +const fs = require('fs'); |
| 3 | +const {env} = require('process'); |
| 4 | +const searchDir = env.PATH.split(path.delimiter); |
| 5 | +const blacklist = [ |
| 6 | +"advapi32.dll", "kernel32.dll", "msvcrt.dll", "ole32.dll", "user32.dll", |
| 7 | +"ws2_32.dll", "comdlg32.dll", "gdi32.dll", "imm32.dll", "oleaut32.dll", |
| 8 | +"shell32.dll", "winmm.dll", "winspool.drv", "wldap32.dll", |
| 9 | +"ntdll.dll", "d3d9.dll", "mpr.dll", "crypt32.dll", "dnsapi.dll", |
| 10 | +"shlwapi.dll", "version.dll", "iphlpapi.dll", "msimg32.dll", "setupapi.dll", |
| 11 | +"opengl32.dll", "dwmapi.dll", "uxtheme.dll", "secur32.dll", "gdiplus.dll", |
| 12 | +"usp10.dll", "comctl32.dll", "wsock32.dll", "netapi32.dll", "userenv.dll", |
| 13 | +"avicap32.dll", "avrt.dll", "psapi.dll", "mswsock.dll", "glu32.dll", |
| 14 | +"bcrypt.dll", "rpcrt4.dll", "hid.dll", "dbghelp.dll", |
| 15 | +"d3d11.dll", "dxgi.dll", "dwrite.dll" |
| 16 | +]; |
| 17 | + |
| 18 | +async function call(file, {args, grep, callback}) { |
| 19 | + const {spawn} = require('child_process'); |
| 20 | + return new Promise((resolve, fail) => { |
| 21 | + const proc = spawn(file, args); |
| 22 | + let aborted = false; |
| 23 | + let stdout = ''; |
| 24 | + let stderr = ''; |
| 25 | + proc.stdout.on('data', data => { |
| 26 | + try { |
| 27 | + stdout = (stdout += data).replace(/^.*$/gm, line => { |
| 28 | + line.replace(grep, callback); |
| 29 | + return ''; |
| 30 | + }) |
| 31 | + } catch (abort) { |
| 32 | + aborted = true; |
| 33 | + proc.kill(); |
| 34 | + } |
| 35 | + }); |
| 36 | + proc.stderr.on('data', (data) => stderr += data); |
| 37 | + proc.on('close', (error) => { |
| 38 | + if (aborted) { |
| 39 | + resolve(stdout); |
| 40 | + } else { |
| 41 | + if (error) fail({file, args, error, stdout, stderr}) |
| 42 | + else resolve(stdout); |
| 43 | + } |
| 44 | + }); |
| 45 | + }); |
| 46 | +} |
| 47 | + |
| 48 | +function copyDependencies(exe, target) { |
| 49 | + call('objdump', { |
| 50 | + args:['-p', exe], |
| 51 | + grep:/DLL Name: (.*)|PE File Base Relocations/gi, |
| 52 | + callback: (_, dll) => { |
| 53 | + if (!dll) |
| 54 | + throw 0; |
| 55 | + if (!blacklist.includes(dll.toLowerCase())) { |
| 56 | + blacklist.push(dll.toLowerCase()); |
| 57 | + addImport(dll, [...searchDir]); |
| 58 | + } |
| 59 | + } |
| 60 | + }); |
| 61 | + |
| 62 | + function addImport(dll, searchQueue) { |
| 63 | + if (!searchQueue || !searchQueue.length) { |
| 64 | + if (dll.toLowerCase() != dll) addImport(dll.toLowerCase(), [...searchDir]); |
| 65 | + else { |
| 66 | + blacklist.push(dll); |
| 67 | + console.log('could not find', dll); |
| 68 | + } |
| 69 | + return; |
| 70 | + } |
| 71 | + const src = path.join(searchQueue.pop(), dll); |
| 72 | + fs.copyFile(src, path.join(target, dll), fs.constants.COPYFILE_FICLONE, (err) => { |
| 73 | + if (err) addImport(dll, searchQueue); |
| 74 | + else { |
| 75 | + console.log('copied', src); |
| 76 | + copyDependencies(src, target); |
| 77 | + } |
| 78 | + }); |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +async function main(exe) { |
| 83 | + if (!exe) { |
| 84 | + console.log('No exe given'); |
| 85 | + } else try { |
| 86 | + await copyDependencies(exe, path.dirname(exe)); |
| 87 | + } catch (ex) { |
| 88 | + if (ex && ex.stderr) { |
| 89 | + console.error(`Running ${ex.file} ${ex.args.join(" ")}:\n${ex.error}`); |
| 90 | + } else { |
| 91 | + console.error(ex); |
| 92 | + } |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +main(require('process').argv[2]); |
0 commit comments