From 3e8f7b5bb7087aada2f6d49197866fb815f644ab Mon Sep 17 00:00:00 2001 From: waiting <1661926154@qq.com> Date: Fri, 28 Jun 2024 15:29:00 +0800 Subject: [PATCH] feat: use koffi instead of ffi-napi to support nodejs >= 18 ref: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 Notable changes summary: 1. Use [koffi] as node-ffi to support nodejs >= 18 2. Remove dependencies ffi-napi, ref-napi, ref-struct-di, ref-union-di 3. Easy structures initialization `_Factory()` 4. Very easy structure/union definition 5. Auto create necessary struct/union when loading library from method def 6. Multiple Choice Parameters details: https://github.com/waitingsong/node-win32-api/CHANGES.v22.md --- .eslintrc.yml | 17 - .githooks/commit-msg | 27 + .githooks/gen-file-from-example.js | 79 +++ .githooks/gen-file-from-example.mts | 102 ++++ .githooks/gen-file-from-example.ts | 102 ++++ .../{init-repo => }/init-example-file.ts | 34 +- .githooks/init-repo.sh | 14 +- .githooks/init-repo/doc-list.ts | 27 - .githooks/init-repo/doc.ts | 224 -------- .githooks/init-repo/gen-file-from-example.ts | 38 -- .githooks/init-repo/init-utils.ts | 91 ---- .githooks/init-repo/is-skip-commitlint.ts | 25 - .githooks/init-repo/test-skip-commitlint.ts | 84 --- .githooks/{init-repo => }/init.config.ts | 9 +- .../is-skip-commitlint-rule.ts | 0 .githooks/pre-commit.sample | 7 +- .githooks/pre-push | 4 + .githooks/pre-push.sample | 6 + .githooks/set-scripts-executable-now.sh | 11 + .githooks/set-scripts-executable.sh | 17 +- .githooks/tsconfig.json | 5 +- .github/workflows/nodejs-win.yml | 69 ++- .github/workflows/nodejs.yml | 22 +- .github/workflows/npm-manual-publish.yml | 34 +- .github/workflows/npm-publish-wo-test.yml | 23 +- .gitignore | 9 + .mocharc.yml | 9 +- .npmrc | 2 + .nycrc.json | 19 +- .scripts/build.sh | 1 + .scripts/change-pkg-types-dist.sh | 12 - .scripts/change-pkg-types-src.sh | 12 - .scripts/ci/ci-env.sh | 4 + .scripts/ci/ci-prepare.sh | 13 +- .scripts/env.sh | 3 + .scripts/pre-publish-valiate.sh | 1 + .scripts/publish.sh | 7 +- .scripts/purge.sh | 21 + .vscode/common.code-snippets | 16 + .vscode/common.code-snippets.example | 16 + .vscode/launch.json.example | 6 +- .vscode/promise.code-snippets | 9 + .vscode/settings.json | 191 ++++++- .vscode/settings.json.example | 221 +++++++- CHANGES.v22.md | 115 ++++ README.md | 190 +------ README.zh-CN.md | 186 +------ appveyor.yml | 51 -- commitlint.config.js => commitlint.config.cjs | 0 eslint.config.mjs | 59 +++ lerna.json | 26 +- package.json | 56 +- packages/win32-api/.nycrc.json | 26 - packages/win32-api/README.md | 194 +------ packages/win32-api/README.zh-CN.md | 188 +------ .../win32-api/demo/EnumDisplayDevicesW.mts | 50 ++ packages/win32-api/demo/GetCursorPos.mts | 34 ++ packages/win32-api/demo/create_window.ts | 13 +- packages/win32-api/demo/find_window.ts | 4 +- packages/win32-api/demo/show-hide-desktop.mts | 53 ++ packages/win32-api/package.json | 101 ++-- packages/win32-api/rollup.config.js | 20 +- packages/win32-api/src/func/func.helper.ts | 43 -- packages/win32-api/src/func/func.ts | 7 - packages/win32-api/src/func/spoolss/helper.ts | 18 - .../src/func/spoolss/index.spoolss.ts | 42 -- .../src/func/spoolss/spoolss.types.ts | 18 - packages/win32-api/src/func/user32/helper.ts | 13 - .../win32-api/src/func/user32/index.user32.ts | 57 -- .../win32-api/src/func/winspool/helper.ts | 224 -------- .../src/func/winspool/index.winspool.ts | 281 ---------- .../src/func/winspool/winspool.types.ts | 18 - packages/win32-api/src/index.comctl32.ts | 3 - packages/win32-api/src/index.consts.ts | 3 - packages/win32-api/src/index.fun.ts | 3 - packages/win32-api/src/index.kernel32.ts | 3 - packages/win32-api/src/index.ntdll.ts | 3 - packages/win32-api/src/index.promise.ts | 9 - packages/win32-api/src/index.spoolss.ts | 3 - packages/win32-api/src/index.ts | 59 +-- packages/win32-api/src/index.user32.ts | 3 - packages/win32-api/src/index.util.ts | 3 + packages/win32-api/src/index.winspool.ts | 3 - .../win32-api/src/lib/comctl32/api.def.ts | 11 + packages/win32-api/src/lib/comctl32/api.ts | 13 - .../win32-api/src/lib/comctl32/api.types.ts | 14 + .../src/lib/comctl32/index.promise.ts | 16 - packages/win32-api/src/lib/comctl32/index.ts | 33 +- packages/win32-api/src/lib/gdi32/api.def.ts | 16 + packages/win32-api/src/lib/gdi32/api.ts | 42 -- packages/win32-api/src/lib/gdi32/api.types.ts | 31 ++ .../win32-api/src/lib/gdi32/index.promise.ts | 16 - packages/win32-api/src/lib/gdi32/index.ts | 33 +- packages/win32-api/src/lib/helper.ts | 493 ------------------ .../win32-api/src/lib/kernel32/api.def.ts | 42 ++ packages/win32-api/src/lib/kernel32/api.ts | 105 ---- .../win32-api/src/lib/kernel32/api.types.ts | 73 +++ .../src/lib/kernel32/index.promise.ts | 16 - packages/win32-api/src/lib/kernel32/index.ts | 33 +- packages/win32-api/src/lib/ntdll/api.ts | 21 - .../win32-api/src/lib/ntdll/index.promise.ts | 16 - packages/win32-api/src/lib/ntdll/index.ts | 24 - packages/win32-api/src/lib/spoolss/api.def.ts | 16 + packages/win32-api/src/lib/spoolss/api.ts | 38 -- .../win32-api/src/lib/spoolss/api.types.ts | 19 + .../src/lib/spoolss/index.promise.ts | 16 - packages/win32-api/src/lib/spoolss/index.ts | 35 +- packages/win32-api/src/lib/types.ts | 3 + packages/win32-api/src/lib/user32/api.def.ts | 9 + packages/win32-api/src/lib/user32/api.ts | 348 ------------- .../win32-api/src/lib/user32/api.types.ts | 12 + .../win32-api/src/lib/user32/dict/AB.def.ts | 12 + .../win32-api/src/lib/user32/dict/AB.types.ts | 22 + .../win32-api/src/lib/user32/dict/CD.def.ts | 45 ++ .../win32-api/src/lib/user32/dict/CD.types.ts | 44 ++ .../win32-api/src/lib/user32/dict/EF.def.ts | 29 ++ .../win32-api/src/lib/user32/dict/EF.types.ts | 43 ++ .../win32-api/src/lib/user32/dict/G.def.ts | 61 +++ .../win32-api/src/lib/user32/dict/G.types.ts | 83 +++ .../win32-api/src/lib/user32/dict/IM.def.ts | 19 + .../win32-api/src/lib/user32/dict/IM.types.ts | 24 + .../win32-api/src/lib/user32/dict/PR.def.ts | 27 + .../win32-api/src/lib/user32/dict/PR.types.ts | 40 ++ .../win32-api/src/lib/user32/dict/S.def.ts | 33 ++ .../win32-api/src/lib/user32/dict/S.types.ts | 58 +++ .../win32-api/src/lib/user32/dict/TU.def.ts | 24 + .../win32-api/src/lib/user32/dict/TU.types.ts | 26 + .../src/lib/user32/dict/index.def.ts | 3 + .../src/lib/user32/dict/index.types.ts | 6 + .../win32-api/src/lib/user32/index.promise.ts | 19 - packages/win32-api/src/lib/user32/index.ts | 36 +- packages/win32-api/src/lib/winmsg.ts | 65 --- .../win32-api/src/lib/winspool/api.def.ts | 103 ++++ packages/win32-api/src/lib/winspool/api.ts | 169 ------ .../win32-api/src/lib/winspool/api.types.ts | 172 ++++++ .../src/lib/winspool/index.promise.ts | 16 - packages/win32-api/src/lib/winspool/index.ts | 35 +- .../lib/winspool/mapper/GetPrinterW.mapper.ts | 34 ++ .../src/lib/winspool/mapper/index.mapper.ts | 11 + .../win32-api/src/util/user32/FindWindowEx.ts | 35 ++ .../src/util/user32/GetWindowText.ts | 39 ++ .../win32-api/src/util/user32/user32.index.ts | 4 + packages/win32-api/src/util/util.index.ts | 4 + .../src/util/winspool/ClosePrinter.ts | 23 + .../src/util/winspool/EndDocPrinter.ts | 20 + .../src/util/winspool/EnumPrinters.ts | 67 +++ .../src/util/winspool/GetDefaultPrinter.ts | 39 ++ .../win32-api/src/util/winspool/GetPrinter.ts | 42 ++ .../src/util/winspool/OpenPrinter.ts | 30 ++ .../src/util/winspool/StartDocPrinter.ts | 30 ++ .../src/util/winspool/winspool.index.ts | 10 + .../src/util/winspool/winspool.types.ts | 38 ++ .../win32-api/test/10.index.comctl32.test.ts | 19 - .../win32-api/test/11.index.kernel32.test.ts | 19 - .../win32-api/test/12.index.ntdll.test.ts | 19 - .../win32-api/test/13.index.user32.test.ts | 19 - packages/win32-api/test/21.main.test.ts | 61 --- packages/win32-api/test/70.user32.test.ts | 179 ------- .../win32-api/test/71.find-calc-async.test.ts | 100 ---- .../test/72.find-notepad-async.test.ts | 105 ---- packages/win32-api/test/80.misc.test.ts | 26 - packages/win32-api/test/81.constants.test.ts | 30 -- .../win32-api/test/90.loop-callback.test.ts | 49 -- packages/win32-api/test/config.unittest.ts | 2 +- packages/win32-api/test/foo1.ts.bak | 73 +++ packages/win32-api/test/foo2.ts.bak | 56 ++ .../test/gdi32/201.CreateCompatibleDC.test.ts | 27 - .../gdi32/202.CreateCompatibleBitmap.test.ts | 21 - .../test/{helper.ts => helper.ts.bak} | 5 +- .../test/helper/91.gen_api_opts.test.ts | 60 --- .../92.comctl32.helper.gen_api_opts.test.ts | 44 -- .../93.kernel32.helper.gen_api_opts.test.ts | 44 -- .../94.ntdll.helper.gen_api_opts.test.ts | 44 -- .../95.user32.helper.gen_api_opts.test.ts | 44 -- .../96.user32.helper.gen_api_opts.test.ts | 47 -- .../test/helper/97.bufferToStruct.test.ts | 58 --- .../test/kernel32/40.GetSystemTimes.test.ts | 62 --- .../win32-api/test/lib/20.comctl32.test.ts | 22 + packages/win32-api/test/lib/21.gdi32.test.ts | 22 + .../win32-api/test/lib/22.kernel32.test.ts | 22 + .../win32-api/test/lib/23.spoolss.test.ts | 22 + packages/win32-api/test/lib/24.user32.test.ts | 24 + .../win32-api/test/lib/25.winspool.test.ts | 22 + packages/win32-api/test/root.config.ts | 47 +- packages/win32-api/test/root.hooks.ts | 27 - packages/win32-api/test/setup.ts | 27 + packages/win32-api/test/tsconfig.json | 19 +- .../test/user32/201.FindWindowEx.test.ts | 28 - .../user32/51.EnumDisplayDevicesW.test.ts | 46 -- .../user32/52.GetRawInputDeviceInfoW.test.ts | 88 ---- .../user32/53.GetRawInputDeviceList.test.ts | 33 -- .../test/user32/54.GetWindowRect.test.ts | 47 -- .../test/user32/55.SendMessageW.test.ts | 67 --- .../user32/56.SendMessageW.SETTEXT.test.ts | 42 -- .../user32/57.SendMessageW.GETTEXT.test.ts | 58 --- .../test/user32/60.FlashWindowEx.test.ts | 68 --- .../test/user32/61.FlashWindow.test.ts | 52 -- .../test/user32/62.GetCaretPos.test.ts | 29 -- .../win32-api/test/user32/63.IsIconic.test.ts | 27 - packages/win32-api/test/util.ts | 2 +- .../test/util/user32/100.FindWindowEx.test.ts | 30 ++ .../util/user32/101.GetWindowText.test.ts | 53 ++ .../util/winspool/200.EnumPrinters.test.ts | 63 +++ .../winspool/201.GetDefaultPrinter.test.ts | 30 ++ .../util/winspool/202.OpenPrinter.test.ts | 16 + .../test/util/winspool/203.GetPrinter.test.ts | 42 ++ .../204.StartDocPrinter-EndDocPrinter.test.ts | 118 +++++ .../util/winspool/209.ClosePrinter.test.ts | 18 + .../winspool/501.GetDefaultPrinter.test.ts | 32 -- .../test/winspool/502.OpenPrinter.test.ts | 27 - .../test/winspool/503.GetPrinter.test.ts | 69 --- .../test/winspool/504.ClosePrinter.test.ts | 40 -- .../test/winspool/505.EnumPrinters.test.ts | 103 ---- .../winspool/506.EnumPrintProcessors.test.ts | 37 -- .../507.EnumPrintProcessorDatatypes.test.ts | 48 -- .../test/winspool/520.print-to-pdf.test.ts | 67 --- packages/win32-api/tsconfig.eslint.json | 20 - packages/win32-api/tsconfig.json | 25 +- packages/win32-def/.nycrc.json | 26 - packages/win32-def/README.md | 97 ++-- .../win32-def/demo/EnumDisplayDevicesW.mts | 42 ++ packages/win32-def/demo/EnumPrintersW.mts | 50 ++ packages/win32-def/demo/GetCursorPos.mts | 21 + packages/win32-def/demo/show-hide-desktop.mts | 63 +++ packages/win32-def/package.json | 70 +-- packages/win32-def/rollup.config.js | 20 +- packages/win32-def/src/index.def.ts | 6 - packages/win32-def/src/index.struct.ts | 8 +- packages/win32-def/src/index.ts | 12 +- packages/win32-def/src/index.types.ts | 13 + packages/win32-def/src/index.union.ts | 4 - packages/win32-def/src/lib/common.def.ts | 55 +- packages/win32-def/src/lib/common.types.ts | 83 ++- packages/win32-def/src/lib/config.ts | 9 +- .../win32-def/src/lib/consts/index.consts.ts | 5 + .../src/lib/consts/user32.enum.ts} | 4 +- .../src/lib/consts/virtual-key.enum.ts | 3 +- .../src/lib/consts/winbase.enum.ts} | 0 .../win32-def/src/lib/consts/wingdi.enum.ts | 6 +- .../win32-def/src/lib/consts/winmsg.enum.ts | 68 +++ .../win32-def/src/lib/consts/winspool.enum.ts | 3 +- .../consts/winspool/PRINTER_STATUS.enum.ts | 36 ++ packages/win32-def/src/lib/data.types.ts.bak | 96 ---- packages/win32-def/src/lib/def.enum.ts | 47 +- packages/win32-def/src/lib/ffi.types.ts | 181 ++----- packages/win32-def/src/lib/fixed-buffer.ts | 119 ----- packages/win32-def/src/lib/helper.ts | 97 ---- .../win32-def/src/lib/loader/def.helper.ts | 88 ++++ .../win32-def/src/lib/loader/loader.cache.ts | 121 +++++ .../win32-def/src/lib/loader/loader.helper.ts | 381 ++++++++++++++ packages/win32-def/src/lib/loader/loader.ts | 54 ++ .../win32-def/src/lib/loader/loader.types.ts | 88 ++++ .../loader/multiple-choice-param.helper.ts | 146 ++++++ .../lib/struct/comctl/INITCOMMONCONTROLSEX.ts | 36 ++ .../src/lib/struct/comctl/comctl.index.ts | 3 + .../src/lib/struct/index.struct.types.ts | 5 - .../src/lib/struct/minwinbase/FILETIME.ts | 36 ++ .../src/lib/struct/minwinbase/SYSTEMTIME.ts | 48 ++ .../lib/struct/minwinbase/minwinbase.index.ts | 4 + .../win32-def/src/lib/struct/struct.cache.ts | 44 ++ .../win32-def/src/lib/struct/struct.def.ts | 216 -------- .../src/lib/struct/struct.factory-map.ts | 15 + .../win32-def/src/lib/struct/struct.helper.ts | 196 +++++++ .../win32-def/src/lib/struct/struct.index.ts | 8 + .../src/lib/struct/struct.simple.helper.ts | 79 +++ .../win32-def/src/lib/struct/struct.types.ts | 241 --------- .../win32-def/src/lib/struct/struct.util.ts | 74 +++ .../src/lib/struct/struct.var.def.ts | 62 --- .../win32-def/src/lib/struct/windef/POINT.ts | 36 ++ .../win32-def/src/lib/struct/windef/RECT.ts | 40 ++ .../src/lib/struct/windef/windef.index.ts | 4 + .../win32-def/src/lib/struct/wingdi.def.ts | 60 --- .../win32-def/src/lib/struct/wingdi.types.ts | 89 ---- .../src/lib/struct/wingdi.var.def.ts | 18 - .../src/lib/struct/wingdi/DEVMODEW.ts | 126 +++++ .../src/lib/struct/wingdi/DISPLAY_DEVICEW.ts | 43 ++ .../src/lib/struct/wingdi/wingdi.index.ts | 4 + .../win32-def/src/lib/struct/winspool.def.ts | 78 --- .../src/lib/struct/winspool.types.ts | 102 ---- .../src/lib/struct/winspool.var.def.ts | 31 -- .../src/lib/struct/winspool/DOC_INFO_1.ts | 39 ++ .../src/lib/struct/winspool/JOB_INFO_1.ts | 61 +++ .../lib/struct/winspool/PRINTER_DEFAULTS.ts | 46 ++ .../src/lib/struct/winspool/PRINTER_INFO_1.ts | 41 ++ .../src/lib/struct/winspool/PRINTER_INFO_4.ts | 45 ++ .../src/lib/struct/winspool/PRINTER_INFO_5.ts | 43 ++ .../src/lib/struct/winspool/PRINTER_INFO_6.ts | 35 ++ .../src/lib/struct/winspool/PRINTER_INFO_8.ts | 35 ++ .../src/lib/struct/winspool/PRINTER_INFO_9.ts | 34 ++ .../struct/winspool/PRINTPROCESSOR_INFO_1.ts | 35 ++ .../src/lib/struct/winspool/helper.types.ts | 84 +++ .../src/lib/struct/winspool/winspool.index.ts | 13 + .../win32-def/src/lib/struct/winuser.def.ts | 29 -- .../win32-def/src/lib/struct/winuser.types.ts | 32 -- .../src/lib/struct/winuser.var.def.ts | 12 - .../src/lib/struct/winuser/ALTTABINFO.ts | 50 ++ .../src/lib/struct/winuser/COPYDATASTRUCT.ts | 38 ++ .../src/lib/struct/winuser/FLASHWINFO.ts | 42 ++ .../src/lib/struct/winuser/HARDWAREINPUT.ts | 36 ++ .../win32-def/src/lib/struct/winuser/INPUT.ts | 58 +++ .../src/lib/struct/winuser/KEYBDINPUT.ts | 42 ++ .../src/lib/struct/winuser/MOUSEINPUT.ts | 44 ++ .../win32-def/src/lib/struct/winuser/MSG.ts | 47 ++ .../src/lib/struct/winuser/RAWHID.ts | 40 ++ .../lib/struct/winuser/RAWINPUTDEVICELIST.ts | 36 ++ .../src/lib/struct/winuser/RAWINPUTHEADER.ts | 40 ++ .../src/lib/struct/winuser/RAWKEYBOARD.ts | 44 ++ .../src/lib/struct/winuser/RID_DEVICE_INFO.ts | 50 ++ .../lib/struct/winuser/RID_DEVICE_INFO_HID.ts | 42 ++ .../winuser/RID_DEVICE_INFO_KEYBOARD.ts | 44 ++ .../struct/winuser/RID_DEVICE_INFO_MOUSE.ts | 40 ++ .../src/lib/struct/winuser/WINDOWINFO.ts | 53 ++ .../src/lib/struct/winuser/WNDCLASSEXW.ts | 58 +++ .../src/lib/struct/winuser/winuser.index.ts | 20 + packages/win32-def/src/lib/types.ts | 119 +++++ .../src/lib/union/index.union.types.ts | 5 - packages/win32-def/src/lib/union/union.def.ts | 9 - .../win32-def/src/lib/union/union.types.ts | 9 - .../win32-def/src/lib/union/union.var.def.ts | 5 - .../src/lib/union/winspool.union.def.ts | 30 -- .../src/lib/union/winspool.union.types.ts | 33 -- .../src/lib/union/winspool.union.var.def.ts | 6 - packages/win32-def/src/lib/util.ts | 48 ++ packages/win32-def/test/.eslintrc.yml | 14 - .../01.loader-no-autoCreateStruct.test.ts | 37 ++ packages/win32-def/test/10.index.test.ts | 7 +- ...index.def.test.ts => 12.index.def.test.ts} | 7 +- .../win32-def/test/12.index.struct.test.ts | 36 -- .../win32-def/test/20.helper.struct.test.ts | 70 --- .../win32-def/test/21.helper.union.test.ts | 45 -- .../win32-def/test/30.fixed-buffer.test.ts | 132 ----- .../win32-def/test/31.StructFactory.test.ts | 149 ------ .../test/asserts/asserts.PRINTER_DEFAULTS.ts | 96 ---- .../test/def.class/20.loader.test.ts | 133 +++++ .../21.loader-multiple-choice.test.ts | 261 ++++++++++ ...der-updateMultipleChoiceMapper.map.test.ts | 67 +++ ...der-updateMultipleChoiceMapper.set.test.ts | 71 +++ .../def.class/25.loader.GetTickCount.test.ts | 29 ++ .../win32-def/test/def.class/api.helper.ts | 200 +++++++ .../test/def.const/20c.loader.test.ts | 108 ++++ .../21c.loader-multiple-choice.test.ts | 260 +++++++++ ...der-updateMultipleChoiceMapper.map.test.ts | 67 +++ ...der-updateMultipleChoiceMapper.set.test.ts | 71 +++ .../def.const/25c.loader.GetTickCount.test.ts | 29 ++ .../win32-def/test/def.const/api.helper.ts | 104 ++++ packages/win32-def/test/helper.ts | 14 + .../win32-def/test/lib/24.LoaderCache.test.ts | 65 +++ .../test/lib/30.ucsBufferFrom.test.ts | 18 + .../test/lib/31.ucsBufferToString.test.ts | 54 ++ .../{ => lib}/consts/40.consts.wingdi.test.ts | 3 +- .../consts/41.consts.key-mouse-vk.test.ts | 3 +- .../test/{ => lib}/consts/42.winuser.test.ts | 2 +- .../lib/struct/41.genSimpleStruct.test.ts | 80 +++ .../lib/struct/42.genComplexStruct.test.ts | 80 +++ .../test/lib/struct/43.genSimpleUnion.test.ts | 62 +++ .../test/lib/struct/44.genUnion.test.ts | 75 +++ .../lib/struct/45.StructUnionCache.test.ts | 58 +++ .../test/lib/struct/46.genFixedArray.test.ts | 24 + .../lib/struct/47.genFixedInt16Array.test.ts | 24 + .../lib/struct/48.decodeInt16Array.test.ts | 39 ++ .../test/lib/struct/50.POINT_Factory.test.ts | 75 +++ .../struct/51.DISPLAY_DEVICEW_Factory.test.ts | 29 ++ .../struct/52.PRINTER_INFO_X_Factory.test.ts | 33 ++ .../comctl/201.INITCOMMONCONTROLSEX.test.ts | 23 + .../struct/minwinbase/401.FILETIME.test.ts | 21 + .../struct/minwinbase/402.SYSTEMTIME.test.ts | 21 + .../test/lib/struct/windef/301.RECT.test.ts | 23 + .../test/lib/struct/windef/302.POINT.test.ts | 28 + .../struct/wingdi/501.DISPLAY_DEVICEW.test.ts | 21 + .../lib/struct/wingdi/502.DEVMODEW.test.ts | 21 + .../601.PRINTPROCESSOR_INFO_1.test.ts | 21 + .../struct/winspool/602.DOC_INFO_1.test.ts | 21 + .../winspool/603.PRINTER_DEFAULTS.test.ts | 21 + .../winspool/604.PRINTER_INFO_1.test.ts | 21 + .../winspool/605.PRINTER_INFO_4.test.ts | 21 + .../winspool/606.PRINTER_INFO_5.test.ts | 21 + .../winspool/607.PRINTER_INFO_6.test.ts | 21 + .../winspool/608.PRINTER_INFO_8.test.ts | 21 + .../winspool/609.PRINTER_INFO_9.test.ts | 21 + .../struct/winspool/610.JOB_INFO_1.test.ts | 21 + .../struct/winuser/101.HARDWAREINPUT.test.ts | 21 + .../lib/struct/winuser/102.KEYBDINPUT.test.ts | 23 + .../lib/struct/winuser/103.MOUSEINPUT.test.ts | 23 + .../struct/winuser/105.FLASHWINFO.ts.test.ts | 23 + .../lib/struct/winuser/106.ALTTABINFO.test.ts | 28 + .../struct/winuser/107.COPYDATASTRUCT.test.ts | 24 + .../test/lib/struct/winuser/109.MSG.test.ts | 23 + .../lib/struct/winuser/110.RAWHID.test.ts | 23 + .../winuser/111.RAWINPUTDEVICELIST.test.ts | 23 + .../struct/winuser/112.RAWINPUTHEADER.test.ts | 23 + .../struct/winuser/113.RAWKEYBOARD.test.ts | 23 + .../struct/winuser/114.WNDCLASSEXW.test.ts | 23 + .../lib/struct/winuser/116.WINDOWINFO.test.ts | 23 + .../winuser/117.RID_DEVICE_INFO_MOUSE.test.ts | 23 + .../118.RID_DEVICE_INFO_KEYBOARD.test.ts | 23 + .../winuser/119.RID_DEVICE_INFO_HID.test.ts | 23 + .../winuser/120.RID_DEVICE_INFO.test.ts | 23 + .../test/lib/struct/winuser/990.INPUT.test.ts | 83 +++ .../winuser/999.loader.forceRegister.test.ts | 57 ++ .../test/mapper/EnumPrintersW.mapper.ts | 33 ++ .../test/mapper/GetPrinterW.mapper.ts | 33 ++ .../win32-def/test/mapper/index.mapper.ts | 15 + packages/win32-def/test/root.config.ts | 34 ++ packages/win32-def/test/root.hooks.ts | 27 - packages/win32-def/test/setup.ts | 13 + .../test/struct/101.ALTTABINFO.test.ts | 53 -- .../test/struct/102.DEVMODEW.test.ts | 20 - .../test/struct/103.PRINTER_DEFAULTS.test.ts | 21 - .../test/struct/104.PRINTER_INFO_X.test.ts | 20 - packages/win32-def/test/test.config.ts | 11 + packages/win32-def/test/tsconfig.json | 19 +- .../win32-def/test/union/202.DEVMODEW.test.ts | 28 - packages/win32-def/tsconfig.eslint.json | 20 - packages/win32-def/tsconfig.json | 57 +- rollup.config.js | 147 ++++++ tsconfig.base.json | 58 +++ tsconfig.eslint.json | 21 +- tsconfig.json | 50 +- 418 files changed, 10970 insertions(+), 8737 deletions(-) delete mode 100644 .eslintrc.yml create mode 100755 .githooks/commit-msg create mode 100755 .githooks/gen-file-from-example.js create mode 100755 .githooks/gen-file-from-example.mts create mode 100755 .githooks/gen-file-from-example.ts rename .githooks/{init-repo => }/init-example-file.ts (55%) mode change 100644 => 100755 delete mode 100644 .githooks/init-repo/doc-list.ts delete mode 100644 .githooks/init-repo/doc.ts delete mode 100644 .githooks/init-repo/gen-file-from-example.ts delete mode 100644 .githooks/init-repo/init-utils.ts delete mode 100644 .githooks/init-repo/is-skip-commitlint.ts delete mode 100644 .githooks/init-repo/test-skip-commitlint.ts rename .githooks/{init-repo => }/init.config.ts (64%) mode change 100644 => 100755 rename .githooks/{init-repo => }/is-skip-commitlint-rule.ts (100%) mode change 100644 => 100755 mode change 100644 => 100755 .githooks/pre-commit.sample create mode 100755 .githooks/pre-push mode change 100644 => 100755 .githooks/pre-push.sample create mode 100755 .githooks/set-scripts-executable-now.sh mode change 100644 => 100755 .githooks/tsconfig.json create mode 100644 .npmrc delete mode 100755 .scripts/change-pkg-types-dist.sh delete mode 100755 .scripts/change-pkg-types-src.sh create mode 100644 .scripts/env.sh create mode 100644 .scripts/purge.sh create mode 100644 .vscode/common.code-snippets create mode 100644 .vscode/common.code-snippets.example create mode 100644 CHANGES.v22.md delete mode 100644 appveyor.yml rename commitlint.config.js => commitlint.config.cjs (100%) create mode 100644 eslint.config.mjs delete mode 100644 packages/win32-api/.nycrc.json create mode 100644 packages/win32-api/demo/EnumDisplayDevicesW.mts create mode 100644 packages/win32-api/demo/GetCursorPos.mts create mode 100644 packages/win32-api/demo/show-hide-desktop.mts delete mode 100644 packages/win32-api/src/func/func.helper.ts delete mode 100644 packages/win32-api/src/func/func.ts delete mode 100644 packages/win32-api/src/func/spoolss/helper.ts delete mode 100644 packages/win32-api/src/func/spoolss/index.spoolss.ts delete mode 100644 packages/win32-api/src/func/spoolss/spoolss.types.ts delete mode 100644 packages/win32-api/src/func/user32/helper.ts delete mode 100644 packages/win32-api/src/func/user32/index.user32.ts delete mode 100644 packages/win32-api/src/func/winspool/helper.ts delete mode 100644 packages/win32-api/src/func/winspool/index.winspool.ts delete mode 100644 packages/win32-api/src/func/winspool/winspool.types.ts delete mode 100644 packages/win32-api/src/index.comctl32.ts delete mode 100644 packages/win32-api/src/index.consts.ts delete mode 100644 packages/win32-api/src/index.fun.ts delete mode 100644 packages/win32-api/src/index.kernel32.ts delete mode 100644 packages/win32-api/src/index.ntdll.ts delete mode 100644 packages/win32-api/src/index.promise.ts delete mode 100644 packages/win32-api/src/index.spoolss.ts delete mode 100644 packages/win32-api/src/index.user32.ts create mode 100644 packages/win32-api/src/index.util.ts delete mode 100644 packages/win32-api/src/index.winspool.ts create mode 100644 packages/win32-api/src/lib/comctl32/api.def.ts delete mode 100644 packages/win32-api/src/lib/comctl32/api.ts create mode 100644 packages/win32-api/src/lib/comctl32/api.types.ts delete mode 100644 packages/win32-api/src/lib/comctl32/index.promise.ts create mode 100644 packages/win32-api/src/lib/gdi32/api.def.ts delete mode 100644 packages/win32-api/src/lib/gdi32/api.ts create mode 100644 packages/win32-api/src/lib/gdi32/api.types.ts delete mode 100644 packages/win32-api/src/lib/gdi32/index.promise.ts create mode 100644 packages/win32-api/src/lib/kernel32/api.def.ts delete mode 100644 packages/win32-api/src/lib/kernel32/api.ts create mode 100644 packages/win32-api/src/lib/kernel32/api.types.ts delete mode 100644 packages/win32-api/src/lib/kernel32/index.promise.ts delete mode 100644 packages/win32-api/src/lib/ntdll/api.ts delete mode 100644 packages/win32-api/src/lib/ntdll/index.promise.ts delete mode 100644 packages/win32-api/src/lib/ntdll/index.ts create mode 100644 packages/win32-api/src/lib/spoolss/api.def.ts delete mode 100644 packages/win32-api/src/lib/spoolss/api.ts create mode 100644 packages/win32-api/src/lib/spoolss/api.types.ts delete mode 100644 packages/win32-api/src/lib/spoolss/index.promise.ts create mode 100644 packages/win32-api/src/lib/user32/api.def.ts delete mode 100644 packages/win32-api/src/lib/user32/api.ts create mode 100644 packages/win32-api/src/lib/user32/api.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/AB.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/AB.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/CD.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/CD.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/EF.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/EF.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/G.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/G.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/IM.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/IM.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/PR.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/PR.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/S.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/S.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/TU.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/TU.types.ts create mode 100644 packages/win32-api/src/lib/user32/dict/index.def.ts create mode 100644 packages/win32-api/src/lib/user32/dict/index.types.ts delete mode 100644 packages/win32-api/src/lib/user32/index.promise.ts delete mode 100644 packages/win32-api/src/lib/winmsg.ts create mode 100644 packages/win32-api/src/lib/winspool/api.def.ts delete mode 100644 packages/win32-api/src/lib/winspool/api.ts create mode 100644 packages/win32-api/src/lib/winspool/api.types.ts delete mode 100644 packages/win32-api/src/lib/winspool/index.promise.ts create mode 100644 packages/win32-api/src/lib/winspool/mapper/GetPrinterW.mapper.ts create mode 100644 packages/win32-api/src/lib/winspool/mapper/index.mapper.ts create mode 100644 packages/win32-api/src/util/user32/FindWindowEx.ts create mode 100644 packages/win32-api/src/util/user32/GetWindowText.ts create mode 100644 packages/win32-api/src/util/user32/user32.index.ts create mode 100644 packages/win32-api/src/util/util.index.ts create mode 100644 packages/win32-api/src/util/winspool/ClosePrinter.ts create mode 100644 packages/win32-api/src/util/winspool/EndDocPrinter.ts create mode 100644 packages/win32-api/src/util/winspool/EnumPrinters.ts create mode 100644 packages/win32-api/src/util/winspool/GetDefaultPrinter.ts create mode 100644 packages/win32-api/src/util/winspool/GetPrinter.ts create mode 100644 packages/win32-api/src/util/winspool/OpenPrinter.ts create mode 100644 packages/win32-api/src/util/winspool/StartDocPrinter.ts create mode 100644 packages/win32-api/src/util/winspool/winspool.index.ts create mode 100644 packages/win32-api/src/util/winspool/winspool.types.ts delete mode 100644 packages/win32-api/test/10.index.comctl32.test.ts delete mode 100644 packages/win32-api/test/11.index.kernel32.test.ts delete mode 100644 packages/win32-api/test/12.index.ntdll.test.ts delete mode 100644 packages/win32-api/test/13.index.user32.test.ts delete mode 100644 packages/win32-api/test/21.main.test.ts delete mode 100644 packages/win32-api/test/70.user32.test.ts delete mode 100644 packages/win32-api/test/71.find-calc-async.test.ts delete mode 100644 packages/win32-api/test/72.find-notepad-async.test.ts delete mode 100644 packages/win32-api/test/80.misc.test.ts delete mode 100644 packages/win32-api/test/81.constants.test.ts delete mode 100644 packages/win32-api/test/90.loop-callback.test.ts create mode 100644 packages/win32-api/test/foo1.ts.bak create mode 100644 packages/win32-api/test/foo2.ts.bak delete mode 100644 packages/win32-api/test/gdi32/201.CreateCompatibleDC.test.ts delete mode 100644 packages/win32-api/test/gdi32/202.CreateCompatibleBitmap.test.ts rename packages/win32-api/test/{helper.ts => helper.ts.bak} (98%) delete mode 100644 packages/win32-api/test/helper/91.gen_api_opts.test.ts delete mode 100644 packages/win32-api/test/helper/92.comctl32.helper.gen_api_opts.test.ts delete mode 100644 packages/win32-api/test/helper/93.kernel32.helper.gen_api_opts.test.ts delete mode 100644 packages/win32-api/test/helper/94.ntdll.helper.gen_api_opts.test.ts delete mode 100644 packages/win32-api/test/helper/95.user32.helper.gen_api_opts.test.ts delete mode 100644 packages/win32-api/test/helper/96.user32.helper.gen_api_opts.test.ts delete mode 100644 packages/win32-api/test/helper/97.bufferToStruct.test.ts delete mode 100644 packages/win32-api/test/kernel32/40.GetSystemTimes.test.ts create mode 100644 packages/win32-api/test/lib/20.comctl32.test.ts create mode 100644 packages/win32-api/test/lib/21.gdi32.test.ts create mode 100644 packages/win32-api/test/lib/22.kernel32.test.ts create mode 100644 packages/win32-api/test/lib/23.spoolss.test.ts create mode 100644 packages/win32-api/test/lib/24.user32.test.ts create mode 100644 packages/win32-api/test/lib/25.winspool.test.ts delete mode 100644 packages/win32-api/test/root.hooks.ts create mode 100644 packages/win32-api/test/setup.ts delete mode 100644 packages/win32-api/test/user32/201.FindWindowEx.test.ts delete mode 100644 packages/win32-api/test/user32/51.EnumDisplayDevicesW.test.ts delete mode 100644 packages/win32-api/test/user32/52.GetRawInputDeviceInfoW.test.ts delete mode 100644 packages/win32-api/test/user32/53.GetRawInputDeviceList.test.ts delete mode 100644 packages/win32-api/test/user32/54.GetWindowRect.test.ts delete mode 100644 packages/win32-api/test/user32/55.SendMessageW.test.ts delete mode 100644 packages/win32-api/test/user32/56.SendMessageW.SETTEXT.test.ts delete mode 100644 packages/win32-api/test/user32/57.SendMessageW.GETTEXT.test.ts delete mode 100644 packages/win32-api/test/user32/60.FlashWindowEx.test.ts delete mode 100644 packages/win32-api/test/user32/61.FlashWindow.test.ts delete mode 100644 packages/win32-api/test/user32/62.GetCaretPos.test.ts delete mode 100644 packages/win32-api/test/user32/63.IsIconic.test.ts create mode 100644 packages/win32-api/test/util/user32/100.FindWindowEx.test.ts create mode 100644 packages/win32-api/test/util/user32/101.GetWindowText.test.ts create mode 100644 packages/win32-api/test/util/winspool/200.EnumPrinters.test.ts create mode 100644 packages/win32-api/test/util/winspool/201.GetDefaultPrinter.test.ts create mode 100644 packages/win32-api/test/util/winspool/202.OpenPrinter.test.ts create mode 100644 packages/win32-api/test/util/winspool/203.GetPrinter.test.ts create mode 100644 packages/win32-api/test/util/winspool/204.StartDocPrinter-EndDocPrinter.test.ts create mode 100644 packages/win32-api/test/util/winspool/209.ClosePrinter.test.ts delete mode 100644 packages/win32-api/test/winspool/501.GetDefaultPrinter.test.ts delete mode 100644 packages/win32-api/test/winspool/502.OpenPrinter.test.ts delete mode 100644 packages/win32-api/test/winspool/503.GetPrinter.test.ts delete mode 100644 packages/win32-api/test/winspool/504.ClosePrinter.test.ts delete mode 100644 packages/win32-api/test/winspool/505.EnumPrinters.test.ts delete mode 100644 packages/win32-api/test/winspool/506.EnumPrintProcessors.test.ts delete mode 100644 packages/win32-api/test/winspool/507.EnumPrintProcessorDatatypes.test.ts delete mode 100644 packages/win32-api/test/winspool/520.print-to-pdf.test.ts delete mode 100644 packages/win32-api/tsconfig.eslint.json delete mode 100644 packages/win32-def/.nycrc.json create mode 100644 packages/win32-def/demo/EnumDisplayDevicesW.mts create mode 100644 packages/win32-def/demo/EnumPrintersW.mts create mode 100644 packages/win32-def/demo/GetCursorPos.mts create mode 100644 packages/win32-def/demo/show-hide-desktop.mts create mode 100644 packages/win32-def/src/index.types.ts delete mode 100644 packages/win32-def/src/index.union.ts rename packages/{win32-api/src/lib/user32/constants.ts => win32-def/src/lib/consts/user32.enum.ts} (98%) rename packages/{win32-api/src/lib/kernel32/constants.ts => win32-def/src/lib/consts/winbase.enum.ts} (100%) create mode 100644 packages/win32-def/src/lib/consts/winmsg.enum.ts create mode 100644 packages/win32-def/src/lib/consts/winspool/PRINTER_STATUS.enum.ts delete mode 100644 packages/win32-def/src/lib/data.types.ts.bak delete mode 100644 packages/win32-def/src/lib/fixed-buffer.ts delete mode 100644 packages/win32-def/src/lib/helper.ts create mode 100644 packages/win32-def/src/lib/loader/def.helper.ts create mode 100644 packages/win32-def/src/lib/loader/loader.cache.ts create mode 100644 packages/win32-def/src/lib/loader/loader.helper.ts create mode 100644 packages/win32-def/src/lib/loader/loader.ts create mode 100644 packages/win32-def/src/lib/loader/loader.types.ts create mode 100644 packages/win32-def/src/lib/loader/multiple-choice-param.helper.ts create mode 100644 packages/win32-def/src/lib/struct/comctl/INITCOMMONCONTROLSEX.ts create mode 100644 packages/win32-def/src/lib/struct/comctl/comctl.index.ts delete mode 100644 packages/win32-def/src/lib/struct/index.struct.types.ts create mode 100644 packages/win32-def/src/lib/struct/minwinbase/FILETIME.ts create mode 100644 packages/win32-def/src/lib/struct/minwinbase/SYSTEMTIME.ts create mode 100644 packages/win32-def/src/lib/struct/minwinbase/minwinbase.index.ts create mode 100644 packages/win32-def/src/lib/struct/struct.cache.ts delete mode 100644 packages/win32-def/src/lib/struct/struct.def.ts create mode 100644 packages/win32-def/src/lib/struct/struct.factory-map.ts create mode 100644 packages/win32-def/src/lib/struct/struct.helper.ts create mode 100644 packages/win32-def/src/lib/struct/struct.index.ts create mode 100644 packages/win32-def/src/lib/struct/struct.simple.helper.ts delete mode 100644 packages/win32-def/src/lib/struct/struct.types.ts create mode 100644 packages/win32-def/src/lib/struct/struct.util.ts delete mode 100644 packages/win32-def/src/lib/struct/struct.var.def.ts create mode 100644 packages/win32-def/src/lib/struct/windef/POINT.ts create mode 100644 packages/win32-def/src/lib/struct/windef/RECT.ts create mode 100644 packages/win32-def/src/lib/struct/windef/windef.index.ts delete mode 100644 packages/win32-def/src/lib/struct/wingdi.def.ts delete mode 100644 packages/win32-def/src/lib/struct/wingdi.types.ts delete mode 100644 packages/win32-def/src/lib/struct/wingdi.var.def.ts create mode 100644 packages/win32-def/src/lib/struct/wingdi/DEVMODEW.ts create mode 100644 packages/win32-def/src/lib/struct/wingdi/DISPLAY_DEVICEW.ts create mode 100644 packages/win32-def/src/lib/struct/wingdi/wingdi.index.ts delete mode 100644 packages/win32-def/src/lib/struct/winspool.def.ts delete mode 100644 packages/win32-def/src/lib/struct/winspool.types.ts delete mode 100644 packages/win32-def/src/lib/struct/winspool.var.def.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/DOC_INFO_1.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/JOB_INFO_1.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_DEFAULTS.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_1.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_4.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_5.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_6.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_8.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_9.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/PRINTPROCESSOR_INFO_1.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/helper.types.ts create mode 100644 packages/win32-def/src/lib/struct/winspool/winspool.index.ts delete mode 100644 packages/win32-def/src/lib/struct/winuser.def.ts delete mode 100644 packages/win32-def/src/lib/struct/winuser.types.ts delete mode 100644 packages/win32-def/src/lib/struct/winuser.var.def.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/ALTTABINFO.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/COPYDATASTRUCT.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/FLASHWINFO.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/HARDWAREINPUT.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/INPUT.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/KEYBDINPUT.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/MOUSEINPUT.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/MSG.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RAWHID.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RAWINPUTDEVICELIST.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RAWINPUTHEADER.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RAWKEYBOARD.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_HID.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_KEYBOARD.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_MOUSE.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/WINDOWINFO.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/WNDCLASSEXW.ts create mode 100644 packages/win32-def/src/lib/struct/winuser/winuser.index.ts create mode 100644 packages/win32-def/src/lib/types.ts delete mode 100644 packages/win32-def/src/lib/union/index.union.types.ts delete mode 100644 packages/win32-def/src/lib/union/union.def.ts delete mode 100644 packages/win32-def/src/lib/union/union.types.ts delete mode 100644 packages/win32-def/src/lib/union/union.var.def.ts delete mode 100644 packages/win32-def/src/lib/union/winspool.union.def.ts delete mode 100644 packages/win32-def/src/lib/union/winspool.union.types.ts delete mode 100644 packages/win32-def/src/lib/union/winspool.union.var.def.ts create mode 100644 packages/win32-def/src/lib/util.ts delete mode 100644 packages/win32-def/test/.eslintrc.yml create mode 100644 packages/win32-def/test/01.loader-no-autoCreateStruct.test.ts rename packages/win32-def/test/{11.index.def.test.ts => 12.index.def.test.ts} (67%) delete mode 100644 packages/win32-def/test/12.index.struct.test.ts delete mode 100644 packages/win32-def/test/20.helper.struct.test.ts delete mode 100644 packages/win32-def/test/21.helper.union.test.ts delete mode 100644 packages/win32-def/test/30.fixed-buffer.test.ts delete mode 100644 packages/win32-def/test/31.StructFactory.test.ts delete mode 100644 packages/win32-def/test/asserts/asserts.PRINTER_DEFAULTS.ts create mode 100644 packages/win32-def/test/def.class/20.loader.test.ts create mode 100644 packages/win32-def/test/def.class/21.loader-multiple-choice.test.ts create mode 100644 packages/win32-def/test/def.class/22.loader-updateMultipleChoiceMapper.map.test.ts create mode 100644 packages/win32-def/test/def.class/23.loader-updateMultipleChoiceMapper.set.test.ts create mode 100644 packages/win32-def/test/def.class/25.loader.GetTickCount.test.ts create mode 100644 packages/win32-def/test/def.class/api.helper.ts create mode 100644 packages/win32-def/test/def.const/20c.loader.test.ts create mode 100644 packages/win32-def/test/def.const/21c.loader-multiple-choice.test.ts create mode 100644 packages/win32-def/test/def.const/22c.loader-updateMultipleChoiceMapper.map.test.ts create mode 100644 packages/win32-def/test/def.const/23c.loader-updateMultipleChoiceMapper.set.test.ts create mode 100644 packages/win32-def/test/def.const/25c.loader.GetTickCount.test.ts create mode 100644 packages/win32-def/test/def.const/api.helper.ts create mode 100644 packages/win32-def/test/helper.ts create mode 100644 packages/win32-def/test/lib/24.LoaderCache.test.ts create mode 100644 packages/win32-def/test/lib/30.ucsBufferFrom.test.ts create mode 100644 packages/win32-def/test/lib/31.ucsBufferToString.test.ts rename packages/win32-def/test/{ => lib}/consts/40.consts.wingdi.test.ts (76%) rename packages/win32-def/test/{ => lib}/consts/41.consts.key-mouse-vk.test.ts (74%) rename packages/win32-def/test/{ => lib}/consts/42.winuser.test.ts (86%) create mode 100644 packages/win32-def/test/lib/struct/41.genSimpleStruct.test.ts create mode 100644 packages/win32-def/test/lib/struct/42.genComplexStruct.test.ts create mode 100644 packages/win32-def/test/lib/struct/43.genSimpleUnion.test.ts create mode 100644 packages/win32-def/test/lib/struct/44.genUnion.test.ts create mode 100644 packages/win32-def/test/lib/struct/45.StructUnionCache.test.ts create mode 100644 packages/win32-def/test/lib/struct/46.genFixedArray.test.ts create mode 100644 packages/win32-def/test/lib/struct/47.genFixedInt16Array.test.ts create mode 100644 packages/win32-def/test/lib/struct/48.decodeInt16Array.test.ts create mode 100644 packages/win32-def/test/lib/struct/50.POINT_Factory.test.ts create mode 100644 packages/win32-def/test/lib/struct/51.DISPLAY_DEVICEW_Factory.test.ts create mode 100644 packages/win32-def/test/lib/struct/52.PRINTER_INFO_X_Factory.test.ts create mode 100644 packages/win32-def/test/lib/struct/comctl/201.INITCOMMONCONTROLSEX.test.ts create mode 100644 packages/win32-def/test/lib/struct/minwinbase/401.FILETIME.test.ts create mode 100644 packages/win32-def/test/lib/struct/minwinbase/402.SYSTEMTIME.test.ts create mode 100644 packages/win32-def/test/lib/struct/windef/301.RECT.test.ts create mode 100644 packages/win32-def/test/lib/struct/windef/302.POINT.test.ts create mode 100644 packages/win32-def/test/lib/struct/wingdi/501.DISPLAY_DEVICEW.test.ts create mode 100644 packages/win32-def/test/lib/struct/wingdi/502.DEVMODEW.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/601.PRINTPROCESSOR_INFO_1.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/602.DOC_INFO_1.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/603.PRINTER_DEFAULTS.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/604.PRINTER_INFO_1.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/605.PRINTER_INFO_4.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/606.PRINTER_INFO_5.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/607.PRINTER_INFO_6.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/608.PRINTER_INFO_8.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/609.PRINTER_INFO_9.test.ts create mode 100644 packages/win32-def/test/lib/struct/winspool/610.JOB_INFO_1.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/101.HARDWAREINPUT.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/102.KEYBDINPUT.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/103.MOUSEINPUT.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/105.FLASHWINFO.ts.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/106.ALTTABINFO.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/107.COPYDATASTRUCT.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/109.MSG.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/110.RAWHID.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/111.RAWINPUTDEVICELIST.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/112.RAWINPUTHEADER.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/113.RAWKEYBOARD.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/114.WNDCLASSEXW.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/116.WINDOWINFO.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/117.RID_DEVICE_INFO_MOUSE.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/118.RID_DEVICE_INFO_KEYBOARD.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/119.RID_DEVICE_INFO_HID.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/120.RID_DEVICE_INFO.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/990.INPUT.test.ts create mode 100644 packages/win32-def/test/lib/struct/winuser/999.loader.forceRegister.test.ts create mode 100644 packages/win32-def/test/mapper/EnumPrintersW.mapper.ts create mode 100644 packages/win32-def/test/mapper/GetPrinterW.mapper.ts create mode 100644 packages/win32-def/test/mapper/index.mapper.ts create mode 100644 packages/win32-def/test/root.config.ts delete mode 100644 packages/win32-def/test/root.hooks.ts create mode 100644 packages/win32-def/test/setup.ts delete mode 100644 packages/win32-def/test/struct/101.ALTTABINFO.test.ts delete mode 100644 packages/win32-def/test/struct/102.DEVMODEW.test.ts delete mode 100644 packages/win32-def/test/struct/103.PRINTER_DEFAULTS.test.ts delete mode 100644 packages/win32-def/test/struct/104.PRINTER_INFO_X.test.ts create mode 100644 packages/win32-def/test/test.config.ts delete mode 100644 packages/win32-def/test/union/202.DEVMODEW.test.ts delete mode 100644 packages/win32-def/tsconfig.eslint.json create mode 100644 rollup.config.js create mode 100644 tsconfig.base.json diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index 84dce0d6..00000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,17 +0,0 @@ -extends: '@waiting/eslint-config' -parserOptions: - project: 'tsconfig.eslint.json' - -# https://eslint.org/docs/rules/ -# https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin -# https://github.com/benmosher/eslint-plugin-import -# https://github.com/sindresorhus/eslint-plugin-unicorn -rules: - # Use tsconfig.json noUnusedLocals:true instead - "@typescript-eslint/no-unused-vars": 0 - "node/no-unpublished-import": 0 - "@typescript-eslint/prefer-ts-expect-error": 0 - "unicorn/filename-case": 0 - "linebreak-style": 0 - "node/shebang": 0 - diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 00000000..f083eadb --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,27 @@ +#!/bin/sh +# +# 根据 commitmsg 以及 branch name 判断是否需要 commitlint +# +# Author: waiting +# Date: 2023.07.21 +# + +if [[ -z $NVM_DIR ]]; then + if [[ -f $HOME/.nvm/nvm.sh ]]; then + . $HOME/.nvm/nvm.sh + fi +fi + +branch=$( git branch | grep \* | cut -d ' ' -f2 ) +# ./.githooks/init-repo/is-skip-commitlint.ts $1 "$branch" + +# code=$? +code=0 +#echo -e 'node exitCode:' $code + +if [[ -f ./node_modules/.bin/commitlint ]]; then + if [[ $code = 0 ]] && [[ -d node_modules ]] ; then + ./node_modules/.bin/commitlint -e ./.git/COMMIT_EDITMSG + fi +fi + diff --git a/.githooks/gen-file-from-example.js b/.githooks/gen-file-from-example.js new file mode 100755 index 00000000..69a05192 --- /dev/null +++ b/.githooks/gen-file-from-example.js @@ -0,0 +1,79 @@ +#!/usr/bin/env tsx +/** + * 搜索指定目录以 file.example 文件为基础生成不带后缀的文件为不带 .example 后缀的文件 + */ +import { dirname, join, sep } from 'node:path'; +import { cp, mkdir, readdir } from 'node:fs/promises'; +import { fileURLToPath } from 'node:url'; +// import { folderArr, globalConfigFileArr } from './init.config.js' +import { genFileFromExample } from './init-example-file.js'; +const folderArr = [ + './', + '.vscode', + '.settings', + 'resource', + 'configs', + 'config', // egg + 'src/config', // midway +]; +const globalConfigFileArr = [ + '.vscode/tasks.json.example', + '.vscode/launch.json.example', + '.vscode/settings.json.example', + '.vscode/ci.code-snippets.example', + '.vscode/midway.code-snippets.example', + '.vscode/promise.code-snippets.example', + './tsconfig.base.json', + './tsconfig.eslint.json', + // './rollup.config.js', + './bin-hashbang.js', +]; +const currentURL = import.meta.url; +const currentPath = fileURLToPath(currentURL); +const currentDir = dirname(currentPath); +const currentFileName = currentPath.split(sep).pop(); +const rootDir = join(currentDir, '..'); +console.log({ rootDir, currentFileName }); +const pkgEntryName = 'packages'; +const pkgBase = join(rootDir, pkgEntryName); +const files = await cpGlobalConfigsToPkgs(rootDir, globalConfigFileArr, pkgBase); +console.log('Sync config:', files); +const files2 = await genFileFromExample(rootDir, folderArr); +console.info(`生成基础文件:${rootDir}`, files2); +const dirs = await readdir(pkgBase); +const arr = []; +for (const name of dirs) { + const pkgPath = join(pkgBase, name); + const files3 = await genFileFromExample(pkgPath, folderArr); + files3.forEach(file => arr.push(`${pkgEntryName}/${name}/${file}`)); + console.info(`生成包文件:`, arr); +} +// --------------------------------------------- +async function cpGlobalConfigsToPkgs(baseDir, configPaths, pkgBase) { + const pkgs = await readdir(pkgBase); + const ret = []; + for (const pkg of pkgs) { + for (const path of configPaths) { + try { + const dst = `${pkg}/${path}`; + const dstDir = dirname(join(pkgBase, dst)); + await mkdir(dstDir, { recursive: true }); + await cp(join(baseDir, path), join(pkgBase, dst)); + ret.push(dst); + } + catch (ex) { + console.log(ex.message); + } + } + } + return ret; +} +/** + * Generate random integer + * + * @see https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random + */ +export function genRandomInt(max) { + return Math.floor(Math.random() * Math.floor(max)); +} +//# sourceMappingURL=gen-file-from-example.js.map \ No newline at end of file diff --git a/.githooks/gen-file-from-example.mts b/.githooks/gen-file-from-example.mts new file mode 100755 index 00000000..0ab5f44a --- /dev/null +++ b/.githooks/gen-file-from-example.mts @@ -0,0 +1,102 @@ +#!/usr/bin/env tsx +/** + * 搜索指定目录以 file.example 文件为基础生成不带后缀的文件为不带 .example 后缀的文件 + */ +import { dirname, join, sep } from 'node:path' +import { cp, mkdir, readdir } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' + +// import { folderArr, globalConfigFileArr } from './init.config.js' +import { genFileFromExample } from './init-example-file.js' + + +const folderArr: string[] = [ + './', + '.vscode', + '.settings', + 'resource', + 'configs', + 'config', // egg + 'src/config', // midway +] + +const globalConfigFileArr: string[] = [ + '.vscode/tasks.json.example', + '.vscode/launch.json.example', + '.vscode/settings.json.example', + '.vscode/ci.code-snippets.example', + '.vscode/midway.code-snippets.example', + '.vscode/promise.code-snippets.example', + './tsconfig.base.json', + './tsconfig.eslint.json', + // './rollup.config.js', + './bin-hashbang.js', +] + +const currentURL = import.meta.url +const currentPath = fileURLToPath(currentURL) +const currentDir = dirname(currentPath) +const currentFileName = currentPath.split(sep).pop() +const rootDir = join(currentDir, '..') +console.log({ rootDir, currentFileName }) + +const pkgEntryName = 'packages' +const pkgBase = join(rootDir, pkgEntryName) + +const files = await cpGlobalConfigsToPkgs(rootDir, globalConfigFileArr, pkgBase) +console.log('Sync config:', files) + +const files2 = await genFileFromExample(rootDir, folderArr) +console.info(`生成基础文件:${rootDir}`, files2) + +const dirs = await readdir(pkgBase) +const arr: string[] = [] + +for (const name of dirs) { + const pkgPath = join(pkgBase, name) + const files3 = await genFileFromExample(pkgPath, folderArr) + files3.forEach(file => arr.push(`${pkgEntryName}/${name}/${file}`)) + console.info(`生成包文件:`, arr) +} + + +// --------------------------------------------- + +async function cpGlobalConfigsToPkgs( + baseDir: string, + configPaths: string[], + pkgBase: string, +): Promise { + + const pkgs = await readdir(pkgBase) + const ret: string[] = [] + + for (const pkg of pkgs) { + for (const path of configPaths) { + try { + const dst = `${pkg}/${path}` + const dstDir = dirname(join(pkgBase, dst)) + await mkdir(dstDir, { recursive: true }) + await cp( + join(baseDir, path), + join(pkgBase, dst), + ) + ret.push(dst) + } + catch (ex: any) { + console.log(ex.message) + } + } + } + + return ret +} + +/** + * Generate random integer + * + * @see https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random + */ +export function genRandomInt(max: number): number { + return Math.floor(Math.random() * Math.floor(max)) +} diff --git a/.githooks/gen-file-from-example.ts b/.githooks/gen-file-from-example.ts new file mode 100755 index 00000000..0ab5f44a --- /dev/null +++ b/.githooks/gen-file-from-example.ts @@ -0,0 +1,102 @@ +#!/usr/bin/env tsx +/** + * 搜索指定目录以 file.example 文件为基础生成不带后缀的文件为不带 .example 后缀的文件 + */ +import { dirname, join, sep } from 'node:path' +import { cp, mkdir, readdir } from 'node:fs/promises' +import { fileURLToPath } from 'node:url' + +// import { folderArr, globalConfigFileArr } from './init.config.js' +import { genFileFromExample } from './init-example-file.js' + + +const folderArr: string[] = [ + './', + '.vscode', + '.settings', + 'resource', + 'configs', + 'config', // egg + 'src/config', // midway +] + +const globalConfigFileArr: string[] = [ + '.vscode/tasks.json.example', + '.vscode/launch.json.example', + '.vscode/settings.json.example', + '.vscode/ci.code-snippets.example', + '.vscode/midway.code-snippets.example', + '.vscode/promise.code-snippets.example', + './tsconfig.base.json', + './tsconfig.eslint.json', + // './rollup.config.js', + './bin-hashbang.js', +] + +const currentURL = import.meta.url +const currentPath = fileURLToPath(currentURL) +const currentDir = dirname(currentPath) +const currentFileName = currentPath.split(sep).pop() +const rootDir = join(currentDir, '..') +console.log({ rootDir, currentFileName }) + +const pkgEntryName = 'packages' +const pkgBase = join(rootDir, pkgEntryName) + +const files = await cpGlobalConfigsToPkgs(rootDir, globalConfigFileArr, pkgBase) +console.log('Sync config:', files) + +const files2 = await genFileFromExample(rootDir, folderArr) +console.info(`生成基础文件:${rootDir}`, files2) + +const dirs = await readdir(pkgBase) +const arr: string[] = [] + +for (const name of dirs) { + const pkgPath = join(pkgBase, name) + const files3 = await genFileFromExample(pkgPath, folderArr) + files3.forEach(file => arr.push(`${pkgEntryName}/${name}/${file}`)) + console.info(`生成包文件:`, arr) +} + + +// --------------------------------------------- + +async function cpGlobalConfigsToPkgs( + baseDir: string, + configPaths: string[], + pkgBase: string, +): Promise { + + const pkgs = await readdir(pkgBase) + const ret: string[] = [] + + for (const pkg of pkgs) { + for (const path of configPaths) { + try { + const dst = `${pkg}/${path}` + const dstDir = dirname(join(pkgBase, dst)) + await mkdir(dstDir, { recursive: true }) + await cp( + join(baseDir, path), + join(pkgBase, dst), + ) + ret.push(dst) + } + catch (ex: any) { + console.log(ex.message) + } + } + } + + return ret +} + +/** + * Generate random integer + * + * @see https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random + */ +export function genRandomInt(max: number): number { + return Math.floor(Math.random() * Math.floor(max)) +} diff --git a/.githooks/init-repo/init-example-file.ts b/.githooks/init-example-file.ts old mode 100644 new mode 100755 similarity index 55% rename from .githooks/init-repo/init-example-file.ts rename to .githooks/init-example-file.ts index 7cda65ee..0b04df8d --- a/.githooks/init-repo/init-example-file.ts +++ b/.githooks/init-example-file.ts @@ -1,31 +1,43 @@ /** - * 搜索指定目录以 file.example 文件为基础生成不带后缀的文件为不带 .example 后缀的文件 + * 搜索指定目录以 file.example 文件为基础生成 去除结尾 .example */ -import { copyFileAsync, isPathAccessible, join, readDirAsync } from './init-utils' +import { join } from 'node:path' +import { cp, readdir, stat } from 'node:fs/promises' -// const rootDir = join(__dirname, '..') export async function genFileFromExample(rootDir: string, list: string[]): Promise { const copied: string[] = [] for (const dir of list) { - const path = join(rootDir, dir.replace(/\.{2,}/, '/')) + const srcPath = join(rootDir, dir.replace(/\.{2,}/, '/')) - if (! await isPathAccessible(path)) { + try { + const pathStat = await stat(srcPath) + if (! pathStat.isDirectory) { continue } + } + catch { continue } - const files = await readDirAsync(path) + + const files = await readdir(srcPath) for (const file of files) { - if (!hasExampleSuffix(file)) { + if (! hasExampleSuffix(file)) { continue } - const source = join(path, file) + const source = join(srcPath, file) const stripped = stripExampleSuffix(file) - const target = join(path, stripped) + const target = join(srcPath, stripped) - if (! await isPathAccessible(target)) { - await copyFileAsync(source, target) + let targetStat + try { + targetStat = await stat(target) + } + catch { + void 0 + } + if (! targetStat) { + await cp(source, target, { force: false }) copied.push(`${dir}/${stripped}`) } } diff --git a/.githooks/init-repo.sh b/.githooks/init-repo.sh index 5027c1dd..0dc09415 100755 --- a/.githooks/init-repo.sh +++ b/.githooks/init-repo.sh @@ -9,15 +9,17 @@ set -e git init git config --global i18n.commitencoding utf-8 +git config --local core.autocrlf input +git config --local core.eol lf if [ -z "$CI" ]; then - git config --local core.autocrlf false - git config --local core.eol lf + git config --local core.filemode false git config --local core.hooksPath ./.githooks git config --local core.ignorecase false git config --local core.precomposeUnicode true git config --local fetch.prune true git config --local pull.rebase true + git config --local push.autoSetupRemote true git config --local push.followTags true git config --local rebase.autoStash true git config --local remote.origin.prune true @@ -25,9 +27,9 @@ if [ -z "$CI" ]; then git config --local remote.pushdefault origin fi; -if [ -z $CI ]; then - echo It may going for a long time. Plese wait... - cd .githooks && tsc && node gen-file-from-example.js && cd - -fi; +echo It may going for a long time. Plese wait... +.githooks/gen-file-from-example.js lerna list +set +e +echo init done diff --git a/.githooks/init-repo/doc-list.ts b/.githooks/init-repo/doc-list.ts deleted file mode 100644 index e3c557f9..00000000 --- a/.githooks/init-repo/doc-list.ts +++ /dev/null @@ -1,27 +0,0 @@ - -/** - * Common files under /packages/ - */ -export const commonList = [ - 'src/lib/index.ts', - 'src/lib/model.ts', -] - -/** - * Custom files with full path under / - */ -export const detailList = [ - // 'packages/foo/src/index.ts', -] - -export const skipPkgList = [ - 'demo', -] - -/** - * Files name in root dir to be copyed to the main pkg folder - */ -export const fileNameToCopyList = [ - 'README.md', - 'README.zh-CN.md', -] diff --git a/.githooks/init-repo/doc.ts b/.githooks/init-repo/doc.ts deleted file mode 100644 index cc4987dc..00000000 --- a/.githooks/init-repo/doc.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { readdirSync } from 'fs' - -import { run, RxSpawnOpts } from 'rxrunscript' -import { Observable, of, firstValueFrom } from 'rxjs' -import { tap, mergeMap, mapTo, defaultIfEmpty } from 'rxjs/operators' - -import { - commonList, - detailList, - skipPkgList, - fileNameToCopyList, -} from './doc-list' -import { join, statAsync, isPathAccessible, copyFileAsync } from './init-utils' - - -const baseDir = join(__dirname, '..') -const pkgEntryName = 'packages' -const pkgDir = join(baseDir, pkgEntryName) - -const rootPkgJson = require(join(baseDir, 'package.json')) -const projectName = rootPkgJson.name - -if (!projectName) { - console.error('Name empty in file package.json') - process.exit(1) -} - - -copyRootFilesToMainPkg(projectName) - .then(async (paths) => { - const cpFiles = await firstValueFrom(commitFiles(paths)) - if (cpFiles && cpFiles.length) { - console.log('Sync Files: ' + cpFiles.join(' ')) - } - - return retrievePkgs() - }) - .then(prefixArr => { - return genFromCommon(prefixArr, commonList) - }) - .then(async (data) => { - const list = await genFromDetail(detailList) - if (data.length > 0 || list.length > 0) { - const arr = [...list, ...data] - return arr - } - return [] - }) - .then(async (srcArr) => { - if (srcArr.length) { - const sh = `typedoc --options typedoc.json --name ${projectName} --readme README.md` - const ps: RxSpawnOpts = { - msgPrefixOpts: { - stderrPrefix: 'stderr:', - errPrefix: 'error:' - }, - stderrMaxBufferSize: 2000, - cwd: baseDir, - } - - await firstValueFrom(run(sh, srcArr, ps) - .pipe( - tap(buf => { - console.log(buf.toString()) - }), - )) - } - else { - process.exit(0) - } - }) - .catch(err => { - console.log(err.message) - }) - - - -async function retrievePkgs(): Promise { - const ret: string[] = [] - const entries = readdirSync(pkgDir) - - for (const name of entries) { - if (skipPkgList.includes(name)) { - continue - } - const path = join(pkgDir, name) - const stat = await statAsync(path) - if (!stat.isDirectory()) { - continue - } - - const pkgJson = join(path, 'package.json') - if (! await isPathAccessible(pkgJson)) { - continue - } - ret.push(name) - } - - return ret -} - - -/** - * @returns format: packages//...file - */ -async function genFromCommon(pkgNameArr: string[], files: string[]): Promise { - const ret: string[] = [] - - for (const prefix of pkgNameArr) { - for (const file of files) { - const relativePath = `${pkgEntryName}/${prefix}/${file}` - const path = join(baseDir, relativePath) - - if (! await isPathAccessible(path)) { - continue - } - - try { - const stat = await statAsync(path) - if (stat.isFile()) { - ret.push(relativePath) - } - } - catch (ex: any) { - console.log(ex.message) - } - } - } - - return ret -} - - -async function genFromDetail(files: string[]): Promise { - const ret: string[] = [] - - for (const file of files) { - const path = join(baseDir, file) - if (! await isPathAccessible(path)) { - console.log('bcz') - continue - } - - try { - const stat = await statAsync(path) - if (stat.isFile()) { - ret.push(file) - } - } - catch (ex: any) { - console.log(ex.message) - } - } - - return ret -} - - -/** - * Copy Readme.md from root to the main package folder, - * @returns - files path - */ -async function copyRootFilesToMainPkg(dstName: string): Promise { - const paths: string[] = [] - - for (const name of fileNameToCopyList) { - const srcPath = join(baseDir, name) - const dstPath = join(pkgDir, dstName, name) - - try { - await copyFileAsync(srcPath, dstPath) - paths.push(dstPath) - } - catch (ex: any) { - console.log(ex.message) - } - } - - return paths -} - -function commitFiles(paths: string[]): Observable { - if (! paths.length) { - return of([]) - } - - const sh = `git diff --name-only` - const ps: RxSpawnOpts = { - msgPrefixOpts: { - stderrPrefix: 'stderr:', - errPrefix: 'error:' - }, - stderrMaxBufferSize: 2000, - cwd: baseDir, - } - - const files$ = run(sh, paths, ps) - .pipe( - mergeMap(buf => { - const str = buf.toString().trim() - if (str.length) { - const files = str.split(/\n|(\r\n)|\r/).filter(val => val && val.trim().length > 0) - // console.log('changed file:', files) - const add = 'git add' - return run(add, files).pipe( - mapTo(files) - ) - } - return [] - }), - mergeMap(files => { - if (files.length) { - const cm = 'git commit -m "docs: sync readme document" -- ' - return run(cm, files).pipe( - mapTo(files) - ) - } - return [] - }), - defaultIfEmpty([] as string[]) - ) - - return files$ -} diff --git a/.githooks/init-repo/gen-file-from-example.ts b/.githooks/init-repo/gen-file-from-example.ts deleted file mode 100644 index 45ef3083..00000000 --- a/.githooks/init-repo/gen-file-from-example.ts +++ /dev/null @@ -1,38 +0,0 @@ -/** - * 搜索指定目录以 file.example 文件为基础生成不带后缀的文件为不带 .example 后缀的文件 - */ -import { folderArr, globalConfigFileArr } from './init.config' -import { genFileFromExample } from './init-example-file' -import { join, readDirAsync, cpGlobalConfigsToPkgs } from './init-utils' - - -const pkgEntryName = 'packages' -const rootDir = join(__dirname, '..') -const pkgBase = join(rootDir, pkgEntryName) - -cpGlobalConfigsToPkgs(rootDir, globalConfigFileArr, pkgBase) - .then(files => { - console.log('Sync config:', files) - - return genFileFromExample(rootDir, folderArr) - .then(files => { - console.info(`生成基础文件:${rootDir}`, files) - }) - }) - .then(() => { - return readDirAsync(pkgBase) - .then(async (dirs) => { - const arr: string[] = [] - - for (const name of dirs) { - const pkgPath = join(pkgBase, name) - await genFileFromExample(pkgPath, folderArr) - .then(files => { - files.forEach(file => arr.push(`${pkgEntryName}/${name}/${file}`)) - }) - } - console.info(`生成包文件:`, arr) - }) - }) - .catch(console.error) - diff --git a/.githooks/init-repo/init-utils.ts b/.githooks/init-repo/init-utils.ts deleted file mode 100644 index ad123291..00000000 --- a/.githooks/init-repo/init-utils.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { - access, - copyFile, - mkdir, - readdir, - readFile, - stat, -} from 'fs' -import { - basename, - dirname, - join, - normalize, -} from 'path' -import { - defer, - Observable, -} from 'rxjs' -import { - map, -} from 'rxjs/operators' -import { promisify } from 'util' - - -export const copyFileAsync = promisify(copyFile) -export const mkdirAsync = promisify(mkdir) -export const readFileAsync = promisify(readFile) -export const readDirAsync = promisify(readdir) -export const statAsync = promisify(stat) -export { - basename, - dirname, - join, - normalize, -} - -/** Return path if accessible, blank if not accessible */ -export function pathAccessible(path: string): Observable { - return defer(() => isPathAccessible(path)).pipe( - map(exists => exists ? normalize(path) : ''), - ) -} -// support relative file ('./foo') -export function isPathAccessible(path: string): Promise { - return path - ? new Promise(resolve => access(path, err => resolve(err ? false : true))) - : Promise.resolve(false) -} - - -/** - * Generate random integer - * - * @see https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random - */ -export function genRandomInt(max: number): number { - return Math.floor(Math.random() * Math.floor(max)) -} - - -export async function cpGlobalConfigsToPkgs( - baseDir: string, - configPaths: string[], - pkgBase: string, -): Promise { - - const pkgs = await readDirAsync(pkgBase) - const ret: string[] = [] - - for (const pkg of pkgs) { - for (const path of configPaths) { - try { - const dst = `${pkg}/${path}` - const dstDir = dirname(join(pkgBase, dst)) - if ( ! await isPathAccessible(dstDir)) { - await mkdirAsync(dstDir) - } - await copyFileAsync( - join(baseDir, path), - join(pkgBase, dst), - ) - ret.push(dst) - } - catch (ex: any) { - console.log(ex.message) - } - } - } - - return ret -} diff --git a/.githooks/init-repo/is-skip-commitlint.ts b/.githooks/init-repo/is-skip-commitlint.ts deleted file mode 100644 index 3b7d4345..00000000 --- a/.githooks/init-repo/is-skip-commitlint.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * 通过设置执行结果 code, 检查是否需要执行 commitlint - */ - -import { tap } from 'rxjs/operators' - -import { join } from './init-utils' -import { protectBranch, skipMsg } from './is-skip-commitlint-rule' -import { isSkipCommitlint } from './test-skip-commitlint' - - -const args = process.argv -const baseDir = join(__dirname, '..') - -isSkipCommitlint({ - baseDir, - branchName: args[3], - COMMIT_EDITMSG: args[2], - protectBranch, - skipMsg, -}).pipe( - tap(exitCode => { - process.exit(exitCode) - }), -).subscribe() diff --git a/.githooks/init-repo/test-skip-commitlint.ts b/.githooks/init-repo/test-skip-commitlint.ts deleted file mode 100644 index 62d723b5..00000000 --- a/.githooks/init-repo/test-skip-commitlint.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { combineLatest, forkJoin, from as ofrom, of, Observable } from 'rxjs' -import { defaultIfEmpty, filter, map, mapTo, mergeMap, share, take, tap } from 'rxjs/operators' - -import { join, pathAccessible, readFileAsync } from './init-utils' - - -// const baseDir = join(__dirname, '..') -// const args = process.argv -// const COMMIT_EDITMSG = args[2] -// const BRANCH = args[3] - -export interface IsNeedCommitlintOpts { - /** app root dir */ - baseDir: string - /** common .git/COMMIT_EDITMSG */ - COMMIT_EDITMSG: string - /** Current git branch name */ - branchName: string - /** Regexp.test(git branch name) to doing commitlint */ - protectBranch: RegExp[] - /** Regexp.test(commit msg) to skipping commitlint */ - skipMsg: RegExp[] -} - -/** Return Observable to check whether skip commitlint */ -export function isSkipCommitlint(options: IsNeedCommitlintOpts): Observable { - const { baseDir, COMMIT_EDITMSG, branchName, protectBranch, skipMsg } = options - - const commitFile = join(baseDir, COMMIT_EDITMSG) - - if (!COMMIT_EDITMSG) { - console.info('COMMIT_EDITMSG value blank') - return of(1) - } - - const protectRule$ = ofrom(protectBranch).pipe(defaultIfEmpty(void 0)) - const skipRule$ = ofrom(skipMsg).pipe(defaultIfEmpty(void 0)) - - const content$ = pathAccessible(commitFile).pipe( - tap(path => { - if (!path) { - console.info(`COMMIT_EDITMSG file not exists: "${commitFile}"`) - process.exit(1) - } - }), - mergeMap(path => readFileAsync(path, { encoding: 'utf8' })), - map(msg => { - const head = msg.split(/\n|\r\n/)[0] - return { head, msg } - }), - share(), - ) - - const protectTest$ = combineLatest({ - branch: of(branchName), - regex: protectRule$, - }).pipe( - map(({ branch, regex}) => regex && regex.test(branch) ? true : false), - filter(matched => matched), - mapTo(0), // process.exit(0) - defaultIfEmpty(1), // not skip commitlint - ) - const skipTest$ = combineLatest({ - content: content$, - regex: skipRule$, - }).pipe( - map(({ content, regex }) => regex && regex.test(content.head) ? true : false), - filter(matched => matched), - mapTo(1), // process.exit(1) - defaultIfEmpty(0), // not skip commitlint - ) - - const exitCode$ = forkJoin(protectTest$, skipTest$).pipe( - map(([pro, skip]) => { - // console.info('pro:skip', pro, skip) - // tslint:disable-next-line:no-bitwise - return pro & skip - }), - defaultIfEmpty(0), // not skip commitlint - take(1), - ) - - return exitCode$ -} diff --git a/.githooks/init-repo/init.config.ts b/.githooks/init.config.ts old mode 100644 new mode 100755 similarity index 64% rename from .githooks/init-repo/init.config.ts rename to .githooks/init.config.ts index edf37560..e7b14ba3 --- a/.githooks/init-repo/init.config.ts +++ b/.githooks/init.config.ts @@ -2,7 +2,7 @@ * 搜索指定目录以 file.example 文件为基础生成不带后缀的文件为不带 .example 后缀的文件 */ -export const folderArr = [ +export const folderArr: string[] = [ './', '.vscode', '.settings', @@ -12,11 +12,16 @@ export const folderArr = [ 'src/config', // midway ] -export const globalConfigFileArr = [ +export const globalConfigFileArr: string[] = [ '.vscode/tasks.json.example', '.vscode/launch.json.example', '.vscode/settings.json.example', '.vscode/ci.code-snippets.example', '.vscode/midway.code-snippets.example', + '.vscode/promise.code-snippets.example', + './tsconfig.base.json', + './tsconfig.eslint.json', + // './rollup.config.js', + './bin-hashbang.js', ] diff --git a/.githooks/init-repo/is-skip-commitlint-rule.ts b/.githooks/is-skip-commitlint-rule.ts old mode 100644 new mode 100755 similarity index 100% rename from .githooks/init-repo/is-skip-commitlint-rule.ts rename to .githooks/is-skip-commitlint-rule.ts diff --git a/.githooks/pre-commit.sample b/.githooks/pre-commit.sample old mode 100644 new mode 100755 index 25f595bc..a68f4bf5 --- a/.githooks/pre-commit.sample +++ b/.githooks/pre-commit.sample @@ -8,6 +8,11 @@ # Date: 2017.02.09 # +if [[ -z $NVM_DIR ]]; then + if [[ -f $HOME/.nvm/nvm.sh ]]; then + . $HOME/.nvm/nvm.sh + fi +fi if git rev-parse --verify HEAD >/dev/null 2>&1 then @@ -25,7 +30,7 @@ fi # ------------- parse ts files=$(git diff --cached --name-only --diff-filter=ACMR $against|grep '\.ts$') if [[ $files != "" ]] ; then - # echo $files | xargs eslint --fix + # echo $files | xargs eslint --fix npm run lint rc=$? if [[ $rc != 0 ]] ; then diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 00000000..d86dd902 --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,4 @@ +#!/bin/sh + +sh .githooks/set-scripts-executable.sh + diff --git a/.githooks/pre-push.sample b/.githooks/pre-push.sample old mode 100644 new mode 100755 index 6161096f..2545298f --- a/.githooks/pre-push.sample +++ b/.githooks/pre-push.sample @@ -10,6 +10,12 @@ remote="$1" url="$2" +if [[ -z $NVM_DIR ]]; then + if [[ -f $HOME/.nvm/nvm.sh ]]; then + . $HOME/.nvm/nvm.sh + fi +fi + z40=0000000000000000000000000000000000000000 while read local_ref local_sha remote_ref remote_sha diff --git a/.githooks/set-scripts-executable-now.sh b/.githooks/set-scripts-executable-now.sh new file mode 100755 index 00000000..9cee06be --- /dev/null +++ b/.githooks/set-scripts-executable-now.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set +e + +dirs=".scripts .github src bin" + +for dir in $dirs; do + [[ -f "$dir" ]] && find $dir -type f \( -iname "*.sh" -o -iname "*.mjs" -o -iname "*.mts" \) -print0 | xargs -0II chmod a+x I +done + +set -e + diff --git a/.githooks/set-scripts-executable.sh b/.githooks/set-scripts-executable.sh index afca5bf4..55a68ce9 100755 --- a/.githooks/set-scripts-executable.sh +++ b/.githooks/set-scripts-executable.sh @@ -1,20 +1,13 @@ #!/bin/bash set +e -find .scripts -type f -iname "*.sh" -print0 \ - | xargs -0II git update-index --ignore-missing --chmod=+x I +dirs=".scripts .github" -find .scripts -type f -iname "*.mjs" -print0 \ - | xargs -0II git update-index --ignore-missing --chmod=+x I +for dir in $dirs; do + [[ -f "$dir" ]] && find $dir -type f \( -iname "*.sh" -o -iname "*.mjs" -o -iname "*.mts" \) -print0 | xargs -0II git update-index --ignore-missing --chmod=+x I +done -find .github -type f -iname "*.sh" -print0 \ - | xargs -0II git update-index --ignore-missing --chmod=+x I - -find .github -type f -iname "*.mjs" -print0 \ - | xargs -0II git update-index --ignore-missing --chmod=+x I - -find .githooks -type f -iname "*.sh" -print0 \ - | xargs -0II git update-index --ignore-missing --chmod=+x I +find .githooks -type f -print0 | xargs -0II git update-index --ignore-missing --chmod=+x I echo "Commit changes if changed!" diff --git a/.githooks/tsconfig.json b/.githooks/tsconfig.json old mode 100644 new mode 100755 index fdea02b3..60666725 --- a/.githooks/tsconfig.json +++ b/.githooks/tsconfig.json @@ -1,11 +1,12 @@ { "compilerOptions": { "declaration": false, - "module": "commonjs", + "module": "ESNext", "newLine": "lf", "noFallthroughCasesInSwitch": true, "noUnusedLocals": false, "noUnusedParameters": false, + "noEmit": true, "outDir": "./", "pretty": true, "skipLibCheck": true, @@ -13,7 +14,7 @@ "target": "esnext" }, "include": [ - "init-repo/**/*.ts" + "*.ts" ], "exclude": [ ] diff --git a/.github/workflows/nodejs-win.yml b/.github/workflows/nodejs-win.yml index 211404c4..6504a8d2 100644 --- a/.github/workflows/nodejs-win.yml +++ b/.github/workflows/nodejs-win.yml @@ -13,8 +13,8 @@ jobs: strategy: matrix: - node: ['16'] - os: [windows-2019, windows-latest] + node: ['lts/*', 'current', '18'] + os: [windows-2019] steps: - uses: actions/checkout@v4 @@ -23,34 +23,31 @@ jobs: with: node-version: ${{ matrix.node }} - - name: Cache - uses: actions/cache@v4 - id: cache-lerna-win - env: - cache-name: cache-lerna-win - with: - path: | - node_modules - node_modules/.cache/nx - package-lock.json - packages/*/.eslintcache - packages/*/.tsbuildinfo - packages/*/.vscode - packages/*/dist - packages/*/package-lock.json - key: ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ matrix.node }}- + # - name: Cache + # uses: actions/cache@v4 + # id: cache-lerna-win + # env: + # cache-name: cache-lerna-win + # with: + # path: | + # node_modules + # package-lock.json + # packages/*/.tsbuildinfo + # packages/*/dist + # packages/*/node_modules + # C:\npm\prefix\node_modules + # key: ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }} + # restore-keys: | + # ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ matrix.node }}- - name: Prepare shell: bash run: | + pwd uname -a npm -v && node -v - npm -g root git --version openssl version - ./.githooks/init-repo.sh git config --local core.autocrlf false git config --local core.eol lf @@ -58,16 +55,16 @@ jobs: timeout-minutes: 15 shell: bash run: | - .github/workflows/fix.sh - npm i -g c8 lerna@6 rollup zx node-gyp - # npm run purge - npm run bootstrap + export cwd=`pwd` + npm i --no-audit -g c8 lerna madge rollup tsx zx + npm i env: CI: true - name: Build shell: bash run: | + pwd whoami export cwd=`pwd` . .scripts/ci/ci-env.sh @@ -76,16 +73,16 @@ jobs: env: CI: true - - name: Lint - shell: bash - run: | - export cwd=`pwd` - . .scripts/ci/ci-env.sh - .scripts/ci/ci-prepare.sh - npm run lint:s - npm run lint:cycle - env: - CI: true + # - name: Lint + # shell: bash + # run: | + # export cwd=`pwd` + # . .scripts/ci/ci-env.sh + # .scripts/ci/ci-prepare.sh + # npm run lint:s + # npm run lint:cycle + # env: + # CI: true - name: Testing shell: bash diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 3114a423..2007ea97 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node: ['16'] + node: ['lts/*', 'current'] os: [ubuntu-latest] steps: @@ -31,14 +31,9 @@ jobs: with: path: | node_modules - node_modules/.cache/nx package-lock.json - packages/*/.eslintcache packages/*/.tsbuildinfo - packages/*/.vscode packages/*/dist - packages/*/node_modules - packages/*/package-lock.json key: ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ matrix.node }}- @@ -54,7 +49,6 @@ jobs: apt-get install -qq --yes postgresql-client libpq-dev > /dev/null uname -a npm -v && node -v - npm -g root git --version openssl version cat /etc/*release @@ -62,32 +56,26 @@ jobs: locale-gen locale -a netstat -tunpl - chmod a+w -R . - dig jaeger + export cwd=`pwd` + git config --global --add safe.directory $cwd - name: Install Dependencies timeout-minutes: 15 run: | - chown -R 1001:121 "/github/home/.npm" - # chmod a+w -R . # DO NOT execute: npm config set unsafe-perm=true export cwd=`pwd` - # .github/workflows/fix.sh - npm i --no-audit -g autocannon c8 lerna@6 rollup zx - # npm run purge - npm run bootstrap + npm i --no-audit -g c8 lerna madge rollup tsx zx + npm i env: CI: true - name: Build run: | pwd - # chmod a+w -R . whoami export cwd=`pwd` . .scripts/ci/ci-env.sh .scripts/ci/ci-prepare.sh - # .github/workflows/fix.sh npm run build --if-present env: CI: true diff --git a/.github/workflows/npm-manual-publish.yml b/.github/workflows/npm-manual-publish.yml index 7785afb1..9af63efe 100644 --- a/.github/workflows/npm-manual-publish.yml +++ b/.github/workflows/npm-manual-publish.yml @@ -31,8 +31,8 @@ jobs: # pulls all tags (needed for lerna / semantic release to correctly version) run: | export cwd=`pwd` - git config --global --add safe.directory $cwd - git fetch --depth=1 origin +refs/tags/*:refs/tags/* + git config --global --add safe.directory $cwd || true + git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@v4 with: @@ -48,9 +48,9 @@ jobs: path: | node_modules package-lock.json - key: ${{ runner.OS }}-build-2-${{ env.cache-name }}-${{ github.ref }}-${{ hashFiles('**/package-lock.json') }} + key: ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}-${{ hashFiles('**/package-lock.json') }} restore-keys: | - ${{ runner.OS }}-build-2-${{ env.cache-name }}-${{ github.ref }}- + ${{ runner.OS }}-build-${{ env.cache-name }}-${{ github.ref }}- - name: Prepare run: | @@ -62,7 +62,6 @@ jobs: apt-get install -qq --yes postgresql-client libpq-dev > /dev/null uname -a npm -v && node -v - npm -g root git --version openssl version cat /etc/*release @@ -70,8 +69,6 @@ jobs: locale-gen locale -a netstat -tunpl - chmod a+w -R . - dig jaeger - name: Verify run: | @@ -79,6 +76,11 @@ jobs: # github project/settings/Secrets/New repository secret: NPM_TOKEN npm ping npm whoami + psql -V + dig postgres + echo "\l" | psql -h $POSTGRES_HOST -p $POSTGRES_PORT -U$POSTGRES_USER -d postgres + psql -h $POSTGRES_HOST -p $POSTGRES_PORT -U$POSTGRES_USER -d $POSTGRES_DB -c "\d+" + psql -h $POSTGRES_HOST -p $POSTGRES_PORT -U$POSTGRES_USER -d $POSTGRES_DB -c "SHOW TIMEZONE;" env: CI: true NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -92,24 +94,18 @@ jobs: - name: Install Dependencies timeout-minutes: 15 run: | - chmod a+w -R . - # DO NOT execute: npm config set unsafe-perm=true export cwd=`pwd` - .github/workflows/fix.sh - npm i --no-audit -g autocannon c8 lerna rollup zx - # npm run purge - npm run bootstrap + npm i --no-audit -g lerna rollup tsx zx madge + npm i --no-audit env: CI: true - name: Build run: | - chmod a+w -R . whoami export cwd=`pwd` . .scripts/ci/ci-env.sh .scripts/ci/ci-prepare.sh - # .github/workflows/fix.sh npm run build --if-present env: CI: true @@ -119,7 +115,7 @@ jobs: export cwd=`pwd` . .scripts/ci/ci-env.sh .scripts/ci/ci-prepare.sh - npm run lint:s + npm run lint:nofix npm run lint:cycle env: CI: true @@ -128,17 +124,17 @@ jobs: run: | npm ping npm whoami - chmod a+w -R . export cwd=`pwd` . .scripts/ci/ci-env.sh # fix: fatal: detected dubious ownership in repository git config --global --add safe.directory $cwd - # git restore . git reset --hard git config user.name $GITHUB_ACTOR git config user.email gh-actions-${GITHUB_ACTOR}@github.com # npm run pub major - .scripts/publish.sh --yes --no-verify-access --conventional-commits --create-release github ${{ github.event.inputs.semver }} + rm -rf package-lock.json + rm -rf packages/*/package-lock.json + .scripts/publish.sh --yes --no-private --conventional-commits --create-release github ${{ github.event.inputs.semver }} git push -v origin --follow-tags env: CI: true diff --git a/.github/workflows/npm-publish-wo-test.yml b/.github/workflows/npm-publish-wo-test.yml index ed698fda..a46b5bea 100644 --- a/.github/workflows/npm-publish-wo-test.yml +++ b/.github/workflows/npm-publish-wo-test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: - node: ['16'] + node: ['lts/*'] os: [ubuntu-latest] steps: @@ -31,8 +31,8 @@ jobs: # pulls all tags (needed for lerna / semantic release to correctly version) run: | export cwd=`pwd` - git config --global --add safe.directory $cwd - git fetch --depth=1 origin +refs/tags/*:refs/tags/* + git config --global --add safe.directory $cwd || true + git fetch --depth=1 origin +refs/tags/*:refs/tags/* || true - name: Use Node.js ${{ matrix.node }} uses: actions/setup-node@v4 with: @@ -69,7 +69,6 @@ jobs: locale-gen locale -a netstat -tunpl - chmod a+w -R . - name: Verify run: | @@ -84,24 +83,18 @@ jobs: - name: Install Dependencies timeout-minutes: 15 run: | - chmod a+w -R . - # DO NOT execute: npm config set unsafe-perm=true export cwd=`pwd` - .github/workflows/fix.sh - npm i --no-audit -g autocannon c8 lerna@6 rollup zx - # npm run purge - npm run bootstrap + npm i --no-audit -g lerna rollup tsx zx madge + npm i --no-audit env: CI: true - name: Build run: | - chmod a+w -R . whoami export cwd=`pwd` . .scripts/ci/ci-env.sh .scripts/ci/ci-prepare.sh - # .github/workflows/fix.sh npm run build --if-present env: CI: true @@ -120,17 +113,17 @@ jobs: run: | npm ping npm whoami - chmod a+w -R . export cwd=`pwd` . .scripts/ci/ci-env.sh # fix: fatal: detected dubious ownership in repository git config --global --add safe.directory $cwd - # git restore . git reset --hard git config user.name $GITHUB_ACTOR git config user.email gh-actions-${GITHUB_ACTOR}@github.com # npm run pub major - .scripts/publish.sh --yes --no-verify-access --conventional-commits --create-release github ${{ github.event.inputs.semver }} + rm -rf package-lock.json + rm -rf packages/*/package-lock.json + .scripts/publish.sh --yes --no-private --conventional-commits --create-release github ${{ github.event.inputs.semver }} git push -v origin --follow-tags env: CI: true diff --git a/.gitignore b/.gitignore index 0a557749..8aebdf90 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,14 @@ +.nx .ssh/ dbconfig.json package-lock.json +package-lock.json.* yarn.lock package.json.lerna_backup tsconfig.tsbuildinfo +npm-shrinkwrap.json +!/tsconfig.base.json +tsconfig.base.json .coveralls.yml .factorypath @@ -40,6 +45,10 @@ v8cov /packages/*/config/ /packages/*/lib/ /packages/*/test/demo/*.js +/packages/*/tsconfig.base.json +/packages/*/tsconfig.eslint.json +/packages/*/.npmrc + test/app/**/*.js test/fixtures/**/*.js **/test/fixtures/**/*.js diff --git a/.mocharc.yml b/.mocharc.yml index 0b704318..c5790860 100644 --- a/.mocharc.yml +++ b/.mocharc.yml @@ -2,11 +2,14 @@ bail: true full-trace: true enable-source-maps: true +node-option: + - no-warnings + - "loader=ts-node/esm" + - "enable-source-maps" require: - - ts-node/register - tsconfig-paths/register.js - - test/root.hooks.ts -#loader: + - test/setup.ts +# loader: # - ts-node/esm spec: - test/**/*.test.ts diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..57628452 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ + +engine-strict = true diff --git a/.nycrc.json b/.nycrc.json index dfc144d8..a87158d1 100644 --- a/.nycrc.json +++ b/.nycrc.json @@ -1,22 +1,21 @@ { "include": [ - "packages/*/src/*.ts", - "packages/*/src/**/*.ts" + "src/*.ts", + "src/**/*.ts" ], "exclude": [ ".githooks", "node_modules*", - "**/src/bin", - "**/src/domain.ts", - "**/src/interface.ts", - "**/dist", + "src/bin", + "src/domain.ts", + "src/interface.ts", "**/node_modules*", - "**/test", - "**/test*", - "**/*.d.ts", - "**/*.js" + "test", + "test*", + "**/*.d.ts" ], "reporter": [ + "text", "html", "json", "text-summary" diff --git a/.scripts/build.sh b/.scripts/build.sh index 76d0f11b..53bcbc80 100755 --- a/.scripts/build.sh +++ b/.scripts/build.sh @@ -1,4 +1,5 @@ #!/bin/bash +. .scripts/env.sh input="$@" scope='' diff --git a/.scripts/change-pkg-types-dist.sh b/.scripts/change-pkg-types-dist.sh deleted file mode 100755 index 7a132d11..00000000 --- a/.scripts/change-pkg-types-dist.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# -------------- -# Should call under sub-package -# -------------- - -currDir=`pwd` -pkgFile="$currDir/package.json" - -echo -e "$pkgFile types will be dist/index.d.ts" - -sed -i "s#\(\"types\":\).\+#\1 \"./dist/index.d.ts\",#g" "$pkgFile" - diff --git a/.scripts/change-pkg-types-src.sh b/.scripts/change-pkg-types-src.sh deleted file mode 100755 index 867d7ae6..00000000 --- a/.scripts/change-pkg-types-src.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# -------------- -# Should call under sub-package -# -------------- - -currDir=`pwd` -pkgFile="$currDir/package.json" - -echo -e "$pkgFile types will be src/index.ts" - -sed -i "s#\(\"types\":\).\+#\1 \"./src/index.ts\",#g" "$pkgFile" - diff --git a/.scripts/ci/ci-env.sh b/.scripts/ci/ci-env.sh index ee66d826..42a98187 100755 --- a/.scripts/ci/ci-env.sh +++ b/.scripts/ci/ci-env.sh @@ -18,3 +18,7 @@ export GRADLE_USER_HOME=.gradle-bin # flutter export PUB_CACHE="$CI_PROJECT_DIR/.pub-cache" +# nodejs +export NODE_OPTIONS="$NODE_OPTIONS --no-warnings" + + diff --git a/.scripts/ci/ci-prepare.sh b/.scripts/ci/ci-prepare.sh index cdc08e81..369c4f0b 100755 --- a/.scripts/ci/ci-prepare.sh +++ b/.scripts/ci/ci-prepare.sh @@ -1,9 +1,16 @@ #!/bin/bash set +e -if [ -n "$TIMEZ" ]; then - ln -sf /usr/share/zoneinfo/${TIMEZ} /etc/localtime - echo "$TIMEZ" > /etc/timezone +os=$(uname) +msystem=$(echo "$MSYSTEM" | tr '[:upper:]' '[:lower:]') +echo os: $os +echo msystem: $msystem + +if [ "$os" == "Linux" ]; then + if [ -n "$TIMEZ" ]; then + ln -sf /usr/share/zoneinfo/${TIMEZ} /etc/localtime + echo "$TIMEZ" > /etc/timezone + fi fi # git config --system core.fileMode false diff --git a/.scripts/env.sh b/.scripts/env.sh new file mode 100644 index 00000000..45769808 --- /dev/null +++ b/.scripts/env.sh @@ -0,0 +1,3 @@ + +export NODE_OPTIONS="${NODE_OPTIONS} --no-warnings" + diff --git a/.scripts/pre-publish-valiate.sh b/.scripts/pre-publish-valiate.sh index b9b9fd53..83931dc1 100755 --- a/.scripts/pre-publish-valiate.sh +++ b/.scripts/pre-publish-valiate.sh @@ -10,6 +10,7 @@ pkgFile="$currDir/package.json" git restore .scripts git add --ignore-errors ./packages str=$( git status ) +echo $str sub="Changes to be committed" if [[ "$str" == *"$sub"* ]]; then diff --git a/.scripts/publish.sh b/.scripts/publish.sh index 0a5a7ced..e99f1ff7 100755 --- a/.scripts/publish.sh +++ b/.scripts/publish.sh @@ -68,10 +68,15 @@ fi # npm run bootstrap # npm run build -echo ">>> lerna publishing..." +rm -rf $appDir/package-lock.json +rm -rf $appDir/packages/*/package-lock.json + +echo ">>> lerna pre-publish-valiate" "$scriptDir/pre-publish-valiate.sh" echo $* +echo ">>> lerna publishing..." +git status if [ -z "$NPM_VERSION_REGISTRY" ]; then lerna publish $* else diff --git a/.scripts/purge.sh b/.scripts/purge.sh new file mode 100644 index 00000000..6cbf8e70 --- /dev/null +++ b/.scripts/purge.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set +e + + +if [[ -d node_modules/nx ]]; then + nx reset +fi + +rm -rf .nx +rm -rf node_modules package-lock.json +npm i +npm run refresh + +if [[ -d node_modules/nx ]]; then + nx reset +fi + +# rm -rf .nx +# workaround for lerna Error: LOCK-FILES-CHANGED +npm run build + diff --git a/.vscode/common.code-snippets b/.vscode/common.code-snippets new file mode 100644 index 00000000..dc34c526 --- /dev/null +++ b/.vscode/common.code-snippets @@ -0,0 +1,16 @@ +{ + "Try-Cache": { + "scope": "typescript,javascript", + "prefix": "trycache", + "body": [ + "try {", + " $1", + "}", + "catch (ex) {", + " $2", + "}" + ], + "description": "" + }, +} + diff --git a/.vscode/common.code-snippets.example b/.vscode/common.code-snippets.example new file mode 100644 index 00000000..dc34c526 --- /dev/null +++ b/.vscode/common.code-snippets.example @@ -0,0 +1,16 @@ +{ + "Try-Cache": { + "scope": "typescript,javascript", + "prefix": "trycache", + "body": [ + "try {", + " $1", + "}", + "catch (ex) {", + " $2", + "}" + ], + "description": "" + }, +} + diff --git a/.vscode/launch.json.example b/.vscode/launch.json.example index c7c0bc2c..bb84cef8 100644 --- a/.vscode/launch.json.example +++ b/.vscode/launch.json.example @@ -42,7 +42,7 @@ "restart": false, "runtimeArgs": [ "run", - "test:local", + "test", "--", "--runInBand", "--preserve-symlinks" @@ -54,6 +54,7 @@ "/**", "/**/*.js" ], + "smartStep": false, "timeout": 30000 }, { @@ -67,7 +68,7 @@ "OTEL_EXPORTER_OTLP_ENDPOINT": "http://127.0.0.1:4317", "TS_NODE_TYPE_CHECK": "false", "TS_NODE_TRANSPILE_ONLY": "true", - "POSTGRES_HOST": "", + "POSTGRES_HOST": "127.0.0.1", "POSTGRES_PORT": "5432", "POSTGRES_DB": "", "POSTGRES_USER": "postgres", @@ -83,7 +84,6 @@ ], "runtimeExecutable": "npm", "skipFiles": [ - "**/node_modules/**", "**/node_modules/rxjs/**", "/**", "/**/*.js" diff --git a/.vscode/promise.code-snippets b/.vscode/promise.code-snippets index b0639f4f..7ac0d561 100644 --- a/.vscode/promise.code-snippets +++ b/.vscode/promise.code-snippets @@ -1,4 +1,13 @@ { + "Pomise unknown": { + "scope": "typescript", + "prefix": "pms.unknown", + "body": [ + "Promise" + ], + "description": "" + }, + "Pomise any": { "scope": "typescript", "prefix": "pms.any", diff --git a/.vscode/settings.json b/.vscode/settings.json index 2a364c40..95ef18f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,8 +7,10 @@ "editor.tabSize": 2, "editor.wordWrap": "on", "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" + "source.fixAll.eslint": "explicit", + "source.organizeImports": "never" }, + "eslint.experimental.useFlatConfig": true, "eslint.run": "onSave", "eslint.validate": [ "javascript", @@ -32,7 +34,8 @@ "build": true, "commitlint.*": true, "coverage": true, - "dist": true, + "dist": false, + "dist*": false, "logs": true, "out": true, "package-lock.json": true, @@ -62,8 +65,10 @@ "files.insertFinalNewline": true, "files.refactoring.autoSave": true, "files.watcherExclude": { + ".tsbuildinfo": true, "coverage/**": true, "dist/**": true, + "dist*": true, "packages/*/dist/**": true, "packages/*/logs/**": true, "packages/*/run/**": true, @@ -81,6 +86,7 @@ "files.trimTrailingWhitespace": true, "git.autofetch": true, "git.ignoreLimitWarning": true, + "markdown.editor.pasteUrlAsFormattedLink.enabled": "smart", "markdown-pdf.outputDirectory": "d:/", "plantuml.render": "PlantUMLServer", "plantuml.server": "https://www.plantuml.com/plantuml", @@ -89,6 +95,8 @@ "search.exclude": { ".gitlab": false, ".scripts": false, + ".tsbuildinfo": true, + "dist": true, "i18n": true, "library/": true, "node_modules": true, @@ -118,7 +126,7 @@ "args": ["-l"] } }, - "terminal.integrated.defaultProfile.windows": "git-bash", + "terminal.integrated.defaultProfile.windows": "Git Bash", "terminal.integrated.defaultProfile.linux": "bash (login)", "typescript.autoClosingTags": false, "typescript.format.enable": true, @@ -147,18 +155,187 @@ "editor.formatOnSave": false }, "workbench.editor.wrapTabs": false, + "workbench.editor.customLabels.enabled": true, + "workbench.editor.customLabels.patterns": { + "src/app/**/*.ts": "${dirname}/${filename}", + "src/**": "${dirname}/${filename}.${extname}", + "test/**": "${filename}.${extname} - test", + "dist/**": "${filename}.${extname} - dist", + "packages/*/src/app/**": "${dirname(1)}/${dirname}/${filename} src", + "packages/*/src/*.*": "${filename}.${extname} src", + "packages/*/test/*.*": "${filename}.${extname} test", + "packages/*/src/**": "${dirname}/${filename}.${extname} - src", + "packages/*/test/**": "${dirname}/${filename}.${extname} - test", + "packages/*/*.*": "${dirname}/${filename}.${extname}", + "packages/*/**": "${dirname(1)}/${dirname}/${filename}.${extname}", + "**/node_modules/**/*": "${filename}.${extname} - ${dirname(2)}/${dirname(1)}/${dirname}" + }, "cSpell.words": [ + "acledit", "ALTTABINFO", + "CCHAR", + "Cdecl", + "COLORREF", + "COPYDATASTRUCT", + "Ctrls", + "DEVICEW", + "DEVMODE", + "DEVMODEW", + "DUMMYUNIONNAME", + "dwflags", + "DWORDLONG", + "EXTENDEDKEY", + "fastcall", + "FILETIME", + "FLASHWINFO", + "HACCEL", + "HARDWAREINPUT", + "HBITMAP", "HBRUSH", + "HCOLORSPACE", + "HCONV", + "HCONVLIST", "HCURSOR", + "HDDEDATA", + "HDESK", + "HDROP", + "HDWP", + "HENHMETAFILE", + "HFONT", + "HGDIOBJ", + "HGLOBAL", + "HHOOK", "HICON", + "hinst", "HINSTANCE", + "HKEY", + "HLOCAL", + "HMENU", + "HMETAFILE", + "hmod", + "HMODULE", + "HMONITOR", + "HPALETTE", + "HPEN", + "HRESULT", + "HRGN", + "HRSRC", + "HWINEVENTHOOK", + "HWINSTA", "HWND", - "LPARAM", + "INITCOMMONCONTROLSEX", + "KEYBDINPUT", + "KEYEVENTF", + "koffi", + "LANGID", + "LBUTTON", + "LCID", + "LGRPID", + "longlong", + "LPALTTABINFO", + "LPBOOL", + "LPBYTE", + "LPCOLORREF", + "LPCOPYDATASTRUCT", + "LPCSTR", "LPCTSTR", + "LPCVOID", + "LPCWSTR", + "LPDEVMODEW", + "LPDISPLAY", + "LPDWORD", + "LPFILETIME", + "LPFLASHWINFO", + "lpfn", + "LPHANDLE", + "LPHARDWAREINPUT", + "LPINITCOMMONCONTROLSEX", + "LPINPUT", + "LPINT", + "LPKEYBDINPUT", + "LPLONG", + "LPMOUSEINPUT", + "LPMSG", + "LPPOINT", + "LPRAWHID", + "LPRAWINPUTDEVICELIST", + "LPRAWINPUTHEADER", + "LPRAWKEYBOARD", + "LPRECT", + "LPRID", + "LPSTR", + "LPTSTR", + "LPVOID", + "LPWINDOWINFO", + "LPWNDCLASSEX", + "LPWNDCLASSEXW", + "LPWORD", + "LPWSTR", + "LRESULT", + "LWIN", + "MIDDLEDOWN", + "MOUSEINPUT", + "NTSTATUS", + "NUMLOCK", + "PBOOL", + "PBOOLEAN", + "PBYTE", + "PCHAR", + "PCSTR", + "PCTSTR", + "PCWSTR", + "PDWORD", + "PDWORDLONG", + "Pels", + "PFILETIME", + "PFLOAT", + "PHALF", + "PHANDLE", + "PHKEY", + "PINPUT", + "PKEYBDINPUT", + "PLCID", + "PLONG", + "PLONGLONG", + "PPEB", + "PPRINTER", + "PPRINTPROCESSOR", + "PRID", + "PRINTPROCESSOR", + "PSHORT", + "PSIZE", + "PSSIZE", + "PSTR", + "PTBYTE", + "PTCHAR", + "PTSTR", + "PUCHAR", + "PUHALF", + "PUINT", + "PULONG", + "PULONGLONG", + "PWCHAR", + "PWINDOWINFO", + "PWORD", "PWSTR", - "WNDPROC", - "WPARAM" + "QWORD", + "RAWHID", + "RAWINPUTDEVICELIST", + "RAWINPUTHEADER", + "RAWKEYBOARD", + "RIGHTDOWN", + "RIGHTUP", + "RWIN", + "SCANCODE", + "SSIZE", + "struct", + "SYSTEMTIME", + "TBYTE", + "TCHAR", + "ulonglong", + "WINDOWINFO", + "WINEVENTPROC", + "WNDCLASSEXW", + "WNDENUMPROC" ] } - diff --git a/.vscode/settings.json.example b/.vscode/settings.json.example index 8a2b9e52..0f0f7b2c 100644 --- a/.vscode/settings.json.example +++ b/.vscode/settings.json.example @@ -3,13 +3,14 @@ "editor.detectIndentation": false, "editor.stickyScroll.enabled": true, "editor.minimap.renderCharacters": false, - "editor.renderFinalNewline": false, + "editor.renderFinalNewline": "off", "editor.tabSize": 2, "editor.wordWrap": "on", "editor.codeActionsOnSave": { - "source.fixAll.eslint": true, - "source.organizeImports": false + "source.fixAll.eslint": "explicit", + "source.organizeImports": "never" }, + "eslint.experimental.useFlatConfig": true, "eslint.run": "onSave", "eslint.validate": [ "javascript", @@ -33,7 +34,8 @@ "build": true, "commitlint.*": true, "coverage": true, - "dist": true, + "dist": false, + "dist*": false, "logs": true, "out": true, "package-lock.json": true, @@ -63,8 +65,10 @@ "files.insertFinalNewline": true, "files.refactoring.autoSave": true, "files.watcherExclude": { + ".tsbuildinfo": true, "coverage/**": true, "dist/**": true, + "dist*": true, "packages/*/dist/**": true, "packages/*/logs/**": true, "packages/*/run/**": true, @@ -82,6 +86,7 @@ "files.trimTrailingWhitespace": true, "git.autofetch": true, "git.ignoreLimitWarning": true, + "markdown.editor.pasteUrlAsFormattedLink.enabled": "smart", "markdown-pdf.outputDirectory": "d:/", "plantuml.render": "PlantUMLServer", "plantuml.server": "https://www.plantuml.com/plantuml", @@ -90,6 +95,8 @@ "search.exclude": { ".gitlab": false, ".scripts": false, + ".tsbuildinfo": true, + "dist": true, "i18n": true, "library/": true, "node_modules": true, @@ -119,7 +126,7 @@ "args": ["-l"] } }, - "terminal.integrated.defaultProfile.windows": "git-bash", + "terminal.integrated.defaultProfile.windows": "Git Bash", "terminal.integrated.defaultProfile.linux": "bash (login)", "typescript.autoClosingTags": false, "typescript.format.enable": true, @@ -147,6 +154,206 @@ "editor.formatOnPaste": true, "editor.formatOnSave": false }, - "workbench.editor.wrapTabs": false + "workbench.editor.wrapTabs": false, + "workbench.editor.customLabels.enabled": true, + "workbench.editor.customLabels.patterns": { + "src/app/**/*.ts": "${dirname}/${filename}", + "src/**": "${dirname}/${filename}.${extname}", + "test/**": "${filename}.${extname} - test", + "dist/**": "${filename}.${extname} - dist", + "packages/*/src/app/**": "${dirname(1)}/${dirname}/${filename} src", + "packages/*/src/*.*": "${filename}.${extname} src", + "packages/*/test/*.*": "${filename}.${extname} test", + "packages/*/src/**": "${dirname}/${filename}.${extname} - src", + "packages/*/test/**": "${dirname}/${filename}.${extname} - test", + "packages/*/*.*": "${dirname}/${filename}.${extname}", + "packages/*/**": "${dirname(1)}/${dirname}/${filename}.${extname}", + "**/node_modules/**/*": "${filename}.${extname} - ${dirname(2)}/${dirname(1)}/${dirname}" + }, + "cSpell.words": [ + "acledit", + "ALTTABINFO", + "CCHAR", + "Cdecl", + "COLORREF", + "COPYDATASTRUCT", + "Ctrls", + "DEVICEW", + "DEVMODE", + "DEVMODEW", + "DUMMYUNIONNAME", + "dwflags", + "DWORDLONG", + "EXTENDEDKEY", + "fastcall", + "FILETIME", + "FLASHWINFO", + "HACCEL", + "HARDWAREINPUT", + "HBITMAP", + "HBRUSH", + "HCOLORSPACE", + "HCONV", + "HCONVLIST", + "HCURSOR", + "HDDEDATA", + "HDESK", + "HDROP", + "HDWP", + "HENHMETAFILE", + "HFONT", + "HGDIOBJ", + "HGLOBAL", + "HHOOK", + "HICON", + "hinst", + "HINSTANCE", + "HKEY", + "HLOCAL", + "HMENU", + "HMETAFILE", + "hmod", + "HMODULE", + "HMONITOR", + "HPALETTE", + "HPEN", + "HRESULT", + "HRGN", + "HRSRC", + "HWINEVENTHOOK", + "HWINSTA", + "HWND", + "INITCOMMONCONTROLSEX", + "KEYBDINPUT", + "KEYEVENTF", + "koffi", + "LANGID", + "LBUTTON", + "LCID", + "LGRPID", + "longlong", + "LPALTTABINFO", + "LPBOOL", + "LPBYTE", + "LPCOLORREF", + "LPCOPYDATASTRUCT", + "LPCSTR", + "LPCTSTR", + "LPCVOID", + "LPCWSTR", + "LPDEVMODEW", + "LPDISPLAY", + "LPDOC", + "lpdw", + "LPDWORD", + "LPFILETIME", + "LPFLASHWINFO", + "lpfn", + "LPHANDLE", + "LPHARDWAREINPUT", + "LPINITCOMMONCONTROLSEX", + "LPINPUT", + "LPINT", + "LPKEYBDINPUT", + "LPLONG", + "LPMOUSEINPUT", + "LPMSG", + "LPPOINT", + "LPRAWHID", + "LPRAWINPUTDEVICELIST", + "LPRAWINPUTHEADER", + "LPRAWKEYBOARD", + "LPRECT", + "LPRID", + "LPSTR", + "LPSTRING", + "LPSYSTEMTIME", + "LPTSTR", + "LPVOID", + "lpwcx", + "LPWINDOWINFO", + "LPWNDCLASSEX", + "LPWNDCLASSEXW", + "LPWORD", + "LPWSTR", + "LRESULT", + "LWIN", + "MIDDLEDOWN", + "minwinbase", + "MOUSEINPUT", + "Ntdll", + "NTSTATUS", + "NUMLOCK", + "pati", + "PBOOL", + "PBOOLEAN", + "PBYTE", + "pcch", + "PCHAR", + "PCSTR", + "PCTSTR", + "PCWSTR", + "PDWORD", + "PDWORDLONG", + "Pels", + "PFILETIME", + "PFLASHWINFO", + "PFLOAT", + "pfwi", + "PHALF", + "PHANDLE", + "PHKEY", + "PINPUT", + "PJOB", + "PKEYBDINPUT", + "PLCID", + "PLONG", + "PLONGLONG", + "PORTPROMPT", + "PPEB", + "PPRINTER", + "PPRINTPROCESSOR", + "PRID", + "PRINTPROCESSOR", + "PSHORT", + "PSIZE", + "PSSIZE", + "PSTR", + "PTBYTE", + "PTCHAR", + "PTSTR", + "PUCHAR", + "PUHALF", + "PUINT", + "PULONG", + "PULONGLONG", + "PWCHAR", + "PWINDOWINFO", + "PWORD", + "PWSTR", + "QWORD", + "Radeon", + "RAWHID", + "RAWINPUTDEVICELIST", + "RAWINPUTHEADER", + "RAWKEYBOARD", + "RIGHTDOWN", + "RIGHTUP", + "RWIN", + "SCANCODE", + "Spoolss", + "SSIZE", + "SYSTEMTIME", + "TBYTE", + "TCHAR", + "Thiscall", + "ulonglong", + "VMBUS", + "winbase", + "WINDOWINFO", + "WINEVENTPROC", + "winmsg", + "WNDCLASSEXW", + "WNDENUMPROC" + ] } - diff --git a/CHANGES.v22.md b/CHANGES.v22.md new file mode 100644 index 00000000..0bd1e01d --- /dev/null +++ b/CHANGES.v22.md @@ -0,0 +1,115 @@ +# Notable Changes v22 + +## Feat + +### 1. Use [koffi] as node-ffi to support nodejs >= 18 + +### 2. Remove dependencies ffi-napi, ref-napi, ref-struct-di, ref-union-di + +### 3. Easy structures initialization `_Factory()` + +### 4. Very easy structure/union definition + +- Simple example [`POINT`] +- Complex example [`DEVMODEW`] contains sub struct and union +- Complex example [`DISPLAY_DEVICEW`] contains FixedInt16Array + +### 5. Auto create necessary struct/union when loading library from method def + +```ts +import * as D from '##/index.def.js' +import * as S from '##/index.struct.js' +import * as T from '##/index.types.js' + +class DefWin { + static ClientToScreen = [D.BOOL, [D.HWND, `_Inout_ ${S.LPPOINT}`]] // S.LPPOINT == 'POINT*' + static EnumDisplayDevicesW = [D.BOOL, [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD]] // S.LPDISPLAY_DEVICEW == 'DISPLAY_DEVICEW*' + static GetCursorPos = [D.BOOL, [`_Out_ ${S.LPPOINT}`]] +} + +``` + +The structures of `LPPOINT`, `LPDISPLAY_DEVICEW` will be created on `load()` automatically + +### 6. Multiple Choice Parameters + +It can define multiple def choice for one parameter: + +```ts +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +export class DefWinspool implements T.LibDefBase { + + static GetPrinterW = [D.BOOL, [ + D.HANDLE, + D.DWORD, + // multiple choice instead of `_Out_ ${D.LPBYTE}`, + [ + `_Out_ ${S.PPRINTER_INFO_1}`, + `_Out_ ${S.PPRINTER_INFO_4}`, + `_Out_ ${S.PPRINTER_INFO_5}`, + `_Out_ ${S.PPRINTER_INFO_6}`, + `_Out_ ${S.PPRINTER_INFO_8}`, + `_Out_ ${S.PPRINTER_INFO_9}`, + ], + D.DWORD, + `_Out_ ${D.LPDWORD}`, + ]] as const // `as const` is required for multipleChoice + +} + +export class Winspool implements T.LibDef2Type { + + GetPrinterW: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pPrinter: S.PRINTER_INFO_X_Type, // multiple choice + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => T.BOOL + + + // You should declare async one only for generics + GetPrinterW_Async: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pPrinter: S.PRINTER_INFO_X_Type, // multiple choice + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => Promise + +} + +``` + +It must define multipleChoice mapper for this method: [`GetPrinterW_mapper`] + + +## Refactor + +### win32-def + +- Change export `/common.def` to `/def` +- rename function `bufferToString()` -> `ucsBufferToString()` + +### win32-api + +- exposed `DTypes` changed to `Def` +- exposed `DStruct` changed to `Struct` +- exposed `DModle` changed to `Types` +- exposed `/func` changed to '/util' +- `winmsg.ts` moved to `win32-def/winmsg.enum.ts` as `WIN_MSG` +- `kernel32/consts.ts` moved to `win32-def/consts/winbase.enum.ts` +- `user32/consts.ts` moved `win32-def/consts/user32.enum.ts` + + + + +[koffi]: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 + +[`POINT`]: https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/windef/POINT.ts +[`DEVMODEW`]: https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/wingdi/DEVMODEW.ts +[`DISPLAY_DEVICEW`]: https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/wingdi/DISPLAY_DEVICEW.ts +[`GetPrinterW_mapper`]: https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/src/lib/winspool/mapper/GetPrinterW.mapper.ts diff --git a/README.md b/README.md index 60354e67..593facad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # win32-api -FFI Definitions of Windows win32 api for [node-ffi-napi] +FFI Definitions of Windows win32 api for [koffi] [![GitHub tag](https://img.shields.io/github/tag/waitingsong/node-win32-api.svg)]() [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) @@ -12,15 +12,17 @@ FFI Definitions of Windows win32 api for [node-ffi-napi] [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/) +## Significant [Changes.V22] + +Compile successfully with +- Node.js v18 +- Node.js v20 +- Node.js v22 + ## Migrate to v13 See [migrate13] -## Initialization - -```sh -npm run bootstrap -``` ## Packages @@ -44,193 +46,34 @@ npm install win32-api ### DLL Wrapper -- [User32](./packages/win32-api/src/func/user32/index.user32.ts) -- [Winspool](./packages/win32-api/src/func/winspool/index.winspool.ts) +- [User32](./src/util/user32/index.user32.ts) +- [Winspool](./src/util/winspool/index.winspool.ts) ```ts import { - user32FindWindowEx, - winspoolGetDefaultPrinter, -} from 'win32-api/fun' + FindWindow, + GetDefaultPrinter, +} from 'win32-api/util' // Retrieves the printer name of the default printer for the current user on the local computer -const printerName = await winspoolGetDefaultPrinter() +const printerName = await GetDefaultPrinter() const child = spawn('notepad.exe') -const hWnd = await user32FindWindowEx(0, 0, 'Notepad', null) -``` - -### Find window and set window title -```ts -// **Find calc's hWnd, need running a calculator program manually at first** - -/** - * Exposed modules: - * Comctl32: Comctl32 from lib/comctl32/api - * Kernel32: kernel32 from lib/kernel32/api - * User32: user32 from lib/user32/api - */ -import { Kernel32, User32 } from 'win32-api/promise' -import ref from 'ref-napi' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -// const user32 = load(['FindWindowExW']) // load only one api defined in lib/{dll}/api from user32.dll - -const title = 'Calculator\0' // null-terminated string -// const title = '计算器\0' // null-terminated string 字符串必须以\0即null结尾! - -const lpszWindow = Buffer.from(title, 'ucs2') -const hWnd = await user32.FindWindowExW(0, 0, null, lpszWindow) - -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0) -console.log('buf: ', hWnd) - -// Change title of the Calculator -const res = await user32.SetWindowTextW(hWnd, Buffer.from('Node-Calculator\0', 'ucs2')) -if ( ! res) { - console.log('SetWindowTextW failed') -} -else { - console.log('window title changed') -} -``` - -### [Ref](https://www.npmjs.com/package/ref-napi) -```ts -import ref from 'ref-napi' - -// so we can all agree that a buffer with the int value written -// to it could be represented as an "int *" -const buf = Buffer.alloc(4) -buf.writeInt32LE(12345, 0) - -const hex = ref.hexAddress(buf) -console.log(typeof hex) -console.log(hex) // ← '7FA89D006FD8' - -buf.type = ref.types.int // @ts-ignore - -// now we can dereference to get the "meaningful" value -console.log(ref.deref(buf)) // ← 12345 -``` - -```ts -// use of types and windef: -import ref from 'ref-napi' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' -import { Kernel32, User32 } from 'win32-api/promise' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('guard64\0', 'ucs2') -const hInstanceBuffer = ref.alloc(W.HANDLE_PVOID) -const hInstanceAddr = ref.address(hInstanceBuffer) - -await knl32.GetModuleHandleExW(0, lpszClass, hInstanceAddr) -// -console.log(hInstanceBuffer) -console.log(hInstanceBuffer.readInt32LE(0)) // -> 1621360640 (60A40000) -console.log(hInstanceBuffer.readBigUInt64LE()) // -> 140734814748672n (7FFF60A40000) -``` - -### [Struct](https://www.npmjs.com/package/ref-struct) -```ts -// struct usage with ref-struct -import { retrieveStructFromPtrAddress, StructFactory } from 'win32-api' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' - -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -const point = StructFactory(DS.POINT) -point.x = 100 -point.y = 200 -console.log(point) -``` - -### [Struct](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/) -```ts -import { StructFactory } from 'win32-api' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' - - -// https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew -const dd: M.DISPLAY_DEVICEW = StructFactory(DS.DISPLAY_DEVICEW) -dd.cb = dd.ref().byteLength -console.log(dd) -// https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test/user32/51.user32.EnumDisplayDevicesW.test.ts -``` - -### Async Find window and set window title -```ts -// **Find calc's hWnd, need running a calculator program manually at first** -import * as ref from 'ref-napi' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' -import { Kernel32, User32 } from 'win32-api/promise' - - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('CalcFrame\0', 'ucs2') -// win10 -const calcLpszWindow = Buffer.from('Calculator\0', 'ucs2') -// for win7/8 -const calcLpszClass = Buffer.from('CalcFrame\0', 'ucs2') - -const child = spawn('calc.exe') -const hWnd = await user32.FindWindowExW(0, 0, null, calcLpszWindow) // win10 -const hWnd = await user32.FindWindowExW(0, 0, calcLpszClass , null) // win7/8 -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0, 'found no calc window') - -const title = 'Node-Calculator' -const len = title.length - -const ret = await user32.SetWindowTextW(hWnd, Buffer.from(title + '\0', 'ucs2')) -assert(ret, 'SetWindowTextW() failed') - -const buf = Buffer.alloc(len * 2) -await user32.GetWindowTextW(hWnd, buf, len + 1) -const str = buf.toString('ucs2').replace(/\0+$/, '') -assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`) - -child.kill() // seems not work under win10 +const hWnd = await FindWindowEx(0, 0, 'Notepad', null) ``` ## Demo -- [create_window](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo/create_window.ts) - [Demos](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo) - [Tests](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test) -## Dependencies Troubleshooting - -Compile successfully with - - Node.js v18, Python v3.9 and VS2019, VS2022 - - Node.js v16, Python v3.9 and VS2019, VS2022 - - Node.js v14, Python v3.7 and VS2019 - -If installation of node-gyp fails: -Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] - ## Relevant - [Windows Api documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ff468919%28v=vs.85%29.aspx) - [Windows Data Types](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751#DWORD) - [System Error Codes](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx) - [FFI doc](https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial) -- [ref doc](https://tootallnate.github.io/ref/) -- [ref-struct](https://github.com/TooTallNate/ref-struct) ## License @@ -265,4 +108,7 @@ Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] [def-dd-link]: https://david-dm.org/waitingsong/node-win32-api?path=packages/win32-def#info=devDependencies +[koffi]: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 [migrate13]: ./migrate13.md +[Changes.V22]: https://github.com/waitingsong/node-win32-api/CHANGES.v22.md + diff --git a/README.zh-CN.md b/README.zh-CN.md index 217a0a67..49d1139e 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -12,6 +12,14 @@ Windows win32 api 接口定义 [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/) + +## Significant [Changes.V22] + +兼容于 +- Node.js v18 +- Node.js v20 +- Node.js v22 + ## Migrate to v13 See [migrate13] @@ -31,7 +39,7 @@ npm run bootstrap ## 用途 -用于 Node.js 通过 [node-ffi-napi] 调用系统user32.dll, kerner32.dll, comctl32.dll 等动态链接库提供的函数 +用于 Node.js 通过 [koffi] 调用系统user32.dll, kerner32.dll, comctl32.dll 等动态链接库提供的函数 ## 安装 @@ -43,190 +51,34 @@ npm install win32-api ### DLL Wrapper -- [User32](./packages/win32-api/src/func/user32/index.user32.ts) -- [Winspool](./packages/win32-api/src/func/winspool/index.winspool.ts) +- [User32](./src/util/user32/index.user32.ts) +- [Winspool](./src/util/winspool/index.winspool.ts) ```ts import { - user32FindWindowEx, - winspoolGetDefaultPrinter, -} from 'win32-api/fun' + FindWindow, + GetDefaultPrinter, +} from 'win32-api/util' // 获取当前电脑当前用户默认打印机名 -const printerName = await winspoolGetDefaultPrinter() +const printerName = await GetDefaultPrinter() const child = spawn('notepad.exe') -const hWnd = await user32FindWindowEx(0, 0, 'Notepad', null) - -``` - -### Find window and set window title -```ts -// **查询计算器程序窗口句柄(需要先手动运行一个计算器)** - -/** - * 导出的模块: - * Comctl32: Comctl32 from lib/comctl32/api - * Kernel32: kernel32 from lib/kernel32/api - * User32: user32 from lib/user32/api - */ -import { Kernel32, User32 } from 'win32-api/promise' -import ref from 'ref-napi' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -// const user32 = load(['FindWindowExW']) // load only one api defined in lib/{dll}/api from user32.dll - -// const title = 'Calculator\0' // null-terminated string - const title = '计算器\0' // null-terminated string 字符串必须以\0即null结尾! - -const lpszWindow = Buffer.from(title, 'ucs2') -const hWnd = await user32.FindWindowExW(0, 0, null, lpszWindow) - -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0) -console.log('buf: ', hWnd) - -// Change title of the Calculator -const res = await user32.SetWindowTextW(hWnd, Buffer.from('Node-Calculator\0', 'ucs2')) -if ( ! res) { - console.log('SetWindowTextW failed') -} -else { - console.log('window title changed') -} -``` - -### [Ref](https://www.npmjs.com/package/ref-napi) -```ts -import ref from 'ref-napi' - -// so we can all agree that a buffer with the int value written -// to it could be represented as an "int *" -const buf = Buffer.alloc(4) -buf.writeInt32LE(12345, 0) - -const hex = ref.hexAddress(buf) -console.log(typeof hex) -console.log(hex) // ← '7FA89D006FD8' - -buf.type = ref.types.int // @ts-ignore - -// now we can dereference to get the "meaningful" value -console.log(ref.deref(buf)) // ← 12345 -``` - -```ts -// use of types and windef: -import ref from 'ref-napi' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' -import { Kernel32, User32 } from 'win32-api/promise' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('guard64\0', 'ucs2') -const hInstanceBuffer = ref.alloc(W.HANDLE_PVOID) -const hInstanceAddr = ref.address(hInstanceBuffer) - -await knl32.GetModuleHandleExW(0, lpszClass, hInstanceAddr) -// -console.log(hInstanceBuffer) -console.log(hInstanceBuffer.readInt32LE(0)) // -> 1621360640 (60A40000) -console.log(hInstanceBuffer.readBigUInt64LE()) // -> 140734814748672n (7FFF60A40000) -``` +const hWnd = await FindWindowEx(0, 0, 'Notepad', null) -### [Struct](https://www.npmjs.com/package/ref-struct) -```ts -// struct usage with ref-struct -import { retrieveStructFromPtrAddress, StructFactory } from 'win32-api' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' - -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -const point = StructFactory(DS.POINT) -point.x = 100 -point.y = 200 -console.log(point) -``` - -### [Struct](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/) -```ts -import { StructFactory } from 'win32-api' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' - -// https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew -const dd: M.DISPLAY_DEVICEW = StructFactory(DS.DISPLAY_DEVICEW) -dd.cb = dd.ref().byteLength -console.log(dd) -// https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test/user32/51.user32.EnumDisplayDevicesW.test.ts -``` - -### Async Find window and set window title -```ts -// **Find calc's hWnd, need running a calculator program manually at first** -import * as ref from 'ref-napi' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' -import { Kernel32, User32 } from 'win32-api/promise' - - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('CalcFrame\0', 'ucs2') -// win10 -const calcLpszWindow = Buffer.from('Calculator\0', 'ucs2') -// for win7/8 -const calcLpszClass = Buffer.from('CalcFrame\0', 'ucs2') - -const child = spawn('calc.exe') -const hWnd = await user32.FindWindowExW(0, 0, null, calcLpszWindow) // win10 -const hWnd = await user32.FindWindowExW(0, 0, calcLpszClass , null) // win7/8 -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0, 'found no calc window') - -const title = 'Node-Calculator' -const len = title.length - -const ret = await user32.SetWindowTextW(hWnd, Buffer.from(title + '\0', 'ucs2')) -assert(ret, 'SetWindowTextW() failed') - -const buf = Buffer.alloc(len * 2) -await user32.GetWindowTextW(hWnd, buf, len + 1) -const str = buf.toString('ucs2').replace(/\0+$/, '') -assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`) - -child.kill() // seems not work under win10 ``` ## Demo -- [create_window](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo/create_window.ts) -- [Demos](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo) -- [Tests](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test) - -## 依赖安装问题 -Compile successfully with - - Node.js v18, Python v3.9 and VS2019, VS2022 - - Node.js v16, Python v3.9 and VS2019, VS2022 - - Node.js v14, Python v3.7 and VS2019 +- [Demos](https://github.com/waitingsong/node-win32-api/packages/win32-api/demo) +- [Tests](https://github.com/waitingsong/node-win32-api/packages/win32-api/test) -If installation of node-gyp fails: -Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] ## 相关文档 - [Windows Api documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ff468919%28v=vs.85%29.aspx) - [Windows Data Types](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751#DWORD) - [System Error Codes](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx) - [FFI doc](https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial) -- [ref doc](https://tootallnate.github.io/ref/) -- [ref-struct](https://github.com/TooTallNate/ref-struct) ## 版权 @@ -260,3 +112,5 @@ Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] [def-dd-svg]: https://david-dm.org/waitingsong/node-win32-api/dev-status.svg?path=packages/win32-def [def-dd-link]: https://david-dm.org/waitingsong/node-win32-api?path=packages/win32-def#info=devDependencies +[Changes.V22]: https://github.com/waitingsong/node-win32-api/CHANGES.v22.md +[koffi]: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 44662cd6..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,51 +0,0 @@ -clone_folder: c:\projects\myproject -shallow_clone: true - -init: - - git config --global core.autocrlf input - -# cache: -# - node_modules # local npm modules -# - '%APPDATA%\npm-cache' # npm cache - - -environment: - matrix: - - nodejs_version: "16" - #- nodejs_version: "18" - -platform: - - x64 - #- x86 - -install: - - ps: Install-Product node $env:nodejs_version $env:platform - - npm root -g - - echo %APPVEYOR_REPO_COMMIT_MESSAGE% - - npm i -g lerna rollup zx - - npm run bootstrap - - echo %APPVEYOR_REPO_COMMIT_MESSAGE% | .\\node_modules\\.bin\\commitlint - -#services: -# - postgresql101 -# -before_test: - - SET PGUSER=postgres - - SET PGPASSWORD=Password12! - - SET PATH=C:\Program Files\PostgreSQL\10\bin\;%PATH% - #- psql -U postgres -c "create database db_ci_test;" - -test_script: - - openssl version - - node --version - - npm --version - - npm run build - - npm run test - -on_success: - #- npm run cov:coveralls - -build: off -deploy: off -skip_tags: true - diff --git a/commitlint.config.js b/commitlint.config.cjs similarity index 100% rename from commitlint.config.js rename to commitlint.config.cjs diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..6ffe1f21 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,59 @@ +import eslint from 'typescript-eslint' + +import srcConfig from '@waiting/eslint-config' +import testConfig from '@waiting/eslint-config/test' +import { genCurrentDirname, genModuleAbsolutePathIfExists } from '@waiting/shared-core' + + +const projectDir = genCurrentDirname(import.meta.url) + +const srcRules = { + 'import/no-extraneous-dependencies': [2, { + devDependencies: false, + optionalDependencies: false, + bundledDependencies: false, + packageDir: [ + '.', + await genModuleAbsolutePathIfExists(projectDir, 'node_modules/@waiting/shared-core') ?? '.', + await genModuleAbsolutePathIfExists(projectDir, 'node_modules/@mwcp/share') ?? '.', + await genModuleAbsolutePathIfExists(projectDir, 'node_modules/win32-def') ?? '.', + ], + }], + 'id-length': 0, + 'unicorn/filename-case': 0, + '@typescript-eslint/no-duplicate-enum-values': 0, +} +const testRules = { + '@typescript-eslint/no-explicit-any': 0, + 'id-length': 0, + 'unicorn/filename-case': 0, + '@typescript-eslint/no-duplicate-enum-values': 0, +} + +const languageOptions = { + parserOptions: { + // project: 'tsconfig.eslint.json', + project: ['./tsconfig.eslint.json', './packages/*/tsconfig.eslint.json'], + tsconfigRootDir: import.meta.dirname, + }, +} + +export default eslint.config( + { + files: ['packages/*/src/**/*.ts', 'src/**/*.ts', 'packages/*/demo/**/*.mts' , 'packages/*/demo/**/*.ts'], + extends: [ + ...srcConfig, + ], + rules: srcRules, + languageOptions, + }, + { + files: ['packages/*/test/**/*.ts', 'test/**/*.ts'], + extends: [ + ...testConfig, + ], + rules: testRules, + languageOptions, + } +) + diff --git a/lerna.json b/lerna.json index 8969dac9..6e69ce62 100644 --- a/lerna.json +++ b/lerna.json @@ -1,12 +1,8 @@ { "version": "21.0.2", - "packages": [ - "packages/*" - ], "command": { "publish": { "ignoreChanges": [ - "*.md", ".githooks", ".scripts", ".vscode", @@ -16,23 +12,21 @@ ], "verifyAccess": false }, - "bootstrap": { - "hoist": true, - "noCi": true, - "nohoist": [ - "cross-env", - "egg" - ], - "npmClientArgs": [ - "--no-audit" - ] - }, "version": { "conventionalCommits": true, "allowBranch": [ "main", + "fix", "release", - "fix" + "versioning_*" + ], + "ignoreChanges": [ + ".githooks", + ".scripts", + ".vscode", + "package-lock.json", + "packages/demo", + "packages/mw-demo" ], "registry": "https://registry.npmjs.org/" } diff --git a/package.json b/package.json index 02642681..9a9b7f21 100644 --- a/package.json +++ b/package.json @@ -3,63 +3,59 @@ "version": "1.0.0", "description": "FFI definitions of windows win32 api for node-ffi", "private": true, + "type": "module", "devDependencies": { - "@commitlint/cli": "17", - "@commitlint/config-conventional": "17", - "@midwayjs/cli": "^2.0.10", - "@midwayjs/mock": "^3.10.3", - "@midwayjs/web": "^3.10.3", - "@rollup/plugin-commonjs": "24", + "@commitlint/cli": "19", + "@commitlint/config-conventional": "19", + "@rollup/plugin-commonjs": "26", "@rollup/plugin-node-resolve": "15", "@types/mocha": "10", - "@types/node": "18", - "@waiting/eslint-config": "^8.8.0", - "@waiting/shared-core": "^20.11.4", - "@waiting/shared-types": "^20.11.0", - "autocannon": "^7.10.0", - "coveralls": "3", - "eslint": "^8.33.0", - "madge": "^6.0.0", + "@types/node": "20", + "@waiting/eslint-config": "^10.26.0", + "@waiting/shared-core": "^23.13.0", + "@waiting/shared-types": "^23.13.0", + "autocannon": "7", + "cross-env": "7", + "eslint": "8", "mocha": "10", - "rollup-plugin-dts": "^5.1.1", + "rollup-plugin-dts": "^6.1.1", "rxjs": "^7.8.0", - "ts-node": "^10.9.1", - "tsc-alias": "^1.8.2", "tsconfig-paths": "4", - "typescript": "^5.4.5", - "zx": "7" + "ts-node": "^10.9.2", + "tsc-alias": "^1.8.10", + "typescript": "^5.5.2" }, "engines": { - "node": ">=16.13.0" + "node": ">=18.11.0" }, + "workspaces": [ + "packages/*" + ], "scripts": { "add:pkg": "sh .scripts/add-pkg.sh", "bp:add": "git remote add bp https://github.com/waitingsong/npm-mono-base", "bp:sync": "git fetch --all -v && git pull origin && git merge bp/main -m \"Merge remote-tracking branch 'bp/main'\" ", + "bp:sync-force": "git fetch --all -v && git pull origin && git merge bp/main --allow-unrelated-histories -m \"Merge remote-tracking branch 'bp/main'\" ", "bp:syncxo": "git fetch --all -v && git pull origin && git merge bp/main -m \"Merge remote-tracking branch 'bp/main'\" -Xours", - "bootstrap": "lerna bootstrap --loglevel notice --concurrency 4", - "bootstrap2": "lerna bootstrap --loglevel notice -- --legacy-peer-deps", - "postbootstrap": "npm run repo:init", + "bootstrap": "npm i --loglevel info --disturl=https://npmmirror.com/dist/", "build": "sh .scripts/build.sh", "ci": "npm run cov", - "clean": "lerna clean --loglevel error --yes & lerna run clean", - "clean:dist": "rm -rf packages/*/dist/ & rm -rf packages/*/.vscode/", + "clean": "lerna clean --loglevel error --yes && lerna run clean", "cov": "sh .scripts/cov.sh", - "doc": "node .githooks/doc.js", "lint": "sh .scripts/lint.sh", "lint:cycle": "lerna exec -- madge --circular --extensions ts src", "lint:nofix": "sh .scripts/lint-no-fix.sh", "lint:s": "sh .scripts/lint-no-fix-s.sh", "postbuild": "rm -rf packages/*/dist/.mwcc-cache", "postinstall": "npm run repo:init", - "pub": "bash .scripts/publish.sh --conventional-commits --create-release github", + "postpublish": "rm -rf packages/*/npm-shrinkwrap.json", + "pub": "bash .scripts/publish.sh --no-private --conventional-commits --create-release github", "pub:canary": "bash .scripts/publish.sh --canary", "pub:beta": "bash .scripts/publish.sh --dist-tag beta --force-publish=*", "pub:next": "bash .scripts/publish.sh --dist-tag next", - "purge": "npm run clean & lerna run purge & rm node_modules -rf & rm package-lock.json -f & nx reset", - "postpurge": "npm run refresh", + "purge": "sh .scripts/purge.sh", "repo:init": "sh .githooks/init-repo.sh", - "refresh": "npm run bootstrap && npm run build", + "refresh": "npm run clean && npm update --no-audit && npm run build", "test": "lerna run test", "ptest": "sh .scripts/test.sh" } diff --git a/packages/win32-api/.nycrc.json b/packages/win32-api/.nycrc.json deleted file mode 100644 index 0d12c44b..00000000 --- a/packages/win32-api/.nycrc.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "include": [ - "src/**/*.ts" - ], - "exclude": [ - ".githooks", - "dist", - "node_modules*", - "src/bin", - "src/domain.ts", - "src/interface.ts", - "test*", - "**/node_modules*", - "**/*.d.ts", - "**/*.js" - ], - "extension": [ - ".ts" - ], - "reporter": [ - "html", - "json", - "text-summary" - ], - "all": true -} diff --git a/packages/win32-api/README.md b/packages/win32-api/README.md index 7cd83335..593facad 100644 --- a/packages/win32-api/README.md +++ b/packages/win32-api/README.md @@ -1,27 +1,28 @@ # win32-api -FFI Definitions of Windows win32 api for [node-ffi-napi] +FFI Definitions of Windows win32 api for [koffi] [![GitHub tag](https://img.shields.io/github/tag/waitingsong/node-win32-api.svg)]() [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) ![](https://img.shields.io/badge/lang-TypeScript-blue.svg) ![Available platform](https://img.shields.io/badge/platform-win32-blue.svg) [![ci](https://github.com/waitingsong/node-win32-api/workflows/ci-win/badge.svg)](https://github.com/waitingsong/node-win32-api/actions?query=workflow%3A%22ci-win%22) -[![Build status](https://ci.appveyor.com/api/projects/status/nrivtykm5uf84fbl/branch/main?svg=true)](https://ci.appveyor.com/project/waitingsong/node-win32-api/branch/main) [![codecov](https://codecov.io/gh/waitingsong/node-win32-api/branch/main/graph/badge.svg?token=WXbZvnAaYO)](https://codecov.io/gh/waitingsong/node-win32-api) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/) +## Significant [Changes.V22] + +Compile successfully with +- Node.js v18 +- Node.js v20 +- Node.js v22 + ## Migrate to v13 See [migrate13] -## Initialization - -```sh -npm run bootstrap -``` ## Packages @@ -45,196 +46,34 @@ npm install win32-api ### DLL Wrapper -- [User32](./packages/win32-api/src/func/user32/index.user32.ts) -- [Winspool](./packages/win32-api/src/func/winspool/index.winspool.ts) +- [User32](./src/util/user32/index.user32.ts) +- [Winspool](./src/util/winspool/index.winspool.ts) ```ts import { - user32FindWindowEx, - winspoolGetDefaultPrinter, -} from 'win32-api/fun' + FindWindow, + GetDefaultPrinter, +} from 'win32-api/util' // Retrieves the printer name of the default printer for the current user on the local computer -const printerName = await winspoolGetDefaultPrinter() +const printerName = await GetDefaultPrinter() const child = spawn('notepad.exe') -const hWnd = await user32FindWindowEx(0, 0, 'Notepad', null) -``` - -### Find window and set window title -```ts -// **Find calc's hWnd, need running a calculator program manually at first** - -/** - * Exposed modules: - * Comctl32: Comctl32 from lib/comctl32/api - * Kernel32: kernel32 from lib/kernel32/api - * User32: user32 from lib/user32/api - */ -import { Kernel32, User32 } from 'win32-api/promise' -import ref from 'ref-napi' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -// const user32 = load(['FindWindowExW']) // load only one api defined in lib/{dll}/api from user32.dll - -const title = 'Calculator\0' // null-terminated string -// const title = '计算器\0' // null-terminated string 字符串必须以\0即null结尾! - -const lpszWindow = Buffer.from(title, 'ucs2') -const hWnd = await user32.FindWindowExW(0, 0, null, lpszWindow) - -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0) -console.log('buf: ', hWnd) - -// Change title of the Calculator -const res = await user32.SetWindowTextW(hWnd, Buffer.from('Node-Calculator\0', 'ucs2')) -if ( ! res) { - console.log('SetWindowTextW failed') -} -else { - console.log('window title changed') -} -``` - -### [Ref](https://www.npmjs.com/package/ref-napi) -```ts -import ref from 'ref-napi' - -// so we can all agree that a buffer with the int value written -// to it could be represented as an "int *" -const buf = Buffer.alloc(4) -buf.writeInt32LE(12345, 0) - -const hex = ref.hexAddress(buf) -console.log(typeof hex) -console.log(hex) // ← '7FA89D006FD8' - -buf.type = ref.types.int // @ts-ignore - -// now we can dereference to get the "meaningful" value -console.log(ref.deref(buf)) // ← 12345 -``` - -```ts -// use of types and windef: -import ref from 'ref-napi' -import { DModel as M } from 'win32-api' -import { Kernel32, User32 } from 'win32-api/promise' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('guard64\0', 'ucs2') -const hInstanceBuffer = ref.alloc(W.HANDLE_PVOID) -const hInstanceAddr = ref.address(hInstanceBuffer) - -await knl32.GetModuleHandleExW(0, lpszClass, hInstanceAddr) -// -console.log(hInstanceBuffer) -console.log(hInstanceBuffer.readInt32LE(0)) // -> 1621360640 (60A40000) -console.log(hInstanceBuffer.readBigUInt64LE()) // -> 140734814748672n (7FFF60A40000) -``` - -### [Struct](https://www.npmjs.com/package/ref-struct) -```ts -// struct usage with ref-struct -import { retrieveStructFromPtrAddress, StructFactory } from 'win32-api' -import { - DModel as M, - DTypes as W, - DStruct as DS, -} from 'win32-api' - -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -const point = StructFactory(DS.POINT) -point.x = 100 -point.y = 200 -console.log(point) -``` - -### [Struct](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/) -```ts -import { StructFactory } from 'win32-api' -import { - DModel as M, - DTypes as W, - DStruct as DS, -} from 'win32-api' - - -// https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew -const dd: M.DISPLAY_DEVICEW = StructFactory(DS.DISPLAY_DEVICEW) -dd.cb = dd.ref().byteLength -console.log(dd) -// https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test/user32/51.user32.EnumDisplayDevicesW.test.ts -``` - -### Async Find window and set window title -```ts -// **Find calc's hWnd, need running a calculator program manually at first** -import * as ref from 'ref-napi' - -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' -import { Kernel32, User32 } from 'win32-api/promise' - - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('CalcFrame\0', 'ucs2') -// win10 -const calcLpszWindow = Buffer.from('Calculator\0', 'ucs2') -// for win7/8 -const calcLpszClass = Buffer.from('CalcFrame\0', 'ucs2') - -const child = spawn('calc.exe') -const hWnd = await user32.FindWindowExW(0, 0, null, calcLpszWindow) // win10 -const hWnd = await user32.FindWindowExW(0, 0, calcLpszClass , null) // win7/8 -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0, 'found no calc window') - -const title = 'Node-Calculator' -const len = title.length - -const ret = await user32.SetWindowTextW(hWnd, Buffer.from(title + '\0', 'ucs2')) -assert(ret, 'SetWindowTextW() failed') - -const buf = Buffer.alloc(len * 2) -await user32.GetWindowTextW(hWnd, buf, len + 1) -const str = buf.toString('ucs2').replace(/\0+$/, '') -assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`) - -child.kill() // seems not work under win10 +const hWnd = await FindWindowEx(0, 0, 'Notepad', null) ``` ## Demo -- [create_window](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo/create_window.ts) - [Demos](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo) - [Tests](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test) -## Dependencies Troubleshooting - -Compile successfully with - - Node.js v18, Python v3.9 and VS2019, VS2022 - - Node.js v16, Python v3.9 and VS2019, VS2022 - - Node.js v14, Python v3.7 and VS2019 - -If installation of node-gyp fails: -Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] - ## Relevant - [Windows Api documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ff468919%28v=vs.85%29.aspx) - [Windows Data Types](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751#DWORD) - [System Error Codes](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx) - [FFI doc](https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial) -- [ref doc](https://tootallnate.github.io/ref/) -- [ref-struct](https://github.com/TooTallNate/ref-struct) ## License @@ -269,4 +108,7 @@ Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] [def-dd-link]: https://david-dm.org/waitingsong/node-win32-api?path=packages/win32-def#info=devDependencies +[koffi]: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 [migrate13]: ./migrate13.md +[Changes.V22]: https://github.com/waitingsong/node-win32-api/CHANGES.v22.md + diff --git a/packages/win32-api/README.zh-CN.md b/packages/win32-api/README.zh-CN.md index 59111c5e..49d1139e 100644 --- a/packages/win32-api/README.zh-CN.md +++ b/packages/win32-api/README.zh-CN.md @@ -7,12 +7,19 @@ Windows win32 api 接口定义 ![](https://img.shields.io/badge/lang-TypeScript-blue.svg) ![Available platform](https://img.shields.io/badge/platform-win32-blue.svg) [![ci](https://github.com/waitingsong/node-win32-api/workflows/ci-win/badge.svg)](https://github.com/waitingsong/node-win32-api/actions?query=workflow%3A%22ci-win%22) -[![Build status](https://ci.appveyor.com/api/projects/status/nrivtykm5uf84fbl/branch/main?svg=true)](https://ci.appveyor.com/project/waitingsong/node-win32-api/branch/main) [![codecov](https://codecov.io/gh/waitingsong/node-win32-api/branch/main/graph/badge.svg?token=WXbZvnAaYO)](https://codecov.io/gh/waitingsong/node-win32-api) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/) + +## Significant [Changes.V22] + +兼容于 +- Node.js v18 +- Node.js v20 +- Node.js v22 + ## Migrate to v13 See [migrate13] @@ -32,7 +39,7 @@ npm run bootstrap ## 用途 -用于 Node.js 通过 [node-ffi-napi] 调用系统user32.dll, kerner32.dll, comctl32.dll 等动态链接库提供的函数 +用于 Node.js 通过 [koffi] 调用系统user32.dll, kerner32.dll, comctl32.dll 等动态链接库提供的函数 ## 安装 @@ -44,191 +51,34 @@ npm install win32-api ### DLL Wrapper -- [User32](./packages/win32-api/src/func/user32/index.user32.ts) -- [Winspool](./packages/win32-api/src/func/winspool/index.winspool.ts) +- [User32](./src/util/user32/index.user32.ts) +- [Winspool](./src/util/winspool/index.winspool.ts) ```ts import { - user32FindWindowEx, - winspoolGetDefaultPrinter, -} from 'win32-api/fun' + FindWindow, + GetDefaultPrinter, +} from 'win32-api/util' // 获取当前电脑当前用户默认打印机名 -const printerName = await winspoolGetDefaultPrinter() +const printerName = await GetDefaultPrinter() const child = spawn('notepad.exe') -const hWnd = await user32FindWindowEx(0, 0, 'Notepad', null) - -``` - -### Find window and set window title -```ts -// **查询计算器程序窗口句柄(需要先手动运行一个计算器)** - -/** - * 导出的模块: - * Comctl32: Comctl32 from lib/comctl32/api - * Kernel32: kernel32 from lib/kernel32/api - * User32: user32 from lib/user32/api - */ -import { Kernel32, User32 } from 'win32-api/promise' -import ref from 'ref-napi' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -// const user32 = load(['FindWindowExW']) // load only one api defined in lib/{dll}/api from user32.dll - -// const title = 'Calculator\0' // null-terminated string - const title = '计算器\0' // null-terminated string 字符串必须以\0即null结尾! - -const lpszWindow = Buffer.from(title, 'ucs2') -const hWnd = await user32.FindWindowExW(0, 0, null, lpszWindow) - -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0) -console.log('buf: ', hWnd) - -// Change title of the Calculator -const res = await user32.SetWindowTextW(hWnd, Buffer.from('Node-Calculator\0', 'ucs2')) -if ( ! res) { - console.log('SetWindowTextW failed') -} -else { - console.log('window title changed') -} -``` - -### [Ref](https://www.npmjs.com/package/ref-napi) -```ts -import ref from 'ref-napi' - -// so we can all agree that a buffer with the int value written -// to it could be represented as an "int *" -const buf = Buffer.alloc(4) -buf.writeInt32LE(12345, 0) - -const hex = ref.hexAddress(buf) -console.log(typeof hex) -console.log(hex) // ← '7FA89D006FD8' - -buf.type = ref.types.int // @ts-ignore - -// now we can dereference to get the "meaningful" value -console.log(ref.deref(buf)) // ← 12345 -``` - -```ts -// use of types and windef: -import ref from 'ref-napi' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - -import { Kernel32, User32 } from 'win32-api/promise' - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('guard64\0', 'ucs2') -const hInstanceBuffer = ref.alloc(W.HANDLE_PVOID) -const hInstanceAddr = ref.address(hInstanceBuffer) +const hWnd = await FindWindowEx(0, 0, 'Notepad', null) -await knl32.GetModuleHandleExW(0, lpszClass, hInstanceAddr) -// -console.log(hInstanceBuffer) -console.log(hInstanceBuffer.readInt32LE(0)) // -> 1621360640 (60A40000) -console.log(hInstanceBuffer.readBigUInt64LE()) // -> 140734814748672n (7FFF60A40000) -``` - -### [Struct](https://www.npmjs.com/package/ref-struct) -```ts -// struct usage with ref-struct -import { retrieveStructFromPtrAddress, StructFactory } from 'win32-api' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' - -// https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx -const point = StructFactory(DS.POINT) -point.x = 100 -point.y = 200 -console.log(point) -``` - -### [Struct](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-def/src/lib/struct/) -```ts -import { StructFactory } from 'win32-api' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' - - -// https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew -const dd: M.DISPLAY_DEVICEW = StructFactory(DS.DISPLAY_DEVICEW) -dd.cb = dd.ref().byteLength -console.log(dd) -// https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test/user32/51.user32.EnumDisplayDevicesW.test.ts -``` - -### Async Find window and set window title -```ts -// **Find calc's hWnd, need running a calculator program manually at first** -import * as ref from 'ref-napi' -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' -import * as DS from 'win32-def/struct.def' -import { Kernel32, User32 } from 'win32-api/promise' - - -const knl32 = Kernel32.load() -const user32 = User32.load() - -const lpszClass = Buffer.from('CalcFrame\0', 'ucs2') -// win10 -const calcLpszWindow = Buffer.from('Calculator\0', 'ucs2') -// for win7/8 -const calcLpszClass = Buffer.from('CalcFrame\0', 'ucs2') - -const child = spawn('calc.exe') -const hWnd = await user32.FindWindowExW(0, 0, null, calcLpszWindow) // win10 -const hWnd = await user32.FindWindowExW(0, 0, calcLpszClass , null) // win7/8 -assert((typeof hWnd === 'string' && hWnd.length > 0) || hWnd > 0, 'found no calc window') - -const title = 'Node-Calculator' -const len = title.length - -const ret = await user32.SetWindowTextW(hWnd, Buffer.from(title + '\0', 'ucs2')) -assert(ret, 'SetWindowTextW() failed') - -const buf = Buffer.alloc(len * 2) -await user32.GetWindowTextW(hWnd, buf, len + 1) -const str = buf.toString('ucs2').replace(/\0+$/, '') -assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`) - -child.kill() // seems not work under win10 ``` ## Demo -- [create_window](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo/create_window.ts) -- [Demos](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/demo) -- [Tests](https://github.com/waitingsong/node-win32-api/blob/main/packages/win32-api/test) - -## 依赖安装问题 -Compile successfully with - - Node.js v18, Python v3.9 and VS2019, VS2022 - - Node.js v16, Python v3.9 and VS2019, VS2022 - - Node.js v14, Python v3.7 and VS2019 +- [Demos](https://github.com/waitingsong/node-win32-api/packages/win32-api/demo) +- [Tests](https://github.com/waitingsong/node-win32-api/packages/win32-api/test) -If installation of node-gyp fails: -Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] ## 相关文档 - [Windows Api documentation](https://msdn.microsoft.com/en-us/library/windows/desktop/ff468919%28v=vs.85%29.aspx) - [Windows Data Types](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751#DWORD) - [System Error Codes](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx) - [FFI doc](https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial) -- [ref doc](https://tootallnate.github.io/ref/) -- [ref-struct](https://github.com/TooTallNate/ref-struct) ## 版权 @@ -262,3 +112,5 @@ Check out [node-gyp] and [node-gyp-on-windows], [windows-build-tools] [def-dd-svg]: https://david-dm.org/waitingsong/node-win32-api/dev-status.svg?path=packages/win32-def [def-dd-link]: https://david-dm.org/waitingsong/node-win32-api?path=packages/win32-def#info=devDependencies +[Changes.V22]: https://github.com/waitingsong/node-win32-api/CHANGES.v22.md +[koffi]: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 diff --git a/packages/win32-api/demo/EnumDisplayDevicesW.mts b/packages/win32-api/demo/EnumDisplayDevicesW.mts new file mode 100644 index 00000000..d7a5cc56 --- /dev/null +++ b/packages/win32-api/demo/EnumDisplayDevicesW.mts @@ -0,0 +1,50 @@ +#!/usr/bin/env tsx +/* eslint-disable import/no-extraneous-dependencies */ +import assert from 'node:assert/strict' + +import ffi from 'koffi' +import { decodeInt16Array } from 'win32-def' +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + + +console.info('EnumDisplayDevicesW()') + +const st = S.DISPLAY_DEVICEW_Factory() +console.info('size', st.size) +const dd = { + cb: st.size, +} as S.DISPLAY_DEVICEW_Type + +const typeInfo = ffi.introspect(st.CType) +console.info({ typeInfo }) + +const user32 = ffi.load('user32.dll') +try { + const func = user32.func( + '__stdcall', + 'EnumDisplayDevicesW', + D.BOOL, + [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD], + ) + + const res = func(null, 0, dd, 1) as number + const DeviceID = decodeInt16Array(dd.DeviceID) + const DeviceKey = decodeInt16Array(dd.DeviceKey) + const DeviceName = decodeInt16Array(dd.DeviceName) + const DeviceString = decodeInt16Array(dd.DeviceString) + + console.info({ res, DeviceID, DeviceKey, DeviceName, DeviceString }) + + assert(DeviceID.startsWith('PCI\\VEN_') || DeviceID.includes('VMBUS') || DeviceID === '', DeviceID) + assert(typeof DeviceKey === 'string', DeviceKey) + assert(DeviceName === '\\\\.\\DISPLAY1', DeviceName) + assert(DeviceString.length > 0) + const flag = ['Microsoft Hyper-V', 'Intel', 'AMD', 'Radeon'].some(val => DeviceString.includes(val)) + assert(flag, DeviceString) +} +finally { + user32.unload() +} + + diff --git a/packages/win32-api/demo/GetCursorPos.mts b/packages/win32-api/demo/GetCursorPos.mts new file mode 100644 index 00000000..33bf2c90 --- /dev/null +++ b/packages/win32-api/demo/GetCursorPos.mts @@ -0,0 +1,34 @@ +#!/usr/bin/env tsx +/* eslint-disable import/no-extraneous-dependencies */ +// link: https://koffi.dev/pointers#pointer-types +import assert from 'node:assert/strict' + +import ffi from 'koffi' +import { registerFunction } from 'win32-api' +import { POINT_Factory, POINT_Type } from 'win32-def/struct' + + +console.info('GetCursorPos()') + +const user32 = ffi.load('user32.dll') + +const comb = POINT_Factory() +const pos = { } as POINT_Type + +try { + // const func = user32.func(`int __stdcall GetCursorPos(_Out_ ${comb.pointer}pos)`) + // const func = user32.func('__stdcall', 'GetCursorPos', 'int', [`_Out_ ${comb.pointer}`]) + const func = registerFunction({ + lib: user32, + name: 'GetCursorPos', + params: ['int', [`_Out_ ${comb.pointer}`]], + }) + console.info(func.info) + + const res = func(pos) as number + console.info({ res, pos }) + assert(pos.x > 0 && pos.y > 0) +} +finally { + user32.unload() +} diff --git a/packages/win32-api/demo/create_window.ts b/packages/win32-api/demo/create_window.ts index 74ca7e6c..2c42af9f 100644 --- a/packages/win32-api/demo/create_window.ts +++ b/packages/win32-api/demo/create_window.ts @@ -31,13 +31,14 @@ import { DTypes as W, // K, U, -} from '../src/index' // as local +} from '../src/index' +// as local const Struct = StructDi(ref) // const knl32 = K.load() -const user32 = U.load() // load all apis defined in lib/{dll}/api from user32.dll -const comctl32 = C.load() // load all apis defined in lib/{dll}/api from user32.dll +const user32 = U.load() // load all apis defined in lib/{dll}/api from user32.dll +const comctl32 = C.load() // load all apis defined in lib/{dll}/api from user32.dll // WndProc const WndProc = ffi.Callback( @@ -123,7 +124,7 @@ function createWindow(title: string): M.HWND { wClass.lpszClassName = className wClass.hIconSm = ref.NULL - if (!user32.RegisterClassExW(wClass.ref())) { + if (! user32.RegisterClassExW(wClass.ref())) { throw new Error('Error registering class') } // const dStyle = U.constants.WS_OVERLAPPEDWINDOW @@ -152,11 +153,11 @@ function createWindow(title: string): M.HWND { function changeTitle(hWnd: Buffer, title: string): string { - if (hWnd && !ref.isNull(hWnd) && ref.address(hWnd)) { + if (hWnd && ! ref.isNull(hWnd) && ref.address(hWnd)) { // Change title of the Calculator const res = user32.SetWindowTextW(hWnd, Buffer.from(title + '\0', 'ucs2')) - if (!res) { + if (! res) { console.error('failed with', res) return '' } diff --git a/packages/win32-api/demo/find_window.ts b/packages/win32-api/demo/find_window.ts index 6dabc849..2678316b 100644 --- a/packages/win32-api/demo/find_window.ts +++ b/packages/win32-api/demo/find_window.ts @@ -10,9 +10,7 @@ import * as ref from 'ref-napi' -import { - U, -} from '../src/index' // as local +import { U } from '../src/index' // as local const user32 = U.load() diff --git a/packages/win32-api/demo/show-hide-desktop.mts b/packages/win32-api/demo/show-hide-desktop.mts new file mode 100644 index 00000000..4bb204a8 --- /dev/null +++ b/packages/win32-api/demo/show-hide-desktop.mts @@ -0,0 +1,53 @@ +#!/usr/bin/env tsx +/* eslint-disable import/no-extraneous-dependencies */ +import assert from 'node:assert/strict' + +import { sleep } from '@waiting/shared-core' +import { User32 } from 'win32-api' +import { INPUT, KEYBDINPUT, VirtualKey } from 'win32-def/consts' +import { INPUT_Factory, type INPUT_Type } from 'win32-def/struct' + + +console.info('Show/hide desktop with Win+D shortcut') + +const { INPUT_KEYBOARD } = INPUT +const { KEYEVENTF_KEYUP } = KEYBDINPUT +const { VK_RWIN } = VirtualKey +const { VK_D } = VirtualKey + +const events: INPUT_Type[] = [ + make_keyboard_event(VK_RWIN, true), + make_keyboard_event(VK_D, true), + make_keyboard_event(VK_D, false), + make_keyboard_event(VK_RWIN, false), +] + +const { size } = INPUT_Factory() + +const lib = User32.load() +const res = await lib.SendInput_Async(events.length, events, size) +assert(res === events.length) + +await sleep(2000) + +lib.SendInput(events.length, events, size) + +// Utility +function make_keyboard_event(vk: VirtualKey, down: boolean) { + const event: INPUT_Type = { + type: INPUT_KEYBOARD, + u: { + ki: { + wVk: vk, + wScan: 0, + dwFlags: down ? 0 : KEYEVENTF_KEYUP, + time: 0, + dwExtraInfo: 0, + }, + }, + } + return event +} + +console.info('finished') + diff --git a/packages/win32-api/package.json b/packages/win32-api/package.json index d413ba91..614fd96e 100644 --- a/packages/win32-api/package.json +++ b/packages/win32-api/package.json @@ -13,6 +13,8 @@ "winspool", "printer", "ffi", + "koffi", + "Electron", "ESM", "typescript", "ts" @@ -21,46 +23,19 @@ "bin": {}, "main": "dist/index.js", "types": "dist/index.d.ts", + "imports": { + "#package.json": "./package.json", + "##/*": "./src/*", + "#@/*": "./test/*" + }, "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.cjs" }, - "./promise": { - "import": "./dist/index.promise.js", - "require": "./dist/index.promise.cjs" - }, - "./consts": { - "import": "./dist/index.consts.js", - "require": "./dist/index.consts.cjs" - }, - "./comctl32": { - "import": "./dist/index.comctl32.js", - "require": "./dist/index.comctl32.cjs" - }, - "./kernel32": { - "import": "./dist/index.kernel32.js", - "require": "./dist/index.kernel32.cjs" - }, - "./ntdll": { - "import": "./dist/index.ntdll.js", - "require": "./dist/index.ntdll.cjs" - }, - "./spoolss": { - "import": "./dist/index.spoolss.js", - "require": "./dist/index.spoolss.cjs" - }, - "./user32": { - "import": "./dist/index.user32.js", - "require": "./dist/index.user32.cjs" - }, - "./winspool": { - "import": "./dist/index.winspool.js", - "require": "./dist/index.winspool.cjs" - }, - "./fun": { - "import": "./dist/index.fun.js", - "require": "./dist/index.fun.cjs" + "./util": { + "import": "./dist/index.util.js", + "require": "./dist/index.util.cjs" }, "./package.json": "./package.json" }, @@ -77,47 +52,43 @@ "win32-def": "^21.0.2" }, "devDependencies": { - "@types/ffi-napi": "*", - "@types/ref-napi": "^3.0.6", - "@types/ref-struct-di": "^1.1.8", - "@types/ref-union-di": "^1.0.5", - "@waiting/shared-core": "^20.11.4", - "cross-env": "7", - "ffi-napi": "^4.0.3", - "ref-napi": "^3.0.3", - "ref-struct-di": "^1.1.1", - "ref-union-di": "^1.0.1" - }, - "peerDependencies": { - "ffi-napi": "^4.0.3", - "ref-napi": "^3.0.3", - "ref-struct-di": "^1.1.1", - "ref-union-di": "^1.0.1" + "@waiting/shared-core": "^23.19.0" }, "engines": { - "node": ">=14.15.0" + "node": ">=16.12.0" }, "files": [ + "README.*.md", + "Dockerfile", + "npm-shrinkwrap.json", "tsconfig.json", + "tsconfig.base.json", + "asset", "src/**/*.ts", - "bin/*.js", - "dist" + "bin", + "database", + "dist", + "!**/*.spec.*", + "!**/*.tsbuildinfo" ], "publishConfig": { "access": "public" }, "scripts": { - "build": "npm run tsc && npm run rp", - "clean": "npm run clean:lock & npm run clean:cache & rm -rf dist/*", - "clean:cache": "rm -rf .eslintcache .vscode/.tsbuildinfo .vscode/.tsbuildinfo.*", - "clean:lock": "rm package-lock.json -f", - "cov": "cross-env TS_NODE_PROJECT=test/tsconfig.json c8 mocha --loader=ts-node/esm --parallel=false", - "lint": "eslint --fix --cache {src,test}/**/*.ts", - "lint:nofix": "eslint --cache {src,test}/**/*.ts", - "purge": "npm run clean && rm node_modules -rf", + "build": "npm run tsc && tsc-alias && npm run rp", + "build:unit": "tsc -p test/tsconfig.json", + "clean": "npm run clean:lock && npm run clean:dist && npm run clean:log", + "clean:cache": "rm -rf .eslintcache .tsbuildinfo", + "clean:dist": "npm run clean:cache && rm -rf dist/*", + "clean:lock": "rm -f package-lock.json", + "clean:log": "rm -rf ./logs ./run", + "cov": "c8 --all npm run test -- --parallel=false", + "lint": "eslint --fix --cache src test demo", + "lint:nofix": "eslint --cache src test", + "pretest": "npm run build:unit", "rp": "rollup -c rollup.config.js --context this", - "test": "cross-env TS_NODE_PROJECT=test/tsconfig.json mocha --loader=ts-node/esm --parallel=false", - "test:local": "cross-env TS_NODE_PROJECT=test/tsconfig.json ../../node_modules/.bin/mocha --loader=ts-node/esm --parallel=false", - "tsc": "tsc -b " + "test": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/tsconfig.json mocha --parallel=false", + "deb8g": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/tsconfig.json mocha --parallel=false", + "tsc": "tsc -p tsconfig.json" } } diff --git a/packages/win32-api/rollup.config.js b/packages/win32-api/rollup.config.js index 713dc641..72bee39e 100644 --- a/packages/win32-api/rollup.config.js +++ b/packages/win32-api/rollup.config.js @@ -1,12 +1,9 @@ -import { basename } from 'node:path' +import { basename, dirname } from 'node:path' import assert from 'node:assert' import dts from "rollup-plugin-dts" -// import commonjs from '@rollup/plugin-commonjs' -// import resolve from '@rollup/plugin-node-resolve' -// import { terser } from 'rollup-plugin-terser' -import pkg from './package.json' assert { type: 'json' } +import pkg from './package.json' with { type: 'json' } // `npm run build` -> `production` is true // `npm run dev` -> `production` is false @@ -211,7 +208,6 @@ function parseName(name) { else { throw new TypeError('name invalid') } - return name } function genFileNamesForCTS(row) { @@ -221,21 +217,25 @@ function genFileNamesForCTS(row) { let srcPath = row.types let baseName = '' + const dir = dirname(path) if (path.startsWith('./src/') && path.endsWith('.ts')) { baseName = basename(path, '.ts') - srcPath = srcPath ?? path + // srcPath = srcPath ?? path + srcPath = srcPath ?? dir.replace('dist', 'src') + `/${baseName}.ts` } else if (path.startsWith('./dist/') && path.endsWith('.js')) { baseName = basename(path, '.js') - srcPath = srcPath ?? `./src/${baseName}.ts` + srcPath = srcPath ?? dir.replace('dist', 'src') + `/${baseName}.ts` } - const ctsPath = `./dist/${baseName}.d.cts` - return { + const ctsPath = `${dir}/${baseName}.d.cts` + const ret = { srcPath, ctsPath, } + // console.log({ ret, dir }) + return ret } export default config diff --git a/packages/win32-api/src/func/func.helper.ts b/packages/win32-api/src/func/func.helper.ts deleted file mode 100644 index 137debf6..00000000 --- a/packages/win32-api/src/func/func.helper.ts +++ /dev/null @@ -1,43 +0,0 @@ -import assert from 'node:assert' - -import { FnName, LoadSettings, PromiseFnModel } from 'win32-def' - -import { - Spoolss, - User32, - Winspool, -} from '../index.promise.js' -import { DllNames } from '../lib/types.js' - - -const loaders = new Map>() -const mods = new Map>() - -loaders.set(DllNames.spoolss, Spoolss.load) -loaders.set(DllNames.user32, User32.load) -loaders.set(DllNames.winspool, Winspool.load) - - -export function getMod(name: DllNames): PromiseFnModel { - assert(name) - const cache = mods.get(name) - - if (cache) { - return cache as PromiseFnModel - } - - const loader = loaders.get(name) as Loader | undefined - if (! loader) { - throw new TypeError(`Loader of "${name}" not found`) - } - - const mod = loader() - assert(mod) - mods.set(name, mod) - - return mod -} - - -type Loader = (fns?: FnName[], settings?: LoadSettings) => PromiseFnModel - diff --git a/packages/win32-api/src/func/func.ts b/packages/win32-api/src/func/func.ts deleted file mode 100644 index 296c25ac..00000000 --- a/packages/win32-api/src/func/func.ts +++ /dev/null @@ -1,7 +0,0 @@ - -export * from './user32/index.user32.js' -export * from './spoolss/index.spoolss.js' - -export * from './winspool/index.winspool.js' -export * from './winspool/winspool.types.js' - diff --git a/packages/win32-api/src/func/spoolss/helper.ts b/packages/win32-api/src/func/spoolss/helper.ts deleted file mode 100644 index e54ea3c5..00000000 --- a/packages/win32-api/src/func/spoolss/helper.ts +++ /dev/null @@ -1,18 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import ref from 'ref-napi' - -import { - DllNames, - DStruct as DS, - DModel as M, -} from '../../index.js' -import { Spoolss as DLL } from '../../index.promise.js' - - -export { - M, DS, ref, -} - -export const dllName = DllNames.spoolss -export type Win32Fns = DLL.Win32Fns - diff --git a/packages/win32-api/src/func/spoolss/index.spoolss.ts b/packages/win32-api/src/func/spoolss/index.spoolss.ts deleted file mode 100644 index 8fe1023a..00000000 --- a/packages/win32-api/src/func/spoolss/index.spoolss.ts +++ /dev/null @@ -1,42 +0,0 @@ -import assert from 'node:assert' - -import { getMod } from '../func.helper.js' - -import { - Win32Fns, - M, - dllName, -} from './helper.js' - - -export async function spoolWritePrinter( - hPrinter: M.HANDLE, - pBuf: M.LPVOID, - cbBuf: M.DWORD, -): Promise { - - const mod = getMod(dllName) - assert(hPrinter) - - const pcWritten = Buffer.alloc(4) - const ret = await mod.WritePrinter( - hPrinter.toString(), - pBuf, - cbBuf, - pcWritten, - ) - - if (ret) { - return pcWritten.readUint32LE() - } - return 0 -} - -export async function spoolEndDocPrinter(hPrinter: M.HANDLE): Promise { - const mod = getMod(dllName) - assert(hPrinter) - - const ret = await mod.EndDocPrinter(hPrinter.toString()) - return !! ret -} - diff --git a/packages/win32-api/src/func/spoolss/spoolss.types.ts b/packages/win32-api/src/func/spoolss/spoolss.types.ts deleted file mode 100644 index dfeba449..00000000 --- a/packages/win32-api/src/func/spoolss/spoolss.types.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { M } from './helper.js' - - -export interface EnumPrintersOptions { - /** - * PrinterEnumFlags - * @see https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-enum-flags - */ - Flags: number - Name?: string - // Level: M.EnumPrinters_Level - Level: Lvl - /** - * @default 4096 - */ - cbBuf?: number -} - diff --git a/packages/win32-api/src/func/user32/helper.ts b/packages/win32-api/src/func/user32/helper.ts deleted file mode 100644 index cab02c38..00000000 --- a/packages/win32-api/src/func/user32/helper.ts +++ /dev/null @@ -1,13 +0,0 @@ -// eslint-disable-next-line import/no-extraneous-dependencies -import ref from 'ref-napi' - -import { DllNames } from '../../index.js' -import { User32 as DLL } from '../../index.promise.js' - - -export { DModel as M } from '../../index.js' -export { ref } - -export const dllName = DllNames.user32 -export type Win32Fns = DLL.Win32Fns - diff --git a/packages/win32-api/src/func/user32/index.user32.ts b/packages/win32-api/src/func/user32/index.user32.ts deleted file mode 100644 index fda2f606..00000000 --- a/packages/win32-api/src/func/user32/index.user32.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { - ucsBufferFrom, - ucsBufferToString, -} from '../../index.js' -import { getMod } from '../func.helper.js' - -import { Win32Fns, dllName, M } from './helper.js' - - -/** - * Retrieves a handle to the specified printer or print server or other types of handles in the print subsystem. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/openprinter - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/openprinter - */ -export async function user32FindWindowEx( - hwndParent: M.HWND, - hwndChildAfter: M.HWND, - lpszClass: string | null, - lpszWindow: string | null, -): Promise { - - const mod = getMod(dllName) - - const lpszClassBuf = ucsBufferFrom(lpszClass) - const lpszWindowBuf = ucsBufferFrom(lpszWindow) - - const hWnd = await mod.FindWindowExW( - hwndParent, - hwndChildAfter, - lpszClassBuf, - lpszWindowBuf, - ) - return hWnd -} - - -/** - * @docs https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw - */ -export async function user32GetWindowText( - hWnd: M.HWND, - /** Not including the null character */ - nMaxCount: M.INT, -): Promise { - - const mod = getMod(dllName) - - const len = nMaxCount + 1 - const buf = Buffer.alloc(len * 2) - - const ret = await mod.GetWindowTextW(hWnd, buf, len) - if (ret > 0) { - const str = ucsBufferToString(buf, len) - return str - } - return '' -} diff --git a/packages/win32-api/src/func/winspool/helper.ts b/packages/win32-api/src/func/winspool/helper.ts deleted file mode 100644 index d408a5d3..00000000 --- a/packages/win32-api/src/func/winspool/helper.ts +++ /dev/null @@ -1,224 +0,0 @@ -import assert from 'node:assert' - -// eslint-disable-next-line import/no-extraneous-dependencies -import ref from 'ref-napi' - -import { - DllNames, - DStruct as DS, - DModel as M, - bufferToStruct, -} from '../../index.js' -import { Winspool as DLL } from '../../index.promise.js' - - -export { - M, DS, ref, -} - -export const dllName = DllNames.winspool -export type Win32Fns = DLL.Win32Fns - - -export function retriveStruct_PRINTER_INFO( - pPrinter: Buffer, - Level: L, - maxCount = 1, - pcbNeeded?: number, -): M.PRINTER_INFO_X[L][] { - - assert(maxCount >= 1, 'maxCount must be >= 1') - - const pcb: number = typeof pcbNeeded === 'number' - ? pcbNeeded - : pPrinter.byteLength - assert(pcb >= 16, 'Buffer too small') - - let ret: M.PRINTER_INFO_X[L][] = [] - - switch (Level) { - case 1: { - const structDef = DS.PRINTER_INFO_1 - // ret = loopRead( - // pPrinter, - // maxCount, - // pcb, - // 1, - // structDef, - // ) as M.PRINTER_INFO_X[L][] - ret = bufferToStruct( - pPrinter, - structDef, - maxCount, - pcb, - ) as M.PRINTER_INFO_X[L][] - - break - } - - case 4: { - const structDef = DS.PRINTER_INFO_4 - // ret = loopRead( - // pPrinter, - // maxCount, - // pcb, - // 4, - // structDef, - // ) as M.PRINTER_INFO_X[L][] - - ret = bufferToStruct( - pPrinter, - structDef, - maxCount, - pcb, - ) as M.PRINTER_INFO_X[L][] - break - } - - default: - throw new Error(`Level not implemented:${Level}`) - } - - return ret -} - - -/* -function rpi1( - addressBuffer: Buffer, - maxByteLength: number, -): M.PRINTER_INFO_1 { - - const structDef = DS.PRINTER_INFO_1 - const blen = maxByteLength - assert(blen >= 16, 'Buffer too small') - - // Flags: DWORD - // pDescription: WCHAR_String - // pName: WCHAR_String - // pComment: WCHAR_String - const struct = StructFactory(structDef) - struct.Flags = addressBuffer.readUInt32LE(0) - - const addr1 = addressBuffer.readUInt64LE(8) - struct.pDescription = ptrToString(addr1, blen) - - const addr2 = addressBuffer.readUInt64LE(16) - struct.pName = ptrToString(addr2, blen) - - const addr3 = addressBuffer.readUInt64LE(24) - struct.pName = ptrToString(addr3, blen) - - return struct -} - - -function rpi4( - addressBuffer: Buffer, - maxByteLength: number, -): M.PRINTER_INFO_4 { - - const structDef = DS.PRINTER_INFO_4 - const blen = maxByteLength - - assert(blen >= 16, 'Buffer too small') - - // const pbuf = Buffer.alloc(blen) - // pPrinter.copy(pbuf, 0, 24) - // const txtArr = ucsBufferSplit(pbuf) - - const struct = StructFactory(structDef) - // pPrinterName: WCHAR_String - // pServerName: WCHAR_String - // Attributes: DWORD - const addrPName = addressBuffer.readUInt64LE(0) - struct.pPrinterName = ptrToString(addrPName, blen) - - const addrSName = addressBuffer.readUInt64LE(8) - struct.pServerName = ptrToString(addrSName, blen) - - struct.Attributes = addressBuffer.readUInt32LE(16) - - return struct -} - - -type LoopFuncs = { - [K in L]: (addressBuffer: Buffer, maxByteLength: number) => M.PRINTER_INFO_X[K] -} -const loopFuncs: LoopFuncs<1 | 4> = { - 1: rpi1, - 4: rpi4, -} - -function loopRead( - pPrinter: Buffer, - maxCount: number, - pcbNeeded: number, - Level: L, - structDef: object, // DS.PRINTER_INFO_[L], -): M.PRINTER_INFO_X[L][] { - - const ret: M.PRINTER_INFO_X[L][] = [] - - const blen = pcbNeeded - // const structDef = DS.PRINTER_INFO_1 - const keyLen = Object.keys(structDef).length - assert(keyLen >= 1, 'keyLen must be >= 1') - - const itemLen = keyLen * 8 // byes - const bufByteLen = maxCount * itemLen - - // @ts-expect-error - const fn = loopFuncs[Level] as LoopFuncs[L] - assert(typeof fn === 'function') - - for (let i = 0; i < maxCount; i += 1) { - const buf = Buffer.alloc(bufByteLen) - pPrinter.copy(buf, 0, i * itemLen) - const struct = fn(buf, blen) - ret.push(struct) - } - - return ret -} -*/ - - - -export function retriveStruct_PRINTPROCESSOR_INFO_1( - pPrintProcessorInfo: Buffer, - count: number, - pcb: number, -): M.PRINTPROCESSOR_INFO_1[] { - - if (! pcb) { return [] } - - const structs = bufferToStruct( - pPrintProcessorInfo, - DS.PRINTPROCESSOR_INFO_1, - count, - pcb, - ) - - return structs -} - - -export function retriveStruct_DATATYPES_INFO_1( - pPrintProcessorInfo: Buffer, - count: number, - pcb: number, -): M.DATATYPES_INFO_1[] { - - if (! pcb) { return [] } - - const structs = bufferToStruct( - pPrintProcessorInfo, - DS.DATATYPES_INFO_1, - count, - pcb, - ) - - return structs -} diff --git a/packages/win32-api/src/func/winspool/index.winspool.ts b/packages/win32-api/src/func/winspool/index.winspool.ts deleted file mode 100644 index e84b41f2..00000000 --- a/packages/win32-api/src/func/winspool/index.winspool.ts +++ /dev/null @@ -1,281 +0,0 @@ -import assert from 'node:assert' - -import { - ucsBufferFrom, - ucsBufferToString, -} from '../../index.js' -import { getMod } from '../func.helper.js' - -import { - Win32Fns, - M, - dllName, - ref, - retriveStruct_PRINTER_INFO, - retriveStruct_PRINTPROCESSOR_INFO_1, - retriveStruct_DATATYPES_INFO_1, -} from './helper.js' -import { EnumPrintersOptions } from './winspool.types.js' - - -export async function winspoolClosePrinter(hPrinter: M.HANDLE): Promise { - assert(hPrinter) - const mod = getMod(dllName) - - const ret = await mod.ClosePrinter(hPrinter.toString()) - return !! ret -} - - -/** - * Enumerates available printers, print servers, domains, or print providers. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinters - */ -export async function winspoolEnumPrinters( - options: EnumPrintersOptions, -): Promise { - - const mod = getMod(dllName) - - const name = ucsBufferFrom(options.Name) - const level = options.Level - assert(level >= 1 && level <= 5, 'level must be >= 1 and <= 5') - - const cbBuf = options.cbBuf ?? 4096 - assert(cbBuf > 2, 'cbBuf must be > 2') - const pPrinterEnum = Buffer.alloc(cbBuf) - - const pcbNeeded = ref.alloc('uint32') - const pcReturned = ref.alloc('uint32') - - const ret = await mod.EnumPrintersW( - options.Flags, - name, - level, - pPrinterEnum, - cbBuf, - pcbNeeded, - pcReturned, - ) - - const count = pcReturned.readUInt32LE() - const pcb = pcbNeeded.readUInt32LE() - - if (ret && count) { - const arr = retriveStruct_PRINTER_INFO(pPrinterEnum, level, count, pcb) - return arr as unknown as Promise - } - return [] -} - - -/** - * Enumerates the print processors installed on the specified server. - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/enumprintprocessors - */ -export async function winspoolEnumPrintProcessors( - pName?: string, - pEnvironment?: string, -): Promise { - - const mod = getMod(dllName) - - const pNameBuf = ucsBufferFrom(pName) - const pEnvironmentBuf = ucsBufferFrom(pEnvironment) - const Level = 1 - const pPrintProcessorInfo = Buffer.alloc(512) - const cbBuf = pPrintProcessorInfo.byteLength - const pcbNeeded = ref.alloc('uint32') - const pcReturned = ref.alloc('uint32') - - const ret = await mod.EnumPrintProcessorsW( - pNameBuf, - pEnvironmentBuf, - Level, - pPrintProcessorInfo, - cbBuf, - pcbNeeded, - pcReturned, - ) - - const count = pcReturned.readUInt32LE() - const pcb = pcbNeeded.readUInt32LE() - - if (ret && count) { - const arr = retriveStruct_PRINTPROCESSOR_INFO_1(pPrintProcessorInfo, count, pcb) - return arr - } - return [] - -} - -export async function winspoolEnumPrintProcessorDatatypes( - pName?: string, - pPrintProcessorName?: string, -): Promise { - - const mod = getMod(dllName) - - const pNameBuf = ucsBufferFrom(pName) - const pPrintProcessorNameBuf = ucsBufferFrom(pPrintProcessorName) - const Level = 1 - const pDatatypes = Buffer.alloc(1024) - const cbBuf = pDatatypes.byteLength - const pcbNeeded = ref.alloc('uint32') - const pcReturned = ref.alloc('uint32') - - const ret = await mod.EnumPrintProcessorDatatypesW( - pNameBuf, - pPrintProcessorNameBuf, - Level, - pDatatypes, - cbBuf, - pcbNeeded, - pcReturned, - ) - - const count = pcReturned.readUInt32LE() - const pcb = pcbNeeded.readUInt32LE() - - if (ret && count) { - const arr = retriveStruct_DATATYPES_INFO_1(pDatatypes, count, pcb) - return arr - } - return [] -} - - -/** - * Retrieves the printer name of the default printer for the current user on the local computer. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/getdefaultprinter - */ -export async function winspoolGetDefaultPrinter(maxNameLength = 256): Promise { - const mod = getMod(dllName) - - assert(maxNameLength > 2) - - const len = maxNameLength + 1 - - const pszBuf = Buffer.alloc(len * 2) - const pcchBuf = Buffer.alloc(4) - pcchBuf.writeUint32LE(len) - - const ret = await mod.GetDefaultPrinterW(pszBuf, pcchBuf) - if (! ret) { - return '' - } - - const pcch = pcchBuf.readUInt32LE() - if (pcch > 0) { - const size = pcch - 1 - const psz = ucsBufferToString(pszBuf, size) - return psz - } - return '' -} - - -/** - * Retrieves a handle to the specified printer or print server or other types of handles in the print subsystem. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/openprinter - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/openprinter - */ -export async function winspoolOpenPrinter(printerName: string): Promise { - const mod = getMod(dllName) - - assert(printerName) - - const nameBuf = ucsBufferFrom(printerName) - const ptr = Buffer.alloc(8) - const ret = await mod.OpenPrinterW(nameBuf, ptr, ref.NULL) - if (ret) { - const hWnd = ptr.readBigInt64LE() - return hWnd - } - return 0 -} - - -/** - * Retrieves information about a specified printer. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinter - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/getprinter - */ -export async function winspoolGetPrinter( - hPrinter: M.HANDLE, - Level: Level, - maxByteLength = 1024, -): Promise { - - const mod = getMod(dllName) - - const pPrinter = Buffer.alloc(maxByteLength) - const cbBuf = pPrinter.byteLength - const pcbNeeded = Buffer.alloc(8) - - const ret = await mod.GetPrinterW( - hPrinter.toString(), - Level, - pPrinter, - cbBuf, - pcbNeeded, - ) - const pcb = pcbNeeded.readUInt32LE() - - if (ret) { - const [struct] = retriveStruct_PRINTER_INFO(pPrinter, Level, 1, pcb) - // const pPrinter2 = Buffer.alloc(pcb) - // const cbBuf2 = pcb - // const pcbNeeded2 = Buffer.alloc(8) - - // await mod.GetPrinterW( - // hPrinter.toString(), - // Level, - // pPrinter2, - // cbBuf2, - // pcbNeeded2, - // ) - - // const [struct] = retriveStruct_PRINTER_INFO(pPrinter2, Level, 1) - - return struct - } - - if (pcb > 0 && pcb > maxByteLength) { - throw new Error(`maxByteLength is too small, increase to value grater than ${pcb}`) - } -} - - -export async function winspoolStartDocPrinter( - hPrinter: M.HANDLE, - pDocInfo: M.LPBYTE, -): Promise { - - const mod = getMod(dllName) - - assert(hPrinter) - assert(pDocInfo) - - const Level = 1 - const ret = await mod.StartDocPrinterW(hPrinter.toString(), Level, pDocInfo) - return ret -} - -export async function winspoolStartPagePrinter(hPrinter: M.HANDLE): Promise { - const mod = getMod(dllName) - - assert(hPrinter) - const ret = await mod.StartPagePrinter(hPrinter.toString()) - return ret -} - - -export async function winspoolEndPagePrinter(hPrinter: M.HANDLE): Promise { - const mod = getMod(dllName) - - assert(hPrinter) - const ret = await mod.EndPagePrinter(hPrinter.toString()) - return ret -} - diff --git a/packages/win32-api/src/func/winspool/winspool.types.ts b/packages/win32-api/src/func/winspool/winspool.types.ts deleted file mode 100644 index dfeba449..00000000 --- a/packages/win32-api/src/func/winspool/winspool.types.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { M } from './helper.js' - - -export interface EnumPrintersOptions { - /** - * PrinterEnumFlags - * @see https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-enum-flags - */ - Flags: number - Name?: string - // Level: M.EnumPrinters_Level - Level: Lvl - /** - * @default 4096 - */ - cbBuf?: number -} - diff --git a/packages/win32-api/src/index.comctl32.ts b/packages/win32-api/src/index.comctl32.ts deleted file mode 100644 index 271dd949..00000000 --- a/packages/win32-api/src/index.comctl32.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/comctl32/index.promise.js' - diff --git a/packages/win32-api/src/index.consts.ts b/packages/win32-api/src/index.consts.ts deleted file mode 100644 index b87d3d1f..00000000 --- a/packages/win32-api/src/index.consts.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/winmsg.js' - diff --git a/packages/win32-api/src/index.fun.ts b/packages/win32-api/src/index.fun.ts deleted file mode 100644 index 536c2a74..00000000 --- a/packages/win32-api/src/index.fun.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './func/func.js' - diff --git a/packages/win32-api/src/index.kernel32.ts b/packages/win32-api/src/index.kernel32.ts deleted file mode 100644 index 339dccf5..00000000 --- a/packages/win32-api/src/index.kernel32.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/kernel32/index.promise.js' - diff --git a/packages/win32-api/src/index.ntdll.ts b/packages/win32-api/src/index.ntdll.ts deleted file mode 100644 index 30887c43..00000000 --- a/packages/win32-api/src/index.ntdll.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/ntdll/index.promise.js' - diff --git a/packages/win32-api/src/index.promise.ts b/packages/win32-api/src/index.promise.ts deleted file mode 100644 index 936fc50f..00000000 --- a/packages/win32-api/src/index.promise.ts +++ /dev/null @@ -1,9 +0,0 @@ - -export * as Comctl32 from './lib/comctl32/index.promise.js' -export * as Gdi32 from './lib/gdi32/index.promise.js' -export * as Kernel32 from './lib/kernel32/index.promise.js' -export * as Ntdll from './lib/ntdll/index.promise.js' -export * as Spoolss from './lib/spoolss/index.promise.js' -export * as User32 from './lib/user32/index.promise.js' -export * as Winspool from './lib/winspool/index.promise.js' - diff --git a/packages/win32-api/src/index.spoolss.ts b/packages/win32-api/src/index.spoolss.ts deleted file mode 100644 index f5a1b855..00000000 --- a/packages/win32-api/src/index.spoolss.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/spoolss/index.promise.js' - diff --git a/packages/win32-api/src/index.ts b/packages/win32-api/src/index.ts index 96bfbfea..097cffbd 100644 --- a/packages/win32-api/src/index.ts +++ b/packages/win32-api/src/index.ts @@ -1,52 +1,27 @@ -import * as Comctl32 from './lib/comctl32/index.js' -import * as Gdi32 from './lib/gdi32/index.js' -import * as Kernel32 from './lib/kernel32/index.js' -import * as Ntdll from './lib/ntdll/index.js' -import * as Spoolss from './lib/spoolss/index.js' -import * as User32 from './lib/user32/index.js' -import * as Constants from './lib/winmsg.js' -import * as Winspool from './lib/winspool/index.js' +export * as Comctl32 from './lib/comctl32/index.js' +export * as Gdi32 from './lib/gdi32/index.js' +export * as Kernel32 from './lib/kernel32/index.js' +export * as Spoolss from './lib/spoolss/index.js' +export * as User32 from './lib/user32/index.js' +export * as Winspool from './lib/winspool/index.js' + +export * from './lib/types.js' +export * from './lib/helper.js' export { - config, Config, - UnionFactory, - UnionFactory as UnionFactor, - UnionType, - StructFactory, - StructType, + config, + ffi, } from 'win32-def' -// model of window data types -export * as DModel from 'win32-def' -// ffi model -export * as FModel from 'win32-def' -// window data types of structure -export * as DStruct from 'win32-def/struct.def' -// window data types -export * as DTypes from 'win32-def/common.def' - - -export { Gdi32 } -export { User32 as U } -export { User32 } +/** model of window data types */ +export * as Types from 'win32-def/types' -export { Kernel32 as K } -export { Kernel32 } +/** window data types of structure */ +export * as Struct from 'win32-def/struct' -export { Comctl32 as C } -export { Comctl32 } +/** window data types */ +export * as Def from 'win32-def/def' -export { Ntdll } - -export { Spoolss } -export { Winspool } - -export * from './lib/types.js' - -export { Constants } -export { Constants as CS } - -export * from './lib/helper.js' diff --git a/packages/win32-api/src/index.user32.ts b/packages/win32-api/src/index.user32.ts deleted file mode 100644 index 372d9bd2..00000000 --- a/packages/win32-api/src/index.user32.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/user32/index.promise.js' - diff --git a/packages/win32-api/src/index.util.ts b/packages/win32-api/src/index.util.ts new file mode 100644 index 00000000..ec45dd8d --- /dev/null +++ b/packages/win32-api/src/index.util.ts @@ -0,0 +1,3 @@ + +export * from './util/util.index.js' + diff --git a/packages/win32-api/src/index.winspool.ts b/packages/win32-api/src/index.winspool.ts deleted file mode 100644 index 5b628825..00000000 --- a/packages/win32-api/src/index.winspool.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export * from './lib/winspool/index.promise.js' - diff --git a/packages/win32-api/src/lib/comctl32/api.def.ts b/packages/win32-api/src/lib/comctl32/api.def.ts new file mode 100644 index 00000000..c2d17b35 --- /dev/null +++ b/packages/win32-api/src/lib/comctl32/api.def.ts @@ -0,0 +1,11 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + + +export class DefComctl32 implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + /** https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-initcommoncontrolsex */ + static InitCommonControlsEx = [D.BOOL, [S.LPINITCOMMONCONTROLSEX]] +} diff --git a/packages/win32-api/src/lib/comctl32/api.ts b/packages/win32-api/src/lib/comctl32/api.ts deleted file mode 100644 index 997d2747..00000000 --- a/packages/win32-api/src/lib/comctl32/api.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -export interface Win32Fns { - InitCommonControlsEx: (lpInitCtrls: M.LPINITCOMMONCONTROLSEX) => M.BOOL -} - - -export const apiDef: M.DllFuncs = { - InitCommonControlsEx: [W.BOOL, [W.LPINITCOMMONCONTROLSEX] ], -} - diff --git a/packages/win32-api/src/lib/comctl32/api.types.ts b/packages/win32-api/src/lib/comctl32/api.types.ts new file mode 100644 index 00000000..b6d9c826 --- /dev/null +++ b/packages/win32-api/src/lib/comctl32/api.types.ts @@ -0,0 +1,14 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { DefComctl32 } from './api.def.js' + + +export class Comctl32 implements T.LibDef2Type { + /** https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-initcommoncontrolsex */ + InitCommonControlsEx: (lpInitCtrls: S.INITCOMMONCONTROLSEX_Type) => T.BOOL +} + + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/comctl32/index.promise.ts b/packages/win32-api/src/lib/comctl32/index.promise.ts deleted file mode 100644 index ede1c401..00000000 --- a/packages/win32-api/src/lib/comctl32/index.promise.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.comctl32 -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/comctl32/index.ts b/packages/win32-api/src/lib/comctl32/index.ts index da6cc763..65b8a527 100644 --- a/packages/win32-api/src/lib/comctl32/index.ts +++ b/packages/win32-api/src/lib/comctl32/index.ts @@ -1,24 +1,21 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' +import { type FLib, type LoadOptions, load as _load } from 'win32-def' -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' +import { DllNames } from '##/lib/types.js' -import { apiDef, Win32Fns } from './api.js' +import { DefComctl32 } from './api.def.js' +import { Comctl32 } from './api.types.js' -export { apiDef } -export { Win32Fns } +export { + DefComctl32, Comctl32, +} + export const dllName = DllNames.comctl32 -/** - * @deprecated use promise instead - * ```ts - * import { Comctl32 } from 'win32-api/promise' - * const comctl32 = Comctl32 .load() - * const ret = await comctl32.InitCommonControlsEx(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) +export type LibComctl32 = FLib + +export const load = (fns?: LoadOptions['usedFuncNames']) => _load({ + dll: dllName + '.dll', + dllFuncs: DefComctl32, + usedFuncNames: fns, +}) diff --git a/packages/win32-api/src/lib/gdi32/api.def.ts b/packages/win32-api/src/lib/gdi32/api.def.ts new file mode 100644 index 00000000..0011bc9f --- /dev/null +++ b/packages/win32-api/src/lib/gdi32/api.def.ts @@ -0,0 +1,16 @@ +import * as D from 'win32-def/def' +import * as T from 'win32-def/types' + + +export class DefGdi32 implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + // static CreateBitmap = [W.HBITMAP, [W.INT, W.INT, W.UINT, W.UINT, W.VOID] ] + + /** https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap */ + static CreateCompatibleBitmap = [D.HBITMAP, [D.HDC, D.INT, D.INT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatibledc */ + static CreateCompatibleDC = [D.HDC, [D.HDC]] + +} diff --git a/packages/win32-api/src/lib/gdi32/api.ts b/packages/win32-api/src/lib/gdi32/api.ts deleted file mode 100644 index d3c1ac75..00000000 --- a/packages/win32-api/src/lib/gdi32/api.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable id-length */ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -export interface Win32Fns { - - // CreateBitmap: ( - // nWidth: M.INT, - // nHeight: M.INT, - // nPlanes: M.UINT, - // nBitCount: M.UINT, - // lpBits: M.LPVOID, - // ) => M.HBITMAP - - /** - * Creates a bitmap compatible with the device that is associated with the specified device context. - * @link https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap - */ - CreateCompatibleBitmap: ( - hdc: M.HDC, - cx: M.INT, - cy: M.INT - ) => M.HBITMAP - - /** - * @link https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatibledc - */ - CreateCompatibleDC: (hdc: M.HDC) => M.HDC -} - - -export const apiDef: M.DllFuncs = { - - // CreateBitmap: [W.HBITMAP, [W.INT, W.INT, W.UINT, W.UINT, W.VOID] ], - - CreateCompatibleBitmap: [W.HBITMAP, [W.HDC, W.INT, W.INT] ], - - CreateCompatibleDC: [W.HDC, [W.HDC] ], - -} - diff --git a/packages/win32-api/src/lib/gdi32/api.types.ts b/packages/win32-api/src/lib/gdi32/api.types.ts new file mode 100644 index 00000000..b2742d69 --- /dev/null +++ b/packages/win32-api/src/lib/gdi32/api.types.ts @@ -0,0 +1,31 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' + +import { DefGdi32 } from './api.def.js' + + +export class Gdi32 implements T.LibDef2Type { + + // CreateBitmap: ( + // nWidth: M.INT, + // nHeight: M.INT, + // nPlanes: M.UINT, + // nBitCount: M.UINT, + // lpBits: M.LPVOID, + // ) => M.HBITMAP + + /** + * Creates a bitmap compatible with the device that is associated with the specified device context. + * @link https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap + */ + CreateCompatibleBitmap: ( + hdc: T.HDC, + cx: T.INT, + cy: T.INT + ) => T.HBITMAP + + /** https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatibledc */ + CreateCompatibleDC: (hdc: T.HDC) => T.HDC +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/gdi32/index.promise.ts b/packages/win32-api/src/lib/gdi32/index.promise.ts deleted file mode 100644 index c1e3d36e..00000000 --- a/packages/win32-api/src/lib/gdi32/index.promise.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.gdi32 -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/gdi32/index.ts b/packages/win32-api/src/lib/gdi32/index.ts index a4c79b2b..4e9d54fa 100644 --- a/packages/win32-api/src/lib/gdi32/index.ts +++ b/packages/win32-api/src/lib/gdi32/index.ts @@ -1,24 +1,21 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' +import { type FLib, type LoadOptions, load as _load } from 'win32-def' -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' +import { DllNames } from '##/lib/types.js' -import { apiDef, Win32Fns } from './api.js' +import { DefGdi32 } from './api.def.js' +import { Gdi32 } from './api.types.js' -export { apiDef } -export { Win32Fns } +export { + DefGdi32, Gdi32, +} + export const dllName = DllNames.gdi32 -/** - * @deprecated use promise instead - * ```ts - * import { User32 } from 'win32-api/promise' - * const user32 = User32.load() - * const hWnd = await user32.FindWindowExW(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) +export type LibGdi32 = FLib + +export const load = (fns?: LoadOptions['usedFuncNames']) => _load({ + dll: dllName + '.dll', + dllFuncs: DefGdi32, + usedFuncNames: fns, +}) diff --git a/packages/win32-api/src/lib/helper.ts b/packages/win32-api/src/lib/helper.ts index d7110d48..04775afc 100644 --- a/packages/win32-api/src/lib/helper.ts +++ b/packages/win32-api/src/lib/helper.ts @@ -1,496 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unsafe-argument */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable import/no-extraneous-dependencies */ -import assert from 'node:assert' -import { copyFileSync, statSync } from 'node:fs' - -import ffi from 'ffi-napi' -import ref from 'ref-napi' -import { - AsyncSyncFuncModel, - DllFuncs, - DllFuncsModel, - Def, - ExpandFnModel, - FnName, - FnParams, - LoadSettings, - PromiseFnModel, - StructDefType, - StructInstanceBase, - settingsDefault, - StructFactory, - HWND, -} from 'win32-def' - export const isArch64 = process.arch.includes('64') -export const defGroupNumber: Def[] = [ - Def.float, Def.int16, Def.int32, Def.int64, Def.int8, - Def.uint16, Def.uint32, Def.uint64, Def.uint8, - Def.long, Def.ulong, Def.longlong, Def.ulonglong, -] - -export const defGroupPointer: Def[] = [ - Def.boolPtr, Def.bytePtr, Def.charPtr, Def.intPtr, Def.int8Ptr, - Def.int16Ptr, Def.int32Ptr, Def.int64Ptr, Def.floatPtr, - Def.longPtr, Def.uintPtr, Def.uint8Ptr, - Def.intPtrPtr, Def.uint16Ptr, Def.uint32Ptr, Def.uint64Ptr, - Def.ulonglongPtr, Def.voidPtr, - Def.uintPtrPtr, Def.uint16PtrPtr, Def.uint32PtrPtr, Def.uint64PtrPtr, - Def.ulonglongPtrPtr, Def.voidPtrPtr, -] - - -const dllInstMap = new Map() // for DLL.load() with settings.singleton === true -// const hasAsyncProxy = '__hasAsyncProxy__' - -export function load( - dllName: string, - dllFuncs: DllFuncs, - fns?: FnName[], - settings?: LoadSettings, -): T { - - const st = parse_settings(settings) - - const name = dllName.endsWith('.drv') - ? preprareDllFile(dllName) - : dllName - - if (st.singleton) { - let inst = get_inst_by_name(name) - - if (! inst) { - const ps = gen_api_opts(dllFuncs, fns) - // ffi.Library.EXT = ext - inst = ffi.Library(name, ps) as unknown as T - set_inst_by_name(name, inst) - } - return inst - } - else { - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return ffi.Library(name, gen_api_opts(dllFuncs, fns)) as unknown as T - } -} - -function preprareDllFile(file: string): string { - - if (file.startsWith('file://')) { - return file - } - else if (file.startsWith('http://') || file.startsWith('https://')) { - return file - } - else if (file.startsWith('/')) { - return file - } - try { - const stat = statSync(file) - if (stat.isFile()) { - return file - } - } - catch { - // void - } - - const { HOME, WINDIR } = process.env - assert(HOME, 'HOME is not defined') - assert(WINDIR, 'WINDIR is not defined') - - const sys32dir = `${WINDIR}/system32` - const path = `${sys32dir}/${file}` - const target = `${HOME}/${file}.dll` - - const stat = statSync(path) - if (! stat.isFile()) { - throw new Error(`${file} is not found in path: "${path}"`) - } - - try { - const stat2 = statSync(target) - if (stat2.isFile()) { - return target - } - copyFileSync(path, target) - } - catch { - copyFileSync(path, target) - } - - return target -} - -/** - * Copy file from src to dest but change the file extension to ext - */ -// export async function copyFileWithDllExt( -// src: string, -// targetDir: string, -// ext = 'dll', -// ): Promise { - -// const [file] = basename(src).split('.') -// assert(file) - -// const target = `${targetDir}/${file}.${ext}` -// if (await isFileExists(target)) { -// return target -// } -// await copyFile(src, target) -// return target -// } - - -export function loadAsync( - dllName: string, - dllFuncs: DllFuncs, - fns?: FnName[], - settings?: LoadSettings, -): PromiseFnModel { - - const inst = load>(dllName, dllFuncs, fns, settings) - assert(inst) - - const instAsync = {} as PromiseFnModel - Object.entries(inst).forEach(([name, value]) => { - if (! Object.hasOwn(inst, name)) { return } - if (typeof value !== 'function') { - Object.defineProperty(instAsync, name, { - enumerable: false, - writable: true, - configurable: true, - value, - }) - } - const fnAsync = new Proxy(value, { - // @ts-ignore - apply(target: AsyncSyncFuncModel, ctx: unknown, args: unknown[]) { - // console.info({ target, ctx, args }) - return callFnAsync(target, args) - }, - }) - Object.defineProperty(instAsync, name, { - enumerable: false, - writable: true, - configurable: true, - value: fnAsync, - }) - - }) - - return instAsync -} - -async function callFnAsync( - target: T, - args: unknown[], -): Promise { - - assert(target) - assert(typeof target.async === 'function') - - return new Promise((done, reject) => { - const cb = (err: Error | void, result: unknown) => { - if (err) { - reject(err) - return - } - done(result) - } - // @ts-ignore - Reflect.apply(target.async, null, [...args, cb]) - }) -} - - -/** - * Generate function definitions via converting macro windows data type (like PVOID) to the expected value. - * Skip assignment if property undefined - */ -export function gen_api_opts( - dllFuncs: DllFuncs, - fns?: FnName[], -): DllFuncs { - - const ret = {} as DllFuncs - - if (fns && Array.isArray(fns) && fns.length) { - for (const fn of fns) { - if (! Object.hasOwn(dllFuncs, fn)) { - continue - } - // @ts-ignore - const ps = dllFuncs[fn] as FnParams | undefined - assert(ps, `dellFuncs has no property mehod name "${fn}"`) - - Object.defineProperty(ret, fn, { - value: ps, - writable: false, - enumerable: true, - configurable: false, - }) - } - } - else { - for (const fn of Object.keys(dllFuncs)) { - // @ts-ignore - const ps = dllFuncs[fn] as FnParams | undefined - assert(ps, `dellFuncs has no property mehod name "${fn}"`) - - Object.defineProperty(ret, fn, { - value: ps as FnParams, - writable: false, - enumerable: true, - configurable: false, - }) - } - } - - return ret -} - -function get_inst_by_name(dllName: string): T | undefined { - return dllInstMap.get(dllName) as T | undefined -} - -function set_inst_by_name(dllName: string, inst: T): void { - dllInstMap.set(dllName, inst) -} - -function parse_settings(settings?: LoadSettings): LoadSettings { - const st: LoadSettings = { ...settingsDefault } - // const st: LoadSettings = { - // singleton: true, - // _WIN64: true, - // } - - if (typeof settings !== 'undefined' && Object.keys(settings).length) { - Object.assign(st, settings) - } - return st -} - - -/** - * @example ```ts - * const point = StructFactory(DS.POINT) - * point.x = 123 - * const lParam = point.ref().address() - * const obj = retrieveStructFromPtrAddress(lParam, DS.POINT) - * obj && console.log({ objx: obj.x, objy: obj.y }) - * ``` - */ -export function retrieveStructFromPtrAddress( - address: number, - dataStructConst: StructDefType, - maxCharLength = 1024, -): R | undefined { - - assert(dataStructConst, 'dataStructConst is required') - - const struct = StructFactory(dataStructConst, { - useStringBuffer: true, - maxCharLength, - }) - assert(struct) - - const refType = struct.ref().ref().type - const buf = Buffer.alloc(8) - buf.writeInt64LE(address, 0) - buf.type = refType - - try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - const ret = buf.deref().deref() as R - return ret - } - catch (ex) { - console.warn(ex) - } -} - - -export function ucsBufferFrom(str: string | undefined | null): Buffer { - if (typeof str === 'string' && str.length) { - return Buffer.from(str + '\0', 'ucs2') - } - return ref.NULL -} - -export function ucsBufferToString(buffer: Buffer, charCount?: number | undefined): string { - const str = typeof charCount === 'number' - ? buffer.toString('ucs2', 0, charCount * 2) - : buffer.toString('ucs2') - return str.replace(/\0+$/u, '').replace(/^\0+/u, '') -} - - -/** - * Split with null till next char (\0) - */ -export function ucsBufferSplit(buffer: Buffer, maxCount?: number): string[] { - const ret: string[] = [] - const row: string[] = [] - const blen = buffer.byteLength - - if (! blen) { return ret } - const count = maxCount ? maxCount : blen - - for (let i = 0; i < blen;) { - const t1 = ref.readCString(buffer, i) - if (t1) { - row.push(t1) - i += t1.length * 2 - continue - } - else if (row.length > 0) { - ret.push(row.join('')) - row.length = 0 - } - else { - i += 2 - } - - if (ret.length >= count) { - break - } - } - - row.length = 0 - return ret -} - - -/** - * Read string from address of ptr - */ -export function ptrToString( - ptrAddress: HWND, - maxByteLength: number, -): string { - - if (! ptrAddress) { - return '' - } - - assert(maxByteLength >= 2, 'maxByteLength is required') - - const tpl = ref.allocCString('', 'ucs2') - const refType = tpl.ref().ref().type - const buf = Buffer.alloc(8) - buf.writeInt64LE(ptrAddress.toString(), 0) - buf.type = refType - - const buf2 = buf.readPointer(0, maxByteLength) - const [txt] = ucsBufferSplit(buf2, 1) - const ret = txt ?? '' - return ret -} - -/** - * Retrieve struct from Buffer - */ -export function bufferToStruct( - src: Buffer, - structDef: StructDefType, - maxCount = 1, - pcbNeeded?: number, - align: 4 | 8 = 8, // btye -): T[] { - - const ret: T[] = [] - - const blen = pcbNeeded ? pcbNeeded : src.byteLength - assert(blen >= 16, 'Buffer too small') - - // const structDef = DS.PRINTER_INFO_1 - const keyLen = Object.keys(structDef).length - assert(keyLen >= 1, 'keyLen must be >= 1') - - const groupBtyeLen = keyLen * align - const bufByteLen = maxCount * groupBtyeLen - - for (let i = 0; i < maxCount; i += 1) { - const buf = Buffer.alloc(bufByteLen) - src.copy(buf, 0, i * groupBtyeLen) - const struct = retriveStruct(structDef, buf, blen, align) - ret.push(struct) - } - - return ret -} - -function retriveStruct( - structDef: StructDefType, // DS.PRINTER_INFO_[L], - src: Buffer, - maxReadByteLength: number, - align: 4 | 8, // 32bit or 64bit -): T { - - const struct = StructFactory(structDef, { useStringBuffer: true }) - - Object.entries(structDef).forEach(([key, defType], idx) => { - const pos = idx * align - - if (typeof defType === 'string') { - const valOrAddr = readAddrValue(src, defType, pos) - assert(typeof valOrAddr !== 'undefined') - - if (defGroupNumber.includes(defType)) { // number value - // @ts-ignore - struct[key] = valOrAddr - } - else if (defGroupPointer.includes(defType)) { // pointer value - const ptrVal = ptrToString(valOrAddr, maxReadByteLength) - // @ts-ignore - struct[key] = ptrVal - } - else { - throw new TypeError(`Unknown key: "${key}", type: "${defType}"`) - } - } - else { - throw new Error(`Not implemented, only Def type is supported: key: "${key}"`) - } - }) - - return struct -} - - -function readAddrValue( - src: Buffer, - defType: Def, - pos: number, -): string | number | bigint | undefined { - - let ret - - if (defGroupPointer.includes(defType)) { - ret = isArch64 ? src.readInt64LE(pos) : src.readInt32LE(pos) - } - else if (defGroupNumber.includes(defType)) { - if (defType.includes('64')) { - ret = src.readInt64LE(pos) - } - else if (defType.includes('32')) { - ret = src.readInt32LE(pos) - } - else if (defType.includes('16')) { - ret = src.readInt16LE(pos) - } - else { - throw new Error(`Unknown defType: ${defType}`) - } - } - else { - throw new Error(`Unknown defType: ${defType}`) - } - - return ret -} diff --git a/packages/win32-api/src/lib/kernel32/api.def.ts b/packages/win32-api/src/lib/kernel32/api.def.ts new file mode 100644 index 00000000..c5a708c8 --- /dev/null +++ b/packages/win32-api/src/lib/kernel32/api.def.ts @@ -0,0 +1,42 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + + +export class DefKernel32 implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + static FormatMessageW = [ + D.DWORD, + [D.DWORD, D.LPCVOID, D.DWORD, D.DWORD, `_Out_ ${D.LPTSTR}`, D.DWORD, D.va_list], + ] + + static FreeConsole = [D.BOOL, []] + static GenerateConsoleCtrlEvent = [D.BOOL, [D.DWORD, D.DWORD]] + + /** err code: https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms681381(v=vs.85).aspx */ + static GetLastError = [D.DWORD, []] + + /** retrieve value from buf by readUInt32() */ + static GetModuleHandleW = [D.HMODULE, [D.LPCTSTR]] + + /** flags, optional LPCTSTR name, ref hModule */ + static GetModuleHandleExW = [D.BOOL, [D.DWORD, D.LPCTSTR, D.HMODULE]] + + static GetProcessHeaps = [D.DWORD, [D.DWORD, D.PHANDLE]] + + static GetSystemTimes = [D.BOOL, [`_Out_ ${S.LPFILETIME}`, `_Out_ ${S.LPFILETIME}`, `_Out_ ${S.LPFILETIME}`]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount */ + static GetTickCount = [D.DWORD, []] + + static HeapFree = [D.BOOL, [D.HANDLE, D.DWORD, D.LPVOID]] + + static OpenProcess = [D.HANDLE, [D.DWORD, D.BOOL, D.DWORD]] + + static OutputDebugStringW = [D.VOID, [D.LPCTSTR]] + + static SetLastError = [D.VOID, [D.DWORD]] + + static SetThreadExecutionState = [D.INT, [D.INT]] +} diff --git a/packages/win32-api/src/lib/kernel32/api.ts b/packages/win32-api/src/lib/kernel32/api.ts deleted file mode 100644 index 4ad6818b..00000000 --- a/packages/win32-api/src/lib/kernel32/api.ts +++ /dev/null @@ -1,105 +0,0 @@ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -export interface Win32Fns { - /** - * https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351(v=vs.85).aspx - * dwLanguageId: https://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx - */ - FormatMessageW: ( - dwFlags: M.DWORD, - lpSource: M.LPCVOID | null, - dwMessageId: M.DWORD, - dwLanguageId: M.DWORD, // 0x0409: US, 0x0000: Neutral locale language - lpBuffer: M.LPTSTR, - nSize: M.DWORD, - Arguments: M.va_list | null, - ) => M.DWORD - - FreeConsole: () => M.BOOL - - GenerateConsoleCtrlEvent: (dwCtrlEvent: M.DWORD, dwProcessGroupId: M.DWORD) => M.BOOL - - /** - * Not works correctly - * @see https://github.com/node-ffi/node-ffi/issues/261 - */ - GetLastError: () => M.DWORD - - GetModuleHandleW: (lpModuleName: M.LPCTSTR | null) => M.HMODULE - - GetModuleHandleExW: (dwFlags: M.DWORD, lpModuleName: M.LPCTSTR | null, phModule: M.HMODULE) => M.BOOL - - GetProcessHeaps: (NumberOfHeaps: M.DWORD, ProcessHeaps: M.PHANDLE) => M.DWORD - - /** https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getsystemtimes */ - GetSystemTimes: (lpIdleTime: M.PFILETIME, lpKernelTime: M.PFILETIME, lpUserTime: M.PFILETIME) => M.BOOL - - HeapFree: (hHeap: M.HANDLE, dwFlags: M.DWORD, lpMem: M.LPVOID | null) => M.BOOL - - OpenProcess: (dwDesiredAccess: M.DWORD, bInheritHandle: M.BOOL, dwProcessId: M.DWORD) => M.HANDLE - - /** https://docs.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-outputdebugstringw */ - OutputDebugStringW: (lpOutputString: M.LPCTSTR) => M.VOID - - /** https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx */ - SetLastError: (dwErrCode: M.DWORD) => M.VOID - - /** - * Enables an application to inform the system that it is in use, - * thereby preventing the system from entering sleep or turning off - * the display while the application is running. - * - * @example - * // Television recording is beginning. Enable away mode and prevent the sleep idle time-out. - * SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED); - * - * // Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally. - * SetThreadExecutionState(ES_CONTINUOUS); - * - * @param esFlags The thread's execution requirements. - * This parameter can be one or more of the following values. Join them with single | - * @returns If the function succeeds, the return value is the previous thread execution state. - * If the function fails, the return value is NULL. - * @see[Docs]{@link https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setthreadexecutionstate} - * - * Note: The return value NULL would be converted to zero by node-ffi - */ - SetThreadExecutionState: (esFlags: M.UINT) => M.UINT -} - - -export const apiDef: M.DllFuncs = { - FormatMessageW: [ - W.DWORD, - [W.DWORD, W.LPCVOID, W.DWORD, W.DWORD, W.LPTSTR, W.DWORD, W.va_list], - ], - - FreeConsole: [W.BOOL, [] ], - - GenerateConsoleCtrlEvent: [W.BOOL, [W.DWORD, W.DWORD] ], - - /** err code: https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms681381(v=vs.85).aspx */ - GetLastError: [W.DWORD, [] ], - - /** retrive value from buf by ret.ref().readUInt32() */ - GetModuleHandleW: [W.HMODULE, [W.LPCTSTR] ], - - /** flags, optional LPCTSTR name, ref hModule */ - GetModuleHandleExW: [W.BOOL, [W.DWORD, W.LPCTSTR, W.HMODULE] ], - - GetProcessHeaps: [W.DWORD, [W.DWORD, W.PHANDLE] ], - - GetSystemTimes: [W.BOOL, [W.PFILETIME, W.PFILETIME, W.PFILETIME] ], - - HeapFree: [W.BOOL, [W.HANDLE, W.DWORD, W.LPVOID] ], - - OpenProcess: [W.HANDLE, [W.DWORD, W.BOOL, W.DWORD] ], - - OutputDebugStringW: [W.VOID, [W.LPCTSTR] ], - - SetLastError: [W.VOID, [W.DWORD] ], - - SetThreadExecutionState: [W.INT, [W.INT] ], -} diff --git a/packages/win32-api/src/lib/kernel32/api.types.ts b/packages/win32-api/src/lib/kernel32/api.types.ts new file mode 100644 index 00000000..b2bb1b62 --- /dev/null +++ b/packages/win32-api/src/lib/kernel32/api.types.ts @@ -0,0 +1,73 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { DefKernel32 } from './api.def.js' + + +export class Kernel32 implements T.LibDef2Type { + /** + * https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-formatmessage?redirectedfrom=MSDN + * dwLanguageId: https://msdn.microsoft.com/en-us/library/windows/desktop/dd318693(v=vs.85).aspx + */ + FormatMessageW: ( + dwFlags: T.DWORD, + lpSource: T.LPCVOID | null, + dwMessageId: T.DWORD, + dwLanguageId: T.DWORD, // 0x0409: US, 0x0000: Neutral locale language + lpBuffer: T.LPTSTR, + nSize: T.DWORD, + Arguments: T.va_list | null, + ) => T.DWORD + + FreeConsole: () => T.BOOL + + GenerateConsoleCtrlEvent: (dwCtrlEvent: T.DWORD, dwProcessGroupId: T.DWORD) => T.BOOL + + GetLastError: () => T.DWORD + + GetModuleHandleW: (lpModuleName: T.LPCTSTR | null) => T.HMODULE + + GetModuleHandleExW: (dwFlags: T.DWORD, lpModuleName: T.LPCTSTR | null, phModule: T.HMODULE) => T.BOOL + + GetProcessHeaps: (NumberOfHeaps: T.DWORD, ProcessHeaps: T.PHANDLE) => T.DWORD + + /** https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getsystemtimes */ + GetSystemTimes: (lpIdleTime: S.FILETIME_Type, lpKernelTime: S.FILETIME_Type, lpUserTime: S.FILETIME_Type) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount */ + GetTickCount: () => T.DWORD + + HeapFree: (hHeap: T.HANDLE, dwFlags: T.DWORD, lpMem: T.LPVOID | null) => T.BOOL + + OpenProcess: (dwDesiredAccess: T.DWORD, bInheritHandle: T.BOOL, dwProcessId: T.DWORD) => T.HANDLE + + /** https://learn.microsoft.com/en-us/windows/win32/api/debugapi/nf-debugapi-outputdebugstringw */ + OutputDebugStringW: (lpOutputString: T.LPCTSTR) => T.VOID + + /** https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx */ + SetLastError: (dwErrCode: T.DWORD) => T.VOID + + /** + * Enables an application to inform the system that it is in use, + * thereby preventing the system from entering sleep or turning off + * the display while the application is running. + * + * @example + * // Television recording is beginning. Enable away mode and prevent the sleep idle time-out. + * SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED); + * + * // Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally. + * SetThreadExecutionState(ES_CONTINUOUS); + * + * @param esFlags The thread's execution requirements. + * This parameter can be one or more of the following values. Join them with single | + * @returns If the function succeeds, the return value is the previous thread execution state. + * If the function fails, the return value is NULL. + * @see [Docs](https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setthreadexecutionstate) + * + */ + SetThreadExecutionState: (esFlags: T.UINT) => T.UINT +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/kernel32/index.promise.ts b/packages/win32-api/src/lib/kernel32/index.promise.ts deleted file mode 100644 index d70de554..00000000 --- a/packages/win32-api/src/lib/kernel32/index.promise.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.kernel32 -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/kernel32/index.ts b/packages/win32-api/src/lib/kernel32/index.ts index 898a2e59..ee8fbb20 100644 --- a/packages/win32-api/src/lib/kernel32/index.ts +++ b/packages/win32-api/src/lib/kernel32/index.ts @@ -1,24 +1,21 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' +import { type FLib, type LoadOptions, load as _load } from 'win32-def' -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' +import { DllNames } from '##/lib/types.js' -import { apiDef, Win32Fns } from './api.js' +import { DefKernel32 } from './api.def.js' +import { Kernel32 } from './api.types.js' -export { apiDef } -export { Win32Fns } +export { + DefKernel32, Kernel32, +} + export const dllName = DllNames.kernel32 -/** - * @deprecated use promise instead - * ```ts - * import { Kernel32 } from 'win32-api/promise' - * const knl32 = Kernel32.load() - * const times = await knl32.GetSystemTimes(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) +export type LibKernel32 = FLib + +export const load = (fns?: LoadOptions['usedFuncNames']) => _load({ + dll: dllName + '.dll', + dllFuncs: DefKernel32, + usedFuncNames: fns, +}) diff --git a/packages/win32-api/src/lib/ntdll/api.ts b/packages/win32-api/src/lib/ntdll/api.ts deleted file mode 100644 index dcd59653..00000000 --- a/packages/win32-api/src/lib/ntdll/api.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -export interface Win32Fns { - // may be altered or unavailable in future versions of Windows - NtQueryInformationProcess: ( - ProcessHandle: M.HANDLE, - ProcessInformationClass: number, - ProcessInformation: M.PVOID, // _Out_ - ProcessInformationLength: M.ULONG, - ReturnLength: M.PULONG | null, // _Out_opt_ ppid - ) => M.NTSTATUS - -} - - -export const apiDef: M.DllFuncs = { - NtQueryInformationProcess: [W.NTSTATUS, [W.HANDLE, W.DWORD32, W.PVOID, W.ULONG, W.PULONG] ], -} - diff --git a/packages/win32-api/src/lib/ntdll/index.promise.ts b/packages/win32-api/src/lib/ntdll/index.promise.ts deleted file mode 100644 index 01610ec9..00000000 --- a/packages/win32-api/src/lib/ntdll/index.promise.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.ntdll -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/ntdll/index.ts b/packages/win32-api/src/lib/ntdll/index.ts deleted file mode 100644 index 9fefcaa8..00000000 --- a/packages/win32-api/src/lib/ntdll/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' - -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.ntdll -/** - * @deprecated use promise instead - * ```ts - * import { Ntdll } from 'win32-api/promise' - * const ntdll = Ntdll.load() - * const ntStatus = await ntdll.NtQueryInformationProcess(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/spoolss/api.def.ts b/packages/win32-api/src/lib/spoolss/api.def.ts new file mode 100644 index 00000000..68c7b7bc --- /dev/null +++ b/packages/win32-api/src/lib/spoolss/api.def.ts @@ -0,0 +1,16 @@ +import * as D from 'win32-def/def' +import * as T from 'win32-def/types' + + +export class DefSpoolss implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + static EndDocPrinter = [D.BOOL, [D.HANDLE]] + + static EndPagePrinter = [D.BOOL, [D.HANDLE]] + + /** https://learn.microsoft.com/en-us/windows/win32/printdocs/writeprinter */ + static WritePrinter = [D.BOOL, [D.HANDLE, D.LPVOID, D.DWORD, `_Out_ ${D.LPDWORD}`]] + +} + diff --git a/packages/win32-api/src/lib/spoolss/api.ts b/packages/win32-api/src/lib/spoolss/api.ts deleted file mode 100644 index 0ff4de8d..00000000 --- a/packages/win32-api/src/lib/spoolss/api.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* eslint-disable id-length */ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -export interface Win32Fns { - - /** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/enddocprinter - */ - EndDocPrinter: (hPrinter: M.HANDLE) => M.BOOL - - EndPagePrinter: (hPrinter: M.HANDLE) => M.BOOL - - /** - * - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/writeprinter - */ - WritePrinter: ( - hPrinter: M.HANDLE, - pBuf: M.LPVOID, - cbBuf: M.DWORD, - pcWritten: M.LPDWORD, - ) => M.BOOL - -} - - -export const apiDef: M.DllFuncs = { - - EndDocPrinter: [W.BOOL, [W.HANDLE] ], - - EndPagePrinter: [W.BOOL, [W.HANDLE] ], - - WritePrinter: [W.BOOL, [W.HANDLE, W.LPVOID, W.DWORD, W.LPDWORD] ], - -} - diff --git a/packages/win32-api/src/lib/spoolss/api.types.ts b/packages/win32-api/src/lib/spoolss/api.types.ts new file mode 100644 index 00000000..bc5008bd --- /dev/null +++ b/packages/win32-api/src/lib/spoolss/api.types.ts @@ -0,0 +1,19 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' + +import { DefSpoolss } from './api.def.js' + + +export class Spoolss implements T.LibDef2Type { + + /** https://learn.microsoft.com/en-us/windows/win32/printdocs/enddocprinter */ + EndDocPrinter: (hPrinter: T.HANDLE) => T.BOOL + + EndPagePrinter: (hPrinter: T.HANDLE) => T.BOOL + + /** https://learn.microsoft.com/zh-cn/windows/win32/printdocs/writeprinter */ + WritePrinter: (hPrinter: T.HANDLE, pBuf: T.LPVOID, cbBuf: T.DWORD, pcWritten: T.LPDWORD,) => T.BOOL + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/spoolss/index.promise.ts b/packages/win32-api/src/lib/spoolss/index.promise.ts deleted file mode 100644 index b7de00c5..00000000 --- a/packages/win32-api/src/lib/spoolss/index.promise.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.winspool -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/spoolss/index.ts b/packages/win32-api/src/lib/spoolss/index.ts index d8456358..8a3efa0a 100644 --- a/packages/win32-api/src/lib/spoolss/index.ts +++ b/packages/win32-api/src/lib/spoolss/index.ts @@ -1,24 +1,21 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' +import { type FLib, type LoadOptions, load as _load } from 'win32-def' -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' +import { DllNames } from '##/lib/types.js' -import { apiDef, Win32Fns } from './api.js' +import { DefSpoolss } from './api.def.js' +import { Spoolss } from './api.types.js' -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.winspool -/** - * @deprecated use promise instead - * ```ts - * import { User32 } from 'win32-api/promise' - * const user32 = User32.load() - * const hWnd = await user32.FindWindowExW(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) +export { + DefSpoolss, Spoolss, +} + +export const dllName = DllNames.spoolss +export type LibSpool = FLib + +export const load = (fns?: LoadOptions['usedFuncNames']) => _load({ + dll: dllName + '.dll', + dllFuncs: DefSpoolss, + usedFuncNames: fns, +}) diff --git a/packages/win32-api/src/lib/types.ts b/packages/win32-api/src/lib/types.ts index 6f7b425d..80deb42a 100644 --- a/packages/win32-api/src/lib/types.ts +++ b/packages/win32-api/src/lib/types.ts @@ -1,4 +1,6 @@ +export type { KoffiFunction } from 'koffi' + export const enum DllNames { comctl32 = 'comctl32', gdi32 = 'gdi32', @@ -9,3 +11,4 @@ export const enum DllNames { winspool = 'winspool.drv', } + diff --git a/packages/win32-api/src/lib/user32/api.def.ts b/packages/win32-api/src/lib/user32/api.def.ts new file mode 100644 index 00000000..7fb6c75c --- /dev/null +++ b/packages/win32-api/src/lib/user32/api.def.ts @@ -0,0 +1,9 @@ +import * as T from 'win32-def/types' + +import { DefUser32Combo } from './dict/index.def.js' + + +export class DefUser32 extends DefUser32Combo implements T.LibDefBase { + [x: string]: T.FnDefFullParams +} + diff --git a/packages/win32-api/src/lib/user32/api.ts b/packages/win32-api/src/lib/user32/api.ts deleted file mode 100644 index 7c92d4c8..00000000 --- a/packages/win32-api/src/lib/user32/api.ts +++ /dev/null @@ -1,348 +0,0 @@ -/* eslint-disable id-length */ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -// export interface Win32Fns extends M.DllFuncsModel { -export interface Win32Fns { - BringWindowToTop: (hWnd: M.HWND) => M.BOOL - - /** - * https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-broadcastsystemmessage - */ - BroadcastSystemMessage: ( - flags: M.DWORD, - lpInfo: M.LPDWORD, - Msg: M.UINT, - wParam: M.WPARAM, - lParam: M.LPARAM) => M.LRESULT - - ClientToScreen: (hWnd: M.HWND, lpPoint: M.LPPOINT) => M.BOOL - - /** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-closewindow */ - CloseWindow: (hWnd: M.HWND) => M.BOOL - - CreateWindowExW: ( - dwExStyle: M.DWORD, - lpClassName: M.LPCTSTR | null, - lpWindowName: M.LPCTSTR | null, - dwStyle: M.DWORD, - x: M.INT, - y: M.INT, - nWidth: M.INT, - nHeight: M.INT, - hWndParent: M.HWND, - HMENU: M.HMENU, - HINSTANCE: M.HINSTANCE, - LPVOID: M.LPVOID, - ) => M.HWND - - DefWindowProcW: (hWnd: M.HWND, Msg: M.UINT, wParam: M.WPARAM, lParam: M.LPARAM) => M.LRESULT - - /** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-destroywindow */ - DestroyWindow: (hWnd: M.HWND) => M.BOOL - - DispatchMessageW: (lpMsg: M.LPMSG) => M.LRESULT - - /** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesw */ - EnumDisplayDevicesW: ( - lpDevice: M.LPCWSTR, - iDevNum: M.DWORD, - lpDisplayDevice: M.PDISPLAY_DEVICEW, - dwFlags: M.DWORD, - ) => M.BOOL - - EnumThreadWindows: (dwThreadId: M.DWORD, lpfn: M.WNDENUMPROC, lParam: M.LPARAM) => M.BOOL - - // EnumWindows: EnumWindows - EnumWindows: (lpEnumFunc: M.WNDENUMPROC, lParam: M.LPARAM) => M.BOOL - - FindWindowExW: ( - hwndParent: M.HWND, - hwndChildAfter: M.HWND, - lpszClass: M.LPCTSTR | null, - lpszWindow: M.LPCTSTR | null, - ) => M.HWND - - FlashWindow: (hWnd: M.HWND, bInvert: M.BOOL) => M.BOOL - - FlashWindowEx: (pfwi: M.PFLASHWINFO) => M.BOOL - - GetAncestor: (hwnd: M.HWND, gaFlags: M.UINT) => M.HWND - - /** https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getalttabinfow */ - GetAltTabInfoW: ( - hWnd: M.HWND, - iItem: M.INT, - pati: M.PALTTABINFO, - pszItemText: M.LPWSTR | null, - cchItemText: M.INT, - ) => M.BOOL - - /** - * Copies the caret's position to the specified POINT structure. - * @link https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcaretpos - */ - GetCaretPos: (lpPoint: M.LPPOINT) => M.BOOL - - GetClassInfoExW: (hinst: M.HINSTANCE, lpszClass: M.LPCTSTR, LPWNDCLASSEX: M.LPWNDCLASSEX) => M.BOOL - - GetForegroundWindow: () => M.HWND - - GetMessageW: (lpMsg: M.LPMSG, HWND: M.HWND, wMsgFilterMin: M.UINT, wMsgFilterMax: M.UINT) => M.BOOL - - GetParent: (hWnd: M.HWND) => M.HWND - - /** https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputdeviceinfow */ - GetRawInputDeviceInfoW: ( - hDevice: M.HANDLE, - uiCommand: M.UINT, - pData: M.LPVOID, - pcbSize: M.PUINT, - ) => M.UINT - - /** https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputdevicelist */ - GetRawInputDeviceList: ( - /** An array of RAWINPUTDEVICELIST */ - pRawInputDeviceList: M.PRAWINPUTDEVICELIST, - /** - * If this value is less than the number of devices attached to the system, - * the function returns the actual number of devices in this variable - * and fails with ERROR_INSUFFICIENT_BUFFER. - */ - puiNumDevices: M.PUINT, - cbSize: M.UINT, - ) => M.INT - - GetTopWindow: (hWnd: M.HWND) => M.HWND - - GetWindow: (hWnd: M.HWND, uCmd: M.UINT) => M.HWND - - GetWindowInfo: (hwnd: M.HWND, pwi: M.PWINDOWINFO) => M.BOOL // Note that you must set the pwi.cbSize! - - GetWindowLongW: (hWnd: M.HWND, nIndex: M.INT) => M.LONG - - /** only under x64 */ - GetWindowLongPtrW: (hWnd: M.HWND, nIndex: M.INT) => M.LONG_PTR - - /** - * @see https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect - */ - GetWindowRect: (hWnd: M.HWND, LPRECT: M.LPRECT) => M.BOOL - - /** - * @docs https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw - */ - GetWindowTextW: (hWnd: M.HWND, lpString: M.LPCTSTR, nMaxCount: M.INT) => M.INT - - GetWindowThreadProcessId: (hWnd: M.HWND, lpdwProcessId: M.LPDWORD | null) => M.DWORD - - /** - * @docs https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow - */ - MonitorFromWindow: (hWnd: M.HWND, dwFlags: M.DWORD) => M.HMONITOR - - IsIconic: (hWnd: M.HWND) => M.BOOL - - IsWindowVisible: (hWnd: M.HWND) => M.BOOL - - PeekMessageW: ( - lpMsg: M.LPMSG, - HWND: M.HWND, - wMsgFilterMin: M.UINT, - wMsgFilterMax: M.UINT, - wRemoveMsg: M.UINT, - ) => M.BOOL - - /** - * ref: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-postmessagew - */ - PostMessageW: (hWnd: M.HWND, Msg: M.UINT, wPARAM: M.WPARAM, lPARAM: M.LPARAM) => M.BOOL - - /** https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-printwindow */ - PrintWindow: ( - hwnd: M.HWND, - hdcBlt: M.HDC, - nFlags: M.UINT, - ) => M.BOOL - - RegisterClassExW: (lpwcx: M.LPWNDCLASSEX) => M.ATOM - - /** - * https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerwindowmessagew - */ - RegisterWindowMessageW: (lpString: M.LPCTSTR) => M.UINT - - /** - * ref: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessagew - */ - SendMessageW: (hWnd: M.HWND, Msg: M.UINT, wPARAM: M.WPARAM, lPARAM: M.LPARAM) => M.LRESULT - - /** - * @url https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-SendMessageTimeoutW - */ - SendMessageTimeoutW: ( - hWnd: M.HWND, - Msg: M.UINT, - wParam: M.WPARAM, - lParam: M.LPARAM, - fuFlags: M.UINT, - uTimeout: M.UINT, - lpdwResult: M.DWORD_PTR) => M.LRESULT - - /** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setforegroundwindow */ - SetForegroundWindow: (hWnd: M.HWND) => M.BOOL - - SetWindowPos: ( - hWnd: M.HWND, - hWndInsertAfter: M.HWND | null, - X: M.INT, - Y: M.INT, - cx: M.INT, - cy: M.INT, - uFlags: M.UINT) => M.BOOL - - SetWindowTextW: (hWnd: M.HWND, lpString: M.LPCTSTR | null) => M.BOOL - - SetWinEventHook: ( - eventMin: M.UINT, - eventMax: M.UINT, - hmodWinEventProc: M.HMODULE, - lpfnWinEventProc: M.WINEVENTPROC, - idProcess: M.DWORD, - idThread: M.DWORD, - dwflags: M.UINT, - ) => M.HWINEVENTHOOK - - ShowWindow: (hWnd: M.HWND, nCmdShow: M.INT) => M.BOOL - - TranslateMessage: (lpMsg: M.LPMSG) => M.BOOL - - TranslateMessageEx: (lpMsg: M.LPMSG) => M.BOOL - - UnhookWinEvent: (hWinEventHook: M.HWINEVENTHOOK) => M.BOOL - - UpdateWindow: (hWnd: M.HWND) => M.BOOL -} - - -export const apiDef: M.DllFuncs = { - BringWindowToTop: [W.BOOL, [W.HWND] ], - - BroadcastSystemMessage: [W.LRESULT, [W.DWORD, W.LPDWORD, W.UINT, W.WPARAM, W.LPARAM] ], - - /** url: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-clienttoscreen */ - ClientToScreen: [W.BOOL, [W.HWND, W.LPPOINT] ], - - CloseWindow: [W.BOOL, [W.HWND] ], - - CreateWindowExW: [ - W.HWND, [ - W.DWORD, W.LPCTSTR, W.LPCTSTR, W.DWORD, - W.INT, W.INT, W.INT, W.INT, - W.HWND, W.HMENU, W.HINSTANCE, W.LPVOID, - ], - ], - - DefWindowProcW: [W.LRESULT, [W.HWND, W.UINT, W.WPARAM, W.LPARAM] ], - - DestroyWindow: [W.BOOL, [W.HWND] ], - - DispatchMessageW: [W.LRESULT, [W.LPMSG] ], - - /** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesw */ - EnumDisplayDevicesW: [W.BOOL, [W.LPCWSTR, W.DWORD, W.DISPLAY_DEVICEW, W.DWORD] ], - - EnumThreadWindows: [W.BOOL, [W.DWORD, W.WNDENUMPROC, W.LPARAM] ], - - EnumWindows: [W.BOOL, [W.WNDENUMPROC, W.LPARAM] ], - - FindWindowExW: [W.HWND, [W.HWND, W.HWND, W.LPCTSTR, W.LPCTSTR] ], - - FlashWindow: [W.BOOL, [W.HWND, W.BOOL] ], - - FlashWindowEx: [W.BOOL, [W.FLASHWINFO] ], - - GetAncestor: [W.HWND, [W.HWND, W.UINT] ], - - GetAltTabInfoW: [W.BOOL, [W.HWND, W.INT, W.INT, W.LPWSTR, W.INT] ], - - /** - * Copies the caret's position to the specified POINT structure. - * @link https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcaretpos - */ - GetCaretPos: [W.BOOL, [W.LPPOINT] ], - - GetClassInfoExW: [W.BOOL, [W.HINSTANCE, W.LPCTSTR, W.LPWNDCLASSEX] ], - - GetForegroundWindow: [W.HWND, [] ], - - GetMessageW: [W.BOOL, [W.LPMSG, W.HWND, W.UINT, W.UINT] ], - - GetParent: [W.HWND, [W.HWND] ], - - GetRawInputDeviceInfoW: [W.UINT, [W.HANDLE, W.UINT, W.LPVOID, W.PUINT] ], - - GetRawInputDeviceList: [W.INT, [W.PRAWINPUTDEVICELIST, W.PUINT, W.UINT] ], - - GetTopWindow: [W.HWND, [W.HWND] ], - - GetWindow: [W.HWND, [W.HWND, W.UINT] ], - - GetWindowInfo: [W.BOOL, [W.HWND, W.PWINDOWINFO] ], - - GetWindowLongW: [W.LONG, [W.HWND, W.INT] ], - - /** only under x64 */ - GetWindowLongPtrW: [W.LONG_PTR, [W.HWND, W.INT] ], - - GetWindowRect: [W.BOOL, [W.HWND, W.RECT] ], - - GetWindowTextW: [W.INT, [W.HWND, W.LPTSTR, W.INT] ], - - GetWindowThreadProcessId: [W.DWORD, [W.HWND, W.LPDWORD] ], - - MonitorFromWindow: [W.HWND, [W.HANDLE, W.DWORD] ], - - IsIconic: [W.BOOL, [W.HWND] ], - - IsWindowVisible: [W.BOOL, [W.HWND] ], - - PeekMessageW: [W.BOOL, [W.LPMSG, W.HWND, W.UINT, W.UINT, W.UINT] ], - - PostMessageW: [W.BOOL, [W.HWND, W.UINT, W.WPARAM, W.LPARAM] ], - - PrintWindow: [W.BOOL, [W.HWND, W.HDC, W.UINT] ], - - RegisterClassExW: [W.ATOM, [W.WNDCLASSEX] ], - - RegisterWindowMessageW: [W.UINT, [W.LPCTSTR] ], - - SendMessageW: [W.LRESULT, [W.HWND, W.UINT, W.WPARAM, W.LPARAM] ], - - SendMessageTimeoutW: [W.LRESULT, [W.HWND, W.UINT, W.WPARAM, W.LPARAM, W.UINT, W.UINT, W.DWORD_PTR] ], - - SetForegroundWindow: [W.BOOL, [W.HWND] ], - - SetWindowPos: [W.BOOL, [W.HWND, W.HWND, W.INT, W.INT, W.INT, W.INT, W.UINT] ], - - SetWindowTextW: [W.BOOL, [W.HWND, W.LPCTSTR] ], - - SetWinEventHook: [W.HWINEVENTHOOK, [W.UINT, W.UINT, W.HMODULE, W.WINEVENTPROC, W.DWORD, W.DWORD, W.UINT] ], - - ShowWindow: [W.BOOL, [W.HWND, W.INT] ], - - TranslateMessage: [W.BOOL, [W.LPMSG] ], - - TranslateMessageEx: [W.BOOL, [W.LPMSG] ], - - UnhookWinEvent: [W.BOOL, [W.HWINEVENTHOOK] ], - - UpdateWindow: [W.BOOL, [W.HWND] ], -} - - -// export interface EnumWindows { -// (lpEnumFunc: M.WNDENUMPROC, lParam: M.LPARAM): M.BOOL -// async: (lpEnumFunc: M.WNDENUMPROC, lParam: M.LPARAM, cb: (err: Error) => void) => void -// } diff --git a/packages/win32-api/src/lib/user32/api.types.ts b/packages/win32-api/src/lib/user32/api.types.ts new file mode 100644 index 00000000..e5c91280 --- /dev/null +++ b/packages/win32-api/src/lib/user32/api.types.ts @@ -0,0 +1,12 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' + +import { DefUser32 } from './api.def.js' +import { User32Combo } from './dict/index.types.js' + + +export class User32 extends User32Combo implements T.LibDef2Type { +} + + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/AB.def.ts b/packages/win32-api/src/lib/user32/dict/AB.def.ts new file mode 100644 index 00000000..b51bfb10 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/AB.def.ts @@ -0,0 +1,12 @@ +import * as D from 'win32-def/def' + + +export class DefUser32_B { + + static BringWindowToTop = [D.BOOL, [D.HWND]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-broadcastsystemmessage */ + static BroadcastSystemMessage = [D.LRESULT, [D.DWORD, D.LPDWORD, D.UINT, D.WPARAM, D.LPARAM]] + +} + diff --git a/packages/win32-api/src/lib/user32/dict/AB.types.ts b/packages/win32-api/src/lib/user32/dict/AB.types.ts new file mode 100644 index 00000000..c2806acb --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/AB.types.ts @@ -0,0 +1,22 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' + +import { DefUser32_B } from './AB.def.js' + + +export class User32_B implements T.LibDef2Type { + + BringWindowToTop: (hWnd: T.HWND) => T.BOOL + /** + * https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-broadcastsystemmessage + */ + BroadcastSystemMessage: ( + flags: T.DWORD, + lpInfo: T.LPDWORD, + Msg: T.UINT, + wParam: T.WPARAM, + lParam: T.LPARAM) => T.LRESULT + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/CD.def.ts b/packages/win32-api/src/lib/user32/dict/CD.def.ts new file mode 100644 index 00000000..17ae0e37 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/CD.def.ts @@ -0,0 +1,45 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + +import { DefUser32_B } from './AB.def.js' + + +export class DefUser32_C extends DefUser32_B { + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-clienttoscreen */ + static ClientToScreen = [D.BOOL, [D.HWND, `_Inout_ ${S.LPPOINT}`]] + + static CloseWindow = [D.BOOL, [D.HWND]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw */ + static CreateWindowExW = [ + D.HWND, [ + D.DWORD, + D.LPCTSTR, + D.LPCTSTR, + D.DWORD, + D.INT, + D.INT, + D.INT, + D.INT, + D.HWND, + D.HMENU, + D.HINSTANCE, + D.LPVOID, + ], + ] + +} + + +export class DefUser32_D extends DefUser32_C { + + static DefWindowProcW = [D.LRESULT, [D.HWND, D.UINT, D.WPARAM, D.LPARAM]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow */ + static DestroyWindow = [D.BOOL, [D.HWND]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessagew */ + static DispatchMessageW = [D.LRESULT, [S.LPMSG]] + +} diff --git a/packages/win32-api/src/lib/user32/dict/CD.types.ts b/packages/win32-api/src/lib/user32/dict/CD.types.ts new file mode 100644 index 00000000..c35363dd --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/CD.types.ts @@ -0,0 +1,44 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' + +import { User32_B } from './AB.types.js' + + +export class User32_C extends User32_B { + + ClientToScreen: (hWnd: T.HWND, lpPoint: T.LPPOINT) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-closewindow */ + CloseWindow: (hWnd: T.HWND) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw */ + CreateWindowExW: ( + dwExStyle: T.DWORD, + lpClassName: T.LPCTSTR | null, + lpWindowName: T.LPCTSTR | null, + dwStyle: T.DWORD, + x: T.INT, + y: T.INT, + nWidth: T.INT, + nHeight: T.INT, + hWndParent: T.HWND, + HMENU: T.HMENU, + HINSTANCE: T.HINSTANCE, + LPVOID: T.LPVOID, + ) => T.HWND + +} + +export class User32_D extends User32_C { + + DefWindowProcW: (hWnd: T.HWND, Msg: T.UINT, wParam: T.WPARAM, lParam: T.LPARAM) => T.LRESULT + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow */ + DestroyWindow: (hWnd: T.HWND) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessagew */ + DispatchMessageW: (lpMsg: T.LPMSG) => T.LRESULT + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/EF.def.ts b/packages/win32-api/src/lib/user32/dict/EF.def.ts new file mode 100644 index 00000000..a2e9e6dd --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/EF.def.ts @@ -0,0 +1,29 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + +import { DefUser32_D } from './CD.def.js' + + +export class DefUser32_E extends DefUser32_D { + + /** https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesw */ + static EnumDisplayDevicesW = [D.BOOL, [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumthreadwindows */ + static EnumThreadWindows = [D.BOOL, [D.DWORD, D.WNDENUMPROC, D.LPARAM]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows */ + static EnumWindows = [D.BOOL, [D.WNDENUMPROC, D.LPARAM]] + +} + +export class DefUser32_F extends DefUser32_E { + + /** https=//learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowexw */ + static FindWindowExW = [D.HWND, [D.HWND, D.HWND, D.LPCTSTR, D.LPCTSTR]] + + static FlashWindow = [D.BOOL, [D.HWND, D.BOOL]] + + static FlashWindowEx = [D.BOOL, [S.PFLASHWINFO]] + +} diff --git a/packages/win32-api/src/lib/user32/dict/EF.types.ts b/packages/win32-api/src/lib/user32/dict/EF.types.ts new file mode 100644 index 00000000..ba30a6aa --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/EF.types.ts @@ -0,0 +1,43 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { User32_D } from './CD.types.js' + + +export class User32_E extends User32_D { + + /** https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesw */ + EnumDisplayDevicesW: ( + lpDevice: T.LPCWSTR | null, + iDevNum: T.DWORD, + lpDisplayDevice: S.DISPLAY_DEVICEW_Type, + dwFlags: T.DWORD, + ) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumthreadwindows */ + EnumThreadWindows: (dwThreadId: T.DWORD, lpfn: T.WNDENUMPROC, lParam: T.LPARAM) => T.BOOL + + // EnumWindows: EnumWindows + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows */ + EnumWindows: (lpEnumFunc: T.WNDENUMPROC, lParam: T.LPARAM) => T.BOOL + +} + +export class User32_F extends User32_E { + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowexw */ + FindWindowExW: ( + hwndParent: T.HWND, + hwndChildAfter: T.HWND, + lpszClass: T.LPCTSTR | null, + lpszWindow: T.LPCTSTR | null, + ) => T.HWND + + FlashWindow: (hWnd: T.HWND, bInvert: T.BOOL) => T.BOOL + + FlashWindowEx: (pfwi: S.FLASHWINFO_Type) => T.BOOL + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/G.def.ts b/packages/win32-api/src/lib/user32/dict/G.def.ts new file mode 100644 index 00000000..8c738c9d --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/G.def.ts @@ -0,0 +1,61 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + +import { DefUser32_F } from './EF.def.js' + + +export class DefUser32_G extends DefUser32_F { + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getancestor */ + static GetAncestor = [D.HWND, [D.HWND, D.UINT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getalttabinfow */ + static GetAltTabInfoW = [D.BOOL, [D.HWND, D.INT, `_Inout_ ${S.LPALTTABINFO}`, `_Out_ ${D.LPWSTR}`, D.INT]] + + /** + * Copies the caret's position to the specified POINT structure. + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcaretpos + */ + static GetCaretPos = [D.BOOL, [`_Out_ ${S.LPPOINT}`]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassinfoexw */ + static GetClassInfoExW = [D.BOOL, [D.HINSTANCE, D.LPCTSTR, `_Out_ ${S.LPWNDCLASSEXW}`]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcursorpos */ + static GetCursorPos = [D.BOOL, [`_Out_ ${S.LPPOINT}`]] + + static GetForegroundWindow = [D.HWND, []] + + static GetMessageW = [D.BOOL, [D.LPMSG, D.HWND, D.UINT, D.UINT]] + + static GetParent = [D.HWND, [D.HWND]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputdeviceinfow */ + static GetRawInputDeviceInfoW = [D.UINT, [D.HANDLE, D.UINT, `_Inout_ ${D.LPVOID}`, D.PUINT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputdevicelist */ + static GetRawInputDeviceList = [D.INT, [`_Out_ ${S.LPRAWINPUTDEVICELIST}`, D.PUINT, D.UINT]] + + static GetTopWindow = [D.HWND, [D.HWND]] + + static GetWindow = [D.HWND, [D.HWND, D.UINT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowinfo */ + static GetWindowInfo = [D.BOOL, [D.HWND, `_Inout_ ${S.LPWINDOWINFO}`]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongw */ + static GetWindowLongW = [D.LONG, [D.HWND, D.INT]] + + /** only under x64 */ + static GetWindowLongPtrW = [D.LONG_PTR, [D.HWND, D.INT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect */ + static GetWindowRect = [D.BOOL, [D.HWND, `_Out_ ${S.LPRECT}`]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw */ + static GetWindowTextW = [D.INT, [D.HWND, D.LPTSTR, D.INT]] + + static GetWindowThreadProcessId = [D.DWORD, [D.HWND, D.LPDWORD]] + +} + diff --git a/packages/win32-api/src/lib/user32/dict/G.types.ts b/packages/win32-api/src/lib/user32/dict/G.types.ts new file mode 100644 index 00000000..46e405c0 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/G.types.ts @@ -0,0 +1,83 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { User32_F } from './EF.types.js' + + +export class User32_G extends User32_F { + + GetAncestor: (hwnd: T.HWND, gaFlags: T.UINT) => T.HWND + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getalttabinfow */ + GetAltTabInfoW: ( + hWnd: T.HWND, + iItem: T.INT, + pati: S.ALTTABINFO_Type, + pszItemText: T.LPWSTR | null, + cchItemText: T.INT, + ) => T.BOOL + + /** + * Copies the caret's position to the specified POINT structure. + * @link https://leran.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcaretpos + */ + GetCaretPos: (lpPoint: T.LPPOINT) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassinfoexw */ + GetClassInfoExW: (hinst: T.HINSTANCE, lpszClass: T.LPCTSTR, LPWNDCLASSEX: S.WNDCLASSEXW_Type) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcursorpos */ + GetCursorPos: (lpPoint: S.POINT_Type) => T.BOOL + + GetForegroundWindow: () => T.HWND + + GetMessageW: (lpMsg: T.LPMSG, HWND: T.HWND, wMsgFilterMin: T.UINT, wMsgFilterMax: T.UINT) => T.BOOL + + GetParent: (hWnd: T.HWND) => T.HWND + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputdeviceinfow */ + GetRawInputDeviceInfoW: ( + hDevice: T.HANDLE, + uiCommand: T.UINT, + pData: T.LPVOID | null, + pcbSize: T.PUINT, + ) => T.UINT + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getrawinputdevicelist */ + GetRawInputDeviceList: ( + /** An array of RAWINPUTDEVICELIST */ + pRawInputDeviceList: S.RAWINPUTDEVICELIST_Type | null, + /** + * If this value is less than the number of devices attached to the system, + * the function returns the actual number of devices in this variable + * and fails with ERROR_INSUFFICIENT_BUFFER. + */ + puiNumDevices: T.PUINT, + cbSize: T.UINT, + ) => T.INT + + GetTopWindow: (hWnd: T.HWND) => T.HWND + + GetWindow: (hWnd: T.HWND, uCmd: T.UINT) => T.HWND + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowinfo */ + GetWindowInfo: (hwnd: T.HWND, pwi: S.WINDOWINFO_Type) => T.BOOL // Note that you must set the pwi.cbSize! + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongw */ + GetWindowLongW: (hWnd: T.HWND, nIndex: T.INT) => T.LONG + + /** only under x64 */ + GetWindowLongPtrW: (hWnd: T.HWND, nIndex: T.INT) => T.LONG_PTR + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowrect */ + GetWindowRect: (hWnd: T.HWND, LPRECT: S.RECT_Type) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw */ + GetWindowTextW: (hWnd: T.HWND, lpString: T.LPCTSTR, nMaxCount: T.INT) => T.INT + + GetWindowThreadProcessId: (hWnd: T.HWND, lpdwProcessId: T.LPDWORD | null) => T.DWORD + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/IM.def.ts b/packages/win32-api/src/lib/user32/dict/IM.def.ts new file mode 100644 index 00000000..c6be66fe --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/IM.def.ts @@ -0,0 +1,19 @@ +import * as D from 'win32-def/def' + +import { DefUser32_G } from './G.def.js' + + +export class DefUser32_I extends DefUser32_G { + + static IsIconic = [D.BOOL, [D.HWND]] + + static IsWindowVisible = [D.BOOL, [D.HWND]] + +} + + +export class DefUser32_M extends DefUser32_I { + + static MonitorFromWindow = [D.HWND, [D.HANDLE, D.DWORD]] + +} diff --git a/packages/win32-api/src/lib/user32/dict/IM.types.ts b/packages/win32-api/src/lib/user32/dict/IM.types.ts new file mode 100644 index 00000000..d85bfd97 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/IM.types.ts @@ -0,0 +1,24 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' + +import { User32_G } from './G.types.js' + + +export class User32_I extends User32_G { + + IsIconic: (hWnd: T.HWND) => T.BOOL + + IsWindowVisible: (hWnd: T.HWND) => T.BOOL + +} + +export class User32_M extends User32_I { + + /** + * @learn https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-monitorfromwindow + */ + MonitorFromWindow: (hWnd: T.HWND, dwFlags: T.DWORD) => T.HMONITOR + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/PR.def.ts b/packages/win32-api/src/lib/user32/dict/PR.def.ts new file mode 100644 index 00000000..c7d40c18 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/PR.def.ts @@ -0,0 +1,27 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + +import { DefUser32_M } from './IM.def.js' + + +export class DefUser32_P extends DefUser32_M { + + static PeekMessageW = [D.BOOL, [D.LPMSG, D.HWND, D.UINT, D.UINT, D.UINT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagew */ + static PostMessageW = [D.BOOL, [D.HWND, D.UINT, D.WPARAM, D.LPARAM]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-printwindow */ + static PrintWindow = [D.BOOL, [D.HWND, D.HDC, D.UINT]] + +} + +export class DefUser32_R extends DefUser32_P { + + /** https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-registerclassexw */ + static RegisterClassExW = [D.ATOM, [S.LPWNDCLASSEXW]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerwindowmessagew */ + static RegisterWindowMessageW = [D.UINT, [D.LPCWSTR]] + +} diff --git a/packages/win32-api/src/lib/user32/dict/PR.types.ts b/packages/win32-api/src/lib/user32/dict/PR.types.ts new file mode 100644 index 00000000..18618529 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/PR.types.ts @@ -0,0 +1,40 @@ +/* c8 ignore start */ +import * as T from 'win32-def/types' +import * as S from 'win32-def/struct' + +import { User32_M } from './IM.types.js' + + +export class User32_P extends User32_M { + + PeekMessageW: ( + lpMsg: T.LPMSG, + HWND: T.HWND, + wMsgFilterMin: T.UINT, + wMsgFilterMax: T.UINT, + wRemoveMsg: T.UINT, + ) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagew */ + PostMessageW: (hWnd: T.HWND | null, Msg: T.UINT, wPARAM: T.WPARAM, lPARAM: T.LPARAM) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-printwindow */ + PrintWindow: ( + hwnd: T.HWND, + hdcBlt: T.HDC, + nFlags: T.UINT, + ) => T.BOOL + +} + +export class User32_R extends User32_P { + + /** https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-registerclassexw */ + RegisterClassExW: (lpwcx: S.WNDCLASSEXW_Type) => T.ATOM + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerwindowmessagew */ + RegisterWindowMessageW: (lpString: T.LPCWSTR) => T.UINT + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/S.def.ts b/packages/win32-api/src/lib/user32/dict/S.def.ts new file mode 100644 index 00000000..95f2ef90 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/S.def.ts @@ -0,0 +1,33 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + +import { DefUser32_R } from './PR.def.js' + + +export class DefUser32_S extends DefUser32_R { + + /** + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput + */ + static SendInput = [D.UINT, [D.UINT, S.LPINPUT, D.INT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagew */ + static SendMessageW = [D.LRESULT, [D.HWND, D.UINT, D.WPARAM, D.LPARAM]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagetimeoutw */ + static SendMessageTimeoutW = [D.LRESULT, [D.HWND, D.UINT, D.WPARAM, D.LPARAM, D.UINT, D.UINT, D.DWORD_PTR]] + static SetForegroundWindow = [D.BOOL, [D.HWND]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos */ + static SetWindowPos = [D.BOOL, [D.HWND, D.HWND, D.INT, D.INT, D.INT, D.INT, D.UINT]] + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowtextw */ + static SetWindowTextW = [D.BOOL, [D.HWND, D.LPCWSTR]] + + // @TODO WINEVENTPROC + static SetWinEventHook = [D.HWINEVENTHOOK, [D.UINT, D.UINT, D.HMODULE, D.WINEVENTPROC, D.DWORD, D.DWORD, D.UINT]] + + static ShowWindow = [D.BOOL, [D.HWND, D.INT]] + +} + diff --git a/packages/win32-api/src/lib/user32/dict/S.types.ts b/packages/win32-api/src/lib/user32/dict/S.types.ts new file mode 100644 index 00000000..247765e1 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/S.types.ts @@ -0,0 +1,58 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { User32_R } from './PR.types.js' + + +export class User32_S extends User32_R { + + /** + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput + */ + SendInput: (cInputs: T.UINT, pInputs: S.INPUT_Type[], cbSize: T.INT) => T.UINT + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagew */ + SendMessageW: (hWnd: T.HWND, Msg: T.UINT, wPARAM: T.WPARAM, lPARAM: T.LPARAM) => T.LRESULT + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessagetimeoutw */ + SendMessageTimeoutW: ( + hWnd: T.HWND, + Msg: T.UINT, + wParam: T.WPARAM, + lParam: T.LPARAM, + fuFlags: T.UINT, + uTimeout: T.UINT, + lpdwResult: T.DWORD_PTR | null) => T.LRESULT + + /** https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-setforegroundwindow */ + SetForegroundWindow: (hWnd: T.HWND) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowpos */ + SetWindowPos: ( + hWnd: T.HWND, + hWndInsertAfter: T.HWND | null, + X: T.INT, + Y: T.INT, + cx: T.INT, + cy: T.INT, + uFlags: T.UINT) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowtextw */ + SetWindowTextW: (hWnd: T.HWND, lpString: T.LPCWSTR | null) => T.BOOL + + SetWinEventHook: ( + eventMin: T.UINT, + eventMax: T.UINT, + hmodWinEventProc: T.HMODULE, + lpfnWinEventProc: T.WINEVENTPROC, + idProcess: T.DWORD, + idThread: T.DWORD, + dwflags: T.UINT, + ) => T.HWINEVENTHOOK + + ShowWindow: (hWnd: T.HWND, nCmdShow: T.INT) => T.BOOL + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/TU.def.ts b/packages/win32-api/src/lib/user32/dict/TU.def.ts new file mode 100644 index 00000000..720ce4cb --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/TU.def.ts @@ -0,0 +1,24 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + +import { DefUser32_S } from './S.def.js' + + +export class DefUser32_T extends DefUser32_S { + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage */ + static TranslateMessage = [D.BOOL, [S.LPMSG]] + + /** https://learn.microsoft.com/en-us/windows/win32/winmsg/translatemessageex */ + static TranslateMessageEx = [D.BOOL, [S.LPMSG]] + +} + +export class DefUser32_U extends DefUser32_T { + + static UnhookWinEvent = [D.BOOL, [D.HWINEVENTHOOK]] + + static UpdateWindow = [D.BOOL, [D.HWND]] + +} + diff --git a/packages/win32-api/src/lib/user32/dict/TU.types.ts b/packages/win32-api/src/lib/user32/dict/TU.types.ts new file mode 100644 index 00000000..4dcb50ca --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/TU.types.ts @@ -0,0 +1,26 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { User32_S } from './S.types.js' + + +export class User32_T extends User32_S { + + /** https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage */ + TranslateMessage: (lpMsg: S.MSG_Type) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/winmsg/translatemessageex */ + TranslateMessageEx: (lpMsg: S.MSG_Type) => T.BOOL + +} + +export class User32_U extends User32_T { + + UnhookWinEvent: (hWinEventHook: T.HWINEVENTHOOK) => T.BOOL + + UpdateWindow: (hWnd: T.HWND) => T.BOOL + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/user32/dict/index.def.ts b/packages/win32-api/src/lib/user32/dict/index.def.ts new file mode 100644 index 00000000..28f5bb91 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/index.def.ts @@ -0,0 +1,3 @@ + +export { DefUser32_U as DefUser32Combo } from './TU.def.js' + diff --git a/packages/win32-api/src/lib/user32/dict/index.types.ts b/packages/win32-api/src/lib/user32/dict/index.types.ts new file mode 100644 index 00000000..c1435a74 --- /dev/null +++ b/packages/win32-api/src/lib/user32/dict/index.types.ts @@ -0,0 +1,6 @@ +import { User32_U } from './TU.types.js' + + +export class User32Combo extends User32_U { +} + diff --git a/packages/win32-api/src/lib/user32/index.promise.ts b/packages/win32-api/src/lib/user32/index.promise.ts deleted file mode 100644 index 04e89ca2..00000000 --- a/packages/win32-api/src/lib/user32/index.promise.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' -// for user32.constants -import * as constants from './constants.js' - - -export { apiDef } -export { constants } -export { Win32Fns } -export const dllName = DllNames.user32 -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/user32/index.ts b/packages/win32-api/src/lib/user32/index.ts index 32381c38..54329121 100644 --- a/packages/win32-api/src/lib/user32/index.ts +++ b/packages/win32-api/src/lib/user32/index.ts @@ -1,27 +1,21 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' +import { type FLib, type LoadOptions, load as _load } from 'win32-def' -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' +import { DllNames } from '##/lib/types.js' -import { apiDef, Win32Fns } from './api.js' -// for user32.constants -import * as constants from './constants.js' +import { DefUser32 } from './api.def.js' +import { User32 } from './api.types.js' -export { apiDef } -export { constants } -export { Win32Fns } +export { + DefUser32, User32, +} + export const dllName = DllNames.user32 -/** - * @deprecated use promise instead - * ```ts - * import { User32 } from 'win32-api/promise' - * const user32 = User32.load() - * const hWnd = await user32.FindWindowExW(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) +export type LibUser32 = FLib + +export const load = (fns?: LoadOptions['usedFuncNames']) => _load({ + dll: dllName + '.dll', + dllFuncs: DefUser32, + usedFuncNames: fns, +}) diff --git a/packages/win32-api/src/lib/winmsg.ts b/packages/win32-api/src/lib/winmsg.ts deleted file mode 100644 index b95275e8..00000000 --- a/packages/win32-api/src/lib/winmsg.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * https://docs.microsoft.com/en-us/windows/win32/winmsg/windowing - */ - - -// https://docs.microsoft.com/zh-cn/windows/win32/winmsg/window-messages -export const MN_GETHMENU = 0x01E1 -export const WM_ERASEBKGND = 0x0014 -export const WM_GETFONT = 0x0031 -export const WM_GETTEXT = 0x000D -export const WM_GETTEXTLENGTH = 0x000E -export const WM_SETFONT = 0x0030 -export const WM_SETICON = 0x0080 -export const WM_SETTEXT = 0x000C - -// https://docs.microsoft.com/zh-cn/windows/win32/winmsg/window-notifications -export const WM_ACTIVATEAPP = 0x001C -export const WM_CANCELMODE = 0x001F -export const WM_CHILDACTIVATE = 0x0022 -export const WM_CLOSE = 0x0010 -export const WM_CREATE = 0x0001 -export const WM_DESTROY = 0x0002 -export const WM_ENABLE = 0x000A -export const WM_ENTERSIZEMOVE = 0x0231 -export const WM_EXITSIZEMOVE = 0x0232 -export const WM_GETICON = 0x007F -export const WM_GETMINMAXINFO = 0x0024 -export const WM_INPUTLANGCHANGE = 0x0051 -export const WM_INPUTLANGCHANGEREQUEST = 0x0050 -export const WM_MOVE = 0x0003 -export const WM_MOVING = 0x0216 -export const WM_NCACTIVATE = 0x0086 -export const WM_NCCALCSIZE = 0x0083 -export const WM_NCCREATE = 0x0081 -export const WM_NCDESTROY = 0x0082 -export const WM_NULL = 0x0000 -export const WM_QUERYDRAGICON = 0x0037 -export const WM_QUERYOPEN = 0x0013 -export const WM_QUIT = 0x0012 -export const WM_SHOWWINDOW = 0x0018 -export const WM_SIZE = 0x0005 -export const WM_SIZING = 0x0214 -export const WM_STYLECHANGED = 0x007D -export const WM_STYLECHANGING = 0x007C -export const WM_THEMECHANGED = 0x031A -export const WM_USERCHANGED = 0x0054 -export const WM_WINDOWPOSCHANGED = 0x0047 -export const WM_WINDOWPOSCHANGING = 0x0046 - -/** https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-copydata */ -export const WM_COPYDATA = 0x004A - -// https://docs.microsoft.com/en-us/windows/win32/menurc/menu-notifications -export const WM_COMMAND = 0x0111 -export const WM_CONTEXTMENU = 0x007B -export const WM_ENTERMENULOOP = 0x0211 -export const WM_EXITMENULOOP = 0x0212 -export const WM_GETTITLEBARINFOEX = 0x033F -export const WM_MENUCOMMAND = 0x0126 -export const WM_MENUDRAG = 0x0123 -export const WM_MENUGETOBJECT = 0x0124 -export const WM_MENURBUTTONUP = 0x0122 -export const WM_NEXTMENU = 0x0213 -export const WM_UNINITMENUPOPUP = 0x0125 - diff --git a/packages/win32-api/src/lib/winspool/api.def.ts b/packages/win32-api/src/lib/winspool/api.def.ts new file mode 100644 index 00000000..9715632e --- /dev/null +++ b/packages/win32-api/src/lib/winspool/api.def.ts @@ -0,0 +1,103 @@ +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + + +export class DefWinspool implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + static ClosePrinter = [D.BOOL, [D.HANDLE]] + + static EndDocPrinter = [D.BOOL, [D.HANDLE]] + + static EndPagePrinter = [D.BOOL, [D.HANDLE]] + + /** + * Enumerates available printers, print servers, domains, or print providers. + * using multipleChoice to accept payload `pPrinterEnum` depends on `Level` + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprinters + */ + static EnumPrintersW = [D.BOOL, + [ + D.DWORD, + D.WString, + D.DWORD, + `_Out_ ${D.LPBYTE}`, + D.DWORD, + D.LPDWORD, + D.LPDWORD, + ]] + + /** + * Enumerates the print processors installed on the specified server. + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessors + */ + static EnumPrintProcessorsW = [D.BOOL, [D.LPTSTR, D.LPTSTR, D.DWORD, `_Out_ ${D.LPBYTE}`, D.DWORD, `_Out_ ${D.LPDWORD}`, `_Out_ ${D.LPDWORD}`]] + + /** + * Enumerates the data types that a specified print processor supports. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessordatatypes + */ + static EnumPrintProcessorDatatypesW = [D.BOOL, [D.LPTSTR, D.LPTSTR, D.DWORD, `_Out_ ${D.LPBYTE}`, D.DWORD, `_Out_ ${D.LPDWORD}`, `_Out_ ${D.LPDWORD}`]] + + /** https://learn.microsoft.com/en-us/windows/win32/printdocs/getdefaultprinter */ + static GetDefaultPrinterW = [D.BOOL, [D.LPTSTR, `_Inout_ ${D.LPDWORD}`]] + + /** + * Retrieves information about a specified print job + * https://learn.microsoft.com/en-us/windows/win32/printdocs/getjob + * @param pJob JOB_INFO_1 or a JOB_INFO_2 + */ + static GetJobW = [D.BOOL, [D.HANDLE, D.DWORD, D.DWORD, `_Out_ ${D.LPBYTE}`, D.DWORD, `_Out_ ${D.LPDWORD}`]] + + /** + * Retrieves information about a specified printer. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/getprinter + */ + static GetPrinterW = [D.BOOL, [ + D.HANDLE, + D.DWORD, + // multiple choice instead of `_Out_ ${D.LPBYTE}`, + // @TODO 2|7 + [ + `_Out_ ${S.PPRINTER_INFO_1}`, + `_Out_ ${S.PPRINTER_INFO_4}`, + `_Out_ ${S.PPRINTER_INFO_5}`, + `_Out_ ${S.PPRINTER_INFO_6}`, + `_Out_ ${S.PPRINTER_INFO_8}`, + `_Out_ ${S.PPRINTER_INFO_9}`, + ], + D.DWORD, + `_Out_ ${D.LPDWORD}`, + ]] as const // `as const` is required for multipleChoice + + /** + * Retrieves a handle to the specified printer or print server or other types of handles in the print subsystem. + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/openprinter + * @docs https://learn.microsoft.com/zh-cn/windows/win32/printdocs/openprinter + */ + static OpenPrinterW = [D.BOOL, [D.WString, `_Out_ ${D.LPHANDLE}`, S.PPRINTER_DEFAULTS]] + + /** + * Notifies the print spooler that a document is to be spooled for printing. + * @param pDocInfo A pointer to a DOC_INFO_1 structure that describes the document to print. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/startdocprinter + */ + static StartDocPrinterW = [D.DWORD, [D.HANDLE, D.DWORD, S.LPDOC_INFO_1]] + + /** + * Notifies the spooler that a page is about to be printed on the specified printer. + * @docs https://learn.microsoft.com/zh-cn/windows/win32/printdocs/startpageprinter + */ + static StartPagePrinter = [D.BOOL, [D.HANDLE]] + + /** + * Notifies the print spooler that data should be written to the specified printer. + * @note Only supports GDI printing and must not be used for XPS printing + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/writeprinter + */ + static WritePrinter = [D.BOOL, [D.HANDLE, D.LPVOID, D.DWORD, `_Out_ ${D.LPDWORD}`]] + +} + diff --git a/packages/win32-api/src/lib/winspool/api.ts b/packages/win32-api/src/lib/winspool/api.ts deleted file mode 100644 index 7b60d315..00000000 --- a/packages/win32-api/src/lib/winspool/api.ts +++ /dev/null @@ -1,169 +0,0 @@ -/* eslint-disable id-length */ -import * as M from 'win32-def' -import * as W from 'win32-def/common.def' - - -export interface Win32Fns { - - /** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/closeprinter - */ - ClosePrinter: (hPrinter: M.HANDLE) => M.BOOL - - /** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/enddocprinter - */ - EndDocPrinter: (hPrinter: M.HANDLE) => M.BOOL - - EndPagePrinter: (hPrinter: M.HANDLE) => M.BOOL - - /** - * Enumerates available printers, print servers, domains, or print providers. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprinters - */ - EnumPrintersW: ( - Flags: M.DWORD, - Name: M.LPTSTR, - Level: M.DWORD, - pPrinterEnum: M.LPBYTE, - cbBuf: M.DWORD, - pcbNeeded: M.LPDWORD, - pcReturned: M.LPDWORD, - ) => M.BOOL - - /** - * Enumerates the print processors installed on the specified server. - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/enumprintprocessors - */ - EnumPrintProcessorsW: ( - pName: M.LPTSTR, - pEnvironment: M.LPTSTR, - Level: M.DWORD, - pPrintProcessorInfo: M.LPBYTE, - cbBuf: M.DWORD, - pcbNeeded: M.LPDWORD, - pcReturned: M.LPDWORD, - ) => M.BOOL - - /** - * Enumerates the data types that a specified print processor supports. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessordatatypes - */ - EnumPrintProcessorDatatypesW: ( - pName: M.LPTSTR, - pPrintProcessorName: M.LPTSTR, - Level: M.DWORD, - pDatatypes: M.LPBYTE, - cbBuf: M.DWORD, - pcbNeeded: M.LPDWORD, - pcReturned: M.LPDWORD, - ) => M.BOOL - - /** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/getdefaultprinter - */ - GetDefaultPrinterW: ( - pszBuffer: M.LPTSTR, - pcchBuffer: M.LPDWORD, - ) => M.BOOL - - /** - * Retrieves information about a specified print job - * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/getjob - */ - GetJobW: ( - Handler: M.HANDLE, - JobId: M.DWORD, - Level: M.DWORD, - pJob: M.LPBYTE, - cbBuf: M.DWORD, - pcbNeeded: M.LPDWORD, - ) => M.BOOL - - /** - * Retrieves information about a specified printer. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinter - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/getprinter - */ - GetPrinterW: ( - hPrinter: M.HANDLE, - Level: M.DWORD, - pPrinter: M.LPBYTE, - cbBuf: M.DWORD, - pcbNeeded: M.LPDWORD, - ) => M.BOOL - - - /** - * Retrieves a handle to the specified printer or print server or other types of handles in the print subsystem. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/openprinter - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/openprinter - */ - OpenPrinterW: ( - pPrinterName: M.LPTSTR, - phPrinter: M.LPHANDLE, - pDefault: M.LPPRINTER_DEFAULTS, - ) => M.BOOL - - - /** - * Notifies the print spooler that a document is to be spooled for printing. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/startdocprinter - */ - StartDocPrinterW: ( - hPrinter: M.HANDLE, - Level: M.DWORD, - pDocInfo: M.LPBYTE, - ) => M.DWORD - - /** - * Notifies the spooler that a page is about to be printed on the specified printer. - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/startpageprinter - */ - StartPagePrinter: (hPrinter: M.HANDLE) => M.BOOL - - /** - * - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/writeprinter - */ - WritePrinter: ( - hPrinter: M.HANDLE, - pBuf: M.LPVOID, - cbBuf: M.DWORD, - pcWritten: M.LPDWORD, - ) => M.BOOL - - -} - - -export const apiDef: M.DllFuncs = { - - ClosePrinter: [W.BOOL, [W.HANDLE] ], - - EndDocPrinter: [W.BOOL, [W.HANDLE] ], - - EndPagePrinter: [W.BOOL, [W.HANDLE] ], - - EnumPrintersW: [W.BOOL, [W.DWORD, W.LPTSTR, W.DWORD, W.LPBYTE, W.DWORD, W.LPDWORD, W.LPDWORD] ], - - EnumPrintProcessorsW: [W.BOOL, [W.LPTSTR, W.LPTSTR, W.DWORD, W.LPBYTE, W.DWORD, W.LPDWORD, W.LPDWORD] ], - - EnumPrintProcessorDatatypesW: [W.BOOL, [W.LPTSTR, W.LPTSTR, W.DWORD, W.LPBYTE, W.DWORD, W.LPDWORD, W.LPDWORD] ], - - GetDefaultPrinterW: [W.BOOL, [W.LPTSTR, W.LPDWORD] ], - - GetJobW: [W.BOOL, [W.HANDLE, W.DWORD, W.DWORD, W.LPBYTE, W.DWORD, W.LPDWORD] ], - - GetPrinterW: [W.BOOL, [W.HANDLE, W.DWORD, W.LPBYTE, W.DWORD, W.LPDWORD] ], - - OpenPrinterW: [W.BOOL, [W.LPTSTR, W.LPHANDLE, W.LPRINTER_DEFAULTS] ], - - StartDocPrinterW: [W.DWORD, [W.HANDLE, W.DWORD, W.LPBYTE] ], - - StartPagePrinter: [W.BOOL, [W.HANDLE] ], - - WritePrinter: [W.BOOL, [W.HANDLE, W.LPVOID, W.DWORD, W.LPDWORD] ], - -} - diff --git a/packages/win32-api/src/lib/winspool/api.types.ts b/packages/win32-api/src/lib/winspool/api.types.ts new file mode 100644 index 00000000..3a51a68e --- /dev/null +++ b/packages/win32-api/src/lib/winspool/api.types.ts @@ -0,0 +1,172 @@ +/* c8 ignore start */ +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +import { DefWinspool } from './api.def.js' + + +export class Winspool implements T.LibDef2Type { + /** + * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/closeprinter + */ + ClosePrinter: (hPrinter: T.HANDLE) => T.BOOL + + /** + * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/enddocprinter + */ + EndDocPrinter: (hPrinter: T.HANDLE) => T.BOOL + + EndPagePrinter: (hPrinter: T.HANDLE) => T.BOOL + + /** + * Enumerates available printers, print servers, domains, or print providers. + * using `Level` to determine the type of `pPrinterEnum` + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprinters + */ + EnumPrintersW: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + // pass Buffer, then ffi.decode() to result S.EnumPrinters_Level_X_Type[] + pPrinterEnum: T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => T.BOOL + + /** + * Enumerates available printers, print servers, domains, or print providers. + * using `Level` to determine the type of `pPrinterEnum` + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprinters + * @description Asynchronous version of EnumPrintersW only for generic type `Level` + */ + EnumPrintersW_Async: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + // pass Buffer, then ffi.decode() to result S.EnumPrinters_Level_X_Type[] + pPrinterEnum: T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => Promise + + /** + * Enumerates the print processors installed on the specified server. + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessors + */ + EnumPrintProcessorsW: ( + pName: T.LPTSTR, + pEnvironment: T.LPTSTR, + Level: T.DWORD, + pPrintProcessorInfo: T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => T.BOOL + + /** + * Enumerates the data types that a specified print processor supports. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprintprocessordatatypes + */ + EnumPrintProcessorDatatypesW: ( + pName: T.LPTSTR, + pPrintProcessorName: T.LPTSTR, + Level: T.DWORD, + pDatatypes: T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => T.BOOL + + /** https://learn.microsoft.com/en-us/windows/win32/printdocs/getdefaultprinter */ + GetDefaultPrinterW: ( + pszBuffer: T.LPTSTR, + pcchBuffer: T.LPDWORD, + ) => T.BOOL + + /** + * Retrieves information about a specified print job + * @param pJob JOB_INFO_1 or a JOB_INFO_2 + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/getjob + */ + GetJobW: ( + Handler: T.HANDLE, + JobId: T.DWORD, + Level: T.DWORD, + // @TODO: JOB_INFO_2 + pJob: S.JOB_INFO_1_Type | T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => T.BOOL + + /** + * Retrieves information about a specified printer. + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter + * @docs https://learn.microsoft.com/zh-cn/windows/win32/printdocs/getprinter + */ + GetPrinterW: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pPrinter: S.PRINTER_INFO_X_Type, // multiple choice + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => T.BOOL + + /** + * Retrieves information about a specified printer. + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter + * @docs https://learn.microsoft.com/zh-cn/windows/win32/printdocs/getprinter + */ + GetPrinterW_Async: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pPrinter: S.PRINTER_INFO_X_Type, // multiple choice + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => Promise + + /** + * Retrieves a handle to the specified printer or print server or other types of handles in the print subsystem. + * @link https://leran.microsoft.com/en-us/windows/win32/printdocs/openprinter + * @link https://leran.microsoft.com/zh-cn/windows/win32/printdocs/openprinter + */ + OpenPrinterW: ( + pPrinterName: T.WString | null, + phPrinter: T.LPHANDLE, + pDefault: S.PRINTER_DEFAULTS_Type | null, + ) => T.BOOL + + + /** + * Notifies the print spooler that a document is to be spooled for printing. + * @param pDocInfo A pointer to a DOC_INFO_1 structure that describes the document to print. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/startdocprinter + */ + StartDocPrinterW: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pDocInfo: S.DOC_INFO_1_Type, + ) => T.DWORD + + /** + * Notifies the spooler that a page is about to be printed on the specified printer. + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/startpageprinter + */ + StartPagePrinter: (hPrinter: T.HANDLE) => T.BOOL + + /** + * Notifies the print spooler that data should be written to the specified printer. + * @note Only supports GDI printing and must not be used for XPS printing + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/writeprinter + */ + WritePrinter: ( + hPrinter: T.HANDLE, + pBuf: T.LPVOID, + cbBuf: T.DWORD, + pcWritten: T.LPDWORD, + ) => T.BOOL + +} + +/* c8 ignore stop */ diff --git a/packages/win32-api/src/lib/winspool/index.promise.ts b/packages/win32-api/src/lib/winspool/index.promise.ts deleted file mode 100644 index b7de00c5..00000000 --- a/packages/win32-api/src/lib/winspool/index.promise.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { FnName, LoadSettings } from 'win32-def' - -import { loadAsync as hload } from '../helper.js' -import { DllNames } from '../types.js' - -import { apiDef, Win32Fns } from './api.js' - - -export { apiDef } -export { Win32Fns } -export const dllName = DllNames.winspool -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload(dllName, apiDef, fns, settings) - diff --git a/packages/win32-api/src/lib/winspool/index.ts b/packages/win32-api/src/lib/winspool/index.ts index d8456358..209e76bc 100644 --- a/packages/win32-api/src/lib/winspool/index.ts +++ b/packages/win32-api/src/lib/winspool/index.ts @@ -1,24 +1,23 @@ -import { ExpandFnModel, FnName, LoadSettings } from 'win32-def' +import { type FLib, type LoadOptions, load as _load } from 'win32-def' -import { load as hload } from '../helper.js' -import { DllNames } from '../types.js' +import { DllNames } from '##/lib/types.js' -import { apiDef, Win32Fns } from './api.js' +import { DefWinspool } from './api.def.js' +import { Winspool } from './api.types.js' +import { multipleChoiceMapperList } from './mapper/index.mapper.js' -export { apiDef } -export { Win32Fns } +export { + DefWinspool, Winspool, +} + export const dllName = DllNames.winspool -/** - * @deprecated use promise instead - * ```ts - * import { User32 } from 'win32-api/promise' - * const user32 = User32.load() - * const hWnd = await user32.FindWindowExW(...) - * ``` - */ -export const load = ( - fns?: FnName[], - settings?: LoadSettings, -) => hload>(dllName, apiDef, fns, settings) +export type LibWinspool = FLib + +export const load = (fns?: LoadOptions['usedFuncNames']) => _load({ + dll: dllName, + dllFuncs: DefWinspool, + usedFuncNames: fns, + multipleChoiceMapperList: multipleChoiceMapperList, +}) diff --git a/packages/win32-api/src/lib/winspool/mapper/GetPrinterW.mapper.ts b/packages/win32-api/src/lib/winspool/mapper/GetPrinterW.mapper.ts new file mode 100644 index 00000000..bd7ab8ac --- /dev/null +++ b/packages/win32-api/src/lib/winspool/mapper/GetPrinterW.mapper.ts @@ -0,0 +1,34 @@ +import assert from 'assert' + +import type { FlattenNestedTuple } from '@waiting/shared-types' +import { getPRINTER_INFO_X_Ptr } from 'win32-def/struct' +import type { EnumPrinters_Level, MultipleChoiceMapper } from 'win32-def/types' + +import { DefWinspool } from '../api.def.js' +import type { Winspool } from '../api.types.js' + + +export const funcName = 'GetPrinterW' +type Func = Winspool[typeof funcName] +type Params = Parameters + +type DefFunc = typeof DefWinspool[typeof funcName] +type DefParams = FlattenNestedTuple + +export const GetPrinterW_mapper: MultipleChoiceMapper = (name, runtimeArgs, defParamsArray) => { + if (name !== funcName) { return } + const argLevel = runtimeArgs[1] as EnumPrinters_Level + const argPtr = getPRINTER_INFO_X_Ptr(argLevel) + assert(argPtr, `getPRINTER_INFO_X_Ptr(${argLevel}) failed`) + + for (const row of defParamsArray) { + assert(Array.isArray(row)) + const defPtr = row[2] as typeof argPtr + if (defPtr.endsWith(argPtr)) { + return row + } + } + // return [] // will throw Error +} + + diff --git a/packages/win32-api/src/lib/winspool/mapper/index.mapper.ts b/packages/win32-api/src/lib/winspool/mapper/index.mapper.ts new file mode 100644 index 00000000..dbc62112 --- /dev/null +++ b/packages/win32-api/src/lib/winspool/mapper/index.mapper.ts @@ -0,0 +1,11 @@ +import type { MultipleChoiceMapperList, MultipleChoiceMapperSet } from 'win32-def/types' + +import * as GetPrinterW from './GetPrinterW.mapper.js' + + +export const multipleChoiceMapperList: MultipleChoiceMapperList = new Map() +export const multipleChoiceMapperSet: MultipleChoiceMapperSet = new Set() + +multipleChoiceMapperList.set(GetPrinterW.funcName, multipleChoiceMapperSet) +multipleChoiceMapperSet.add(GetPrinterW.GetPrinterW_mapper) + diff --git a/packages/win32-api/src/util/user32/FindWindowEx.ts b/packages/win32-api/src/util/user32/FindWindowEx.ts new file mode 100644 index 00000000..cb64fc87 --- /dev/null +++ b/packages/win32-api/src/util/user32/FindWindowEx.ts @@ -0,0 +1,35 @@ +import assert from 'assert' + +import { type LibUser32, load } from '##/lib/user32/index.js' + + +const fnName: keyof LibUser32 = 'FindWindowExW' +const fnAsyncName: keyof LibUser32 = 'FindWindowExW_Async' +type FnType = LibUser32[typeof fnAsyncName] +type RetType = ReturnType +type ParamType = Parameters + +/** + * Retrieves a handle to a window whose class name and window name match the specified strings. + * The function searches child windows, beginning with the one following the specified child window. + * This function does not perform a case-sensitive search. + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindowexw + * + * 检索其类名和窗口名称与指定字符串匹配的窗口的句柄。 函数搜索子窗口,从指定子窗口后面的子窗口开始。 此函数不执行区分大小写的搜索。 + * @link https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-findwindowexw + */ +export async function FindWindowEx( + hwndParent: ParamType[0], + hwndChildAfter: ParamType[1], + lpszClass: ParamType[2], + lpszWindow: ParamType[3], +): Promise { + + const lib = load([fnName]) + const fn = lib[fnAsyncName] as FnType + assert(typeof fn === 'function', `Function "${fnAsyncName}" not found`) + + const hwnd = await fn(hwndParent, hwndChildAfter, lpszClass, lpszWindow) + return hwnd +} + diff --git a/packages/win32-api/src/util/user32/GetWindowText.ts b/packages/win32-api/src/util/user32/GetWindowText.ts new file mode 100644 index 00000000..c726bd87 --- /dev/null +++ b/packages/win32-api/src/util/user32/GetWindowText.ts @@ -0,0 +1,39 @@ +import assert from 'assert' + +import { ucsBufferToString } from 'win32-def' + +import { type LibUser32, load } from '##/lib/user32/index.js' + + +const fnName: keyof LibUser32 = 'GetWindowTextW' +const fnAsyncName: keyof LibUser32 = 'GetWindowTextW_Async' +type FnType = LibUser32[typeof fnAsyncName] +// type RetType = ReturnType +type ParamType = Parameters + +/** + * Retrieves a handle to a window whose class name and window name match the specified strings. + * The function searches child windows, beginning with the one following the specified child window. + * This function does not perform a case-sensitive search. + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowtextw + * + * 检索其类名和窗口名称与指定字符串匹配的窗口的句柄。 函数搜索子窗口,从指定子窗口后面的子窗口开始。 此函数不执行区分大小写的搜索。 + * @link https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-getwindowtextw + */ +export async function GetWindowText( + hWnd: ParamType[0], + nMaxCount: ParamType[2], +): Promise { + + const lib = load([fnName]) + const fn = lib[fnAsyncName] as FnType + assert(typeof fn === 'function', `Function "${fnAsyncName}" not found`) + + const buf = Buffer.alloc(nMaxCount * 2) + const resLength = await fn(hWnd, buf, nMaxCount) + const len2 = Math.min(resLength, nMaxCount - 1) + + const title = ucsBufferToString(buf, len2) + return title || '' +} + diff --git a/packages/win32-api/src/util/user32/user32.index.ts b/packages/win32-api/src/util/user32/user32.index.ts new file mode 100644 index 00000000..c85856a8 --- /dev/null +++ b/packages/win32-api/src/util/user32/user32.index.ts @@ -0,0 +1,4 @@ + +export * from './FindWindowEx.js' +export * from './GetWindowText.js' + diff --git a/packages/win32-api/src/util/util.index.ts b/packages/win32-api/src/util/util.index.ts new file mode 100644 index 00000000..3b59f469 --- /dev/null +++ b/packages/win32-api/src/util/util.index.ts @@ -0,0 +1,4 @@ + +export * from './user32/user32.index.js' +export * from './winspool/winspool.index.js' + diff --git a/packages/win32-api/src/util/winspool/ClosePrinter.ts b/packages/win32-api/src/util/winspool/ClosePrinter.ts new file mode 100644 index 00000000..aa450d19 --- /dev/null +++ b/packages/win32-api/src/util/winspool/ClosePrinter.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert' + +import type { HWND } from 'win32-def/types' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + + +const funcName: keyof LibWinspool = 'ClosePrinter' +// type RetType = ReturnType +// type ParamType = Parameters + + +/** + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/closeprinter + */ +export async function ClosePrinter(hwnd: HWND): Promise { + assert(hwnd, 'hwnd must be a valid handle') + + const lib = load([funcName]) + const res = await lib.ClosePrinter_Async(hwnd) + return !! res +} + diff --git a/packages/win32-api/src/util/winspool/EndDocPrinter.ts b/packages/win32-api/src/util/winspool/EndDocPrinter.ts new file mode 100644 index 00000000..997489bb --- /dev/null +++ b/packages/win32-api/src/util/winspool/EndDocPrinter.ts @@ -0,0 +1,20 @@ +import assert from 'node:assert' + +import type { HWND } from 'win32-def/types' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + + +const funcName: keyof LibWinspool = 'EndDocPrinter' + +/** + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/EndDocPrinter + */ +export async function EndDocPrinter(hwnd: HWND): Promise { + assert(hwnd, 'hwnd must be a valid handle') + + const lib = load([funcName]) + const res = await lib.EndDocPrinter_Async(hwnd) + return !! res +} + diff --git a/packages/win32-api/src/util/winspool/EnumPrinters.ts b/packages/win32-api/src/util/winspool/EnumPrinters.ts new file mode 100644 index 00000000..7b6e9399 --- /dev/null +++ b/packages/win32-api/src/util/winspool/EnumPrinters.ts @@ -0,0 +1,67 @@ +import assert from 'node:assert' + +// must use ffi from 'win32-def' +import { ffi } from 'win32-def' +import { + type EnumPrinters_Level, + type EnumPrinters_Level_X_Type, + PRINTER_INFO_X_Factory, + getPRINTER_INFO_X_Ptr, +} from 'win32-def/struct' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + +import type { EnumPrintersOptions } from './winspool.types.js' + + +const funcName: keyof LibWinspool = 'EnumPrintersW' + + +/** + * Enumerates available printers, print servers, domains, or print providers. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprinters + * + * 枚举可用的打印机、打印服务器、域或打印提供程序 + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/enumprinters + */ +export async function EnumPrinters( + options: EnumPrintersOptions, +): Promise[]> { + + const level = options.Level + + const lib = load([funcName]) + + const name = '' + // assert(level >= 1 && level <= 5, 'level must be >= 1 and <= 5') + + const cbBuf = options.cbBuf ?? 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const buf = Buffer.alloc(cbBuf) + + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + + const ret = await lib.EnumPrintersW_Async( + options.Flags, + name, + level, + buf, + cbBuf, + pcbNeeded, + pcReturned, + ) + assert(ret, 'EnumPrintersW() failed') + + PRINTER_INFO_X_Factory(level) + + const count = pcReturned.readUInt32LE() + // const pcb = pcbNeeded.readUInt32LE() + const ptr = getPRINTER_INFO_X_Ptr(level) + const key = ptr.replace(/\s*\*/u, '') // 'PRINTER_INFO_1' | 'PRINTER_INFO_2' + const decodeType = `${key}[${count}]` + + const infoArr = ffi.decode(buf, decodeType) as EnumPrinters_Level_X_Type[] + return infoArr +} + diff --git a/packages/win32-api/src/util/winspool/GetDefaultPrinter.ts b/packages/win32-api/src/util/winspool/GetDefaultPrinter.ts new file mode 100644 index 00000000..549504eb --- /dev/null +++ b/packages/win32-api/src/util/winspool/GetDefaultPrinter.ts @@ -0,0 +1,39 @@ +import assert from 'node:assert' + +import { ucsBufferToString } from 'win32-def' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + + +const funcName: keyof LibWinspool = 'GetDefaultPrinterW' + + +/** + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/getdefaultprinter + */ +export async function GetDefaultPrinter(maxNameLength = 256): Promise { + const lib = load([funcName]) + + assert(maxNameLength > 2, 'maxNameLength must be greater than 2') + + const len = maxNameLength + 1 + + const pszBuf = Buffer.alloc(len * 2) + const pcchBuf = Buffer.alloc(4) + pcchBuf.writeUint32LE(len) + + const ret = await lib.GetDefaultPrinterW_Async(pszBuf, pcchBuf) + if (! ret) { + // throw new Error('GetDefaultPrinterW() failed. May maxNameLength be too small?') + return null + } + + const pcch = pcchBuf.readUInt32LE() + if (pcch > 0) { + const size = pcch - 1 + const psz = ucsBufferToString(pszBuf, size) + return psz + } + return '' +} + diff --git a/packages/win32-api/src/util/winspool/GetPrinter.ts b/packages/win32-api/src/util/winspool/GetPrinter.ts new file mode 100644 index 00000000..18137835 --- /dev/null +++ b/packages/win32-api/src/util/winspool/GetPrinter.ts @@ -0,0 +1,42 @@ +import type { PRINTER_INFO_LEVEL, PRINTER_INFO_X_Type } from 'win32-def/struct' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + +import type { GetPrinterOptions } from './winspool.types.js' + + +const funcName: keyof LibWinspool = 'GetPrinterW' +// type RetType = ReturnType +// type ParamType = Parameters + + +/** + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/getprinter + */ +export async function GetPrinter(options: GetPrinterOptions): Promise | null> { + const { hPrinter, Level, maxLength = 1024 } = options + + const lib = load([funcName]) + + const pPrinter = {} as PRINTER_INFO_X_Type + const cbBuf = (maxLength + 1) * 2 + const pcbNeeded = Buffer.alloc(8) + + const ret = await lib.GetPrinterW_Async( + hPrinter, + Level, + pPrinter, + cbBuf, + pcbNeeded, + ) + const pcb = pcbNeeded.readUInt32LE() + if (! ret) { + if (pcb > maxLength) { + throw new Error(`maxLength is too small, increase to value grater than ${pcb}`) + } + return null + } + + return pPrinter +} + diff --git a/packages/win32-api/src/util/winspool/OpenPrinter.ts b/packages/win32-api/src/util/winspool/OpenPrinter.ts new file mode 100644 index 00000000..137a633b --- /dev/null +++ b/packages/win32-api/src/util/winspool/OpenPrinter.ts @@ -0,0 +1,30 @@ +import type { HWND } from 'win32-def/types' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + + +const funcName: keyof LibWinspool = 'OpenPrinterW' +// type RetType = ReturnType +// type ParamType = Parameters + + +/** + * Retrieves a handle to the specified printer or print server or other types of handles in the print subsystem + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/openprinter + * + * 检索指定打印机或打印服务器或打印子系统中其他类型的句柄的句柄 + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/openprinter + */ +export async function OpenPrinter(printerName: string): Promise { + const lib = load([funcName]) + + const buf = Buffer.alloc(8) + const res = await lib.OpenPrinterW_Async(printerName, buf, null) + if (! res) { + return null + } + // const hwnd = ffi.address(buf) + const hwnd = buf.readBigUInt64LE() + return hwnd +} + diff --git a/packages/win32-api/src/util/winspool/StartDocPrinter.ts b/packages/win32-api/src/util/winspool/StartDocPrinter.ts new file mode 100644 index 00000000..06c07e18 --- /dev/null +++ b/packages/win32-api/src/util/winspool/StartDocPrinter.ts @@ -0,0 +1,30 @@ +import assert from 'node:assert' + +import { load, LibWinspool } from '##/lib/winspool/index.js' + +import type { StartDocPrinterOptions } from './winspool.types.js' + + +const funcName: keyof LibWinspool = 'StartDocPrinterW' + + +/** + * Notifies the print spooler that a document is to be spooled for printing + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/StartDocPrinter + * + * 函数通知打印后台处理程序文档将进行假脱机打印 + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/StartDocPrinter + */ +export async function StartDocPrinter(options: StartDocPrinterOptions): Promise { + const { hPrinter, pDocInfo } = options + assert(hPrinter, 'hPrinter must be a valid handle') + assert(pDocInfo, 'pDocInfo must be a valid') + // assert(Buffer.isBuffer(pDocInfo), 'pDocInfo must be a valid pointer (Buffer)') + + const lib = load([funcName]) + + const Level = 1 + const ret = await lib.StartDocPrinterW_Async(hPrinter, Level, pDocInfo) + return !! ret +} + diff --git a/packages/win32-api/src/util/winspool/winspool.index.ts b/packages/win32-api/src/util/winspool/winspool.index.ts new file mode 100644 index 00000000..ff006192 --- /dev/null +++ b/packages/win32-api/src/util/winspool/winspool.index.ts @@ -0,0 +1,10 @@ + +export * from './winspool.types.js' +export * from './ClosePrinter.js' +export * from './EndDocPrinter.js' +export * from './EnumPrinters.js' +export * from './GetDefaultPrinter.js' +export * from './GetPrinter.js' +export * from './OpenPrinter.js' +export * from './StartDocPrinter.js' + diff --git a/packages/win32-api/src/util/winspool/winspool.types.ts b/packages/win32-api/src/util/winspool/winspool.types.ts new file mode 100644 index 00000000..53e7d6bf --- /dev/null +++ b/packages/win32-api/src/util/winspool/winspool.types.ts @@ -0,0 +1,38 @@ +import type { DOC_INFO_1_Type } from 'win32-def/struct' +import type { + EnumPrinters_Level, + HANDLE, + PRINTER_INFO_LEVEL, +} from 'win32-def/types' + + +export interface EnumPrintersOptions { + Level: Level + /** + * PrinterEnumFlags + * @see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/2a1fe8a4-e8be-4cf3-8b37-8d19f9a2edcd + */ + Flags: number + Name?: string + /** + * @default 4096 + */ + cbBuf?: number +} + + +export interface GetPrinterOptions { + hPrinter: HANDLE + Level: Level + /** + * @default 1024 + */ + maxLength?: number +} + + +export interface StartDocPrinterOptions { + hPrinter: HANDLE + pDocInfo: DOC_INFO_1_Type +} + diff --git a/packages/win32-api/test/10.index.comctl32.test.ts b/packages/win32-api/test/10.index.comctl32.test.ts deleted file mode 100644 index 22d322af..00000000 --- a/packages/win32-api/test/10.index.comctl32.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - apiDef, - dllName, - load, -} from '../src/index.comctl32.js' - - -describe(fileShortPath(import.meta.url), () => { - it('Should exports work', () => { - assert(dllName === 'comctl32') - assert(Object.keys(apiDef).length > 0) - assert(typeof load === 'function') - }) -}) - diff --git a/packages/win32-api/test/11.index.kernel32.test.ts b/packages/win32-api/test/11.index.kernel32.test.ts deleted file mode 100644 index e96fb4c8..00000000 --- a/packages/win32-api/test/11.index.kernel32.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - apiDef, - dllName, - load, -} from '../src/index.kernel32.js' - - -describe(fileShortPath(import.meta.url), () => { - it('Should exports work', () => { - assert(dllName === 'kernel32') - assert(Object.keys(apiDef).length > 0) - assert(typeof load === 'function') - }) -}) - diff --git a/packages/win32-api/test/12.index.ntdll.test.ts b/packages/win32-api/test/12.index.ntdll.test.ts deleted file mode 100644 index 985b353a..00000000 --- a/packages/win32-api/test/12.index.ntdll.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - apiDef, - dllName, - load, -} from '../src/index.ntdll.js' - - -describe(fileShortPath(import.meta.url), () => { - it('Should exports work', () => { - assert(dllName === 'ntdll') - assert(Object.keys(apiDef).length > 0) - assert(typeof load === 'function') - }) -}) - diff --git a/packages/win32-api/test/13.index.user32.test.ts b/packages/win32-api/test/13.index.user32.test.ts deleted file mode 100644 index 3e6335da..00000000 --- a/packages/win32-api/test/13.index.user32.test.ts +++ /dev/null @@ -1,19 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - apiDef, - dllName, - load, -} from '../src/index.user32.js' - - -describe(fileShortPath(import.meta.url), () => { - it('Should exports work', () => { - assert(dllName === 'user32') - assert(Object.keys(apiDef).length > 0) - assert(typeof load === 'function') - }) -}) - diff --git a/packages/win32-api/test/21.main.test.ts b/packages/win32-api/test/21.main.test.ts deleted file mode 100644 index 2f8b2b47..00000000 --- a/packages/win32-api/test/21.main.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import assert from 'node:assert/strict' -import fs from 'node:fs' -import { join, normalize } from 'node:path' - -import { fileShortPath, genCurrentDirname } from '@waiting/shared-core' - -import { - DModel as M, - DTypes as W, - DStruct as DS, -} from '../src/index.js' -import * as Win from '../src/index.js' - - -const __dirname = genCurrentDirname(import.meta.url) -// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -const dllDir = normalize(join(__dirname, '/../src/lib/')) -const dlls: string[] = [] - -for (const key of fs.readdirSync(dllDir)) { - const dll = normalize(dllDir + key) - const stat = fs.statSync(dll) - if (stat.isDirectory()) { - dlls.push(key) - } -} - -describe(fileShortPath(import.meta.url), () => { - - for (const dll of dlls) { - const apiName: string = dll.slice(0, 1).toUpperCase() + dll.slice(1).toLowerCase() // User32, Kernel32, ... - console.log({ apiName }) - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const module = Win[apiName] - assert(module, `${apiName} is not found`) - - describe(apiName, () => { - - it('normal', async () => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - const api = module.load() as M.DllFuncs - - for (const fn in api) { - if (! {}.hasOwnProperty.call(api, fn)) { - continue - } - it(`Should ${fn}() be typeof "function"`, () => { - assert(typeof api[fn] === 'function', `${fn}`) - }) - } - } - else { - assert(false, 'module or module.apiDef invalie') - } - }) - }) - } -}) - diff --git a/packages/win32-api/test/70.user32.test.ts b/packages/win32-api/test/70.user32.test.ts deleted file mode 100644 index 09b569f7..00000000 --- a/packages/win32-api/test/70.user32.test.ts +++ /dev/null @@ -1,179 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ffi from 'ffi-napi' -import { sleep } from 'zx' - -import { - user32FindWindowEx, - user32GetWindowText, -} from '../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - retrieveStructFromPtrAddress, - StructFactory, - ucsBufferFrom, - ucsBufferToString, -} from '../src/index.js' - -import { calcLpszClassNotepad, calcLpszNotepad } from './config.unittest.js' -import { assertsHwnd, user32, user32Sync } from './helper.js' - - -const tmpMap = new Map() -const title = 'new-title-' + Math.random().toString() - -describe(fileShortPath(import.meta.url), () => { - - describe('find app window by user32.EnumWindows()', () => { - it('await', async () => { - const child = spawn('notepad.exe') - const enumWindowsProc = createEnumWinProc() - - console.log(new Date().toLocaleTimeString()) - await sleep(3000) - console.log(new Date().toLocaleTimeString()) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assert(hWnd) - assertsHwnd(hWnd) - - // Change title of the Calculator - await user32.SetWindowTextW(hWnd, ucsBufferFrom(title)) - - const len = title.length - assert(len > 0) - - const text = await user32GetWindowText(hWnd, len) - assert(text && text === title, `title should be changed to ${title}, bug got ${text ?? 'n/a'}`) - - const point = StructFactory(DS.POINT) - point.x = 101 - point.y = Math.round(Math.random() * 1000000) - - const address = point.ref().address() - tmpMap.delete(address) - - await enumWindows(enumWindowsProc, address) - console.log({ address }) - - const point2 = tmpMap.get(address) - assert(point2, 'point2 should be got') - if (point2) { - assert(point.x === point2.x) - assert(point.y === point2.y) - } - tmpMap.delete(address) - - child.kill() - console.log({ killed: child.killed }) - console.log(new Date().toLocaleTimeString()) - }) - - it('sync', async () => { - const child = spawn('notepad.exe') - const enumWindowsProc = createEnumWinProc() - - console.log(new Date().toLocaleTimeString()) - await sleep(3000) - console.log(new Date().toLocaleTimeString()) - - const hWnd = user32Sync.FindWindowExW(0, 0, calcLpszClassNotepad, null) - assertsHwnd(hWnd) - - // Change title of the Calculator - user32Sync.SetWindowTextW(hWnd, ucsBufferFrom(title)) - - const len = title.length + 1 - assert(len > 0) - const buf = Buffer.alloc(len * 2) - let str = '' - - user32Sync.GetWindowTextW(hWnd, buf, len) - str = ucsBufferToString(buf) - assert(str === title, `title should be changed to ${title}, bug got ${str}`) - - const point = StructFactory(DS.POINT) - point.x = 101 - point.y = Math.round(Math.random() * 1000000) - - const address = point.ref().address() - tmpMap.delete(address) - - await enumWindows(enumWindowsProc, address) - console.log({ address }) - - const point2 = tmpMap.get(address) - assert(point2, 'point2 should be got') - if (point2) { - assert(point.x === point2.x) - assert(point.y === point2.y) - } - tmpMap.delete(address) - - child.kill() - console.log({ killed: child.killed }) - console.log(new Date().toLocaleTimeString()) - }) - - }) -}) - - -/** - * Note: It will got "errno 3221225725" - * if calling frequently in a short time - */ -function createEnumWinProc(): M.WNDENUMPROC { - const enumWindowsProc = ffi.Callback( - W.BOOL, - [W.HWND, W.LPARAM], - (hWnd: M.HWND, lParam: M.LPARAM): M.BOOLEAN => { - const visible = user32Sync.IsWindowVisible(hWnd) - if (! visible) { - return true - } - - const maxLen = 127 - const buf = Buffer.alloc(maxLen * 2) - const len = user32Sync.GetWindowTextW(hWnd, buf, maxLen) - const name = ucsBufferToString(buf) - name && console.log(name, len) - - if (len && name === title) { - if (typeof lParam === 'number') { - const point = retrieveStructFromPtrAddress(lParam, DS.POINT) - if (point) { - console.log({ px: point.x, py: point.y }) - tmpMap.set(lParam, point) - } - } - else { - console.warn('lParam is not number') - } - return false // stop loop if return false - } - - return true - }, - ) - - process.on('exit', () => { - typeof enumWindowsProc // avoid gc - }) - - return enumWindowsProc -} - - -// function enumWindows(proc: M.WNDENUMPROC, id: M.UINT32): void { -// user32Sync.EnumWindows(proc, id) -// } - -function enumWindows(proc: M.WNDENUMPROC, id: M.UINT32): Promise { - return user32.EnumWindows(proc, id) -} - diff --git a/packages/win32-api/test/71.find-calc-async.test.ts b/packages/win32-api/test/71.find-calc-async.test.ts deleted file mode 100644 index b4ebeacc..00000000 --- a/packages/win32-api/test/71.find-calc-async.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { spawn } from 'child_process' -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { sleep } from 'zx' - -import { user32FindWindowEx } from '../src/index.fun.js' -import { ucsBufferFrom, ucsBufferToString } from '../src/index.js' -import * as UP from '../src/index.user32.js' - -import { calcLpszWindow } from './config.unittest.js' -import { assertsHwnd, user32, user32Sync } from './helper.js' - - -describe.skip(fileShortPath(import.meta.url), () => { - - describe('Should FindWindowExW() work', () => { - it('find window hWnd via await', async () => { - const child = spawn('calc.exe') - - console.log(new Date().toLocaleTimeString()) - await sleep(2000) - console.log(new Date().toLocaleTimeString()) - - const hWnd = await user32FindWindowEx(0, 0, null, calcLpszWindow) - assertsHwnd(hWnd) - child.kill() - }) - - it('find window hWnd via callback async', async () => { - const child = spawn('calc.exe') - - console.log(new Date().toLocaleTimeString()) - await sleep(2000) - console.log(new Date().toLocaleTimeString()) - - await new Promise((done) => { - const buf = ucsBufferFrom(calcLpszWindow) - user32Sync.FindWindowExW.async(0, 0, null, buf, (err, hWnd) => { - if (err) { - assert(false, err.message) - } - - assertsHwnd(hWnd) - child.kill() - done() - }) - }) - }) - - - it('change window title', async () => { - const child = spawn('calc.exe') - await sleep(2000) - await findNSetWinTitleAsync() - }) - - it('change window title with partial loading', async () => { - const child = spawn('calc.exe') - await sleep(2000) - await findNSetWinTitleAsyncPartial() - }) - - }) -}) - - -async function findNSetWinTitleAsync(): Promise { - const title = 'Node-Calculator' - const len = title.length - const hWnd = await user32.FindWindowExW(0, 0, null, ucsBufferFrom(calcLpszWindow)) - - assertsHwnd(hWnd) - const ret = await user32.SetWindowTextW(hWnd, ucsBufferFrom(title)) - assert(ret, 'SetWindowTextW() failed') - - const buf = Buffer.alloc(len * 2) - await user32.GetWindowTextW(hWnd, buf, len + 1) - const str = ucsBufferToString(buf) - assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`) -} - - -async function findNSetWinTitleAsyncPartial(): Promise { - const u32 = UP.load(['FindWindowExW', 'SetWindowTextW']) - - const title = 'Node-Calculator' - const len = title.length - const hWnd = await u32.FindWindowExW(0, 0, null, ucsBufferFrom(calcLpszWindow)) - - assertsHwnd(hWnd) - // Change title of the Calculator - await u32.SetWindowTextW(hWnd, ucsBufferFrom(title)) - - const buf = Buffer.alloc(len * 2) - await u32.GetWindowTextW(hWnd, buf, len + 1) - const str = ucsBufferToString(buf) - assert(str === title, `title should be changed to ${title}, bug got ${str}`) -} - diff --git a/packages/win32-api/test/72.find-notepad-async.test.ts b/packages/win32-api/test/72.find-notepad-async.test.ts deleted file mode 100644 index 3c092de9..00000000 --- a/packages/win32-api/test/72.find-notepad-async.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { spawn } from 'child_process' -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { sleep } from 'zx' - -import { user32FindWindowEx } from '../src/index.fun.js' -import { ucsBufferToString, ucsBufferFrom } from '../src/index.js' -import * as UP from '../src/index.user32.js' - -import { calcLpszClassNotepad, calcLpszNotepad } from './config.unittest.js' -import { assertsHwnd, destroyWin, user32, user32Sync } from './helper.js' - - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should FindWindowExW() work', () => { - it('find window hWnd via await', async () => { - const child = spawn('notepad.exe') - - console.log(new Date().toLocaleTimeString()) - await sleep(2000) - console.log(new Date().toLocaleTimeString()) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - await destroyWin(hWnd) - child.kill() - }) - - it.skip('find window hWnd via callback async', async () => { - const child = spawn('notepad.exe') - - console.log(new Date().toLocaleTimeString()) - await sleep(2000) - console.log(new Date().toLocaleTimeString()) - - await new Promise((done) => { - user32Sync.FindWindowExW.async(0, 0, null, calcLpszClassNotepad, (err, hWnd) => { - if (err) { - assert(false, err.message) - } - - assertsHwnd(hWnd) - child.kill() - done() - }) - }) - }) - - - it('change window title', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - await findNSetWinTitleAsync() - child.kill() - }) - - it('change window title with partial loading', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - await findNSetWinTitleAsyncPartial() - child.kill() - }) - - }) -}) - - -async function findNSetWinTitleAsync(): Promise { - const title = 'Node-Notepad' + Math.random().toString() - const len = title.length - const size = len + 1 - const hWnd = await user32.FindWindowExW(0, 0, calcLpszClassNotepad, null) - - assertsHwnd(hWnd) - const ret = await user32.SetWindowTextW(hWnd, ucsBufferFrom(title)) - assert(ret, 'SetWindowTextW() failed') - - const buf = Buffer.alloc(size * 2) - await user32.GetWindowTextW(hWnd, buf, size) - const str = buf.toString('ucs2').replace(/\0+$/u, '') - assert(str === title.trim(), `title should be changed to "${title}", bug got "${str}"`) -} - - -async function findNSetWinTitleAsyncPartial(): Promise { - const u32 = UP.load(['FindWindowExW', 'SetWindowTextW']) - - const title = 'Node-Notepad' + Math.random().toString() - const len = title.length - const size = len + 1 - const hWnd = await u32.FindWindowExW(0, 0, calcLpszClassNotepad, null) - - assertsHwnd(hWnd) - // Change title of the Calculator - await u32.SetWindowTextW(hWnd, ucsBufferFrom(title)) - - const buf = Buffer.alloc(size * 2) - await u32.GetWindowTextW(hWnd, buf, size) - const str = ucsBufferToString(buf) - assert(str === title, `title should be changed to ${title}, bug got ${str}`) -} - diff --git a/packages/win32-api/test/80.misc.test.ts b/packages/win32-api/test/80.misc.test.ts deleted file mode 100644 index 5ead7f27..00000000 --- a/packages/win32-api/test/80.misc.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../src/index.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('Should ref-struct-di initialized correctly', () => { - const point = StructFactory(DS.POINT) - point.x = 100 - point.y = 200 - - assert(point.x === 100) - assert(point.y === 200) - assert(Buffer.isBuffer(point.ref())) - }) - -}) - diff --git a/packages/win32-api/test/81.constants.test.ts b/packages/win32-api/test/81.constants.test.ts deleted file mode 100644 index 1388ea66..00000000 --- a/packages/win32-api/test/81.constants.test.ts +++ /dev/null @@ -1,30 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import * as CS from '../src/index.consts.js' -import { MN_GETHMENU } from '../src/index.consts.js' -import { Constants } from '../src/index.js' - - -describe(fileShortPath(import.meta.url), () => { - describe('Should Constants exported correctly', () => { - it('Constants.MN_GETHMENU', () => { - assert(CS.MN_GETHMENU === 481) - assert(Constants.MN_GETHMENU === 481) - assert(MN_GETHMENU === 481) - }) - - it('Constants.WM_QUIT', () => { - assert(CS.WM_QUIT === 18) - assert(Constants.WM_QUIT === 18) - }) - - it('Constants.WM_COPYDATA', () => { - assert(CS.WM_COPYDATA === 74) - assert(Constants.WM_COPYDATA === 74) - }) - }) - -}) - diff --git a/packages/win32-api/test/90.loop-callback.test.ts b/packages/win32-api/test/90.loop-callback.test.ts deleted file mode 100644 index ddf1a71f..00000000 --- a/packages/win32-api/test/90.loop-callback.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { sleep } from 'zx' - -import { - DModel as M, - DTypes as W, - DStruct as DS, -} from '../src/index.js' - -import { - changeTitle, - createWindow, - createWndProc, - destroyWin, -} from './helper.js' - - -// skip due to timout -// Note: may crash -describe.skip(fileShortPath(import.meta.url), () => { - - it('Should WndProc works at more loops', async () => { - const loops = 8 - const titlePrefix = `win32-api-${Math.random().toString()}-` - const wndProc: M.WNDPROC = createWndProc() - - const hWnd = await createWindow(wndProc) - await sleep(3000) - assert(hWnd) - const start = new Date().getTime() - - for (let i = 0; i < loops; i += 1) { - assert(i + 1 <= loops, `index(${i}) exceed loops(${loops})`) - const newTitle = titlePrefix + i.toString() - const title2 = await changeTitle(hWnd, newTitle) - assert(title2 === newTitle, `title should be changed to "${newTitle}", bug got "${title2}"`) - await sleep(300) - } - const end = new Date().getTime() - const delta = end - start - console.info(`elp ${delta}ms at ${loops} loops`) - typeof wndProc // avoid gc - - await destroyWin(hWnd) - }) -}) - diff --git a/packages/win32-api/test/config.unittest.ts b/packages/win32-api/test/config.unittest.ts index 1bc1cbbe..a64c132a 100644 --- a/packages/win32-api/test/config.unittest.ts +++ b/packages/win32-api/test/config.unittest.ts @@ -9,7 +9,7 @@ export const calcLpszClass = Buffer.from('CalcFrame\0', 'ucs2') // export const calcLpszWindow = Buffer.from('Calculator\0', 'ucs2') // export const calcLpszWindowNotepad = Buffer.from('Notepad\0', 'ucs2') export const calcLpszWindow = isWinChinese ? '计算器' : 'Calculator' -export const calcLpszWindowNotepad = isWinChinese ? '记事本' : 'Notepad' +export const calcLpszWindowNotepad = isWinChinese ? '无标题 - 记事本' : 'Notepad' export const calcLpszClassNotepad = Buffer.from('Notepad\0', 'ucs2') export const calcLpszClassNotepadEdit = Buffer.from('Edit\0', 'ucs2') diff --git a/packages/win32-api/test/foo1.ts.bak b/packages/win32-api/test/foo1.ts.bak new file mode 100644 index 00000000..8a8b6e9b --- /dev/null +++ b/packages/win32-api/test/foo1.ts.bak @@ -0,0 +1,73 @@ +import { resolve } from 'node:path' + +import koffi from 'koffi' + + +const user32 = koffi.load('user32.dll') + +// const FindW = lib.func('__stdcall', 'FindWindowW', 'int', ['str', 'str']) +// const FindW = user32.func('FindWindowW', 'int', ['str', 'str']) + +// // let ret = FindW('Calculator', '') +// let ret = FindW('Chrome_WidgetWin_1', null) + +// console.log('ret', ret) + + +const DWORD = koffi.alias('DWORD', 'uint32_t') +const HANDLE = koffi.pointer('HANDLE', koffi.opaque()) +const HWND = koffi.alias('HWND', HANDLE) + +const FindWindowEx = user32.func('HWND FindWindowExW(HWND hWndParent, HWND hWndChildAfter, const char16_t *lpszClass, const char16_t *lpszWindow)') +// const FindWindowEx = user32.func('__stdcall', 'FindWindowW', 'int', ['int', 'int', 'str', 'str']) + +const GetWindowThreadProcessId = user32.func('DWORD __stdcall GetWindowThreadProcessId(HWND hWnd, _Out_ DWORD *lpdwProcessId)') + +// GetWindowTextW: [W.INT, [W.HWND, W.LPTSTR, W.INT] ], +const GetWindowText = user32.func('int __stdcall GetWindowTextW(HWND hWnd, _Out_ uint16_t *lpString, int nMaxCount)') + +for (let hwnd = null; ;) { + // hwnd = FindWindowEx(0, hwnd, 'Chrome_WidgetWin_1', null) + // hwnd = FindWindowEx(0, hwnd, 'Notepad', null) + // hwnd = FindWindowEx(0, hwnd, 'ApplicationFrameWindow', null) + hwnd = FindWindowEx(0, hwnd, null, '计算器') + if (! hwnd) { + console.log('No more windows') + break + } + console.log({ hwnd }) + + // Get PID + let pid + const ptr = [null] + const tid = GetWindowThreadProcessId(hwnd, ptr) + if (! tid) { + // Maybe the process ended in-between? + continue + } + pid = ptr[0] + // Get window title + + let title + const buf = Buffer.alloc(1024) + // const buf = Buffer.allocUnsafe(128) + const length = GetWindowText(hwnd, buf, buf.length) + if (! length) { + // Maybe the process ended in-between? + continue + } + + // split buf at first null byte + const txt = buf.toString('ucs2', 0, length * 2) + + // const txt = buf.toString('ucs2') + // .replace(/\0+/ug, '').trim() + // .replace(/\s+/ug, ' ') + // console.log(txt) + + // convert buf to utf8 string + + title = koffi.decode(buf, 'char', length) + console.log({ tid, PID: pid, Title: txt, length }) + +} diff --git a/packages/win32-api/test/foo2.ts.bak b/packages/win32-api/test/foo2.ts.bak new file mode 100644 index 00000000..c5f900ab --- /dev/null +++ b/packages/win32-api/test/foo2.ts.bak @@ -0,0 +1,56 @@ +import koffi from 'koffi' + + +const user32 = koffi.load('user32.dll') + +// const FindWindowEx = user32.func('FindWindowExW', 'int', ['int', 'int', 'str16', 'str16']) +// const FindWindowEx = user32.func('FindWindowExW', 'int', ['int', 'int', 'int16*', 'int16*']) +const FindWindowEx = user32.func('FindWindowExW', 'int', ['int', 'int', 'int16_t*', 'int16*']) +const GetWindowThreadProcessId = user32.func('GetWindowThreadProcessId', 'int', ['int', 'int16*']) +const GetWindowTextW = user32.func('GetWindowTextW', 'int', ['int', 'uint16*', 'int']) +// const GetWindowTextW = user32.func('GetWindowTextW', 'int', ['int', 'str16', 'int']) + +for (let hwnd = 0; ;) { + // hwnd = FindWindowEx(0, hwnd, 'Chrome_WidgetWin_1', null) + // hwnd = FindWindowEx(0, hwnd, 'Notepad', null) + // hwnd = FindWindowEx(0, hwnd, Buffer.from('Notepad', 'ucs2'), null) + // hwnd = FindWindowEx(0, hwnd, Buffer.from('Notepad', 'ucs2'), '无标题 - 记事本') + // hwnd = FindWindowEx(0, hwnd, Buffer.from('Notepad', 'ucs2'), Buffer.from('无标题 - 记事本', 'ucs2')) + // hwnd = FindWindowEx(0, hwnd, 'Notepad', '无标题 - 记事本') + // hwnd = FindWindowEx(0, hwnd, 'ApplicationFrameWindow', null) + hwnd = FindWindowEx(0, hwnd, 'ApplicationFrameWindow', '计算器') + // hwnd = FindWindowEx(0, hwnd, null, '计算器') + + // hwnd = await new Promise((resolve, reject) => { + // FindWindowEx.async(0, hwnd, Buffer.from('Notepad', 'ucs2'), Buffer.from('无标题 - 记事本', 'ucs2'), (err, ret) => { + // if (err) { reject(err) } + // else { resolve(ret) } + // }) + // }) + + if (! hwnd) { + console.log('No more windows') + break + } + + const ptr = Buffer.alloc(8) + const tid = GetWindowThreadProcessId(hwnd, ptr) + if (! tid) { + // Maybe the process ended in-between? + continue + } + const pid = ptr.readUInt32LE() + + let title + // const buf2 = Buffer.alloc(1024) + const buf = Buffer.allocUnsafe(1024) + const length = GetWindowTextW(hwnd, buf, buf.length) + if (! length) { + // Maybe the process ended in-between? + continue + } + + const txt = buf.toString('ucs2', 0, length * 2) + + console.log({ hwnd, tid, PID: pid, Title: txt, length }) +} diff --git a/packages/win32-api/test/gdi32/201.CreateCompatibleDC.test.ts b/packages/win32-api/test/gdi32/201.CreateCompatibleDC.test.ts deleted file mode 100644 index 3f2d275d..00000000 --- a/packages/win32-api/test/gdi32/201.CreateCompatibleDC.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { sleep } from 'zx' - -import * as CS from '../../src/index.consts.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { gdi32 } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should CreateCompatibleDC() work', () => { - it('normal', async () => { - const hdc = await gdi32.CreateCompatibleDC(0) - console.log({ hdc }) - assert(hdc) - }) - }) -}) - diff --git a/packages/win32-api/test/gdi32/202.CreateCompatibleBitmap.test.ts b/packages/win32-api/test/gdi32/202.CreateCompatibleBitmap.test.ts deleted file mode 100644 index e928c25e..00000000 --- a/packages/win32-api/test/gdi32/202.CreateCompatibleBitmap.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { assertsHwnd, gdi32 } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should CreateCompatibleBitmap() work', () => { - it('normal', async () => { - const hdc = await gdi32.CreateCompatibleDC(0) - assert(hdc) - - const hBitmap = await gdi32.CreateCompatibleBitmap(hdc, 100, 100) - console.log({ hBitmap }) - assertsHwnd(hBitmap) - }) - }) -}) - diff --git a/packages/win32-api/test/helper.ts b/packages/win32-api/test/helper.ts.bak similarity index 98% rename from packages/win32-api/test/helper.ts rename to packages/win32-api/test/helper.ts.bak index b80c4314..50188f81 100644 --- a/packages/win32-api/test/helper.ts +++ b/packages/win32-api/test/helper.ts.bak @@ -2,14 +2,14 @@ import assert from 'node:assert' import { genCurrentDirname } from '@waiting/shared-core' -import ffi from 'ffi-napi' +import ffi from 'koffi' import ref from 'ref-napi' import StructDi from 'ref-struct-di' import UnionDi from 'ref-union-di' import { $ } from 'zx' import { - DModel as M, + Types as M, DTypes as W, DStruct as DS, K, @@ -39,6 +39,7 @@ export const winspool = Winspool.load() /** WndProc */ export function createWndProc(): M.WNDPROC { + // @ts-expect-error const WndProc = ffi.Callback( W.UINT32, [W.HWND, W.UINT, W.WPARAM, W.LPARAM], diff --git a/packages/win32-api/test/helper/91.gen_api_opts.test.ts b/packages/win32-api/test/helper/91.gen_api_opts.test.ts deleted file mode 100644 index 1c68062d..00000000 --- a/packages/win32-api/test/helper/91.gen_api_opts.test.ts +++ /dev/null @@ -1,60 +0,0 @@ -import assert from 'node:assert/strict' -import fs from 'node:fs' -import { join, normalize } from 'node:path' - -import { fileShortPath, genCurrentDirname } from '@waiting/shared-core' - -import * as Win from '../../src/index.js' -import { DModel as M } from '../../src/index.js' -import * as H from '../../src/lib/helper.js' - - -const __dirname = genCurrentDirname(import.meta.url) -// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -const dllDir = normalize(join(__dirname, '../../src/lib/')) -const dlls: string[] = [] - -for (const key of fs.readdirSync(dllDir)) { - const stat = fs.statSync(normalize(dllDir + key)) - if (stat.isDirectory()) { - dlls.push(key) - } -} - -describe(fileShortPath(import.meta.url), () => { - for (const dll of dlls) { - const apiName: string = dll.slice(0, 1).toUpperCase() + dll.slice(1).toLowerCase() // User32, Kernel32, ... - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const module = Win[apiName] - assert(module) - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - const api = module.apiDef as M.DllFuncs - assert(api) - let n = 0 - - for (const fn in api) { - if (! {}.hasOwnProperty.call(api, fn)) { - continue - } - n += 1 - } - - it(`Should ${apiName} number of fns equal to the number of fns return by gen_api_opts`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api) - const keysize = Object.keys(fns).length - - assert(typeof fns === 'object' && fns, 'fns return by gen_api_opts() not object') - assert(keysize === n, `the items of fns ${keysize} not equal to the ${n} numbers of item of the Win.${apiName}`) - }) - - } - else { - assert(false, 'module or module.apiDef invalie') - } - - } -}) - diff --git a/packages/win32-api/test/helper/92.comctl32.helper.gen_api_opts.test.ts b/packages/win32-api/test/helper/92.comctl32.helper.gen_api_opts.test.ts deleted file mode 100644 index 6cb35fb9..00000000 --- a/packages/win32-api/test/helper/92.comctl32.helper.gen_api_opts.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { DModel as M } from '../../src/index.js' -import * as Win from '../../src/index.js' -import * as H from '../../src/lib/helper.js' - - -describe(fileShortPath(import.meta.url), () => { - const apiName = 'Comctl32' - const module: any = Win[apiName] - const fn = 'InitCommonControlsEx' - const fakeFn = fn + Math.random().toString() - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const api: M.DllFuncs = module.apiDef - assert(api) - - it(`Should ${apiName} gen_api_opts(["${fn}"]) correctly`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fn]) - - const keysize = Object.keys(fns).length - - assert(keysize === 1) - assert(typeof fns[fn] === 'object' && fns[fn]) - }) - - it(`Should ${apiName} gen_api_opts(["${fakeFn}"]) return none`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fakeFn]) - const keysize = Object.keys(fns).length - - assert(keysize === 0) - assert(typeof fns[fakeFn] === 'undefined') - }) - } - else { - assert(false, 'module or module.apiDef invalie') - } -}) - diff --git a/packages/win32-api/test/helper/93.kernel32.helper.gen_api_opts.test.ts b/packages/win32-api/test/helper/93.kernel32.helper.gen_api_opts.test.ts deleted file mode 100644 index 2f527a7e..00000000 --- a/packages/win32-api/test/helper/93.kernel32.helper.gen_api_opts.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { DModel as M } from '../../src/index.js' -import * as Win from '../../src/index.js' -import * as H from '../../src/lib/helper.js' - - -describe(fileShortPath(import.meta.url), () => { - const apiName = 'Kernel32' - const module: any = Win[apiName] - const fn = 'GetSystemTimes' - const fakeFn = fn + Math.random().toString() - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const api: M.DllFuncs = module.apiDef - assert(api) - - it(`Should ${apiName} gen_api_opts(["${fn}"]) correctly`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fn]) - - const keysize = Object.keys(fns).length - - assert(keysize === 1) - assert(typeof fns[fn] === 'object' && fns[fn]) - }) - - it(`Should ${apiName} gen_api_opts(["${fakeFn}"]) return none`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fakeFn]) - const keysize = Object.keys(fns).length - - assert(keysize === 0) - assert(typeof fns[fakeFn] === 'undefined') - }) - } - else { - assert(false, 'module or module.apiDef invalie') - } -}) - diff --git a/packages/win32-api/test/helper/94.ntdll.helper.gen_api_opts.test.ts b/packages/win32-api/test/helper/94.ntdll.helper.gen_api_opts.test.ts deleted file mode 100644 index 299d2752..00000000 --- a/packages/win32-api/test/helper/94.ntdll.helper.gen_api_opts.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { DModel as M } from '../../src/index.js' -import * as Win from '../../src/index.js' -import * as H from '../../src/lib/helper.js' - - -describe(fileShortPath(import.meta.url), () => { - const apiName = 'Ntdll' - const module: any = Win[apiName] - const fn = 'NtQueryInformationProcess' - const fakeFn = fn + Math.random().toString() - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const api: M.DllFuncs = module.apiDef - assert(api) - - it(`Should ${apiName} gen_api_opts(["${fn}"]) correctly`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fn]) - - const keysize = Object.keys(fns).length - - assert(keysize === 1) - assert(typeof fns[fn] === 'object' && fns[fn]) - }) - - it(`Should ${apiName} gen_api_opts(["${fakeFn}"]) return none`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fakeFn]) - const keysize = Object.keys(fns).length - - assert(keysize === 0) - assert(typeof fns[fakeFn] === 'undefined') - }) - } - else { - assert(false, 'module or module.apiDef invalie') - } -}) - diff --git a/packages/win32-api/test/helper/95.user32.helper.gen_api_opts.test.ts b/packages/win32-api/test/helper/95.user32.helper.gen_api_opts.test.ts deleted file mode 100644 index 03ad6c1c..00000000 --- a/packages/win32-api/test/helper/95.user32.helper.gen_api_opts.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { DModel as M } from '../../src/index.js' -import * as Win from '../../src/index.js' -import * as H from '../../src/lib/helper.js' - - -describe(fileShortPath(import.meta.url), () => { - const apiName = 'User32' - const module: any = Win[apiName] - const fn = 'CreateWindowExW' - const fakeFn = fn + Math.random().toString() - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const api: M.DllFuncs = module.apiDef - assert(api) - - it(`Should ${apiName} gen_api_opts(["${fn}"]) correctly`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fn]) - - const keysize = Object.keys(fns).length - - assert(keysize === 1) - assert(typeof fns[fn] === 'object' && fns[fn]) - }) - - it(`Should ${apiName} gen_api_opts(["${fakeFn}"]) return none`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fakeFn]) - const keysize = Object.keys(fns).length - - assert(keysize === 0) - assert(typeof fns[fakeFn] === 'undefined') - }) - } - else { - assert(false, 'module or module.apiDef invalie') - } -}) - diff --git a/packages/win32-api/test/helper/96.user32.helper.gen_api_opts.test.ts b/packages/win32-api/test/helper/96.user32.helper.gen_api_opts.test.ts deleted file mode 100644 index df2481ec..00000000 --- a/packages/win32-api/test/helper/96.user32.helper.gen_api_opts.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { DModel as M } from '../../src/index.js' -import * as Win from '../../src/index.js' -import * as H from '../../src/lib/helper.js' - - -describe(fileShortPath(import.meta.url), () => { - const apiName = 'User32' - const module: any = Win[apiName] - const fn = 'GetWindowLongPtrW' - const fakeFn = fn + Math.random().toString() - - if (process.arch !== 'x64') { - return - } - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (module && module.apiDef) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const api: M.DllFuncs = module.apiDef - assert(api) - - it(`Should ${apiName} gen_api_opts(["${fn}"]) correctly`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fn]) - - const keysize = Object.keys(fns).length - - assert(keysize === 1) - assert(typeof fns[fn] === 'object' && fns[fn]) - }) - - it(`Should ${apiName} gen_api_opts(["${fakeFn}"]) return none`, () => { - const fns: M.DllFuncs = H.gen_api_opts(api, [fakeFn]) - const keysize = Object.keys(fns).length - - assert(keysize === 0) - assert(typeof fns[fakeFn] === 'undefined') - }) - } - else { - assert(false, 'module or module.apiDef invalie') - } -}) - diff --git a/packages/win32-api/test/helper/97.bufferToStruct.test.ts b/packages/win32-api/test/helper/97.bufferToStruct.test.ts deleted file mode 100644 index 466ab34d..00000000 --- a/packages/win32-api/test/helper/97.bufferToStruct.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' - -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, - ucsBufferFrom, - bufferToStruct, -} from '../../src/index.js' -import { githubPrinterNames } from '../config.unittest.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should work ', () => { - it('useStringBuffer: false', async () => { - const docInfo = StructFactory(DS.DOC_INFO_1, { useStringBuffer: false }) - assert(Buffer.isBuffer(docInfo.pDocName)) - docInfo.pDocName = ucsBufferFrom('nodefoo') - docInfo.pDatatype = ucsBufferFrom('RAW') - - const docInfoBuf = docInfo.ref() - const arr = bufferToStruct(docInfoBuf, DS.DOC_INFO_1) - assert(arr.length === 1) - const [struct] = arr - assert(struct) - assert(struct.pDocName.toString() === 'nodefoo') - assert(struct.pDatatype.toString() === 'RAW') - void arr - }) - - it.skip('useStringBuffer: true not support', async () => { - const name = 'nodefoo' - const docInfo = StructFactory(DS.DOC_INFO_1, { useStringBuffer: true, maxCharLength: 16 }) - const docInfo2 = StructFactory(DS.DOC_INFO_1, { useStringBuffer: false, maxCharLength: 16 }) - // assert(typeof docInfo.pDocName === 'string') - docInfo.pDocName = ucsBufferFrom(name) - docInfo.pDatatype = ucsBufferFrom('RAW') - - docInfo2.pDocName = ucsBufferFrom(name) - docInfo2.pDatatype = ucsBufferFrom('RAW') - - const docInfoBuf = docInfo.ref() - const docInfoBuf2 = docInfo2.ref() - const arr = bufferToStruct(docInfoBuf, DS.DOC_INFO_1) - assert(arr) - void arr - }) - - }) - -}) - diff --git a/packages/win32-api/test/kernel32/40.GetSystemTimes.test.ts b/packages/win32-api/test/kernel32/40.GetSystemTimes.test.ts deleted file mode 100644 index f9229511..00000000 --- a/packages/win32-api/test/kernel32/40.GetSystemTimes.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { - knl32, - knl32Sync, -} from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should GetSystemTimes() work', () => { - it('await', async () => { - const idleTime = StructFactory(DS.FILETIME) - const kernelTime = StructFactory(DS.FILETIME) - const userTime = StructFactory(DS.FILETIME) - - await knl32.GetSystemTimes(idleTime.ref(), kernelTime.ref(), userTime.ref()) - assert(fileTimeToNumber(idleTime) > 0) - assert(fileTimeToNumber(kernelTime) > 0) - assert(fileTimeToNumber(userTime) > 0) - }) - - it('sync', () => { - const idleTime = StructFactory(DS.FILETIME) - const kernelTime = StructFactory(DS.FILETIME) - const userTime = StructFactory(DS.FILETIME) - - knl32Sync.GetSystemTimes(idleTime.ref(), kernelTime.ref(), userTime.ref()) - assert(fileTimeToNumber(idleTime) > 0) - assert(fileTimeToNumber(kernelTime) > 0) - assert(fileTimeToNumber(userTime) > 0) - }) - - it('callback .async', () => { - const idleTime = StructFactory(DS.FILETIME) - const kernelTime = StructFactory(DS.FILETIME) - const userTime = StructFactory(DS.FILETIME) - - knl32Sync.GetSystemTimes.async(idleTime.ref(), kernelTime.ref(), userTime.ref(), (err) => { - if (err) { - return assert(false, err.message ? err.message : 'unknown error') - } - assert(fileTimeToNumber(idleTime) > 0) - assert(fileTimeToNumber(kernelTime) > 0) - assert(fileTimeToNumber(userTime) > 0) - }) - }) - }) -}) - - -function fileTimeToNumber(fileTime: M.FILETIME): number { - return fileTime.dwLowDateTime + fileTime.dwHighDateTime * Math.pow(2, 32) -} diff --git a/packages/win32-api/test/lib/20.comctl32.test.ts b/packages/win32-api/test/lib/20.comctl32.test.ts new file mode 100644 index 00000000..c6260aff --- /dev/null +++ b/packages/win32-api/test/lib/20.comctl32.test.ts @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { Comctl32 as Lib } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('Comctl32', () => { + it('load', () => { + const lib = Lib.load() + assert(lib) + assert(Object.keys(lib).length === Object.keys(Lib.DefComctl32).length * 2, 'lib function count not match') + + assert(typeof lib.InitCommonControlsEx === 'function') + assert(typeof lib.InitCommonControlsEx_Async === 'function') + }) + }) + +}) + diff --git a/packages/win32-api/test/lib/21.gdi32.test.ts b/packages/win32-api/test/lib/21.gdi32.test.ts new file mode 100644 index 00000000..c3e41162 --- /dev/null +++ b/packages/win32-api/test/lib/21.gdi32.test.ts @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { Gdi32 as Lib } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('Gdi32', () => { + it('load', () => { + const lib = Lib.load() + assert(lib) + assert(Object.keys(lib).length === Object.keys(Lib.DefGdi32).length * 2, 'lib function count not match') + + assert(typeof lib.CreateCompatibleBitmap === 'function') + assert(typeof lib.CreateCompatibleBitmap_Async === 'function') + }) + }) + +}) + diff --git a/packages/win32-api/test/lib/22.kernel32.test.ts b/packages/win32-api/test/lib/22.kernel32.test.ts new file mode 100644 index 00000000..bdab1ca2 --- /dev/null +++ b/packages/win32-api/test/lib/22.kernel32.test.ts @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { Kernel32 as Lib } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('Kernel32', () => { + it('load', () => { + const lib = Lib.load() + assert(lib) + assert(Object.keys(lib).length === Object.keys(Lib.DefKernel32).length * 2, 'lib function count not match') + + assert(typeof lib.FormatMessageW === 'function') + assert(typeof lib.FormatMessageW_Async === 'function') + }) + }) + +}) + diff --git a/packages/win32-api/test/lib/23.spoolss.test.ts b/packages/win32-api/test/lib/23.spoolss.test.ts new file mode 100644 index 00000000..633a409b --- /dev/null +++ b/packages/win32-api/test/lib/23.spoolss.test.ts @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { Spoolss as Lib } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('Spoolss', () => { + it('load', () => { + const lib = Lib.load() + assert(lib) + assert(Object.keys(lib).length === Object.keys(Lib.DefSpoolss).length * 2, 'lib function count not match') + + assert(typeof lib.EndDocPrinter === 'function') + assert(typeof lib.EndDocPrinter_Async === 'function') + }) + }) + +}) + diff --git a/packages/win32-api/test/lib/24.user32.test.ts b/packages/win32-api/test/lib/24.user32.test.ts new file mode 100644 index 00000000..144ea13b --- /dev/null +++ b/packages/win32-api/test/lib/24.user32.test.ts @@ -0,0 +1,24 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { User32 as Lib } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('User32', () => { + it('load', () => { + const lib = Lib.load() + assert(lib) + + const len = Object.keys(lib).length + assert(len > 0, 'ffi lib object is empty') + + assert(typeof lib.BringWindowToTop === 'function', 'lib.BringWindowToTop is not function') + assert(typeof lib.BringWindowToTop_Async === 'function', 'lib.BringWindowToTopAsync is not function') + }) + }) + +}) + diff --git a/packages/win32-api/test/lib/25.winspool.test.ts b/packages/win32-api/test/lib/25.winspool.test.ts new file mode 100644 index 00000000..ce11f097 --- /dev/null +++ b/packages/win32-api/test/lib/25.winspool.test.ts @@ -0,0 +1,22 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { Winspool as Lib } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('Winspool', () => { + it('load', () => { + const lib = Lib.load() + assert(lib) + assert(Object.keys(lib).length === Object.keys(Lib.DefWinspool).length * 2, 'lib function count not match') + + assert(typeof lib.ClosePrinter === 'function') + assert(typeof lib.ClosePrinter_Async === 'function') + }) + }) + +}) + diff --git a/packages/win32-api/test/root.config.ts b/packages/win32-api/test/root.config.ts index 7344d320..7063715e 100644 --- a/packages/win32-api/test/root.config.ts +++ b/packages/win32-api/test/root.config.ts @@ -1,6 +1,49 @@ +import { homedir } from 'node:os' +import { join } from 'node:path' + import { genCurrentDirname } from '@waiting/shared-core' +import { isWinLocaleChinese } from './util.js' + + +export const testDir = genCurrentDirname(import.meta.url) +export const baseDir = join(testDir, '..') + +export const CI = !! process.env['CI'] // GithubAction +export const TEST = !! (CI + || process.env['MIDWAY_SERVER_ENV'] === 'unittest' + || process.env['MIDWAY_SERVER_ENV'] === 'local' + || process.env['NODE_ENV'] === 'unittest' + || process.env['NODE_ENV'] === 'local' +) + +export interface TestConfig { + baseDir: string + testDir: string + testAppDir: string + CI: boolean + TEST: boolean + isWinChinese: boolean + notepadTitle: string + pDocName: string + startDocPrinterTargetFile: string +} + +const testAppDir = join(testDir, 'fixtures', 'base-app') +const isWinChinese = await isWinLocaleChinese() + +const pDocNameRndStr = 'win32-api_test_' + Math.random().toString(36).slice(2) +const pDocNamePath = `${homedir()}/Documents/${pDocNameRndStr}.pdf` -export const CI = !! process.env['CI'] -export const testBaseDir = genCurrentDirname(import.meta.url) +export const testConfig = { + baseDir, + testDir, + testAppDir, + CI, + TEST, + isWinChinese, + notepadTitle: isWinChinese ? '无标题 - 记事本' : 'Untitled - Notepad', + pDocName: pDocNameRndStr, + startDocPrinterTargetFile: pDocNamePath, +} as TestConfig diff --git a/packages/win32-api/test/root.hooks.ts b/packages/win32-api/test/root.hooks.ts deleted file mode 100644 index 04af7d24..00000000 --- a/packages/win32-api/test/root.hooks.ts +++ /dev/null @@ -1,27 +0,0 @@ - -/** - * @see https://mochajs.org/#root-hook-plugins - * beforeAll: - * - In serial mode(Mocha’s default ), before all tests begin, once only - * - In parallel mode, run before all tests begin, for each file - * beforeEach: - * - In both modes, run before each test - */ -export const mochaHooks = async () => { - // avoid run multi times - if (! process.env['mochaRootHookFlag']) { - process.env['mochaRootHookFlag'] = 'true' - } - - return { - beforeAll: async () => { - return - }, - - afterAll: async () => { - return - }, - } - -} - diff --git a/packages/win32-api/test/setup.ts b/packages/win32-api/test/setup.ts new file mode 100644 index 00000000..96ab7b2f --- /dev/null +++ b/packages/win32-api/test/setup.ts @@ -0,0 +1,27 @@ +// https://mochajs.org/#global-fixtures +import assert from 'node:assert/strict' +import { rm } from 'node:fs/promises' +import { join } from 'node:path' + +import { isFileExists } from '@waiting/shared-core' + +import { testConfig } from '#@/root.config.js' + + + +export async function mochaGlobalSetup(): Promise { + void 0 +} + +export async function mochaGlobalTeardown(): Promise { + void 0 + + const targetExists = await isFileExists(testConfig.startDocPrinterTargetFile) + console.log('startDocPrinterTargetFile: ', testConfig.startDocPrinterTargetFile) + assert( + targetExists === true, + `204.StartDocPrinter-EndDocPrinter.test.ts StartDocPrinter(): file not exists: ${testConfig.startDocPrinterTargetFile}`, + ) + await rm(testConfig.startDocPrinterTargetFile, { force: true, recursive: false }) +} + diff --git a/packages/win32-api/test/tsconfig.json b/packages/win32-api/test/tsconfig.json index 16ed73e6..c2f79e68 100644 --- a/packages/win32-api/test/tsconfig.json +++ b/packages/win32-api/test/tsconfig.json @@ -1,24 +1,15 @@ { - "extends": "../tsconfig.json", + "extends": "../tsconfig.base.json", "compilerOptions": { - "declaration": false, - "declarationMap": false, - "inlineSourceMap": false, "noEmit": true, "noImplicitAny": false, "noImplicitThis": false, + "noPropertyAccessFromIndexSignature": false, "noUnusedLocals": false, - "sourceMap": false, - "target": "ESNEXT" + "rootDir": ".." }, "include": [ - "**/*.ts" - ], - "exclude": [ - "asset/", - "fixtures/", - "node_modules*", - "**/*.d.ts", - "**/*.spec.ts" + "../src", + "." ] } diff --git a/packages/win32-api/test/user32/201.FindWindowEx.test.ts b/packages/win32-api/test/user32/201.FindWindowEx.test.ts deleted file mode 100644 index 4093d8bd..00000000 --- a/packages/win32-api/test/user32/201.FindWindowEx.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import { sleep } from 'zx' - -import { user32FindWindowEx } from '../../src/index.fun.js' -import { calcLpszNotepad } from '../config.unittest.js' -import { assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should work', () => { - it('normal', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assert(hWnd) - assertsHwnd(hWnd) - - child.kill() - }) - }) -}) - - diff --git a/packages/win32-api/test/user32/51.EnumDisplayDevicesW.test.ts b/packages/win32-api/test/user32/51.EnumDisplayDevicesW.test.ts deleted file mode 100644 index b57133bf..00000000 --- a/packages/win32-api/test/user32/51.EnumDisplayDevicesW.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' - -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { user32Sync } from '../helper.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - it('EnumDisplayDevicesW()', () => { - const dd = StructFactory(DS.DISPLAY_DEVICEW) - dd.cb = dd.ref().byteLength - - const ret = user32Sync.EnumDisplayDevicesW(ref.NULL, 0, dd.ref(), 0) - assert(ret) - const { - DeviceID, - DeviceKey, - DeviceName, - DeviceString, - } = dd - console.log({ - DeviceID, - DeviceKey, - DeviceName, - DeviceString, - }) - - assert(DeviceID.startsWith('PCI\\VEN_') || DeviceID.includes('VMBUS') || DeviceID === '', DeviceID) - assert(typeof DeviceKey === 'string', DeviceKey) - assert(DeviceName === '\\\\.\\DISPLAY1', DeviceName) - assert(DeviceString.length > 0) - const flag = ['Microsoft Hyper-V', 'Intel', 'AMD', 'Radeon'].some(val => DeviceString.includes(val)) - assert(flag === true, DeviceString) - }) - -}) - diff --git a/packages/win32-api/test/user32/52.GetRawInputDeviceInfoW.test.ts b/packages/win32-api/test/user32/52.GetRawInputDeviceInfoW.test.ts deleted file mode 100644 index 7d44d315..00000000 --- a/packages/win32-api/test/user32/52.GetRawInputDeviceInfoW.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - config, - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { user32Sync } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - it('Should GetRawInputDeviceInfoW() calling passed', () => { - const limit = 64 - const rawInputDeviceList = StructFactory(DS.RAWINPUTDEVICELIST) - const byteLen = rawInputDeviceList.ref().byteLength - console.log({ byteLen }) - const pRawInputDeviceList = Buffer.alloc(byteLen * limit) - const puiNumDevices = Buffer.alloc(4) - puiNumDevices[0] = limit - - const nDevices = user32Sync.GetRawInputDeviceList( - pRawInputDeviceList, - puiNumDevices, - rawInputDeviceList.ref().byteLength, - ) - - // console.log(buf) - console.log({ nDevices, puiNumDevices }) - assert(nDevices > 0 && nDevices <= limit) - - const delta = config._WIN64 ? 8 : 4 - const readFn = config._WIN64 ? 'readBigUInt64LE' : 'readUInt32LE' - - let offset = 0 - let count = 0 - while (count < nDevices) { - const hDevice: number | bigint = pRawInputDeviceList[readFn](offset) - offset += delta - const dwType = pRawInputDeviceList.readUInt32LE(offset) - offset += delta - count += 1 - console.log({ count, hDevice, dwType }) - - const pcbSize = Buffer.alloc(4) - const buf = Buffer.alloc(255) - - const nameLen = user32Sync.GetRawInputDeviceInfoW( - hDevice.toString(), - 0x20000007, - buf, - pcbSize, - ) - console.log({ - nameLen, - pcbSize, - buf: buf.toString('ucs2').replace(/\0/ug, ''), - }) - - const pData = StructFactory(DS.RID_DEVICE_INFO) - pData.cbSize = pData.ref().byteLength - - const infoLen = user32Sync.GetRawInputDeviceInfoW( - hDevice.toString(), - 0x2000000b, - pData.ref(), - pcbSize, - ) - assert(pData) - console.log({ - infoLen, - pcbSize, - }) - assert(pData.DUMMYUNIONNAME) - console.log({ - pData_dwType: pData.dwType, - union_mouse: pData.DUMMYUNIONNAME.mouse, - union_keyboard: pData.DUMMYUNIONNAME.keyboard, - union_hid: pData.DUMMYUNIONNAME.hid, - }) - } - - }) -}) - diff --git a/packages/win32-api/test/user32/53.GetRawInputDeviceList.test.ts b/packages/win32-api/test/user32/53.GetRawInputDeviceList.test.ts deleted file mode 100644 index a18332af..00000000 --- a/packages/win32-api/test/user32/53.GetRawInputDeviceList.test.ts +++ /dev/null @@ -1,33 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { user32Sync } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - it('GetRawInputDeviceList()', () => { - const limit = 64 - const rawInputDeviceList = StructFactory(DS.RAWINPUTDEVICELIST) - const pRawInputDeviceList = Buffer.alloc(rawInputDeviceList.ref().byteLength * limit) - const puiNumDevices = Buffer.alloc(4) - puiNumDevices[0] = limit - - const nDevices = user32Sync.GetRawInputDeviceList( - pRawInputDeviceList, - puiNumDevices, - rawInputDeviceList.ref().byteLength, - ) - - // console.log(buf) - console.log({ nDevices, puiNumDevices }) - assert(nDevices > 0 && nDevices <= limit) - }) -}) - diff --git a/packages/win32-api/test/user32/54.GetWindowRect.test.ts b/packages/win32-api/test/user32/54.GetWindowRect.test.ts deleted file mode 100644 index 06e683ac..00000000 --- a/packages/win32-api/test/user32/54.GetWindowRect.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import { sleep } from 'zx' - -import { user32FindWindowEx } from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { calcLpszWindow } from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe.skip(fileShortPath(import.meta.url), () => { - it('GetWindowRect()', async () => { - const child = spawn('calc.exe') - await sleep(1500) - - const rect = StructFactory(DS.RECT) - - const hWnd = await user32FindWindowEx(0, 0, null, calcLpszWindow) - assertsHwnd(hWnd) - - const ret = await user32.GetWindowRect(hWnd, rect.ref()) - assert(ret !== 0) - assert(ret) - console.log({ - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - }) - assert(rect.top >= 0) - assert(rect.left >= 0) - assert(rect.right > 0) - assert(rect.bottom > 0) - - await destroyWin(hWnd) - child.kill() - }) - -}) - diff --git a/packages/win32-api/test/user32/55.SendMessageW.test.ts b/packages/win32-api/test/user32/55.SendMessageW.test.ts deleted file mode 100644 index 3dde56bd..00000000 --- a/packages/win32-api/test/user32/55.SendMessageW.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { sleep } from 'zx' - -import * as CS from '../../src/index.consts.js' -import { user32FindWindowEx } from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { calcLpszWindow } from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - it('Should send CS.WM_COMMAND and CS.WM_DESTROY works', async () => { - const child = spawn('calc.exe') - await sleep(1500) - - child.on('exit', (code) => { - assert(code === 0) - }) - child.on('error', (ex: Error) => { - assert(false, ex.message) - }) - - const hWnd = await user32FindWindowEx(0, 0, null, calcLpszWindow) - assertsHwnd(hWnd) - - let ret = await user32.SendMessageW(hWnd, CS.WM_COMMAND, 1000, 3) - assert(ret === 0) - - ret = await user32.SendMessageW(hWnd, CS.WM_DESTROY, 0, 0) - assert(ret === 0) - }) - - it('Should send WM_COPYDATA works', async () => { - const child = spawn('calc.exe') - await sleep(1500) - - const hWnd = await user32FindWindowEx(0, 0, null, calcLpszWindow) - assertsHwnd(hWnd) - - const copyData = StructFactory(DS.COPYDATASTRUCT) - const msgBuff = Buffer.from('foo\0', 'ucs2') - const msgBuffAddr = ref.address(msgBuff) - copyData.dwData = msgBuffAddr - const copyDataAddr = ref.address(copyData.ref()) - - console.info({ - msgBuff, msgBuffAddr, copyDataAddr, - }) - - // send WM_COPYDATA (74) message - const ret = await user32.SendMessageW(hWnd, CS.WM_COPYDATA, 0, copyDataAddr) - assert(ret === 0) - - await destroyWin(hWnd) - child.kill() - }) -}) - diff --git a/packages/win32-api/test/user32/56.SendMessageW.SETTEXT.test.ts b/packages/win32-api/test/user32/56.SendMessageW.SETTEXT.test.ts deleted file mode 100644 index f65a0ede..00000000 --- a/packages/win32-api/test/user32/56.SendMessageW.SETTEXT.test.ts +++ /dev/null @@ -1,42 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { sleep } from 'zx' - -import * as CS from '../../src/index.consts.js' -import { user32FindWindowEx } from '../../src/index.fun.js' -import { ucsBufferFrom } from '../../src/index.js' -import { - calcLpszNotepad, - calcLpszNotepadEdit, -} from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('Should send WM_SETTEXT to Notepad work', async () => { - const child = spawn('notepad.exe') - await sleep(1500) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - - const hWndEdit = await user32FindWindowEx(hWnd, 0, calcLpszNotepadEdit, null) - assertsHwnd(hWndEdit) - - const txt = 'Hello World.' + Math.random().toString() - const msgBuff = ucsBufferFrom(txt) - const msgBuffAddr = ref.address(msgBuff) - - await user32.SendMessageW(hWndEdit, CS.WM_SETTEXT, 0, msgBuffAddr) - await sleep(1000) - - await destroyWin(hWnd) - child.kill() - }) - -}) - diff --git a/packages/win32-api/test/user32/57.SendMessageW.GETTEXT.test.ts b/packages/win32-api/test/user32/57.SendMessageW.GETTEXT.test.ts deleted file mode 100644 index c294f1c9..00000000 --- a/packages/win32-api/test/user32/57.SendMessageW.GETTEXT.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { sleep } from 'zx' - -import * as CS from '../../src/index.consts.js' -import { user32FindWindowEx } from '../../src/index.fun.js' -import { ucsBufferFrom, ucsBufferToString } from '../../src/index.js' -import { - calcLpszNotepad, - calcLpszNotepadEdit, -} from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('Should send WM_SETTEXT, WM_GETTEXT works', async () => { - const child = spawn('notepad.exe') - await sleep(1500) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - - const hWndEdit = await user32FindWindowEx(hWnd, 0, calcLpszNotepadEdit, null) - assertsHwnd(hWndEdit) - - const txt = 'Hello World.' + Math.random().toString() - const msgBuff = ucsBufferFrom(txt) - const msgBuffAddr = ref.address(msgBuff) - - await user32.SendMessageW(hWndEdit, CS.WM_SETTEXT, 0, msgBuffAddr) - - const len = await user32.SendMessageW(hWndEdit, CS.WM_GETTEXTLENGTH, 0, 0) - assert(len > 0) - assert(len === txt.length) - - const size = len + 1 - const getTextBuf = Buffer.alloc(size * 2) - const getTextBufAddr = ref.address(getTextBuf) - - const ret = await user32.SendMessageW(hWndEdit, CS.WM_GETTEXT, size, getTextBufAddr) - assert(ret === len) - - const txtResult = ucsBufferToString(getTextBuf) - console.log({ txtResult, txt }) - assert(txtResult === txt) - - await sleep(1000) - - await destroyWin(hWnd) - child.kill() - }) - -}) - diff --git a/packages/win32-api/test/user32/60.FlashWindowEx.test.ts b/packages/win32-api/test/user32/60.FlashWindowEx.test.ts deleted file mode 100644 index 4da3bed9..00000000 --- a/packages/win32-api/test/user32/60.FlashWindowEx.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { FLASHW_ALL, FLASHW_CAPTION } from 'win32-def/consts' -import { sleep } from 'zx' - -// import * as CS from '../../src/index.consts.js' -import { user32FindWindowEx } from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { calcLpszNotepad } from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should FlashWindowEx() work', () => { - it('FLASHW_ALL', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - - const pfwi = StructFactory(DS.FLASHWINFO) - pfwi.cbSize = pfwi.ref().byteLength - pfwi.hwnd = hWnd - pfwi.dwFlags = FLASHW_ALL // 0x03 - pfwi.uCount = 10 // sec - pfwi.dwTimeout = 0 - - await user32.FlashWindowEx(pfwi.ref()) - - await sleep(3000) - await destroyWin(hWnd) - child.kill() - }) - - it('FLASHW_CAPTION', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - - const pfwi = StructFactory(DS.FLASHWINFO) - pfwi.cbSize = pfwi.ref().byteLength - pfwi.hwnd = hWnd - pfwi.dwFlags = FLASHW_CAPTION // 0x01 - pfwi.uCount = 10 // sec - pfwi.dwTimeout = 0 - - await user32.FlashWindowEx(pfwi.ref()) - - await sleep(3000) - await destroyWin(hWnd) - child.kill() - }) - }) - -}) - diff --git a/packages/win32-api/test/user32/61.FlashWindow.test.ts b/packages/win32-api/test/user32/61.FlashWindow.test.ts deleted file mode 100644 index 14c3de6d..00000000 --- a/packages/win32-api/test/user32/61.FlashWindow.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { sleep } from 'zx' - -// import * as CS from '../../src/index.consts.js' -import { user32FindWindowEx } from '../../src/index.fun.js' -import { calcLpszNotepad } from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should FlashWindow() work', () => { - it('true', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - - const state = await user32.FlashWindow(hWnd, 1) - assert(state > 0) - await sleep(100) - const state2 = await user32.FlashWindow(hWnd, 0) - assert(state2 === 0, state2.toString()) - - // await sleep(10000) - await destroyWin(hWnd) - child.kill() - }) - - it('false', async () => { - const child = spawn('notepad.exe') - await sleep(1000) - - const hWnd = await user32FindWindowEx(0, 0, calcLpszNotepad, null) - assertsHwnd(hWnd) - - const state = await user32.FlashWindow(hWnd, 0) - assert(state > 0) - - // await sleep(10000) - await destroyWin(hWnd) - child.kill() - }) - - }) -}) - diff --git a/packages/win32-api/test/user32/62.GetCaretPos.test.ts b/packages/win32-api/test/user32/62.GetCaretPos.test.ts deleted file mode 100644 index ee3e6ba3..00000000 --- a/packages/win32-api/test/user32/62.GetCaretPos.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { sleep } from 'zx' - -// import * as CS from '../../src/index.consts.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { user32 } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should GetCaretPos() work', () => { - it('true', async () => { - const point = StructFactory(DS.POINT) - const ret = await user32.GetCaretPos(point.ref()) - assert(ret > 0) - console.log({ x: point.x, y: point.y }) - }) - }) -}) - diff --git a/packages/win32-api/test/user32/63.IsIconic.test.ts b/packages/win32-api/test/user32/63.IsIconic.test.ts deleted file mode 100644 index 2cf5bb98..00000000 --- a/packages/win32-api/test/user32/63.IsIconic.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import assert from 'node:assert/strict' -import { spawn } from 'node:child_process' - -import { fileShortPath } from '@waiting/shared-core' -import { sleep } from 'zx' - -import { user32FindWindowEx } from '../../src/index.fun.js' -import { calcLpszWindow } from '../config.unittest.js' -import { user32, destroyWin, assertsHwnd } from '../helper.js' - - -describe(fileShortPath(import.meta.url), () => { - it('IsIconic()', async () => { - const child = spawn('calc.exe') - await sleep(1500) - - const hWnd = await user32FindWindowEx(0, 0, null, calcLpszWindow) - assertsHwnd(hWnd) - - assert(! await user32.IsIconic(hWnd)) - await user32.ShowWindow(hWnd, 2) // minimize - assert(await user32.IsIconic(hWnd)) - - await destroyWin(hWnd) - child.kill() - }) -}) diff --git a/packages/win32-api/test/util.ts b/packages/win32-api/test/util.ts index 1a8999e4..3ecad8c7 100644 --- a/packages/win32-api/test/util.ts +++ b/packages/win32-api/test/util.ts @@ -3,7 +3,7 @@ import { $ } from 'zx' export async function isWinLocaleChinese(): Promise { - const res = await $`powershell -Command "Get-WinSystemLocale"` + const res = await $`powershell -Command 'Get-WinSystemLocale'` const isWinChinese = res.stdout.includes('zh-CN') || res.stdout.includes('zh-Hans') return isWinChinese } diff --git a/packages/win32-api/test/util/user32/100.FindWindowEx.test.ts b/packages/win32-api/test/util/user32/100.FindWindowEx.test.ts new file mode 100644 index 00000000..8814e538 --- /dev/null +++ b/packages/win32-api/test/util/user32/100.FindWindowEx.test.ts @@ -0,0 +1,30 @@ +import assert from 'node:assert/strict' +import { spawn } from 'node:child_process' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { FindWindowEx } from '##/index.util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('FindWindowEx()', () => { + it('find Notepad hwnd', async () => { + const child = spawn('notepad.exe') + try { + await sleep(1500) + const hwnd = await FindWindowEx(0, 0, 'Notepad', null) + assert(typeof hwnd === 'number' || typeof hwnd === 'bigint') + assert(hwnd) + + const hwnd2 = await FindWindowEx(0, 0, 'Notepad', null) + assert(typeof hwnd2 === 'number' || typeof hwnd2 === 'bigint') + assert(hwnd2) + } + finally { + child.kill() + } + }) + }) + +}) + diff --git a/packages/win32-api/test/util/user32/101.GetWindowText.test.ts b/packages/win32-api/test/util/user32/101.GetWindowText.test.ts new file mode 100644 index 00000000..a0d34d41 --- /dev/null +++ b/packages/win32-api/test/util/user32/101.GetWindowText.test.ts @@ -0,0 +1,53 @@ +import assert from 'node:assert/strict' +import { spawn } from 'node:child_process' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { FindWindowEx, GetWindowText } from '##/index.util.js' +import { testConfig } from '#@/root.config.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('GetWindowText()', () => { + + it('find Notepad hwnd', async () => { + const expectTitle = testConfig.isWinChinese ? '无标题 - 记事本' : 'Untitled - Notepad' + + const child = spawn('notepad.exe') + try { + await sleep(1500) + const hwnd = await FindWindowEx(0, 0, 'Notepad', null) + assert(hwnd) + + const count = 128 + const title = await GetWindowText(hwnd, count) + console.log({ title }) + assert(title) + assert(title === testConfig.notepadTitle) + } + finally { + child.kill() + } + }) + + it('find Notepad hwnd - count', async () => { + const child = spawn('notepad.exe') + try { + await sleep(1500) + const hwnd = await FindWindowEx(0, 0, 'Notepad', null) + assert(hwnd) + + const count = 2 // include null terminator + const title = await GetWindowText(hwnd, count) + console.log({ title }) + assert(title) + assert(title === testConfig.notepadTitle.slice(0, count - 1)) // exclude null terminator + } + finally { + child.kill() + } + }) + }) + +}) + diff --git a/packages/win32-api/test/util/winspool/200.EnumPrinters.test.ts b/packages/win32-api/test/util/winspool/200.EnumPrinters.test.ts new file mode 100644 index 00000000..0668fbac --- /dev/null +++ b/packages/win32-api/test/util/winspool/200.EnumPrinters.test.ts @@ -0,0 +1,63 @@ +import assert from 'node:assert/strict' + +import { fileShortPath, sleep } from '@waiting/shared-core' +import { PrinterEnumFlags } from 'win32-def/consts' + +import { EnumPrinters } from '##/index.util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('EnumPrinters()', () => { + const needles = [ + 'Microsoft XPS Document Writer', 'Microsoft Print to PDF', // Github Actions + 'FAX', '621', // local + ] + + it('PRINTER_ENUM_LOCAL Level=1', async () => { + const Level = 1 + const infoArr = await EnumPrinters({ + Flags: PrinterEnumFlags.PRINTER_ENUM_LOCAL, + Level, + }) + assert(infoArr) + console.info({ Level, info: infoArr }) + + const match = infoArr.some((info) => { + return needles.some(needle => info.pName.includes(needle)) + }) + assert(match) + }) + + it('PRINTER_ENUM_LOCAL Level=4', async () => { + const Level = 4 + const infoArr = await EnumPrinters({ + Flags: PrinterEnumFlags.PRINTER_ENUM_LOCAL, + Level, + }) + assert(infoArr) + console.info({ Level, info: infoArr }) + + const match = infoArr.some((info) => { + return needles.some(needle => info.pPrinterName.includes(needle)) + }) + assert(match) + }) + + it('PRINTER_ENUM_LOCAL Level=5', async () => { + const Level = 5 + const infoArr = await EnumPrinters({ + Flags: PrinterEnumFlags.PRINTER_ENUM_LOCAL, + Level, + }) + assert(infoArr) + console.info({ Level, info: infoArr }) + + const match = infoArr.some((info) => { + return needles.some(needle => info.pPrinterName.includes(needle)) + }) + assert(match) + }) + }) + +}) + diff --git a/packages/win32-api/test/util/winspool/201.GetDefaultPrinter.test.ts b/packages/win32-api/test/util/winspool/201.GetDefaultPrinter.test.ts new file mode 100644 index 00000000..5e8a1832 --- /dev/null +++ b/packages/win32-api/test/util/winspool/201.GetDefaultPrinter.test.ts @@ -0,0 +1,30 @@ +import assert from 'node:assert/strict' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { GetDefaultPrinter } from '##/index.util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('GetDefaultPrinter()', () => { + + it('normal', async () => { + const pName = await GetDefaultPrinter() + assert(pName) + console.log('default printer:', pName) + }) + + it('max512', async () => { + const pName = await GetDefaultPrinter(512) + assert(pName) + console.log('default printer:', pName) + }) + + it('max3', async () => { + const pName = await GetDefaultPrinter(3) + assert(pName === null) + }) + }) + +}) + diff --git a/packages/win32-api/test/util/winspool/202.OpenPrinter.test.ts b/packages/win32-api/test/util/winspool/202.OpenPrinter.test.ts new file mode 100644 index 00000000..d67e0855 --- /dev/null +++ b/packages/win32-api/test/util/winspool/202.OpenPrinter.test.ts @@ -0,0 +1,16 @@ +import assert from 'node:assert/strict' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { OpenPrinter } from '##/index.util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('OpenPrinter()', () => { + it('normal', async () => { + const hwnd = await OpenPrinter('Microsoft Print to PDF') + assert(hwnd) + }) + }) +}) + diff --git a/packages/win32-api/test/util/winspool/203.GetPrinter.test.ts b/packages/win32-api/test/util/winspool/203.GetPrinter.test.ts new file mode 100644 index 00000000..25401974 --- /dev/null +++ b/packages/win32-api/test/util/winspool/203.GetPrinter.test.ts @@ -0,0 +1,42 @@ +import assert from 'node:assert/strict' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { OpenPrinter, GetPrinter, ClosePrinter } from '##/index.util.js' + + +describe(fileShortPath(import.meta.url), () => { + const pName = 'Microsoft Print to PDF' + + describe('GetPrinter()', () => { + it(pName, async () => { + const hwnd = await OpenPrinter(pName) + assert(hwnd) + + try { + const info = await GetPrinter({ hPrinter: hwnd, Level: 1 }) + assert(info) + assert(info.pName === pName, JSON.stringify(info)) + } + finally { + await sleep(100) + assert(await ClosePrinter(hwnd)) + } + }) + + it('Level=6', async () => { + const hwnd = await OpenPrinter(pName) + assert(hwnd) + + try { + const info = await GetPrinter({ hPrinter: hwnd, Level: 6 }) + assert(info) + } + finally { + await sleep(100) + assert(await ClosePrinter(hwnd)) + } + }) + }) +}) + diff --git a/packages/win32-api/test/util/winspool/204.StartDocPrinter-EndDocPrinter.test.ts b/packages/win32-api/test/util/winspool/204.StartDocPrinter-EndDocPrinter.test.ts new file mode 100644 index 00000000..b1727018 --- /dev/null +++ b/packages/win32-api/test/util/winspool/204.StartDocPrinter-EndDocPrinter.test.ts @@ -0,0 +1,118 @@ +import assert from 'node:assert' +import { rm } from 'node:fs/promises' +import { homedir } from 'node:os' + +import { fileShortPath, sleep, isFileExists } from '@waiting/shared-core' +import { PRINTER_STATUS } from 'win32-def/consts' +import { DOC_INFO_1_Factory } from 'win32-def/struct' + +import { EndDocPrinter, OpenPrinter, GetPrinter, ClosePrinter, StartDocPrinter } from '##/index.util.js' +import { testConfig } from '#@/root.config.js' + + +describe(fileShortPath(import.meta.url), () => { + const pName = 'Microsoft Print to PDF' + const local = 'LBP621C' + const xps = 'Microsoft XPS Document Writer' + + describe('StartDocPrinter()', () => { + it(pName, async () => { + const hwnd = await OpenPrinter(pName) + assert(hwnd) + + try { + const info = await GetPrinter({ hPrinter: hwnd, Level: 1 }) + assert(info) + assert(info.pName === pName, JSON.stringify(info)) + + const { payload } = DOC_INFO_1_Factory() + payload.pDocName = testConfig.pDocName + payload.pOutputFile = null + payload.pDatatype = 'RAW' + + // generate a pdf file (zero size) + const ret = await StartDocPrinter({ hPrinter: hwnd, pDocInfo: payload }) + assert(ret) + + const info6 = await GetPrinter({ hPrinter: hwnd, Level: 6 }) + assert(info6) + + await sleep(500) + assert(await EndDocPrinter(hwnd), 'EndDocPrinter() failed') + } + finally { + await sleep(500) + assert(await ClosePrinter(hwnd), 'ClosePrinter() failed') + } + }) + + it(xps, async () => { + const hwnd = await OpenPrinter(xps) + if (! hwnd) { return } + + try { + const info = await GetPrinter({ hPrinter: hwnd, Level: 1 }) + if (! info) { return } + assert(info.pName === xps, JSON.stringify(info)) + + const { payload } = DOC_INFO_1_Factory() + payload.pDocName = testConfig.pDocName + payload.pOutputFile = null + payload.pDatatype = 'RAW' + + // generate a pdf file (zero size) + const ret = await StartDocPrinter({ hPrinter: hwnd, pDocInfo: payload }) + assert(ret) + console.info('StartDocPrinter: ', ret) + + const info6 = await GetPrinter({ hPrinter: hwnd, Level: 6 }) + assert(info6) + assert( + info6.dwStatus === PRINTER_STATUS.PRINTER_STATUS_PAUSED || info6.dwStatus === PRINTER_STATUS.unknown, + info6.dwStatus.toString(), + ) + + await sleep(500) + assert(await EndDocPrinter(hwnd), 'EndDocPrinter() failed') + } + finally { + await sleep(500) + assert(await ClosePrinter(hwnd), 'ClosePrinter() failed') + } + }) + + it(local, async () => { + const hwnd = await OpenPrinter(local) + if (! hwnd) { return } + + try { + const info = await GetPrinter({ hPrinter: hwnd, Level: 1 }) + if (! info) { return } + assert(info.pName === local, JSON.stringify(info)) + + const { payload } = DOC_INFO_1_Factory() + payload.pDocName = testConfig.pDocName + payload.pOutputFile = null + payload.pDatatype = 'RAW' + + // generate a pdf file (zero size) + const ret = await StartDocPrinter({ hPrinter: hwnd, pDocInfo: payload }) + assert(ret) + console.info('StartDocPrinter: ', ret) + + const info6 = await GetPrinter({ hPrinter: hwnd, Level: 6 }) + assert(info6) + assert(info6.dwStatus === PRINTER_STATUS.PRINTER_STATUS_PAUSED, info6.dwStatus.toString()) + + await sleep(500) + assert(await EndDocPrinter(hwnd), 'EndDocPrinter() failed') + } + finally { + await sleep(500) + assert(await ClosePrinter(hwnd), 'ClosePrinter() failed') + } + }) + + }) +}) + diff --git a/packages/win32-api/test/util/winspool/209.ClosePrinter.test.ts b/packages/win32-api/test/util/winspool/209.ClosePrinter.test.ts new file mode 100644 index 00000000..72b261f3 --- /dev/null +++ b/packages/win32-api/test/util/winspool/209.ClosePrinter.test.ts @@ -0,0 +1,18 @@ +import assert from 'node:assert/strict' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { ClosePrinter, OpenPrinter } from '##/index.util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('OpenPrinter()', () => { + it('normal', async () => { + const hwnd = await OpenPrinter('Microsoft Print to PDF') + assert(hwnd) + const res = await ClosePrinter(hwnd) + assert(res, 'ClosePrinter() failed') + }) + }) +}) + diff --git a/packages/win32-api/test/winspool/501.GetDefaultPrinter.test.ts b/packages/win32-api/test/winspool/501.GetDefaultPrinter.test.ts deleted file mode 100644 index 0d6b44b1..00000000 --- a/packages/win32-api/test/winspool/501.GetDefaultPrinter.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { winspoolGetDefaultPrinter } from '../../src/index.fun.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should work', () => { - it('normal', async () => { - const ret = await winspoolGetDefaultPrinter() - assert(ret) - assert(ret.length) - console.log(ret) - if (CI) { - assert(ret === 'Microsoft Print to PDF') - } - }) - - it('cache', async () => { - const ret = await winspoolGetDefaultPrinter() - assert(ret) - assert(ret.length) - if (CI) { - assert(ret === 'Microsoft Print to PDF') - } - }) - }) -}) - diff --git a/packages/win32-api/test/winspool/502.OpenPrinter.test.ts b/packages/win32-api/test/winspool/502.OpenPrinter.test.ts deleted file mode 100644 index db8a3379..00000000 --- a/packages/win32-api/test/winspool/502.OpenPrinter.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - winspoolGetDefaultPrinter, - winspoolOpenPrinter, -} from '../../src/index.fun.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should work', () => { - it('normal', async () => { - const name = await winspoolGetDefaultPrinter() - assert(name) - const hWnd = await winspoolOpenPrinter(name) - assert(hWnd) - }) - - it('fake', async () => { - const hWnd = await winspoolOpenPrinter(Math.random().toString()) - assert(! hWnd) - }) - }) -}) - diff --git a/packages/win32-api/test/winspool/503.GetPrinter.test.ts b/packages/win32-api/test/winspool/503.GetPrinter.test.ts deleted file mode 100644 index c5f3a473..00000000 --- a/packages/win32-api/test/winspool/503.GetPrinter.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { PRINTER_INFO_1, PRINTER_INFO_4 } from 'win32-def' - -import { - winspoolGetDefaultPrinter, - winspoolGetPrinter, - winspoolOpenPrinter, -} from '../../src/index.fun.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should winspoolGetPrinter() work', () => { - it('Level 1', async () => { - const pname = await winspoolGetDefaultPrinter() - assert(pname) - const hWnd = await winspoolOpenPrinter(pname) - assert(hWnd) - - const ret: PRINTER_INFO_1 | undefined = await winspoolGetPrinter(hWnd, 1) - assert(ret) - - const { - Flags, - pDescription, - pName, - pComment, - } = ret - const desc = pDescription - const name = pName - const comment = pComment.toString() - - assert(typeof Flags === 'number') - - assert(typeof pDescription === 'string') - assert(typeof pName === 'string') - assert(typeof pComment === 'string') - - console.log({ desc, name, comment }) - if (CI) { - assert(name.includes('Microsoft Print to PDF')) - assert(desc.includes('Microsoft Print to PDF')) - } - }) - - it('Level 4', async () => { - const pname = await winspoolGetDefaultPrinter() - assert(pname) - const hWnd = await winspoolOpenPrinter(pname) - assert(hWnd) - - const ret: PRINTER_INFO_4 | undefined = await winspoolGetPrinter(hWnd, 4) - assert(ret) - - const { pPrinterName, pServerName, Attributes } = ret - assert(pPrinterName) - assert(Attributes === 576) - console.log({ pPrinterName, pServerName, Attributes }) - if (CI) { - assert(pPrinterName.includes('Microsoft Print to PDF')) - assert(pServerName === '') - } - }) - }) -}) - diff --git a/packages/win32-api/test/winspool/504.ClosePrinter.test.ts b/packages/win32-api/test/winspool/504.ClosePrinter.test.ts deleted file mode 100644 index 6870c0ab..00000000 --- a/packages/win32-api/test/winspool/504.ClosePrinter.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - winspoolClosePrinter, - winspoolGetDefaultPrinter, - winspoolGetPrinter, - winspoolOpenPrinter, -} from '../../src/index.fun.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should winspoolClosePrinter() work', () => { - it('normal', async () => { - const pname = await winspoolGetDefaultPrinter() - assert(pname) - const hWnd = await winspoolOpenPrinter(pname) - assert(hWnd) - - const ret = await winspoolClosePrinter(hWnd) - assert(ret) - }) - - it('twice', async () => { - const pname = await winspoolGetDefaultPrinter() - assert(pname) - const hWnd = await winspoolOpenPrinter(pname) - assert(hWnd) - - await winspoolClosePrinter(hWnd) - const ret = await winspoolClosePrinter(hWnd) - assert(! ret) - }) - - }) -}) - diff --git a/packages/win32-api/test/winspool/505.EnumPrinters.test.ts b/packages/win32-api/test/winspool/505.EnumPrinters.test.ts deleted file mode 100644 index a50b2231..00000000 --- a/packages/win32-api/test/winspool/505.EnumPrinters.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { PrinterEnumFlags } from 'win32-def/consts' - -import { - winspoolOpenPrinter, - winspoolEnumPrinters, - EnumPrintersOptions, -} from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { githubPrinterNames } from '../config.unittest.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should PRINTER_ENUM_LOCAL work ', () => { - it('normal', async () => { - const ret = await winspoolEnumPrinters({ - Flags: PrinterEnumFlags.PRINTER_ENUM_LOCAL, - Level: 4, - }) - assertsPInfo_4(ret, true) - }) - - it('options<4>', async () => { - const opts: EnumPrintersOptions<4> = { - Flags: PrinterEnumFlags.PRINTER_ENUM_LOCAL, - Level: 4, - } - const ret = await winspoolEnumPrinters(opts) - assertsPInfo_4(ret, false) - }) - - it('options as const', async () => { - const opts = { - Flags: PrinterEnumFlags.PRINTER_ENUM_LOCAL, - Level: 4, - } as const // <-- `as const` - const ret = await winspoolEnumPrinters(opts) - assertsPInfo_4(ret, false) - }) - - }) - - describe('Should PRINTER_ENUM_CATEGORY_ALL + PRINTER_ENUM_LOCAL work ', () => { - it('normal', async () => { - const ret = await winspoolEnumPrinters({ - Flags: PrinterEnumFlags.PRINTER_ENUM_CATEGORY_ALL | PrinterEnumFlags.PRINTER_ENUM_LOCAL, - Level: 1, - }) - assertsPInfo_1(ret, true) - }) - - }) -}) - - -function assertsPInfo_1(infos: M.PRINTER_INFO_X[1][], verbose: boolean): void { - assert(infos.length) - - infos.forEach((info, idx) => { - assert(info) - const { pDescription, pName, pComment, Flags } = info - // assert(info.pPrinterName) - verbose && console.log({ - idx, - pDescription, - pName, - pComment, - Flags, - }) - // if (CI) { - // githubPrinterNames.includes(pPrinterName) - // } - }) -} - - -function assertsPInfo_4(infos: M.PRINTER_INFO_X[4][], verbose: boolean): void { - assert(infos.length) - - infos.forEach((info, idx) => { - assert(info) - const { pPrinterName, pServerName, Attributes } = info - assert(info.pPrinterName) - verbose && console.log({ - idx, - pPrinterName, - pServerName, - Attributes, - }) - if (CI) { - githubPrinterNames.includes(pPrinterName) - } - }) -} diff --git a/packages/win32-api/test/winspool/506.EnumPrintProcessors.test.ts b/packages/win32-api/test/winspool/506.EnumPrintProcessors.test.ts deleted file mode 100644 index 3eca175d..00000000 --- a/packages/win32-api/test/winspool/506.EnumPrintProcessors.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { PrinterEnumFlags } from 'win32-def/consts' - -import { - winspoolEnumPrinters, - winspoolEnumPrintProcessors, -} from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should work ', () => { - it('normal', async () => { - const ret = await winspoolEnumPrintProcessors() - assert(ret && ret.length) - ret.forEach((info) => { - console.log(info.pName) - if (typeof info.pName === 'string') { - assert(info.pName === 'winprint') - } - }) - }) - - - }) - -}) - diff --git a/packages/win32-api/test/winspool/507.EnumPrintProcessorDatatypes.test.ts b/packages/win32-api/test/winspool/507.EnumPrintProcessorDatatypes.test.ts deleted file mode 100644 index 51b019f6..00000000 --- a/packages/win32-api/test/winspool/507.EnumPrintProcessorDatatypes.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import { PrinterEnumFlags } from 'win32-def/consts' - -import { - winspoolEnumPrinters, - winspoolEnumPrintProcessorDatatypes, - winspoolEnumPrintProcessors, -} from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, -} from '../../src/index.js' -import { processDataTypes } from '../config.unittest.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should work ', () => { - it('normal', async () => { - const ret = await winspoolEnumPrintProcessors() - assert(ret && ret.length) - ret.forEach((info) => { - console.log(info.pName) - if (typeof info.pName === 'string') { - assert(info.pName === 'winprint') - } - }) - - const [info] = ret - assert(info) - - const pDataTypes = await winspoolEnumPrintProcessorDatatypes('', info.pName) - assert(pDataTypes.length) - pDataTypes.forEach((type, idx) => { - console.log(`${idx}: ${type.pName}`) - processDataTypes.includes(type.pName) - }) - }) - - }) - -}) - diff --git a/packages/win32-api/test/winspool/520.print-to-pdf.test.ts b/packages/win32-api/test/winspool/520.print-to-pdf.test.ts deleted file mode 100644 index eb9c0e93..00000000 --- a/packages/win32-api/test/winspool/520.print-to-pdf.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' -import ref from 'ref-napi' -import { StructPropToWCHAR } from 'win32-def' -import { PrinterEnumFlags } from 'win32-def/consts' - -import { - winspoolGetDefaultPrinter, - winspoolOpenPrinter, - winspoolStartDocPrinter, - winspoolStartPagePrinter, - spoolWritePrinter, - spoolEndDocPrinter, - winspoolClosePrinter, - winspoolEndPagePrinter, -} from '../../src/index.fun.js' -import { - DModel as M, - DTypes as W, - DStruct as DS, - StructFactory, - ucsBufferFrom, -} from '../../src/index.js' -import { CI } from '../root.config.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('Should print to Microsoft Print to PDF work ', () => { - it('pass, but created pdf file size is zero', async () => { - const pname = await winspoolGetDefaultPrinter() - assert(pname) - const hWnd = await winspoolOpenPrinter(pname) - assert(hWnd) - - const docInfo = StructFactory(DS.DOC_INFO_1, { useStringBuffer: false }) - docInfo.pDocName = ucsBufferFrom('foo') - docInfo.pDatatype = ucsBufferFrom('RAW') - docInfo.pOutputFile = ref.NULL - const ptr = docInfo.ref() - const jobId = await winspoolStartDocPrinter(hWnd, ptr) - assert(jobId) - console.log({ jobId }) - - const r1 = await winspoolStartPagePrinter(hWnd) - assert(r1) - - const pBuf = ucsBufferFrom('Hello World!') - const r2 = await spoolWritePrinter(hWnd, pBuf, pBuf.byteLength) - assert(r2) - console.log({ r2 }) - - const re3 = await winspoolEndPagePrinter(hWnd) - assert(re3) - - const r4 = await spoolEndDocPrinter(hWnd) - assert(r4) - - await winspoolClosePrinter(hWnd) - }) - - - }) - -}) - diff --git a/packages/win32-api/tsconfig.eslint.json b/packages/win32-api/tsconfig.eslint.json deleted file mode 100644 index b1910adb..00000000 --- a/packages/win32-api/tsconfig.eslint.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": true - }, - "include": [ - "src/**/*.ts", - "test/**/*.ts", - "test_browser/**/*.ts" - ], - "exclude": [ - "asset", - "app/public", - "app/views", - "dist", - "node_modules*", - "test/fixtures", - "**/*.d.ts" - ] -} diff --git a/packages/win32-api/tsconfig.json b/packages/win32-api/tsconfig.json index 842960f3..320b868a 100644 --- a/packages/win32-api/tsconfig.json +++ b/packages/win32-api/tsconfig.json @@ -1,26 +1,5 @@ { - "extends": "../../tsconfig.json", + "extends": "./tsconfig.base.json", "compilerOptions": { - "baseUrl": ".", - "incremental": true, - "module": "NodeNext", - "moduleResolution": "NodeNext", - "outDir": "dist", - "paths": { - "~/*": ["./src/*"], - "@/*": ["./test/*"] - }, - "target": "ES2022", - "tsBuildInfoFile": ".tsbuildinfo" - }, - "ts-node": { - "esm": true, - "experimentalResolver": true, - "experimentalSpecifierResolution": "node", - "preferTsExts": true, - "transpileOnly": false - }, - "include": [ - "src/**/*.ts" - ] + } } diff --git a/packages/win32-def/.nycrc.json b/packages/win32-def/.nycrc.json deleted file mode 100644 index 0d12c44b..00000000 --- a/packages/win32-def/.nycrc.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "include": [ - "src/**/*.ts" - ], - "exclude": [ - ".githooks", - "dist", - "node_modules*", - "src/bin", - "src/domain.ts", - "src/interface.ts", - "test*", - "**/node_modules*", - "**/*.d.ts", - "**/*.js" - ], - "extension": [ - ".ts" - ], - "reporter": [ - "html", - "json", - "text-summary" - ], - "all": true -} diff --git a/packages/win32-def/README.md b/packages/win32-def/README.md index 44607b56..22f38c6a 100644 --- a/packages/win32-def/README.md +++ b/packages/win32-def/README.md @@ -1,23 +1,22 @@ # win32-api -Definitions of Windows Date Types for [node-ffi], [node-ffi-napi] +Definitions of Windows Date Types for [koffi] [![GitHub tag](https://img.shields.io/github/tag/waitingsong/node-win32-api.svg)]() [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) ![](https://img.shields.io/badge/lang-TypeScript-blue.svg) ![Available platform](https://img.shields.io/badge/platform-win32-blue.svg) [![ci](https://github.com/waitingsong/node-win32-api/workflows/ci-win/badge.svg)](https://github.com/waitingsong/node-win32-api/actions?query=workflow%3A%22ci-win%22) -[![Build status](https://ci.appveyor.com/api/projects/status/nrivtykm5uf84fbl/branch/main?svg=true)](https://ci.appveyor.com/project/waitingsong/node-win32-api/branch/main) [![codecov](https://codecov.io/gh/waitingsong/node-win32-api/branch/main/graph/badge.svg?token=WXbZvnAaYO)](https://codecov.io/gh/waitingsong/node-win32-api) [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) [![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lernajs.io/) +## Significant [Changes.V22] -## Initialization - -```sh -npm run repo:init -``` +Compile successfully with +- Node.js v18 +- Node.js v20 +- Node.js v22 ## Packages @@ -29,7 +28,7 @@ npm run repo:init ## What can I do with this? -Write [node-ffi] or [node-ffi-napi] calling win32 native functions code by Typescript with Types support. +Write [koffi] calling win32 native functions code by Typescript with Types support. ## Installing @@ -40,50 +39,55 @@ npm install win32-def ## Usage -### FFI +### FFI Def ```ts -import * as ffi from 'ffi-napi' -import { DModel as M, DTypes as W, FModel as FM } from 'win32-def' - -export interface Win32Fns extends FM.DllFuncsModel { - ClientToScreen(hWnd: M.HWND, lpPoint: M.LPPOINT): M.BOOL - GetAncestor(hwnd: M.HWND, gaFlags: M.UINT): M.HWND +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' +import * as T from 'win32-def/types' + +export class DefWin32 extends Def_B implements T.LibDefBase { + [x: string]: T.FnDefFullParams + static ClientToScreen = [D.BOOL, [D.HWND, `_Inout_ ${S.LPPOINT}`]] + static EnumDisplayDevicesW = [D.BOOL, [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD]] + static FindWindowExW = [D.HWND, [D.HWND, D.HWND, D.LPCTSTR, D.LPCTSTR]] + static GetCursorPos = [D.BOOL, [`_Out_ ${S.LPPOINT}`]] } -export const user32: Win32Fns = ffi.Library('user32.dll', { - ClientToScreen: [W.BOOL, [W.HWND, W.LPPOINT] ], - GetAncestor: [W.HWND, [W.HWND, W.UINT] ], -}) +export class Win32 implements T.LibDef2Type { + // test fake struct LPPOINT + ClientToScreen: (hWnd: T.HWND, lpPoint: T.LPPOINT) => T.BOOL + + EnumDisplayDevicesW: ( + lpDevice: T.LPCWSTR | null, + iDevNum: T.DWORD, + lpDisplayDevice: S.DISPLAY_DEVICEW_Type, + dwFlags: T.DWORD, + ) => T.BOOL + + FindWindowExW: ( + hwndParent: T.HWND, + hwndChildAfter: T.HWND, + lpszClass: T.LPCTSTR | null, + lpszWindow: T.LPCTSTR | null, + ) => T.HWND + + GetCursorPos: (lpPoint: S.POINT_Type) => T.BOOL +} ``` +### Calling + ```ts -import * as ffi from 'ffi-napi' -import { DModel as M, DTypes as W, FModel as FM } from 'win32-def' +import { load } from 'win32-def' +import { POINT_Factory } from 'win32-def/struct' -export interface Win32Fns extends FM.DllFuncsModel { - ClientToScreen(hWnd: M.HWND, lpPoint: M.LPPOINT): M.BOOL - GetAncestor(hwnd: M.HWND, gaFlags: M.UINT): M.HWND -} +const lib = load(options) +const { payload: pos } = POINT_Factory() -export const user32: FM.ExpandFnModel = ffi.Library('user32.dll', { - ClientToScreen: [W.BOOL, [W.HWND, W.LPPOINT] ], - GetAncestor: [W.HWND, [W.HWND, W.UINT] ], -}) - -// You can calling with BOTH sync and async method -const hWnd = user32.GetAncestor(hWnd, uint) -user32.GetAncestor.async(handle, uint, (err, hWnd) => { - // typeof hWnd will be the same of ReturnType of sync method - if (err) { - throw err - } - if (hWnd && !ref.isNull(hWnd) && ref.address(hWnd)) { - // ... - } - else { - throw new Error('hWnd invalid') - } -}) +const res = await lib.GetCursorPos_Async(pos) +assert(res > 0) +console.info({ res, pos }) +assert(pos.x >= 0 && pos.y >= 0) ``` @@ -92,8 +96,6 @@ user32.GetAncestor.async(handle, uint, (err, hWnd) => { - [Windows Data Types](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751#DWORD) - [System Error Codes](https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381%28v=vs.85%29.aspx) - [FFI doc](https://github.com/node-ffi/node-ffi/wiki/Node-FFI-Tutorial) -- [ref doc](https://tootallnate.github.io/ref/) -- [ref-struct](https://github.com/TooTallNate/ref-struct) ## License @@ -126,3 +128,6 @@ user32.GetAncestor.async(handle, uint, (err, hWnd) => { [def-dd-svg]: https://david-dm.org/waitingsong/node-win32-api/dev-status.svg?path=packages/win32-def [def-dd-link]: https://david-dm.org/waitingsong/node-win32-api?path=packages/win32-def#info=devDependencies + +[Changes.V22]: https://github.com/waitingsong/node-win32-api/CHANGES.v22.md +[koffi]: https://github.com/node-ffi-napi/node-ffi-napi/issues/269 diff --git a/packages/win32-def/demo/EnumDisplayDevicesW.mts b/packages/win32-def/demo/EnumDisplayDevicesW.mts new file mode 100644 index 00000000..bd24007b --- /dev/null +++ b/packages/win32-def/demo/EnumDisplayDevicesW.mts @@ -0,0 +1,42 @@ +#!/usr/bin/env tsx +/* eslint-disable import/no-extraneous-dependencies */ +import assert from 'node:assert/strict' + +import ffi from 'koffi' +import { decodeInt16Array } from 'win32-def' +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + + +console.info('Running EnumDisplayDevicesW()') + +const { size, payload } = S.DISPLAY_DEVICEW_Factory() + +const user32 = ffi.load('user32.dll') +try { + const func = user32.func( + '__stdcall', + 'EnumDisplayDevicesW', + D.BOOL, + [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD], + ) + + const res = func(null, 0, payload, 1) as number + const DeviceID = decodeInt16Array(payload.DeviceID) + const DeviceKey = decodeInt16Array(payload.DeviceKey) + const DeviceName = decodeInt16Array(payload.DeviceName) + const DeviceString = decodeInt16Array(payload.DeviceString) + + console.info({ res, DeviceID, DeviceKey, DeviceName, DeviceString }) + + assert(DeviceID.startsWith('PCI\\VEN_') || DeviceID.includes('VMBUS') || DeviceID === '', DeviceID) + assert(typeof DeviceKey === 'string', DeviceKey) + assert(DeviceName === '\\\\.\\DISPLAY1', DeviceName) + assert(DeviceString.length > 0) + const flag = ['Microsoft Hyper-V', 'Intel', 'AMD', 'Radeon'].some(val => DeviceString.includes(val)) + assert(flag, DeviceString) +} +finally { + user32.unload() +} + diff --git a/packages/win32-def/demo/EnumPrintersW.mts b/packages/win32-def/demo/EnumPrintersW.mts new file mode 100644 index 00000000..a229a851 --- /dev/null +++ b/packages/win32-def/demo/EnumPrintersW.mts @@ -0,0 +1,50 @@ +#!/usr/bin/env tsx +/* eslint-disable import/no-extraneous-dependencies */ + +import ffi from 'koffi' +import { PrinterEnumFlags } from 'win32-def/consts' +import * as D from 'win32-def/def' +import * as S from 'win32-def/struct' + + +console.info('Running EnumPrintersW()') + +S.PRINTER_INFO_1_Factory() +// S.PRINTER_INFO_4_Factory() +// S.PRINTER_INFO_5_Factory() + +const lib = ffi.load('winspool.drv') + +const func1 = lib.func( + 'EnumPrintersW', + D.BOOL, + [D.DWORD, D.WString, D.DWORD, `_Out_ ${D.LPBYTE}`, D.DWORD, D.LPDWORD, D.LPDWORD], +) + +const level = 1 +const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL +const name = '' +const pcbNeeded = Buffer.alloc(4) +const pcReturned = Buffer.alloc(4) + +const cbBuf = 4096 +const buf = Buffer.alloc(cbBuf) + +const ret1 = func1( + flags, + name, + level, + buf, + cbBuf, + pcbNeeded, + pcReturned, +) as number + +const count = pcReturned.readUInt32LE() +// const pcb = pcbNeeded.readUInt32LE() + +const decodeType1 = `${S.PRINTER_INFO_1_Name}[${count}]` +const infoArr1 = ffi.decode(buf, decodeType1) as S.PRINTER_INFO_1_Type[] + +console.info({ ret1, level, infoArr1 }) + diff --git a/packages/win32-def/demo/GetCursorPos.mts b/packages/win32-def/demo/GetCursorPos.mts new file mode 100644 index 00000000..7d2b26d6 --- /dev/null +++ b/packages/win32-def/demo/GetCursorPos.mts @@ -0,0 +1,21 @@ +#!/usr/bin/env tsx +// link: https://koffi.dev/pointers#pointer-types +import assert from 'node:assert/strict' + +import ffi from 'koffi' +import { POINT_Factory } from 'win32-def/struct' + + +console.info('Running GetCursorPos()') + +const user32 = ffi.load('user32.dll') + +const { payload: pos, pointer } = POINT_Factory() + +const func = user32.func('GetCursorPos', 'int', [`_Out_ ${pointer}`]) +// const func = user32.func(`int __stdcall GetCursorPos(_Out_ ${comb.pointer}pos)`) + +const res = func(pos) as number +console.info({ res, pos }) +assert(pos.x >= 0 && pos.y >= 0) + diff --git a/packages/win32-def/demo/show-hide-desktop.mts b/packages/win32-def/demo/show-hide-desktop.mts new file mode 100644 index 00000000..5b0add9f --- /dev/null +++ b/packages/win32-def/demo/show-hide-desktop.mts @@ -0,0 +1,63 @@ +#!/usr/bin/env tsx +import assert from 'node:assert/strict' + +import { sleep } from '@waiting/shared-core' +import ffi from 'koffi' +import { INPUT, KEYBDINPUT, VirtualKey } from 'win32-def/consts' +import { INPUT_Factory, type INPUT_Type } from 'win32-def/struct' + + +console.info('Show/hide desktop with Win+D shortcut') + +const user32 = ffi.load('user32.dll') + +const { INPUT_KEYBOARD } = INPUT +const { KEYEVENTF_KEYUP } = KEYBDINPUT +const { VK_RWIN } = VirtualKey +const { VK_D } = VirtualKey + +export const events: INPUT_Type[] = [ + make_keyboard_event(VK_RWIN, true), + make_keyboard_event(VK_D, true), + make_keyboard_event(VK_D, false), + make_keyboard_event(VK_RWIN, false), +] + +export const { size, pointer } = INPUT_Factory() + +const SendInput = user32.func('__stdcall', 'SendInput', 'uint', ['uint', pointer, 'int']) + +const res = SendInput(events.length, events, size) as number +assert(res === events.length) +// console.info({ res }) + +await sleep(2000) + +await SendInput.async(events.length, events, size, (err: Error | undefined, res2: number) => { + if (err) { + console.error(err) + throw err + } + assert(res2 === events.length) +}) as number + + +console.info('finished') + +// Utility +export function make_keyboard_event(vk: VirtualKey, down: boolean) { + const event: INPUT_Type = { + type: INPUT_KEYBOARD, + u: { + ki: { + wVk: vk, + wScan: 0, + dwFlags: down ? 0 : KEYEVENTF_KEYUP, + time: 0, + dwExtraInfo: 0, + }, + }, + } + return event +} + diff --git a/packages/win32-def/package.json b/packages/win32-def/package.json index 26e52f24..ecf68a28 100644 --- a/packages/win32-def/package.json +++ b/packages/win32-def/package.json @@ -6,8 +6,10 @@ "keywords": [ "api", "ffi", + "koffi", "win32", "windows", + "Electron", "ESM", "typescript", "ts" @@ -16,6 +18,11 @@ "bin": {}, "main": "dist/index.js", "types": "dist/index.d.ts", + "imports": { + "#package.json": "./package.json", + "##/*": "./src/*", + "#@/*": "./test/*" + }, "exports": { ".": { "import": "./dist/index.js", @@ -25,17 +32,17 @@ "import": "./dist/index.consts.js", "require": "./dist/index.consts.cjs" }, - "./common.def": { + "./def": { "import": "./dist/index.def.js", "require": "./dist/index.def.cjs" }, - "./struct.def": { + "./struct": { "import": "./dist/index.struct.js", "require": "./dist/index.struct.cjs" }, - "./union.def": { - "import": "./dist/index.union.js", - "require": "./dist/index.union.cjs" + "./types": { + "import": "./dist/index.types.js", + "require": "./dist/index.types.cjs" }, "./package.json": "./package.json" }, @@ -49,44 +56,47 @@ }, "license": "MIT", "dependencies": { - "@waiting/shared-types": "^20.11.0" + "@waiting/shared-types": "^23.19.0", + "koffi": "^2.8.11" }, "devDependencies": { - "@types/ref-napi": "^3.0.6", - "@types/ref-struct-di": "^1.1.8", - "@types/ref-union-di": "^1.0.5", - "@waiting/shared-core": "^20.11.4", - "cross-env": "7" - }, - "peerDependencies": { - "ref-napi": "^3.0.3", - "ref-struct-di": "^1.1.1", - "ref-union-di": "^1.0.1" + "@waiting/shared-core": "^23.19.0" }, "engines": { - "node": ">=14.15.0" + "node": ">=16.12.0" }, "files": [ + "README.*.md", + "Dockerfile", + "npm-shrinkwrap.json", "tsconfig.json", + "tsconfig.base.json", + "asset", "src/**/*.ts", - "bin/*.js", - "dist" + "bin", + "database", + "dist", + "!**/*.spec.*", + "!**/*.tsbuildinfo" ], "publishConfig": { "access": "public" }, "scripts": { - "build": "npm run tsc && npm run rp", - "clean": "npm run clean:lock & npm run clean:cache & rm -rf dist/*", - "clean:cache": "rm -rf .eslintcache .vscode/.tsbuildinfo .vscode/.tsbuildinfo.*", - "clean:lock": "rm package-lock.json -f", - "cov": "cross-env TS_NODE_PROJECT=test/tsconfig.json c8 mocha --loader=ts-node/esm --parallel=false", - "lint": "eslint --fix --cache {src,test}/**/*.ts", - "lint:nofix": "eslint --cache {src,test}/**/*.ts", - "purge": "npm run clean && rm node_modules -rf", + "build": "npm run tsc && tsc-alias && npm run rp", + "build:unit": "tsc -p test/tsconfig.json", + "clean": "npm run clean:lock && npm run clean:dist && npm run clean:log", + "clean:cache": "rm -rf .eslintcache .tsbuildinfo", + "clean:dist": "npm run clean:cache && rm -rf dist/*", + "clean:lock": "rm -f package-lock.json", + "clean:log": "rm -rf ./logs ./run", + "cov": "c8 --all npm run test -- ", + "lint": "eslint --fix --cache src test demo", + "lint:nofix": "eslint --cache src test", + "pretest": "npm run build:unit", "rp": "rollup -c rollup.config.js --context this", - "test": "cross-env TS_NODE_PROJECT=test/tsconfig.json mocha --loader=ts-node/esm", - "test:local": "cross-env TS_NODE_PROJECT=test/tsconfig.json ../../node_modules/.bin/mocha --loader=ts-node/esm --parallel=false", - "tsc": "tsc -b " + "test": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/tsconfig.json mocha", + "deb8g": "cross-env NODE_ENV=test TS_NODE_PROJECT=test/tsconfig.json mocha --parallel=false", + "tsc": "tsc -p tsconfig.json" } } diff --git a/packages/win32-def/rollup.config.js b/packages/win32-def/rollup.config.js index 713dc641..72bee39e 100644 --- a/packages/win32-def/rollup.config.js +++ b/packages/win32-def/rollup.config.js @@ -1,12 +1,9 @@ -import { basename } from 'node:path' +import { basename, dirname } from 'node:path' import assert from 'node:assert' import dts from "rollup-plugin-dts" -// import commonjs from '@rollup/plugin-commonjs' -// import resolve from '@rollup/plugin-node-resolve' -// import { terser } from 'rollup-plugin-terser' -import pkg from './package.json' assert { type: 'json' } +import pkg from './package.json' with { type: 'json' } // `npm run build` -> `production` is true // `npm run dev` -> `production` is false @@ -211,7 +208,6 @@ function parseName(name) { else { throw new TypeError('name invalid') } - return name } function genFileNamesForCTS(row) { @@ -221,21 +217,25 @@ function genFileNamesForCTS(row) { let srcPath = row.types let baseName = '' + const dir = dirname(path) if (path.startsWith('./src/') && path.endsWith('.ts')) { baseName = basename(path, '.ts') - srcPath = srcPath ?? path + // srcPath = srcPath ?? path + srcPath = srcPath ?? dir.replace('dist', 'src') + `/${baseName}.ts` } else if (path.startsWith('./dist/') && path.endsWith('.js')) { baseName = basename(path, '.js') - srcPath = srcPath ?? `./src/${baseName}.ts` + srcPath = srcPath ?? dir.replace('dist', 'src') + `/${baseName}.ts` } - const ctsPath = `./dist/${baseName}.d.cts` - return { + const ctsPath = `${dir}/${baseName}.d.cts` + const ret = { srcPath, ctsPath, } + // console.log({ ret, dir }) + return ret } export default config diff --git a/packages/win32-def/src/index.def.ts b/packages/win32-def/src/index.def.ts index 36f07cbf..411e6370 100644 --- a/packages/win32-def/src/index.def.ts +++ b/packages/win32-def/src/index.def.ts @@ -1,10 +1,4 @@ export * from './lib/common.def.js' export * from './lib/def.enum.js' -export * from './lib/struct/struct.var.def.js' -export * from './lib/struct/wingdi.var.def.js' -export * from './lib/struct/winspool.var.def.js' -export * from './lib/struct/winuser.var.def.js' -export * from './lib/union/union.var.def.js' -export * from './lib/union/winspool.union.var.def.js' diff --git a/packages/win32-def/src/index.struct.ts b/packages/win32-def/src/index.struct.ts index ce05ca2e..61ec2a82 100644 --- a/packages/win32-def/src/index.struct.ts +++ b/packages/win32-def/src/index.struct.ts @@ -1,6 +1,6 @@ -export * from './lib/struct/struct.def.js' -export * from './lib/struct/wingdi.def.js' -export * from './lib/struct/winspool.def.js' -export * from './lib/struct/winuser.def.js' +export * from './lib/struct/struct.index.js' +export * from './lib/struct/struct.util.js' +export * from './lib/struct/struct.helper.js' +export * from './lib/struct/struct.simple.helper.js' diff --git a/packages/win32-def/src/index.ts b/packages/win32-def/src/index.ts index 5e21b319..9bc9b021 100644 --- a/packages/win32-def/src/index.ts +++ b/packages/win32-def/src/index.ts @@ -5,15 +5,19 @@ * @license MIT * @link https://github.com/waitingsong/node-win32-api */ +import ffi from 'koffi' + export * from './lib/config.js' export * from './lib/def.enum.js' export * from './lib/common.types.js' -export * from './lib/helper.js' +export * from './lib/loader/loader.js' export * from './lib/ffi.types.js' -export * from './lib/fixed-buffer.js' +export * from './lib/struct/struct.helper.js' +export * from './lib/struct/struct.factory-map.js' +export * from './lib/types.js' +export * from './lib/util.js' -export * from './lib/struct/index.struct.types.js' -export * from './lib/union/index.union.types.js' +export { ffi } diff --git a/packages/win32-def/src/index.types.ts b/packages/win32-def/src/index.types.ts new file mode 100644 index 00000000..dab013eb --- /dev/null +++ b/packages/win32-def/src/index.types.ts @@ -0,0 +1,13 @@ + +export * from './lib/common.types.js' +export * from './lib/ffi.types.js' +export * from './lib/types.js' + +export type{ + EnumPrinters_Level, + EnumPrinters_Level_Type, + EnumPrinters_Level_X_Type, + PRINTER_INFO_LEVEL, + PRINTER_INFO_Type, + PRINTER_INFO_X_Type, +} from './lib/struct/winspool/helper.types.js' diff --git a/packages/win32-def/src/index.union.ts b/packages/win32-def/src/index.union.ts deleted file mode 100644 index a9026fde..00000000 --- a/packages/win32-def/src/index.union.ts +++ /dev/null @@ -1,4 +0,0 @@ - -export * from './lib/union/union.def.js' -export * from './lib/union/winspool.union.def.js' - diff --git a/packages/win32-def/src/lib/common.def.ts b/packages/win32-def/src/lib/common.def.ts index f303a6af..8fb99f18 100644 --- a/packages/win32-def/src/lib/common.def.ts +++ b/packages/win32-def/src/lib/common.def.ts @@ -13,6 +13,7 @@ const { _WIN64 } = config export const ACCESS_MASK = Def.int32 export const ATOM = Def.uint16 export const DWORD = Def.uint32 +export const ptr = _WIN64 ? Def.uint64Ptr : Def.uint32Ptr export const PVOID = _WIN64 ? Def.uint64Ptr : Def.uint32Ptr /** * `uint32` or `uint64` used as value usage (memory address) instead of PVOID (Buffer), @@ -30,10 +31,10 @@ export const VOID = Def.void export const WCHAR = Def.uint16 export const WORD = Def.int16 -export const BOOL = Def.int +export const BOOL = Def.int32 export const BOOLEAN = Def.bool export const BYTE = Def.byte -export const CALLBACK = Def.ptr // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx +export const CALLBACK = ptr // https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx export const CCHAR = Def.uint8 export const CHAR = Def.uint8 export const COLORREF = DWORD @@ -99,24 +100,23 @@ export const LPARAM = LONG_PTR export const LPBOOL = BOOL export const LPBYTE = Def.bytePtr export const LPCOLORREF = DWORD -export const LPCSTR = Def.uint8Ptr -export const LPCWSTR = Def.uint16Ptr -export const LPCTSTR = Def.uint16Ptr +export const LPCSTR = Def.int8Ptr +export const LPCWSTR = Def.int16Ptr +export const LPCTSTR = Def.int16Ptr export const LPVOID = Def.voidPtr export const LPCVOID = LPVOID export const LPDWORD = Def.uint16Ptr export const LPHANDLE = _WIN64 ? Def.int64Ptr : Def.int32Ptr -export const LPINT = Def.intPtr +export const LPINT = ptr export const LPLONG = Def.int32Ptr -export const LPMSG = Def.ptr -export const LPPOINT = Def.ptr +export const LPMSG = ptr export const LPSTR = Def.charPtr export const LPWSTR = Def.uint16Ptr export const LPTSTR = Def.uint16Ptr export const LPWORD = Def.uint16Ptr export const LRESULT = LONG_PTR export const NTSTATUS = Def.uint32 -export const PBOOL = Def.intPtr +export const PBOOL = ptr export const PBOOLEAN = Def.boolPtr export const PBYTE = Def.bytePtr export const PCHAR = Def.charPtr @@ -129,10 +129,10 @@ export const PDWORD_PTR = DWORD_PTR export const PDWORD32 = Def.uint32Ptr export const PDWORD64 = Def.uint64Ptr export const PFLOAT = Def.floatPtr -export const PHALF_PTR = Def.ptr +export const PHALF_PTR = ptr export const PHANDLE = _WIN64 ? Def.uint64PtrPtr : Def.uint32PtrPtr export const PHKEY = _WIN64 ? Def.uint64PtrPtr : Def.uint32PtrPtr -export const PINT = Def.intPtr +export const PINT = ptr export const PINT_PTR = Def.intPtrPtr export const PINT8 = Def.int8Ptr export const PINT16 = Def.int16Ptr @@ -141,7 +141,7 @@ export const PINT64 = Def.int64Ptr export const PLCID = Def.uint32Ptr export const PLONG = Def.longPtr export const PLONGLONG = Def.int64Ptr -export const PLONG_PTR = Def.ptr +export const PLONG_PTR = ptr export const PLONG32 = Def.int32Ptr export const PLONG64 = Def.int64Ptr // ? A 32-bit pointer. On a 32-bit system, this is a native pointer. @@ -150,17 +150,17 @@ export const POINTER_32 = _WIN64 ? Def.int32Ptr : Def.int32Ptr // ? A 64-bit pointer. On a 64-bit system, this is a native pointer. // On a 32-bit system, this is a sign-extended 32-bit pointer. export const POINTER_64 = _WIN64 ? Def.int64Ptr : Def.int32Ptr -export const POINTER_SIGNED = Def.ptr -export const POINTER_UNSIGNED = Def.ptr +export const POINTER_SIGNED = ptr +export const POINTER_UNSIGNED = ptr export const PSHORT = Def.int16Ptr export const PSIZE_T = ULONG_PTR -export const PSSIZE_T = Def.ptr +export const PSSIZE_T = ptr export const PSTR = Def.charPtr export const PTBYTE = Def.int16Ptr export const PTCHAR = Def.uint16Ptr export const PTSTR = Def.uint16Ptr -export const PUCHAR = Def.ptr -export const PUHALF_PTR = Def.ptr +export const PUCHAR = ptr +export const PUHALF_PTR = ptr export const PUINT = Def.uintPtr export const PUINT_PTR = Def.uintPtrPtr export const PUINT8 = Def.uint8Ptr @@ -200,23 +200,22 @@ export const ULONG64 = Def.uint64 export const USHORT = Def.ushort export const USN = LONGLONG // export const WINAPI; -export const WINEVENTPROC = Def.ptr -export const WNDENUMPROC = Def.ptr -export const WNDPROC = Def.ptr +export const WINEVENTPROC = ptr +export const WNDENUMPROC = ptr +export const WNDPROC = ptr /** * Note: original be typedef UINT_PTR WPARAM; * CALLBACK WNDCLASSEX.lpfnWndProc may pass negative number and cause process exit. */ export const WPARAM = UINT_PTR -// A pointer to an INITCOMMONCONTROLSEX -export const LPINITCOMMONCONTROLSEX = Def.ptr -export const LPWNDCLASSEX = Def.ptr // A pointer to a WNDCLASSEX -export const PWINDOWINFO = Def.ptr // A pointer to a WINDOWINFO structure -export const PFILETIME = Def.ptr // A pointer to a FILETIME -export const LPFILETIME = Def.ptr // A pointer to a FILETIME - -export const va_list = Def.charPtr +// from https://koffi.dev/input +export const va_list = 'str16' +/** + * For 'str16' from https://koffi.dev/input + */ +export const WString = 'str16' +export const String = 'str' diff --git a/packages/win32-def/src/lib/common.types.ts b/packages/win32-def/src/lib/common.types.ts index 0b533508..577f8672 100644 --- a/packages/win32-def/src/lib/common.types.ts +++ b/packages/win32-def/src/lib/common.types.ts @@ -1,16 +1,14 @@ /* ---------- data types for TypeScript ----------- */ -// https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types -// https://docs.microsoft.com/en-us/windows/win32/winprog64/the-new-data-types -// https://docs.microsoft.com/en-us/windows/win32/intl/windows-data-types-for-strings +// https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types +// https://learn.microsoft.com/en-us/windows/win32/winprog64/the-new-data-types +// https://learn.microsoft.com/en-us/windows/win32/intl/windows-data-types-for-strings import { BigIntStr } from '@waiting/shared-types' -// eslint-disable-next-line import/no-extraneous-dependencies -import ref from 'ref-napi' export type _POINTER = Buffer export type WNDPROC = Buffer -/** number: 32bit, bitint: 64bit */ +/** number: 32bit, bigint: 64bit */ export type PTR_Addr = number | BigIntStr /** @@ -22,7 +20,7 @@ export type DWORD = number export type PVOID = Buffer /** * `uint32` or `uint64` used as value usage (memory address) instead of PVOID (Buffer), - * Use `HANDLE` (number) for params defintion of the api, + * Use `HANDLE` (number) for params definition of the api, * @see https://stackoverflow.com/questions/18266626/what-is-the-range-of-a-windows-handle-on-a-64-bits-application/29526711#29526711 */ export type HANDLE = number | BigIntStr @@ -50,7 +48,7 @@ export type COLORREF = number export type DWORDLONG = number export type DWORD_PTR = ULONG_PTR export type DWORD32 = number -export type DWORD64 = number +export type DWORD64 = BigIntStr export type FLOAT = number export type HACCEL = HANDLE export type HALF_PTR = number @@ -88,7 +86,7 @@ export type HRSRC = HANDLE export type HSZ = HANDLE export type HWINEVENTHOOK = HANDLE export type HWINSTA = HANDLE -export type HWND = HANDLE // for use of hWnd.ref(), deref() etc +export type HWND = HANDLE /** A 32-bit signed integer */ export type INT = number export type INT_PTR = PTR_Addr @@ -109,19 +107,19 @@ export type LPBOOL = _POINTER export type LPBYTE = _POINTER export type LPCOLORREF = _POINTER export type LPCSTR = _POINTER -export type LPCWSTR = PUINT8 -export type LPCTSTR = PUINT16 +export type LPCWSTR = PUINT16 | string +export type LPCTSTR = PUINT16 | string export type LPVOID = _POINTER export type LPCVOID = LPVOID -export type LPDWORD = PUINT16 +export type LPDWORD = PUINT16 | string export type LPHANDLE = _POINTER export type LPINT = PINT export type LPLONG = PINT32 export type LPMSG = _POINTER export type LPPOINT = _POINTER -export type LPSTR = _POINTER -export type LPWSTR = PUINT16 -export type LPTSTR = _POINTER +export type LPSTR = _POINTER | string +export type LPWSTR = PUINT16 | string +export type LPTSTR = _POINTER | string export type LPWORD = PUINT16 export type LRESULT = number export type NTSTATUS = UINT32 @@ -131,7 +129,7 @@ export type PBYTE = _POINTER export type PCHAR = _POINTER export type PCSTR = PUINT8 export type PCTSTR = _POINTER -export type PCWSTR = PUINT16 +export type PCWSTR = PUINT16 | string export type PDWORD = PUINT32 export type PDWORDLONG = PUINT64 export type PDWORD_PTR = DWORD_PTR @@ -209,43 +207,8 @@ export type WNDENUMPROC = WNDPROC export type WORD = INT16 export type WPARAM = UINT_PTR - - export type va_list = _POINTER -/* ------------------ struct ---------------------- */ -// see src/lib/win-model/struct.ts - - -export interface StructInstanceBase { - ref: () => Buffer -} - -export interface UnionInstanceBase { - ref: () => Buffer -} - - -export interface StringBuffer extends ref.Type { - size: number - encoding: BufferEncoding | void - set: ( - buffer: Buffer, - offset: number, - value: string | number[] | Buffer, - ) => void -} - - -/** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinter#parameters - */ -export type PRINTER_INFO_LEVEL = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 -/** - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/enumprinters - */ -export type EnumPrinters_Level = 1 | 2 | 4 | 5 - /** * Convert Struct property to WCHAR_String if Buffer @@ -264,3 +227,21 @@ export type StructPropToBuffer = { : T[P] } + +/** + * Generate a fixed-length array of int16_t, + * via genFixedInt16Array() + */ +export interface WCHAR_Array { + buffer: object + byteLength: number + byteOffset: number + length: number +} + +/** + * For 'str16' and 'str' from https://koffi.dev/input + */ +export type WString = string +export type String = string + diff --git a/packages/win32-def/src/lib/config.ts b/packages/win32-def/src/lib/config.ts index b7a4889c..e42ffbc0 100644 --- a/packages/win32-def/src/lib/config.ts +++ b/packages/win32-def/src/lib/config.ts @@ -1,5 +1,6 @@ // dict of windef value -import { LoadSettings } from './ffi.types.js' +import { CallingConvention } from './ffi.types.js' +import { LoadOptions } from './types.js' export const config: Config = { @@ -9,7 +10,9 @@ export interface Config { _WIN64: boolean } -export const settingsDefault: LoadSettings = { - singleton: true, +export const loadOptionsDefault: Omit = { _WIN64: config._WIN64, + convention: CallingConvention.Cdecl, + autoCreateStruct: true, } + diff --git a/packages/win32-def/src/lib/consts/index.consts.ts b/packages/win32-def/src/lib/consts/index.consts.ts index 39f208d1..219719a0 100644 --- a/packages/win32-def/src/lib/consts/index.consts.ts +++ b/packages/win32-def/src/lib/consts/index.consts.ts @@ -1,9 +1,14 @@ +export * from './user32.enum.js' export * from './virtual-key.enum.js' +export * from './winbase.enum.js' export * from './wingdi.enum.js' export * from './winspool.enum.js' export * from './winuser.const.js' export * from './winuser-input.enum.js' export * from './winuser-keybdinput.enum.js' export * from './winuser-mouseinput.enum.js' +export * from './winmsg.enum.js' + +export * from './winspool/PRINTER_STATUS.enum.js' diff --git a/packages/win32-api/src/lib/user32/constants.ts b/packages/win32-def/src/lib/consts/user32.enum.ts similarity index 98% rename from packages/win32-api/src/lib/user32/constants.ts rename to packages/win32-def/src/lib/consts/user32.enum.ts index ecbb5d69..96c1c4ad 100644 --- a/packages/win32-api/src/lib/user32/constants.ts +++ b/packages/win32-def/src/lib/consts/user32.enum.ts @@ -1,6 +1,8 @@ /* eslint-disable no-bitwise */ -// https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx +/** + * @link https://learn.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-showwindow + */ export enum CmdShow { // Hides the window and activates another window. SW_HIDE = 0, diff --git a/packages/win32-def/src/lib/consts/virtual-key.enum.ts b/packages/win32-def/src/lib/consts/virtual-key.enum.ts index 26a07f4d..74a211f0 100644 --- a/packages/win32-def/src/lib/consts/virtual-key.enum.ts +++ b/packages/win32-def/src/lib/consts/virtual-key.enum.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-duplicate-enum-values */ /** * Virtual-Key Codes * @@ -37,7 +38,7 @@ export enum VirtualKey { /** IME Kana mode */ VK_KANA = 0x15, /** IME Hanguel mode(maintained for compatibility; use VK_HANGUL) */ - VK_HANGUEL = 0x15, + // VK_HANGUEL = 0x15, /** IME Hangul mode */ VK_HANGUL = 0x15, /** IME On */ diff --git a/packages/win32-api/src/lib/kernel32/constants.ts b/packages/win32-def/src/lib/consts/winbase.enum.ts similarity index 100% rename from packages/win32-api/src/lib/kernel32/constants.ts rename to packages/win32-def/src/lib/consts/winbase.enum.ts diff --git a/packages/win32-def/src/lib/consts/wingdi.enum.ts b/packages/win32-def/src/lib/consts/wingdi.enum.ts index 137f18d1..f416c60a 100644 --- a/packages/win32-def/src/lib/consts/wingdi.enum.ts +++ b/packages/win32-def/src/lib/consts/wingdi.enum.ts @@ -8,7 +8,7 @@ export const enum DISPLAYCONFIG_ROTATION { DISPLAYCONFIG_ROTATION_ROTATE90 = 2, DISPLAYCONFIG_ROTATION_ROTATE180 = 3, DISPLAYCONFIG_ROTATION_ROTATE270 = 4, - DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF + DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF, } /** @@ -23,7 +23,7 @@ export const enum DISPLAYCONFIG_SCALING { DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4, DISPLAYCONFIG_SCALING_CUSTOM = 5, DISPLAYCONFIG_SCALING_PREFERRED = 128, - DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF + DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF, } /** @@ -36,6 +36,6 @@ export const enum DISPLAYCONFIG_SCANLINE_ORDERING { DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2, DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST, DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3, - DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF + DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF, } diff --git a/packages/win32-def/src/lib/consts/winmsg.enum.ts b/packages/win32-def/src/lib/consts/winmsg.enum.ts new file mode 100644 index 00000000..cbcbbc31 --- /dev/null +++ b/packages/win32-def/src/lib/consts/winmsg.enum.ts @@ -0,0 +1,68 @@ +/** + * @link https://learn.microsoft.com/en-us/windows/win32/winmsg/windowing + * @link https://learn.microsoft.com/zh-cn/windows/win32/winmsg/window-notifications + */ + +export enum WIN_MSG { + /** https://docs.microsoft.com/zh-cn/windows/win32/winmsg/window-messages */ + MN_GETHMENU = 0x01E1, + WM_ERASEBKGND = 0x0014, + WM_GETFONT = 0x0031, + WM_GETTEXT = 0x000D, + WM_GETTEXTLENGTH = 0x000E, + WM_SETFONT = 0x0030, + WM_SETICON = 0x0080, + WM_SETTEXT = 0x000C, + + /** https://docs.microsoft.com/zh-cn/windows/win32/winmsg/window-notifications */ + WM_ACTIVATEAPP = 0x001C, + WM_CANCELMODE = 0x001F, + WM_CHILDACTIVATE = 0x0022, + WM_CLOSE = 0x0010, + WM_CREATE = 0x0001, + WM_DESTROY = 0x0002, + WM_ENABLE = 0x000A, + WM_ENTERSIZEMOVE = 0x0231, + WM_EXITSIZEMOVE = 0x0232, + WM_GETICON = 0x007F, + WM_GETMINMAXINFO = 0x0024, + WM_INPUTLANGCHANGE = 0x0051, + WM_INPUTLANGCHANGEREQUEST = 0x0050, + WM_MOVE = 0x0003, + WM_MOVING = 0x0216, + WM_NCACTIVATE = 0x0086, + WM_NCCALCSIZE = 0x0083, + WM_NCCREATE = 0x0081, + WM_NCDESTROY = 0x0082, + WM_NULL = 0x0000, + WM_QUERYDRAGICON = 0x0037, + WM_QUERYOPEN = 0x0013, + WM_QUIT = 0x0012, + WM_SHOWWINDOW = 0x0018, + WM_SIZE = 0x0005, + WM_SIZING = 0x0214, + WM_STYLECHANGED = 0x007D, + WM_STYLECHANGING = 0x007C, + WM_THEMECHANGED = 0x031A, + WM_USERCHANGED = 0x0054, + WM_WINDOWPOSCHANGED = 0x0047, + WM_WINDOWPOSCHANGING = 0x0046, + + /** https://learn.microsoft.com/en-us/windows/win32/dataxchg/wm-copydata */ + WM_COPYDATA = 0x004A, + + // https://learn.microsoft.com/en-us/windows/win32/menurc/menu-notifications + WM_COMMAND = 0x0111, + WM_CONTEXTMENU = 0x007B, + WM_ENTERMENULOOP = 0x0211, + WM_EXITMENULOOP = 0x0212, + WM_GETTITLEBARINFOEX = 0x033F, + WM_MENUCOMMAND = 0x0126, + WM_MENUDRAG = 0x0123, + WM_MENUGETOBJECT = 0x0124, + WM_MENURBUTTONUP = 0x0122, + WM_NEXTMENU = 0x0213, + WM_UNINITMENUPOPUP = 0x0125, + +} + diff --git a/packages/win32-def/src/lib/consts/winspool.enum.ts b/packages/win32-def/src/lib/consts/winspool.enum.ts index fec55912..c139d793 100644 --- a/packages/win32-def/src/lib/consts/winspool.enum.ts +++ b/packages/win32-def/src/lib/consts/winspool.enum.ts @@ -3,7 +3,6 @@ export enum PrinterEnumFlags { PRINTER_ENUM_DEFAULT = 0x00000001, PRINTER_ENUM_LOCAL = 0x00000002, PRINTER_ENUM_CONNECTIONS = 0x00000004, - PRINTER_ENUM_FAVORITE = 0x00000004, PRINTER_ENUM_NAME = 0x00000008, PRINTER_ENUM_REMOTE = 0x00000010, PRINTER_ENUM_SHARED = 0x00000020, @@ -21,6 +20,6 @@ export enum PrinterEnumFlags { PRINTER_ENUM_ICON8 = 0x00800000, PRINTER_ENUM_HIDE = 0x01000000, PRINTER_ENUM_CATEGORY_ALL = 0x02000000, - PRINTER_ENUM_CATEGORY_3D = 0x04000000 + PRINTER_ENUM_CATEGORY_3D = 0x04000000, } diff --git a/packages/win32-def/src/lib/consts/winspool/PRINTER_STATUS.enum.ts b/packages/win32-def/src/lib/consts/winspool/PRINTER_STATUS.enum.ts new file mode 100644 index 00000000..ce97ea43 --- /dev/null +++ b/packages/win32-def/src/lib/consts/winspool/PRINTER_STATUS.enum.ts @@ -0,0 +1,36 @@ + +/** + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/printer-info-6 + * @link https://github.com/wine-mirror/wine/blob/master/include/winspool.h + */ +export enum PRINTER_STATUS { + unknown = 0, + PRINTER_STATUS_PAUSED = 0x00000001, + PRINTER_STATUS_ERROR = 0x00000002, + PRINTER_STATUS_PENDING_DELETION = 0x00000004, + PRINTER_STATUS_PAPER_JAM = 0x00000008, + PRINTER_STATUS_PAPER_OUT = 0x00000010, + PRINTER_STATUS_MANUAL_FEED = 0x00000020, + PRINTER_STATUS_PAPER_PROBLEM = 0x00000040, + PRINTER_STATUS_OFFLINE = 0x00000080, + PRINTER_STATUS_IO_ACTIVE = 0x00000100, + PRINTER_STATUS_BUSY = 0x00000200, + PRINTER_STATUS_PRINTING = 0x00000400, + PRINTER_STATUS_OUTPUT_BIN_FULL = 0x00000800, + PRINTER_STATUS_NOT_AVAILABLE = 0x00001000, + PRINTER_STATUS_WAITING = 0x00002000, + PRINTER_STATUS_PROCESSING = 0x00004000, + PRINTER_STATUS_INITIALIZING = 0x00008000, + PRINTER_STATUS_WARMING_UP = 0x00010000, + PRINTER_STATUS_TONER_LOW = 0x00020000, + PRINTER_STATUS_NO_TONER = 0x00040000, + PRINTER_STATUS_PAGE_PUNT = 0x00080000, + PRINTER_STATUS_USER_INTERVENTION = 0x00100000, + PRINTER_STATUS_OUT_OF_MEMORY = 0x00200000, + PRINTER_STATUS_DOOR_OPEN = 0x00400000, + PRINTER_STATUS_SERVER_UNKNOWN = 0x00800000, + PRINTER_STATUS_POWER_SAVE = 0x01000000, + PRINTER_STATUS_SERVER_OFFLINE = 0x02000000, + PRINTER_STATUS_DRIVER_UPDATE_NEEDED = 0x04000000, +} + diff --git a/packages/win32-def/src/lib/data.types.ts.bak b/packages/win32-def/src/lib/data.types.ts.bak deleted file mode 100644 index 95379492..00000000 --- a/packages/win32-def/src/lib/data.types.ts.bak +++ /dev/null @@ -1,96 +0,0 @@ -import { BigIntStr } from '@waiting/shared-types' - -import { - ATOM, - HANDLE, - HINSTANCE, - PTR_Addr, - StructInstanceBase, -} from './common.types.js' -import { POINT } from './struct/struct.types.js' - - -export interface WinDataType { - /** uint16 */ - ATOM: ATOM - BOOL: number - BOOLEAN: number - BYTE: number - CCHAR: number - CHAR: number - COLORREF: number - DWORD: number - DWORDLONG: number - DWORD_PTR: PTR_Addr - DWORD32: number - DWORD64: number - FLOAT: number - HACCEL: HANDLE - HALF_PTR: number - HBITMAP: HANDLE - HBRUSH: HANDLE - HCOLORSPACE: HANDLE - HCONV: HANDLE - HCONVLIST: HANDLE - HCURSOR: HANDLE - HDC: HANDLE - HDDEDATA: HANDLE - HDESK: HANDLE - HDROP: HANDLE - HDWP: HANDLE - HENHMETAFILE: HANDLE - HFILE: HANDLE - HFONT: HANDLE - HGDIOBJ: HANDLE - HGLOBAL: HANDLE - HHOOK: HANDLE - HICON: HANDLE - HINSTANCE: HANDLE - HKEY: HANDLE - HKL: HANDLE - HLOCAL: HANDLE - HMENU: HANDLE - HMETAFILE: HANDLE - HMODULE: HINSTANCE - HMONITOR: HANDLE - HPALETTE: HANDLE - HPEN: HANDLE - HRESULT: number - HRGN: HANDLE - HRSRC: HANDLE - HSZ: HANDLE - HWINEVENTHOOK: HANDLE - HWINSTA: HANDLE - HWND: HANDLE - INT: number - INT_PTR: PTR_Addr - INT8: number - INT16: number - INT32: number - INT64: BigIntStr - - /** - * `uint32` or `uint64` used as value usage (memory address) instead of PVOID (Buffer), - * Use `HANDLE` (number) for params defintion of the api, - * @see https://stackoverflow.com/questions/18266626/what-is-the-range-of-a-windows-handle-on-a-64-bits-application/29526711#29526711 - */ - HANDLE: PTR_Addr - LONG_PTR: PTR_Addr - POINT: POINT - ULONG_PTR: PTR_Addr - - WCHAR: number - WCHAR_String: string - WORD: number - -} -/** - * Struct element has functions properts like ref(), defef() - */ -export type DataType = { - [K in keyof T]: T[K] extends object ? (StructInstanceBase & T[K]) : T[K] -} - -// declare const foo: DataType['POINT'] -// export const bar = foo.ref() - diff --git a/packages/win32-def/src/lib/def.enum.ts b/packages/win32-def/src/lib/def.enum.ts index c18c9a1d..f8a8a3ab 100644 --- a/packages/win32-def/src/lib/def.enum.ts +++ b/packages/win32-def/src/lib/def.enum.ts @@ -1,55 +1,56 @@ /* eslint-disable id-length */ /** + * @link https://koffi.dev/input * @link https://tootallnate.github.io/ref/ */ export enum Def { bool = 'bool', - byte = 'byte', + byte = 'int*', int = 'int', - int8 = 'int8', - int16 = 'int16', - int32 = 'int32', - int64 = 'int64', + int8 = 'int8_t', + int16 = 'int16_t', + int32 = 'int32_t', + int64 = 'int64_t', float = 'float', long = 'long', longlong = 'longlong', - ptr = 'pointer', + // ptr = 'pointer', uchar = 'uchar', uint = 'uint', - uint8 = 'uint8', - uint16 = 'uint16', - uint32 = 'uint32', - uint64 = 'uint64', + uint8 = 'uint8_t', + uint16 = 'uint16_t', + uint32 = 'uint32_t', + uint64 = 'uint64_t', ulong = 'ulong', ulonglong = 'ulonglong', ushort = 'ushort', void = 'void', boolPtr = 'bool*', - bytePtr = 'byte*', + bytePtr = 'int*', charPtr = 'char*', - intPtr = 'int*', - int8Ptr = 'int8*', - int16Ptr = 'int16*', - int32Ptr = 'int32*', - int64Ptr = 'int64*', + intPtr = 'int', + int8Ptr = 'int8_t*', + int16Ptr = 'int16_t*', + int32Ptr = 'int32_t*', + int64Ptr = 'int64_t*', floatPtr = 'float*', longPtr = 'long*', uintPtr = 'uint*', - uint8Ptr = 'uint8*', + uint8Ptr = 'uint8_t*', intPtrPtr = 'int**', - uint16Ptr = 'uint16*', - uint32Ptr = 'uint32*', - uint64Ptr = 'uint64*', + uint16Ptr = 'uint16_t*', + uint32Ptr = 'uint32_t*', + uint64Ptr = 'uint64_t*', ulonglongPtr = 'ulonglong*', voidPtr = 'void*', uintPtrPtr = 'uint**', - uint16PtrPtr = 'uint16**', - uint32PtrPtr = 'uint32**', - uint64PtrPtr = 'uint64**', + uint16PtrPtr = 'uint16_t**', + uint32PtrPtr = 'uint32_t**', + uint64PtrPtr = 'uint64_t**', ulonglongPtrPtr = 'ulonglong**', voidPtrPtr = 'void**', } diff --git a/packages/win32-def/src/lib/ffi.types.ts b/packages/win32-def/src/lib/ffi.types.ts index ad33e40d..f08967c1 100644 --- a/packages/win32-def/src/lib/ffi.types.ts +++ b/packages/win32-def/src/lib/ffi.types.ts @@ -1,180 +1,57 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/prefer-ts-expect-error */ -import { BigIntStr, TuplePush as Push } from '@waiting/shared-types' - -import { StringBuffer, UnionInstanceBase } from './common.types.js' -import { Def } from './def.enum.js' +import type { BigIntStr, MethodTypeUnknown } from '@waiting/shared-types' export type _WIN64 = boolean export type _UNICODE = boolean -/* windows data defination type */ -export interface StructDefType { - [prop: string]: Def | StructDefType | StringBuffer | UnionInstanceBase | StructTypeConstructor -} export type StructTypeConstructor = new () => Record -export interface LoadSettings { - singleton: boolean // for DLL.load() - _WIN64?: boolean // default from process.arch -} - - /** - * node-ffi-buffer extends from Buffer - * - * I don't found the way to merge the ffi-buffer types automatically - * so have to copy the def from node-ffi-buffer.d.ts. - * with it hWnd.ref() wihout error TS2339: Property 'ref' does not exist on type 'Buffer'. + * @link https://koffi.dev/functions#calling-conventions */ -// export interface FFIBuffer extends Buffer { -// /** Shorthand for `ref.address`. */ -// address: () => number -// /** Shorthand for `ref.deref`. */ -// deref: () => any -// /** Shorthand for `ref.isNull`. */ -// isNull: () => boolean -// /** Shorthand for `ref.readCString`. */ -// readCString: (offset?: number) => string -// /** Shorthand for `ref.readInt64BE`. */ -// readInt64BE: (offset?: number) => string -// /** Shorthand for `ref.readInt64LE`. */ -// readInt64LE: (offset?: number) => string -// /** Shorthand for `ref.readObject`. */ -// readObject: (offset?: number) => string -// /** Shorthand for `ref.readPointer`. */ -// readPointer: (offset?: number) => string -// /** Shorthand for `ref.readUInt64BE`. */ -// readUInt64BE: (offset?: number) => string -// /** Shorthand for `ref.readUInt64LE`. */ -// readUInt64LE: (offset?: number) => string -// /** Shorthand for `ref.ref`. */ -// ref: () => FFIBuffer -// /** Shorthand for `ref.reinterpret`. */ -// reinterpret: (size: number, offset?: number) => FFIBuffer -// /** Shorthand for `ref.reinterpretUntilZeros`. */ -// reinterpretUntilZeros: (size: number, offset?: number) => FFIBuffer -// /** Shorthand for `ref.writeCString`. */ -// writeCString: (offset: number, input: string, encoding?: string) => void -// /** Shorthand for `ref.writeInt64BE`. */ -// writeInt64BE: (offset: number, input: number | string) => any -// /** Shorthand for `ref.writeInt64LE`. */ -// writeInt64LE: (offset: number, input: number | string) => any -// /** Shorthand for `ref.writeObject`. */ -// writeObject: (offset: number, object: Record) => void // tslint:disable-line -// /** Shorthand for `ref.writePointer`. */ -// writePointer: (offset: number, pointer: FFIBuffer) => void -// /** Shorthand for `ref.writeUInt64BE`. */ -// writeUInt64BE: (offset: number, input: number | string) => any -// /** Shorthand for `ref.writeUInt64LE`. */ -// writeUInt64LE: (offset: number, input: number | string) => any -// /** -// * Generate string for inspecting. -// * String includes the hex-encoded memory address of the Buffer instance. -// */ -// inspect: () => string -// /** add by waiting. below extened via Buffer.prototype by ref.js */ -// hexAddress: () => string -// } -// export { FFIBuffer as Buffer } - +export enum CallingConvention { + Cdecl = '', + Stdcall = '__stdcall', + Fastcall = '__fastcall', + Thiscall = '__thiscall', +} // custom export type PID = number export type PPID = number -export type FnName = string -export type FnParam = string // param type for definition of FFI -export type FnRetType = FnParam -export type FnCallParam = FnParam // each param of calling function -export type FnCallParams = FnCallParam[] | never[] // calling params -export type FnParams = [FnRetType, FnCallParams] // def for ffi [returnType, [calling param, ...]] -// export interface DllFuncs { -// [fn: string]: FnParams -// } -// export type DllFuncs = Record -export type DllFuncs = Record - -/** - * usage: - * ```ts - * import { DModel as M, FModel as FM } from 'win32-def' - * export interface Foo extends FM.DllFuncsModel { - * SDT_OpenPort(port: M.UINT): M.INT - * SDT_ClosePort(): M.INT - * } - * ``` - */ -export interface DllFuncsModel { - [funcName: string]: SyncFnModel -} -export type SyncFnModel = (...args: any[]) => boolean | number | BigIntStr | Buffer | void -export type AsyncFnModel = (...args: any[]) => Promise -export type AsyncSyncFuncModel = SyncFnModel & { - async: (...args: any[]) => void, -} -export interface AsyncFuncModel { - [key: string]: AsyncFnModel +export type FnDefName = string +export type FnDefParam = string // param type for definition of FFI +export type FnDefRetType = FnDefParam +export type FnDefMultipleChoiceParam = FnDefParam[] +/** Runtime input arguments of typeDef */ +export type FnDefArgs = FnDefParam[] // ['int', 'int32', ...] +export type FnDefCallParam = FnDefParam | FnDefMultipleChoiceParam // 'int' | ['PRINTER_INFO_1*', 'PRINTER_INFO_4*'] +/** Input parameters array of typeDef */ +export type FnDefCallParams = readonly FnDefCallParam[] | never[] // ['int', 'int32'] | ['int', ['PRINTER_INFO_1*', 'PRINTER_INFO_4*']] +/** Full parameters include input/output of typeDef */ +export type FnDefFullParams = [FnDefRetType, FnDefCallParams] // def for ffi [returnType, [calling param, ...]] +export type FuncDefListInner = Map<(keyof T) & string, FnDefFullParams> +// export type FuncDefList = Record<(keyof T) & string, any[] | readonly any[]> +export type FuncDefList = { + [K in keyof T as K extends `${string}_Async` ? never : `${K & string}`]: any[] | readonly any[] } -/* eslint-disable @typescript-eslint/indent */ +export type FnDefListMap = Map /** - * Expand FnModel with async() - * typeof arguments and typeof argument result of callback(err: Error, result) - * will be retrieved from input method - * * usage: * ```ts - * export interface SDT extends DllFuncsModel { - * foo: { - * (msg: M.POINT): M.VOID, - * async(msg: M.POINT, cb: (err: Error, result: M.VOINT)): void, - * } - * bar: BarFn - * barz(port: M.INT): M.POINT - * } - * export interface BarFn extends AsyncSyncFuncModel { - * (port: M.INT): M.INT - * async( - * port: M.INT - * cb: (err: Error, code: M.INT) => void, - * ): void + * import * as T from 'win32-def' + * export interface Foo extends FM.DllFuncsModel { + * SDT_OpenPort(port: T.UINT): T.INT + * SDT_ClosePort(): T.INT * } - * - * // Will append async() method to barz() with correct parameter's types of the (last) callback parameter of barz() - * export type SDTFnModel = ExpandFnModel - * // So we can calling async method - * const api: SDTFnModel = .... - * api.barz.async(port, (err, result) => { - * // type of result will get correct typeof Buffer (according to ReresultType of api.barz) automatically - * }) * ``` */ -export type ExpandFnModel = { - [K in keyof T]: 'async' extends keyof T[K] - ? T[K] - : T[K] extends AsyncSyncFuncModel - ? T[K] - : T[K] extends SyncFnModel - ? T[K] & AppendSyncFnWithAsync - : never -} -interface AppendSyncFnWithAsync { - async: ( - ...args: Push, - (err: Error | null | undefined, result: ReturnType) => any> - ) => void -} +export type DllFuncsType = Record -export type PromiseFnModel = { - [K in keyof T]: T[K] extends AsyncFnModel - ? T[K] - : T[K] extends SyncFnModel - ? (...args: Parameters) => Promise> - : never -} - diff --git a/packages/win32-def/src/lib/fixed-buffer.ts b/packages/win32-def/src/lib/fixed-buffer.ts deleted file mode 100644 index ea902939..00000000 --- a/packages/win32-def/src/lib/fixed-buffer.ts +++ /dev/null @@ -1,119 +0,0 @@ -import assert from 'assert' - -// eslint-disable-next-line import/no-extraneous-dependencies -import { types } from 'ref-napi' - -import { StringBuffer } from './common.types.js' - -/** - * Fixed length "Buffer" type, for use in Struct type definitions. - * Like `wchar Name[32]` in C, - * `getter` and `setter` functions are provided to access the buffer contents. - * The starting and tailing terminal-null of returned string via `getter` is removed. - */ -export function wcharBuffer(charLength: number): StringBuffer { - assert(charLength >= 0) - return BufferTypeFactory(charLength * 2, 'ucs2') -} - - -/** - * Fixed length "Buffer" type, for use in Struct type definitions. - * - * Optionally setting the `encoding` param will force to call - * `toString(encoding)` on the buffer returning a String instead. - * - * @see https://github.com/TooTallNate/ref-struct/issues/28#issuecomment-265626611 - * @ref https://gist.github.com/TooTallNate/80ac2d94b950216a2705 - */ -export function BufferTypeFactory(byteLength: number, encoding?: BufferEncoding): StringBuffer { - assert(byteLength >= 0) - - const inst = Object.create(types.byte, { - constructor: { - configurable: true, - enumerable: false, - writable: true, - value: BufferTypeFactory, - }, - - size: { - configurable: true, - enumerable: true, - writable: false, - value: byteLength, - }, - - encoding: { - configurable: true, - enumerable: true, - writable: true, - value: encoding, - }, - - get: { - configurable: true, - enumerable: true, - writable: true, - value: getFn, - }, - - set: { - configurable: true, - enumerable: true, - writable: true, - value: setFn, - }, - }) as StringBuffer - - return inst -} - - -function getFn( - this: StringBuffer, - buffer: Buffer, - offset: number, -): Buffer | string { - - const buf = buffer.subarray(offset, offset + this.size) - if (this.encoding) { - const str = buf.toString(this.encoding) - return str.replace(/^\0+|\0+$/ug, '') - } - return buf -} - -function setFn( - this: StringBuffer, - buffer: Buffer, - offset: number, - value: string | number[] | Buffer, -): void { - - let buf: Buffer - - if (typeof value === 'string') { - assert(this.encoding, 'BufferType.encoding is required when setting a string') - buf = Buffer.from(value, this.encoding) - } - else if (Array.isArray(value)) { - buf = Buffer.from(value) - } - else if (Buffer.isBuffer(value)) { - buf = value - } - else { - throw new TypeError('Buffer instance expected') - } - - - if (buf.length > this.size) { - throw new Error( - `Buffer given is ${buf.length} bytes, but only ${this.size} bytes available`, - ) - } - - buf.copy(buffer, offset) -} - diff --git a/packages/win32-def/src/lib/helper.ts b/packages/win32-def/src/lib/helper.ts deleted file mode 100644 index 9c6e0f5c..00000000 --- a/packages/win32-def/src/lib/helper.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import ref from 'ref-napi' -import StructDi from 'ref-struct-di' -import UnionDi from 'ref-union-di' - -import { LPMSG, LPSTR, LPTSTR, LPWORD, LPWSTR } from './common.def.js' -import { Def } from './def.enum.js' -import { StructDefType, StructTypeConstructor } from './ffi.types.js' -import { wcharBuffer } from './fixed-buffer.js' - - -// const UnionDi = _UnionDi -const Union = UnionDi(ref) -export function UnionType(input: T): StructTypeConstructor { - // @ts-ignore - return Union(input) -} -export function UnionFactory(input: StructDefType): T { - // @ts-ignore - return new Union(input)() as unknown as T -} - -export const defaultStructCharOptions: Required = { - useStringBuffer: true, - maxCharLength: 1024, - CharDefs: [ - LPMSG, - LPSTR, - LPWSTR, - LPTSTR, - LPWORD, - ], -} - -const Struct = StructDi(ref) -export function StructType( - input: T, - options?: StructCharOptions, -): StructTypeConstructor { - // @ts-ignore - return genInitTyp(input, options) -} -export function StructFactory(input: StructDefType, options?: StructCharOptions): T { - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call - return new genInitTyp(input, options)() -} - -function genInitTyp(input: StructDefType, options?: StructCharOptions): StructTypeConstructor { - const opts: Required = { - ...defaultStructCharOptions, - ...options, - } - - const initType = {} as StructDefType - Object.entries(input).forEach(([key, value]) => { - if (opts.useStringBuffer - && typeof value === 'string' - && opts.CharDefs.includes(value)) { - - initType[key] = wcharBuffer(opts.maxCharLength) - } - else if ( - typeof value === 'object' - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - && value - // This is the same check "ref-napi" does to determine if the type - && ! ('size' in value && 'indirection' in value) - ) { - initType[key] = genInitTyp(value as StructDefType, options) - } - else { - initType[key] = value - } - }) - - // @ts-ignore - return Struct(initType) -} - -export interface StructCharOptions { - /** - * @default true - * @description convert property of Struct from POINTER(like LPSTR, LPWSTR) to StringBuffer, - * **Note: typeof value may be WCHAR_String instead of _POINTER** - */ - useStringBuffer?: boolean - /** - * @default 1024 - */ - maxCharLength?: number - /** - * @default [LPMSG, LPSTR, LPWSTR, LPTSTR, LPWORD ] - */ - CharDefs?: Def[] -} - diff --git a/packages/win32-def/src/lib/loader/def.helper.ts b/packages/win32-def/src/lib/loader/def.helper.ts new file mode 100644 index 00000000..d2a41de0 --- /dev/null +++ b/packages/win32-def/src/lib/loader/def.helper.ts @@ -0,0 +1,88 @@ +import assert from 'node:assert' + +import { MethodTypeUnknown } from '@waiting/shared-types' + +import type { + FnDefFullParams, + FnDefName, + FuncDefList, + FuncDefListInner, +} from '##/lib/ffi.types.js' + + +// #region processDefList() + +export function processDefList( + dllFuncs: FuncDefList, + fns: FnDefName[] | readonly FnDefName[] | undefined, +): FuncDefListInner { + + const map = genDefList(dllFuncs) + const map2: FuncDefListInner = new Map() + + if (fns && Array.isArray(fns) && fns.length) { + fns.forEach((fnName) => { + if (fnName.endsWith('_Async')) { + const syncFnName = fnName.replace(/_Async$/u, '') + const data = map.get(syncFnName) + if (data) { + map2.set(syncFnName, data) + } + } + else { // sync + const data = map.get(fnName) + if (data) { + map2.set(fnName, data) + } + } + }) + return map2 + } + + return map +} + + +// #region genDefList() + +/** + * Generate function definitions via converting macro windows data type (like PVOID) to the expected value. + */ +export function genDefList(dllFuncs: FuncDefList): FuncDefListInner { + const ret = typeof dllFuncs === 'function' + ? genListFromClass(dllFuncs) // class def + : genListFromObject(dllFuncs) // const def + return ret +} + + +function genListFromObject(input: object): FuncDefListInner { + const ret: FuncDefListInner = new Map() + for (const fnName of Object.keys(input)) { + // @ts-ignore + const ps = input[fnName] as unknown + if (Array.isArray(ps) && ps.length === 2) { + assert(ps[0] && ps[1], `dellFuncs has no property method name "${fnName}"`) + assert(typeof ps[0] === 'string', `dellFuncs has no property method name "${fnName}"`) + ret.set(fnName, ps as FnDefFullParams) + } + } + return ret +} + +function genListFromClass(input: MethodTypeUnknown): FuncDefListInner { + assert(typeof input === 'function', 'input must be a class') + + const ret: FuncDefListInner = new Map() + for (const key in input) { + // @ts-ignore + const ps = input[key] as unknown + if (Array.isArray(ps) && ps.length === 2) { + assert(ps[0] && ps[1], `dellFuncs has no property method name "${key}"`) + assert(typeof ps[0] === 'string', `dellFuncs has no property method name "${key}"`) + ret.set(key, ps as FnDefFullParams) + } + } + return ret +} + diff --git a/packages/win32-def/src/lib/loader/loader.cache.ts b/packages/win32-def/src/lib/loader/loader.cache.ts new file mode 100644 index 00000000..577ce088 --- /dev/null +++ b/packages/win32-def/src/lib/loader/loader.cache.ts @@ -0,0 +1,121 @@ +import assert from 'node:assert' + +import type { FnDefArgs } from '##/lib/ffi.types.js' +import type { IKoffiLib, KoffiFunction, MultipleChoiceMapperList, MultipleChoiceMapperSet } from '##/lib/types.js' + + +type DllName = string +type FnName = string + +export class LoaderCache { + + static readonly cacheLibMap = new Map() + static readonly regCacheMap = new WeakMap>>() + static readonly multipleChoiceMapperList = new WeakMap() + + /** + * Get function by definition arguments of the function + */ + static getFuncByDefArgs(lib: IKoffiLib, fnName: string, defArgs: FnDefArgs): KoffiFunction | undefined { + assert(defArgs.length > 1, 'runtimeDefArgs.length must > 1') + const map = LoaderCache.getRegisteredFuncMap(lib, fnName) + return map?.get(defArgs) + } + + /** + * Get function definition arguments + */ + static getFnDefArgs(lib: IKoffiLib, fnName: string): FnDefArgs[] { + const cacheMap = LoaderCache.regCacheMap.get(lib) + const map = cacheMap?.get(fnName) + return map ? [...map.keys()] : [] + } + + // #region cacheLibMap + + static getLibByName(dllName: string): IKoffiLib | undefined { + return LoaderCache.cacheLibMap.get(dllName) + } + + static setLibByName(dllName: string, lib: IKoffiLib): void { + LoaderCache.cacheLibMap.set(dllName, lib) + } + + static removeLibByName(dllName: string): void { + LoaderCache.cacheLibMap.delete(dllName) + } + + // #region regCacheMap + + static getRegisteredFunc(lib: IKoffiLib, fnName: string): KoffiFunction | undefined { + const cacheMap = LoaderCache.regCacheMap.get(lib) + const map = cacheMap?.get(fnName) + if (map?.size) { + const arr = map.entries().next().value as [FnDefArgs, KoffiFunction] | undefined + const ret = arr?.[1] + return ret + } + } + + /** + * + * @note return Map | undefined + */ + static getRegisteredFuncMap(lib: IKoffiLib, fnName: string): Map | undefined { + const cacheMap = LoaderCache.regCacheMap.get(lib) + return cacheMap?.get(fnName) + } + + static setRegisteredFuncToCache(lib: IKoffiLib, name: string, fn: KoffiFunction, defArgs: FnDefArgs): void { + let map1 = LoaderCache.regCacheMap.get(lib) + if (! map1) { + map1 = new Map>() + LoaderCache.regCacheMap.set(lib, map1) + } + + let map2 = map1.get(name) + if (! map2) { + map2 = new Map() + map1.set(name, map2) + } + map2.set([...defArgs], fn) + } + + static removeRegisteredFuncFromCache(lib: IKoffiLib, name: string): void { + const cacheMap = LoaderCache.regCacheMap.get(lib) + cacheMap?.delete(name) + } + + // #region multipleChoiceMapperList + + /** + * Get multiple choice list mapper by function name, return Set + * + */ + static getMultipleChoiceListMapperSet(lib: IKoffiLib, fnName: string): MultipleChoiceMapperSet | undefined { + return LoaderCache.multipleChoiceMapperList.get(lib)?.get(fnName) + } + + static updateMultipleChoiceListMapper(lib: IKoffiLib, fnMapperList: MultipleChoiceMapperList): void { + let map = LoaderCache.multipleChoiceMapperList.get(lib) + if (! map) { + map = new Map() + LoaderCache.multipleChoiceMapperList.set(lib, fnMapperList) + } + fnMapperList.forEach((fnMappers, fnName) => { + const set = map.get(fnName) + if (set) { + fnMappers.forEach(fn => set.add(fn)) + } + else { + map.set(fnName, fnMappers) + } + }) + } + + static removeMultipleChoiceListMapper(lib: IKoffiLib, fnName: string): void { + LoaderCache.multipleChoiceMapperList.get(lib)?.delete(fnName) + } + +} + diff --git a/packages/win32-def/src/lib/loader/loader.helper.ts b/packages/win32-def/src/lib/loader/loader.helper.ts new file mode 100644 index 00000000..d55bd773 --- /dev/null +++ b/packages/win32-def/src/lib/loader/loader.helper.ts @@ -0,0 +1,381 @@ +import assert from 'node:assert' + +import { expandFFIParamArray } from '@waiting/shared-core' +import koffi from 'koffi' + +import { loadOptionsDefault } from '##/lib/config.js' +import { Def } from '##/lib/def.enum.js' +import { + type FuncDefListInner, + type FnDefArgs, + type FnDefFullParams, + CallingConvention, +} from '##/lib/ffi.types.js' +import { structFactoryMap } from '##/lib/struct/struct.factory-map.js' +import type { + FLib, + IKoffiLib, + KoffiFunction, + LoadOptions, + MultipleChoiceMapperList, + UpdateMultipleChoiceMapperOptions, + StructFactory, +} from '##/lib/types.js' + +import { LoaderCache } from './loader.cache.js' +import type { + BindOptions, + KoffiFunctionLike, + RegisterFunctionOpts, + RegisterFunctionOptsInner, +} from './loader.types.js' +import { createProxyMethod, updateMultipleChoiceMapperToCache } from './multiple-choice-param.helper.js' + + +export const isArch64 = process.arch.includes('64') + +export const defGroupNumber: Def[] = [ + Def.float, Def.int16, Def.int32, Def.int64, Def.int8, + Def.uint16, Def.uint32, Def.uint64, Def.uint8, + Def.long, Def.ulong, Def.longlong, Def.ulonglong, +] + +export const defGroupPointer: Def[] = [ + Def.boolPtr, Def.bytePtr, Def.charPtr, Def.intPtr, Def.int8Ptr, + Def.int16Ptr, Def.int32Ptr, Def.int64Ptr, Def.floatPtr, + Def.longPtr, Def.uintPtr, Def.uint8Ptr, + Def.intPtrPtr, Def.uint16Ptr, Def.uint32Ptr, Def.uint64Ptr, + Def.ulonglongPtr, Def.voidPtr, + Def.uintPtrPtr, Def.uint16PtrPtr, Def.uint32PtrPtr, Def.uint64PtrPtr, + Def.ulonglongPtrPtr, Def.voidPtrPtr, +] + + +// #region loadIKoffiLibAndBindProperties + +export function loadIKoffiLib(libName: string): IKoffiLib { + const lib = koffi.load(libName) + assert(lib, `load library ${libName} failed`) + LoaderCache.setLibByName(libName, lib) + return lib +} + +export function bindFLibExtMethods(libName: string, lib: IKoffiLib, inst: FLib) { + assert(lib, `load library undefined`) + + if (typeof inst.unload === 'undefined') { + Object.defineProperty(inst, 'unload', { + enumerable: false, + value: () => { + LoaderCache.removeLibByName(libName) + lib.unload() + }, + }) + } + + if (typeof inst.updateMultipleChoiceMapper === 'undefined') { + Object.defineProperty(inst, 'updateMultipleChoiceMapper', { + enumerable: false, + value: function (this: IKoffiLib, opts2: UpdateMultipleChoiceMapperOptions) { + updateMultipleChoiceMapperToCache({ + ...opts2, + lib: this, + }) + }.bind(lib), + }) + } +} + +// #region bindMethodsFromFuncDefList + + +export function bindMethodsFromFuncDefList(options: BindOptions): void { + const { lib, inst, loadOptions, funcDefList, multipleChoiceMapperList: multipleChoiceMapper } = options + + for (const [name, params] of funcDefList) { + const funcs = registerFunction({ + lib, + fnName: name, + fnFullParams: params, + /* c8 ignore next */ + convention: loadOptions.convention ?? CallingConvention.Cdecl, + forceRegister: !! loadOptions.forceRegister, + }) + + const { size } = funcs + if (size === 1) { + for (const [, fn] of funcs.entries()) { + bindMethod(inst, name, fn) + } + } + else if (size > 1) { + if (! multipleChoiceMapper) { + console.info(`multipleChoiceMapper should be set and be a function when multiple choice used. + Syntax: (fnName: string, params: string[]) => string[] + const user32 = load({ + dll: 'user32.dll', + dllFuncs: defWin32, + multipleChoiceMapperList: multipleChoiceMapperList + }) + // OR + const user32 = load({ + dll: 'user32.dll', + dllFuncs: defWin32, + }) + user32.updateMultipleChoiceMapper({ mapperList: mapperList }) + `) + } + + const fn = createProxyMethod({ + lib, + name, + fnDefRetType: params[0], + fnDefCallParams: params[1], + }) + bindMethod(inst, name, fn) + } + } +} + + +function bindMethod(inst: FLib, name: string, fn: KoffiFunction | KoffiFunctionLike): void { + const nameSync = name + if (typeof inst[nameSync] === 'undefined') { + Object.defineProperty(inst, nameSync, { + enumerable: true, + value: fn, + }) + } + + const nameAsync = `${name}_Async` + if (typeof inst[nameAsync] === 'undefined') { + Object.defineProperty(inst, nameAsync, { + enumerable: true, + value: (...args: unknown[]) => callFnAsync(fn, args), + }) + } +} + +function callFnAsync(fn: KoffiFunction | KoffiFunctionLike, args: unknown[]) { + return new Promise((done, reject) => { + const asyncCallback = (err: Error | undefined, result: unknown) => { + if (err) { + reject(err) + return + } + done(result) + } + fn.async(...args, asyncCallback) + }) +} + + + +export function parse_settings(options: LoadOptions): LoadOptions { + const opts: LoadOptions = { + ...loadOptionsDefault, + ...options, + } + return opts +} + +// #region createStructFromFuncDefList + +export function createStructFromFuncDefList(input: FuncDefListInner): void { + const structFactories = prepareStructFromFuncDefList(input) + structFactories.forEach((factory) => { + factory() + }) +} + +function prepareStructFromFuncDefList(input: FuncDefListInner): Set { + const fns = new Set() + for (const [name, params] of input) { + try { + const p2 = expandFFIParamArray(params[1]) + p2.forEach((args: string[]) => { + const structSet = retrieveStructFactoryFromParams(args) + if (structSet.size) { + structSet.forEach((fn) => { + fns.add(fn) + }) + } + }) + } + catch (ex) { + assert(ex instanceof Error) + const msg = `Failed to create struct for function: ${name}, you may need to create it manually. + Error: ${ex.message}` + throw new Error(msg, { cause: ex }) + } + } + return fns +} + +function retrieveStructFactoryFromParams(params: string[]): Set { + const fns = new Set() + + const structNames = retrieveStructTypeStringFromParams(params) + if (! structNames.length) { + return fns + } + + const failed: string[] = [] + + structNames.forEach((key) => { + const factoryName = `${key}_Factory` + const fn = structFactoryMap.get(factoryName) + if (fn) { + fns.add(fn) + } + else { + failed.push(key) + } + }) + + if (failed.length) { + throw new Error(`Failed to find struct factory for: ${failed.join(', ')}`) + } + + return fns +} + +const DefValuesSet = new Set(Object.values(Def)) +// @ts-expect-error +DefValuesSet.add('char') + +function retrieveStructTypeStringFromParams(params: string[]): string[] { + const ret: string[] = [] + // '_Inout_ POINT*' or 'POINT *' or 'POINT*' + const regex = /\b(\w+)\s?\*$/u + params.map((val) => { + const match = val.match(regex) + const key = match?.[1]?.trim() + if (key) { + // if Def contains key, then skip + // @ts-expect-error + if (DefValuesSet.has(key)) { + return + } + ret.push(key) + } + }) + + return ret +} + + +// #region registerFunction + +/** + * @note do not call it directly, use `load()` instead! + * Case of making sure the library is loaded only once + */ +function registerFunction(options: RegisterFunctionOpts): Map { + const { lib, fnName, fnFullParams: params, convention = CallingConvention.Stdcall } = options + const cache = options.forceRegister ? null : LoaderCache.getRegisteredFuncMap(lib, fnName) + if (cache?.size) { + return cache + } + + const map = new Map() + const { [0]: retType, [1]: args } = params + if (args.length === 0) { + const params2 = [retType, []] as FnDefFullParams + // @ts-expect-error params2 is FnDefParams + const func = _registerFunction({ lib, fnName: fnName, fnFullParams: params2, convention }) + map.set([], func) + return map + } + + // 对于 args 每个成员检查是否为数组,是则迭代处理每个组合进行多次绑定方法 + const ps = expandFFIParamArray(args) + + ps.forEach((args2) => { + const params2 = [retType, args2] as FnDefFullParams + // @ts-expect-error params2 is FnDefParams + const func = _registerFunction({ lib, fnName: fnName, fnFullParams: params2, convention }) + map.set(args2, func) + }) + + return map +} + +function _registerFunction(options: RegisterFunctionOptsInner): KoffiFunction { + const { lib, fnName, fnFullParams, convention = CallingConvention.Stdcall } = options + const { [0]: retType, [1]: args } = fnFullParams + assert(retType, 'retType is empty') + assert(args, 'args is empty') + + // let func: KoffiFunction + // const func = user32.func('GetCursorPos', 'int', [`_Out_ ${comb.pointer}`]) + // switch (convention) { + // case CallingConvention.Cdecl: + // func = lib.func(fnName, retType, args) + // break + + // default: + // func = lib.func(convention, fnName, retType, args) + // } + const func = convention ? lib.func(convention, fnName, retType, args) : lib.func(fnName, retType, args) + // console.log(func.info) + LoaderCache.setRegisteredFuncToCache(lib, fnName, func, args) + return func +} + +// #region SaveFnMultipleChoiceMapper + +export function saveFnMultipleChoiceMapperList(lib: IKoffiLib, fnMultipleChoiceMapperList: MultipleChoiceMapperList): void { + assert(fnMultipleChoiceMapperList.size > 0, 'options.fnMultipleChoiceMapperList contains no item') + LoaderCache.updateMultipleChoiceListMapper(lib, fnMultipleChoiceMapperList) +} + +/* +export function prepareDllFile(file: string): string { + + if (file.startsWith('file://')) { + return file + } + else if (file.startsWith('http://') || file.startsWith('https://')) { + return file + } + else if (file.startsWith('/')) { + return file + } + try { + const stat = statSync(file) + if (stat.isFile()) { + return file + } + } + catch { + // void + } + + const { HOME, WINDIR } = process.env + assert(HOME, 'HOME is not defined') + assert(WINDIR, 'WINDIR is not defined') + + const sys32dir = `${WINDIR}/system32` + const path = `${sys32dir}/${file}` + const target = `${HOME}/${file}.dll` + + const stat = statSync(path) + if (! stat.isFile()) { + throw new Error(`${file} is not found in path: "${path}"`) + } + + try { + const stat2 = statSync(target) + if (stat2.isFile()) { + return target + } + copyFileSync(path, target) + } + catch { + copyFileSync(path, target) + } + + return target +} */ + diff --git a/packages/win32-def/src/lib/loader/loader.ts b/packages/win32-def/src/lib/loader/loader.ts new file mode 100644 index 00000000..c8a3d332 --- /dev/null +++ b/packages/win32-def/src/lib/loader/loader.ts @@ -0,0 +1,54 @@ +import assert from 'node:assert' + +import type { DllFuncsType } from '##/lib/ffi.types.js' +import type { LoadOptions, FLib } from '##/lib/types.js' + +import { processDefList } from './def.helper.js' +import { LoaderCache } from './loader.cache.js' +import { + bindFLibExtMethods, + bindMethodsFromFuncDefList, + createStructFromFuncDefList, + loadIKoffiLib, + parse_settings, + saveFnMultipleChoiceMapperList, +} from './loader.helper.js' + + +export function load(options: LoadOptions): FLib { + const { dll, dllFuncs, usedFuncNames } = options + + // const libName = dll.endsWith('.drv') ? prepareDllFile(dll) : dll + const libName = dll + const opts = parse_settings(options) + const funcDefListMap = processDefList(dllFuncs, usedFuncNames) + + assert(dllFuncs) + const inst = {} as FLib + + let lib = LoaderCache.getLibByName(libName) + if (! lib) { + lib = loadIKoffiLib(libName) + } + + if (options.multipleChoiceMapperList) { + saveFnMultipleChoiceMapperList(lib, options.multipleChoiceMapperList) + } + + if (opts.autoCreateStruct) { + createStructFromFuncDefList(funcDefListMap) + } + + bindMethodsFromFuncDefList({ + lib, + inst, + loadOptions: opts, + funcDefList: funcDefListMap, + multipleChoiceMapperList: opts.multipleChoiceMapperList, + forceRegister: !! opts.forceRegister, + }) + + bindFLibExtMethods(libName, lib, inst) + + return inst as FLib +} diff --git a/packages/win32-def/src/lib/loader/loader.types.ts b/packages/win32-def/src/lib/loader/loader.types.ts new file mode 100644 index 00000000..669f2384 --- /dev/null +++ b/packages/win32-def/src/lib/loader/loader.types.ts @@ -0,0 +1,88 @@ +/* c8 ignore start */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { AsyncMethodType, MethodType } from '@waiting/shared-types' + +import { + type FuncDefListInner, + type DllFuncsType, + type FnDefFullParams, + type FnDefRetType, + type FnDefParam, + CallingConvention, + FnDefCallParams, +} from '##/lib/ffi.types.js' +import type { IKoffiLib, FLib, LoadOptions, MultipleChoiceMapperList } from '##/lib/types.js' + + +export interface BindOptions { + lib: IKoffiLib + inst: FLib + loadOptions: LoadOptions + funcDefList: FuncDefListInner + multipleChoiceMapperList: MultipleChoiceMapperList | undefined + /** + * Force re-register the library, overwriting the existing one + * @default false + */ + forceRegister: boolean +} + + +export interface RegisterFunctionOpts { + /** + * DLL library, + * lib = koffi.load('user32.dll') + */ + lib: IKoffiLib + /** function name */ + fnName: string + /** function parameters */ + fnFullParams: FnDefFullParams + /** + * Calling convention + * @default 'Stdcall' (for Windows) + * @link https://koffi.dev/functions#calling-conventions + */ + convention?: CallingConvention + /** + * Force re-register the library, overwriting the existing one + */ + forceRegister: BindOptions['forceRegister'] +} + +export interface RegisterFunctionOptsInner { + lib: IKoffiLib + fnName: string + fnFullParams: [FnDefRetType, FnDefParam[]] + convention?: CallingConvention +} + + +export interface CreateProxyMethodOptions { + lib: IKoffiLib + name: string + fnDefRetType: FnDefParam + fnDefCallParams: FnDefCallParams +} + + +export interface KoffiFunctionLike { + (...args: any[]): any + async: (...args: any[]) => any + info: { + name: string, + fnDefRetType: FnDefRetType, + fnDefCallParams: FnDefCallParams, + } +} + +export interface CreateKoffiFunctionOpts { + name: string + fnDefRetType: FnDefRetType + fnDefCallParams: FnDefCallParams + funcSync: MethodType + funcAsync: AsyncMethodType +} + + +/* c8 ignore stop */ diff --git a/packages/win32-def/src/lib/loader/multiple-choice-param.helper.ts b/packages/win32-def/src/lib/loader/multiple-choice-param.helper.ts new file mode 100644 index 00000000..ccb5db20 --- /dev/null +++ b/packages/win32-def/src/lib/loader/multiple-choice-param.helper.ts @@ -0,0 +1,146 @@ +import assert from 'node:assert' + +import type { FnDefArgs } from '##/lib/ffi.types.js' +import type { IKoffiLib, MultipleChoiceMapperList, MultipleChoiceMapperSet } from '##/lib/types.js' + +import { LoaderCache } from './loader.cache.js' +import type { CreateProxyMethodOptions, CreateKoffiFunctionOpts, KoffiFunctionLike } from './loader.types.js' + + +export function createProxyMethod(options: CreateProxyMethodOptions): KoffiFunctionLike { + const { name, fnDefRetType, fnDefCallParams, lib } = options + + const fnDefArgs = LoaderCache.getFnDefArgs(lib, name) + assert(fnDefArgs.length > 0, 'fnDefArgs.length <= 0') + + const proxyFn = createKoffiFunctionLike({ + name, + fnDefRetType, + fnDefCallParams, + funcSync: (...args: unknown[]) => createExecutionFn({ lib, name, args, type: 'sync' }), + funcAsync: (...args: unknown[]) => createExecutionFn>({ lib, name, args, type: 'async' }), + }) + + return proxyFn +} + +interface CreateFnOptions { + type: 'sync' | 'async' + lib: IKoffiLib + name: string + args: unknown[] +} + +function createExecutionFn(options: CreateFnOptions): R { + const { lib, name, args, type } = options + + // args includes the last callback function for async call + const pureArgs = type === 'async' ? args.slice(0, -1) : args + + const fnDefArgs = LoaderCache.getFnDefArgs(lib, name) + assert(fnDefArgs.length > 0, 'fnDefArgs.length <= 0') + + const runtimeDefArgs = multipleChoiceMapperProcessor(lib, name, pureArgs) + const func = LoaderCache.getFuncByDefArgs(lib, name, runtimeDefArgs) + assert(typeof func === 'function', `Function ${name} not found in cache, For: + args: ${JSON.stringify(runtimeDefArgs)}, + fnDefCallParamsExpanded: ${JSON.stringify(fnDefArgs)} `) + if (type === 'async') { + return func.async(...args) as R + } + else { + return func(...args) as R + } +} + +function multipleChoiceMapperProcessor( + lib: IKoffiLib, + fnName: string, + runtimeArgs: unknown[], +): T[number] { + + const fnDefCallParamsExpanded = LoaderCache.getFnDefArgs(lib, fnName) + assert(fnDefCallParamsExpanded.length > 0, 'fnDefArgs.length <= 0') + + const mapperList = LoaderCache.getMultipleChoiceListMapperSet(lib, fnName) + assert(mapperList && mapperList.size > 0, `multiple choice mapper not found for ${fnName}. It's may not be set.`) + + let matched: T[number] | undefined + for (const mapper of mapperList) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const res = mapper(fnName, runtimeArgs, fnDefCallParamsExpanded) + if (res) { + assert(Array.isArray(res), `mapper must return an array`) + assert(res.length > 0, `fnDefArgs not matched for ${fnName}. + matchArgs: none, + fnDefCallParamsExpanded: ${JSON.stringify(fnDefCallParamsExpanded)}`) + + matched = res + break + } + // try next mapper if return undefined + } + + assert(matched, `fnDefArgs not matched for ${fnName}. + Check if missing function fnDefArgs, like + EnumPrintersW: [D.BOOL, + [ + D.DWORD, + D.String, + D.DWORD, + [\`_Out_ \${S.PPRINTER_INFO_1}\`, \`_Out_ \${S.PPRINTER_INFO_4}\`], <== missing PPRINTER_INFO_5 + D.DWORD, + D.LPDWORD, + D.LPDWORD, + ]], + . + `) + return matched +} + + +function createKoffiFunctionLike(options: CreateKoffiFunctionOpts): KoffiFunctionLike { + const { name, fnDefRetType, fnDefCallParams, funcSync, funcAsync } = options + + const info: KoffiFunctionLike['info'] = { + name, + fnDefRetType, + fnDefCallParams, + } + Object.defineProperty(funcSync, 'info', { + value: info, + }) + Object.defineProperty(funcSync, 'async', { + value: funcAsync, + }) + + return funcSync as KoffiFunctionLike +} + +// #region updateMultipleChoiceMapperToCache + +export interface UpdateMultipleChoiceMapperToCacheOptions { + lib: IKoffiLib + fnName?: string + mapperSet?: MultipleChoiceMapperSet + mapperList?: MultipleChoiceMapperList +} + +export function updateMultipleChoiceMapperToCache(options: UpdateMultipleChoiceMapperToCacheOptions): void { + const { lib, fnName, mapperSet, mapperList } = options + if (mapperList?.size) { + LoaderCache.updateMultipleChoiceListMapper(lib, mapperList) + } + + if (fnName && mapperSet?.size) { + const set = LoaderCache.getMultipleChoiceListMapperSet(lib, fnName) + if (set) { + for (const mapper of mapperSet) { + set.add(mapper) + } + } + else { + LoaderCache.updateMultipleChoiceListMapper(lib, new Map([[fnName, mapperSet]])) + } + } +} diff --git a/packages/win32-def/src/lib/struct/comctl/INITCOMMONCONTROLSEX.ts b/packages/win32-def/src/lib/struct/comctl/INITCOMMONCONTROLSEX.ts new file mode 100644 index 00000000..6e57897e --- /dev/null +++ b/packages/win32-def/src/lib/struct/comctl/INITCOMMONCONTROLSEX.ts @@ -0,0 +1,36 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'INITCOMMONCONTROLSEX' +const ptr = `${key}*` as const +const init: StructInitType = { + dwSize: D.DWORD, + dwICC: D.DWORD, +} as const + + +/** + * INITCOMMONCONTROLSEX structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-initcommoncontrolsex + */ +export function INITCOMMONCONTROLSEX_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['dwSize']) +} + +/** + * INITCOMMONCONTROLSEX structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-initcommoncontrolsex + */ +export interface INITCOMMONCONTROLSEX_Type { + dwSize: T.DWORD + dwICC: T.DWORD +} + +export const LPINITCOMMONCONTROLSEX = ptr +export const INITCOMMONCONTROLSEX_Name = key +export const INITCOMMONCONTROLSEX_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/comctl/comctl.index.ts b/packages/win32-def/src/lib/struct/comctl/comctl.index.ts new file mode 100644 index 00000000..148d04eb --- /dev/null +++ b/packages/win32-def/src/lib/struct/comctl/comctl.index.ts @@ -0,0 +1,3 @@ + +export * from './INITCOMMONCONTROLSEX.js' + diff --git a/packages/win32-def/src/lib/struct/index.struct.types.ts b/packages/win32-def/src/lib/struct/index.struct.types.ts deleted file mode 100644 index ab914b2c..00000000 --- a/packages/win32-def/src/lib/struct/index.struct.types.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export * from './struct.types.js' -export * from './wingdi.types.js' -export * from './winspool.types.js' -export * from './winuser.types.js' diff --git a/packages/win32-def/src/lib/struct/minwinbase/FILETIME.ts b/packages/win32-def/src/lib/struct/minwinbase/FILETIME.ts new file mode 100644 index 00000000..1201bab5 --- /dev/null +++ b/packages/win32-def/src/lib/struct/minwinbase/FILETIME.ts @@ -0,0 +1,36 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'FILETIME' +const ptr = `${key}*` as const +const init: StructInitType = { + dwLowDateTime: D.DWORD, + dwHighDateTime: D.DWORD, +} as const + + +/** + * FILETIME structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + */ +export function FILETIME_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * FILETIME structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + */ +export interface FILETIME_Type { + dwLowDateTime: T.DWORD + dwHighDateTime: T.DWORD +} + +export const LPFILETIME = ptr +export const LPFILETIME_Name = key +export const FILETIME_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/minwinbase/SYSTEMTIME.ts b/packages/win32-def/src/lib/struct/minwinbase/SYSTEMTIME.ts new file mode 100644 index 00000000..984637ef --- /dev/null +++ b/packages/win32-def/src/lib/struct/minwinbase/SYSTEMTIME.ts @@ -0,0 +1,48 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'SYSTEMTIME' +const ptr = `${key}*` as const +const init: StructInitType = { + wYear: D.WORD, + wMonth: D.WORD, + wDayOfWeek: D.WORD, + wDay: D.WORD, + wHour: D.WORD, + wMinute: D.WORD, + wSecond: D.WORD, + wMilliseconds: D.WORD, +} as const + + +/** + * SYSTEMTIME structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime + */ +export function SYSTEMTIME_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * SYSTEMTIME structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime + */ +export interface SYSTEMTIME_Type { + wYear: T.WORD + wMonth: T.WORD + wDayOfWeek: T.WORD + wDay: T.WORD + wHour: T.WORD + wMinute: T.WORD + wSecond: T.WORD + wMilliseconds: T.WORD +} + +export const LPSYSTEMTIME = ptr +export const SYSTEMTIME_Name = key +export const SYSTEMTIME_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/minwinbase/minwinbase.index.ts b/packages/win32-def/src/lib/struct/minwinbase/minwinbase.index.ts new file mode 100644 index 00000000..019ae3bc --- /dev/null +++ b/packages/win32-def/src/lib/struct/minwinbase/minwinbase.index.ts @@ -0,0 +1,4 @@ + +export * from './FILETIME.js' +export * from './SYSTEMTIME.js' + diff --git a/packages/win32-def/src/lib/struct/struct.cache.ts b/packages/win32-def/src/lib/struct/struct.cache.ts new file mode 100644 index 00000000..dd1f7116 --- /dev/null +++ b/packages/win32-def/src/lib/struct/struct.cache.ts @@ -0,0 +1,44 @@ +import assert from 'node:assert' + +import { StructDetail } from '##/lib/types.js' + + +export class StructUnionCache { + static readonly cacheStructMap = new Map() + static readonly cacheUnionMap = new Map() + + // #region STRUCT + + static getStruct(key: string): StructDetail | undefined { + assert(key, `key is empty`) + return StructUnionCache.cacheStructMap.get(key) + } + + static setStruct(key: string, value: StructDetail): void { + assert(key, `key is empty`) + StructUnionCache.cacheStructMap.set(key, value) + } + + static removeStruct(key: string): boolean { + assert(key, `key is empty`) + return StructUnionCache.cacheStructMap.delete(key) + } + + // #region UNION + + static getUnion(key: string): StructDetail | undefined { + assert(key, `key is empty`) + return StructUnionCache.cacheUnionMap.get(key) + } + + static setUnion(key: string, value: StructDetail): void { + assert(key, `key is empty`) + StructUnionCache.cacheUnionMap.set(key, value) + } + + static removeUnion(key: string): boolean { + assert(key, `key is empty`) + return StructUnionCache.cacheUnionMap.delete(key) + } +} + diff --git a/packages/win32-def/src/lib/struct/struct.def.ts b/packages/win32-def/src/lib/struct/struct.def.ts deleted file mode 100644 index 9753e136..00000000 --- a/packages/win32-def/src/lib/struct/struct.def.ts +++ /dev/null @@ -1,216 +0,0 @@ -/* eslint-disable id-length */ -// windows data types struct for ref-struct module https://github.com/TooTallNate/ref-struct -/** - * Complex structure see: - * https://github.com/waitingsong/node-win32-api/blob/master/packages/win32-api/src/data-struct-ext/ -*/ - -import { - ATOM, - BYTE, - DWORD, - HANDLE, - HBRUSH, - HCURSOR, - HICON, - HINSTANCE, - HWND, - INT, - LONG, - LPARAM, - LPCTSTR, - PVOID, - PWSTR, - UINT, - ULONG, - ULONG_PTR, - USHORT, - WNDPROC, - WORD, - WPARAM, -} from '../common.def.js' -import { StructType } from '../helper.js' - - -/** - * Struct usage: - * - * import * as Struct from 'ref-struct'; - * import { DStruct as DS, DModel as M } from 'win32-api'; - * - * const point: M.PointStruct = new Struct(DS.POINT)(); - * point.x = 100; - * point.y = 200; - * // const buf = point.ref() - * - */ - -/** https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx */ -export const POINT = { - x: LONG, - y: LONG, -} as const - -/** - * @link https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-pointl - */ -export const POINTL = { - x: LONG, - y: LONG, -} as const - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-alttabinfo */ -export const ALTTABINFO = { - cbSize: DWORD, - cItems: INT, - cColumns: INT, - cRows: INT, - iColFocus: INT, - iRowFocus: INT, - cxItem: INT, - cyItem: INT, - ptStart: StructType(POINT), -} as const - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-copydatastruct */ -export const COPYDATASTRUCT = { - dwData: ULONG_PTR, - cbData: DWORD, - lpData: PVOID, -} as const - - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taghardwareinput */ -export const HARDWAREINPUT = { - uMsg: DWORD, - wParamL: WORD, - wParamH: WORD, -} as const - -export const INITCOMMONCONTROLSEX = { - dwSize: DWORD, - dwICC: DWORD, -} as const - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagkeybdinput */ -export const KEYBDINPUT = { - wVk: WORD, - wScan: WORD, - dwFlags: DWORD, - time: DWORD, - dwExtraInfo: ULONG_PTR, -} as const - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagmouseinput */ -export const MOUSEINPUT = { - dx: LONG, - dy: LONG, - mouseData: DWORD, - dwFlags: DWORD, - time: DWORD, - dwExtraInfo: ULONG_PTR, -} as const - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg */ -export const MSG = { - hwnd: HWND, - message: UINT, - wParam: WPARAM, - lParam: LPARAM, - time: DWORD, - pt: StructType(POINT), - lPrivate: DWORD, -} as const - - -export const PROCESS_BASIC_INFORMATION = { - Reserved1: PVOID, - PebBaseAddress: PVOID, // PPEB - Reserved2: PVOID, - UniqueProcessId: ULONG_PTR, - InheritedFromUniqueProcessId: PVOID, -} as const - - -export const UNICODE_STRING = { - Length: USHORT, - MaximumLength: USHORT, - Buffer: PWSTR, -} as const - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawhid */ -export const RAWHID = { - dwSizeHid: DWORD, - dwCount: DWORD, - /** bRawData[1] */ - bRawData: BYTE, -} as const - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-rawinputdevicelist */ -export const RAWINPUTDEVICELIST = { - hDevice: HANDLE, - dwType: DWORD, -} as const - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawinputheader */ -export const RAWINPUTHEADER = { - dwType: DWORD, - dwSize: DWORD, - hDevice: HANDLE, - wParam: WPARAM, -} as const - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawkeyboard */ -export const RAWKEYBOARD = { - MakeCode: USHORT, - Flags: USHORT, - Reserved: USHORT, - VKey: USHORT, - Message: UINT, - ExtraInformation: ULONG, -} as const - - -/** https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms633577(v=vs.85).aspx */ -export const WNDCLASSEX = { - cbSize: UINT, - style: UINT, - // 'lpfnWndProc': ffi.Function('int32', ['pointer', 'uint32', 'int32', 'uint32']) , - lpfnWndProc: WNDPROC, - cbClsExtra: INT, - cbWndExtra: INT, - hInstance: HINSTANCE, - hIcon: HICON, - hCursor: HCURSOR, - hbrBackground: HBRUSH, - lpszMenuName: LPCTSTR, - lpszClassName: LPCTSTR, - hIconSm: HICON, -} as const - -export const RECT = { - left: LONG, - top: LONG, - right: LONG, - bottom: LONG, -} as const - -export const WINDOWINFO = { - cbSize: DWORD, - rcWindow: RECT, - rcClient: RECT, - dwStyle: DWORD, - dwExStyle: DWORD, - dwWindowStatus: DWORD, - cxWindowBorders: UINT, - cyWindowBorders: UINT, - atomWindowType: ATOM, - wCreatorVersion: WORD, -} as const - -/** https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime */ -export const FILETIME = { - dwLowDateTime: DWORD, - dwHighDateTime: DWORD, -} as const - diff --git a/packages/win32-def/src/lib/struct/struct.factory-map.ts b/packages/win32-def/src/lib/struct/struct.factory-map.ts new file mode 100644 index 00000000..cb16274d --- /dev/null +++ b/packages/win32-def/src/lib/struct/struct.factory-map.ts @@ -0,0 +1,15 @@ +import type { StructFactory } from '##/lib/types.js' + +import * as Structs from './struct.index.js' + + +export const structFactoryMap = new Map() + +if (! structFactoryMap.size) { + Object.entries(Structs).forEach(([key, val]) => { + if (typeof val === 'function') { + structFactoryMap.set(key, val) + } + }) +} + diff --git a/packages/win32-def/src/lib/struct/struct.helper.ts b/packages/win32-def/src/lib/struct/struct.helper.ts new file mode 100644 index 00000000..ad424dd1 --- /dev/null +++ b/packages/win32-def/src/lib/struct/struct.helper.ts @@ -0,0 +1,196 @@ +import assert from 'assert' + +import ffi from 'koffi' +import type { IKoffiCType } from 'koffi' + +import type { + StructDetail, + StructFactoryResult, + StructInitPlainType, + StructInitType, +} from '##/lib/types.js' + +import { StructUnionCache } from './struct.cache.js' +import { genSimpleStruct, genSimpleUnion } from './struct.simple.helper.js' + + +// #region genStruct() + +/** + * Generate a complex struct, + * def can have nested struct or union + * - key s{number} means struct + * - key u{number} means union + */ +export function genStruct( + def: StructInitType, + name?: string, + pointer?: string, + sizeColumns?: (keyof T)[], +): StructFactoryResult { + + const struct = genComplexStruct(def, name, pointer) as StructFactoryResult | StructDetail + bindPayloadGetter(struct as StructFactoryResult, sizeColumns) + return struct as StructFactoryResult +} + +function bindPayloadGetter(struct: StructFactoryResult, sizeColumns: PropertyKey[] | undefined): void { + if (typeof struct.sizeColumns === 'undefined') { + Object.defineProperty(struct, 'sizeColumns', { + enumerable: true, + writable: false, + value: sizeColumns, + }) + } + + if (typeof struct.payload === 'undefined') { + // payload must be the new one after each call of the struct factory function + Object.defineProperty(struct, 'payload', { + get: function (this: StructFactoryResult) { + if (! this.sizeColumns?.length) { + return {} + } + + const ret = {} + this.sizeColumns.forEach((key) => { + if (key) { + Object.defineProperty(ret, key, { + enumerable: true, + writable: false, + value: this.size, + }) + } + }) + return ret + }, + }) + } + +} + + +// #region genComplexStruct() + +/** + * Generate a complex struct, + * def can have nested struct or union + * - key s{number} means struct + * - key u{number} means union + */ +export function genComplexStruct(def: StructInitType, name?: string, pointer?: string): StructDetail { + const key = name ? name.trim() : '' + const ret = genStructCached(def, key, pointer) + if (name) { + assert(ret.name === key, `name: "${ret.name}" !== "${key}"`) + } + return ret +} + +const regStructName = /^s\d*$/u +const regUnionName = /^u\d*$/u + +function genStructCached(def: StructInitType, name: string, pointer: string | undefined): StructDetail { + if (name) { + const data = StructUnionCache.getStruct(name) + if (data) { + return data + } + } + const data = { ...def } + // detect nested struct or union, key name start at "s{number*}" means struct, start at "u{number*}" means union + genItem(data) + const ret = genSimpleStruct(data as StructInitPlainType, name, pointer) + return ret +} + + +// @region genUnion() + +export function genUnion(def: StructInitType, name?: string, pointer?: string): StructDetail { + const key = name ? name.trim() : '' + let pname = pointer ?? '' + if (key && ! pname) { + pname = key + '*' + } + + const ret = genUnionCached(def, key, pname) + if (name) { + assert(ret.name === key, `name: ${ret.name} !== ${key}`) + } + return ret +} + + +function genUnionCached(def: StructInitType, name: string, pointer: string | undefined): StructDetail { + if (name) { + const data = StructUnionCache.getUnion(name) + if (data) { + return data + } + } + + const data = { ...def } + // detect nested struct or union, key name start at "s{number*}" means struct, start at "u{number*}" means union + genItem(data) + const ret = genSimpleUnion(data as StructInitPlainType, name, pointer) + return ret +} + + +function genItem(data: StructInitType) { + // detect nested struct or union, key name start at "s{number*}" means struct, start at "u{number*}" means union + Object.keys(data).forEach((key) => { + const value = data[key] + assert(value, `value of key ${key} is null or undefined`) + + if (typeof value === 'string') { return } + + if (typeof value === 'function') { + const nested = value() as StructDetail + assert(nested, `nested struct must be an object, but got ${typeof nested}`) + data[key] = nested.CType + } + else if (typeof value === 'object') { + // Do not check value, because it can be KoffiCType + // assert(Object.keys(value).length > 0, `value of key ${key} is empty object`) + + if (regStructName.test(key)) { + const nested = genComplexStruct(value as StructInitType) // do not pass key + data[key] = nested.CType + } + else if (regUnionName.test(key)) { + const nested = genUnion(value as StructInitType) // do not pass key + data[key] = nested.CType + } + else if (Object.keys(value).length === 0) { + return // maybe fix array + } + /* c8 ignore next 3 */ + else { + assert(false, `key ${key} must start with 's' or 'u'`) + } + } + /* c8 ignore next 3 */ + else { + assert(data[key], `value of key ${key} is null or undefined`) + } + }) +} + + +/** + * Generate a fixed int16_t array. + * convert it back to string through decodeInt16Array() + */ +export function genFixedInt16Array(length: number): IKoffiCType { + assert(length > 0, `length must be greater than 0, but got ${length}`) + const type = ffi.array('int16_t', length) + return type +} + +export function genFixedArray(length: number): IKoffiCType { + assert(length > 0, `length must be greater than 0, but got ${length}`) + const type = ffi.array('int16_t', length, 'Array') + return type +} + diff --git a/packages/win32-def/src/lib/struct/struct.index.ts b/packages/win32-def/src/lib/struct/struct.index.ts new file mode 100644 index 00000000..4fe1237b --- /dev/null +++ b/packages/win32-def/src/lib/struct/struct.index.ts @@ -0,0 +1,8 @@ + +export * from './comctl/comctl.index.js' +export * from './minwinbase/minwinbase.index.js' +export * from './windef/windef.index.js' +export * from './wingdi/wingdi.index.js' +export * from './winspool/winspool.index.js' +export * from './winuser/winuser.index.js' + diff --git a/packages/win32-def/src/lib/struct/struct.simple.helper.ts b/packages/win32-def/src/lib/struct/struct.simple.helper.ts new file mode 100644 index 00000000..2eb66d01 --- /dev/null +++ b/packages/win32-def/src/lib/struct/struct.simple.helper.ts @@ -0,0 +1,79 @@ +import assert from 'assert' + +import ffi from 'koffi' + +import type { StructDetail, StructInitPlainType } from '##/lib/types.js' + +import { StructUnionCache } from './struct.cache.js' + + +// #region genSimpleStruct() + +/** + * Generate a simple struct + * - def must has no nested struct or union + */ +export function genSimpleStruct( + def: StructInitPlainType, + name?: string, + pointer?: string, +): StructDetail { + + const key = name ? name.trim() : '' + let ptr = pointer ?? '' + if (key && ! ptr) { + ptr = key + ' *' + } + + if (key) { + const data = StructUnionCache.getStruct(key) + if (data) { return data } + } + + let ret: StructDetail + if (key) { + const type = ffi.struct(key, def) + const size = ffi.sizeof(type) + ret = { name: key, pointer: ptr, CType: type, size } + StructUnionCache.setStruct(key, ret) // cache named struct only + } + else { + const type = ffi.struct(def) + const size = ffi.sizeof(type) + ret = { name: key, pointer: ptr, CType: type, size } + } + assert(ret, `ret is null or undefined`) + + return ret +} + +// #region genSimpleUnion() + +export function genSimpleUnion(def: StructInitPlainType, name?: string, pointer?: string): StructDetail { + const key = name ? name.trim() : '' + let ptr = pointer ? pointer.trim() : '' + if (key && ! ptr) { + ptr = key + ' *' + } + + if (key) { + const data = StructUnionCache.getUnion(key) + if (data) { return data } + } + + let ret: StructDetail + if (key) { + const type = ffi.union(key, def) + const size = ffi.sizeof(type) + ret = { name: key, pointer: ptr, CType: type, size } + StructUnionCache.setUnion(key, ret) // cache named union only + } + else { + const type = ffi.union(def) + const size = ffi.sizeof(type) + ret = { name: key, pointer: ptr, CType: type, size } + } + + return ret +} + diff --git a/packages/win32-def/src/lib/struct/struct.types.ts b/packages/win32-def/src/lib/struct/struct.types.ts deleted file mode 100644 index b1c20052..00000000 --- a/packages/win32-def/src/lib/struct/struct.types.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { - ATOM, - BYTE, - DWORD, - HANDLE, - HBRUSH, - HCURSOR, - HICON, - HINSTANCE, - HWND, - INT, - LONG, - LPARAM, - LPCTSTR, - _POINTER, - PVOID, - PWSTR, - UINT, - ULONG, - ULONG_PTR, - USHORT, - WNDPROC, - WORD, - WPARAM, - StructInstanceBase, -} from '../common.types.js' - - -/** - * Struct usage: - * - * import * as Struct from 'ref-struct-napi'; - * import { DStruct as DS, DModel as M } from 'win32-api'; - * - * const point: M.PointStruct = new Struct(DS.POINT)(); - * point.x = 100; - * point.y = 200; - * // const buf = point.ref() - * - */ - - -/** https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx */ -export interface POINT extends StructInstanceBase { - x: LONG - y: LONG -} - -/** - * @link https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-pointl - */ -export interface POINTL extends StructInstanceBase { - x: LONG - y: LONG -} -export type PPOINTL = _POINTER - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-alttabinfo */ -export interface ALTTABINFO extends StructInstanceBase { - cbSize: DWORD - cItems: INT - cColumns: INT - cRows: INT - iColFocus: INT - iRowFocus: INT - cxItem: INT - cyItem: INT - ptStart: POINT -} -export type PALTTABINFO = _POINTER - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-copydatastruct */ -export interface COPYDATASTRUCT extends StructInstanceBase { - dwData: ULONG_PTR - cbData: DWORD - lpData: PVOID -} -export type PCOPYDATASTRUCT = _POINTER - - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taghardwareinput */ -export interface HARDWAREINPUT extends StructInstanceBase { - uMsg: DWORD - wParamL: WORD - wParamH: WORD -} -export type PHARDWAREINPUT = _POINTER - -export interface INITCOMMONCONTROLSEX extends StructInstanceBase { - dwSize: DWORD - dwICC: DWORD -} -/** A pointer to an INITCOMMONCONTROLSEX */ -export type LPINITCOMMONCONTROLSEX = _POINTER - - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagkeybdinput */ -export interface KEYBDINPUT extends StructInstanceBase { - wVk: WORD - wScan: WORD - dwFlags: DWORD - time: DWORD - dwExtraInfo: ULONG_PTR -} -export type PKEYBDINPUT = _POINTER - -/** - * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput - */ -export interface MOUSEINPUT extends StructInstanceBase { - dx: LONG - dy: LONG - mouseData: DWORD - dwFlags: DWORD - time: DWORD - dwExtraInfo: ULONG_PTR -} -export type PMOUSEINPUT = _POINTER - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg */ -export interface MSG extends StructInstanceBase { - hwnd: HWND - message: UINT - wParam: WPARAM - lParam: LPARAM - time: DWORD - pt: POINT - lPrivate: DWORD -} -export type PMSG = _POINTER - - -export interface PROCESS_BASIC_INFORMATION extends StructInstanceBase { - Reserved1: PVOID - PebBaseAddress: PVOID // PPEB - Reserved2: PVOID - UniqueProcessId: ULONG_PTR - InheritedFromUniqueProcessId: PVOID -} -export type PPROCESS_BASIC_INFORMATION = _POINTER - - -export interface UNICODE_STRING extends StructInstanceBase { - Length: USHORT - MaximumLength: USHORT - Buffer: PWSTR -} -export type PUNICODE_STRING = _POINTER - - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagrawhid */ -export interface RAWHID extends StructInstanceBase { - dwSizeHid: DWORD - dwCount: DWORD - /** bRawData[1] */ - bRawData: BYTE -} -export type PRAWHID = _POINTER - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawinputdevicelist */ -export interface RAWINPUTDEVICELIST extends StructInstanceBase { - hDevice: HANDLE - dwType: DWORD -} -export type PRAWINPUTDEVICELIST = _POINTER - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagrawinputheader */ -export interface RAWINPUTHEADER extends StructInstanceBase { - dwType: DWORD - dwSize: DWORD - hDevice: HANDLE - wParam: WPARAM -} -export type PRAWINPUTHEADER = _POINTER - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagrawkeyboard */ -export interface RAWKEYBOARD extends StructInstanceBase { - MakeCode: USHORT - Flags: USHORT - Reserved: USHORT - VKey: USHORT - Message: UINT - ExtraInformation: ULONG -} -export type PRAWKEYBOARD = _POINTER - - -/** https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms633577(v=vs.85).aspx */ -export interface WNDCLASSEX extends StructInstanceBase { - cbSize: UINT - style: UINT - lpfnWndProc: WNDPROC - cbClsExtra: INT - cbWndExtra: INT - /** can be 0? */ - hInstance: HINSTANCE - hIcon: HICON - hCursor: HCURSOR - hbrBackground: HBRUSH - lpszMenuName: LPCTSTR - lpszClassName: LPCTSTR - hIconSm: HICON -} -/** A pointer to a WNDCLASSEX */ -export type LPWNDCLASSEX = _POINTER - - -export interface RECT extends StructInstanceBase { - left: LONG - top: LONG - right: LONG - bottom: LONG -} -export type LPRECT = _POINTER - - -export interface WINDOWINFO extends StructInstanceBase { - cbSize: DWORD - rcWindow: RECT - rcClient: RECT - dwStyle: DWORD - dwExStyle: DWORD - dwWindowStatus: DWORD - cxWindowBorders: UINT - cyWindowBorders: UINT - atomWindowType: ATOM - wCreatorVersion: WORD -} -/** A pointer to a WINDOWINFO structure */ -export type PWINDOWINFO = _POINTER - -/** https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime */ -export interface FILETIME extends StructInstanceBase { - dwLowDateTime: DWORD - dwHighDateTime: DWORD -} -/** A pointer to a FILETIME */ -export type PFILETIME = _POINTER -/** A pointer to a FILETIME */ -export type LPFILETIME = _POINTER - diff --git a/packages/win32-def/src/lib/struct/struct.util.ts b/packages/win32-def/src/lib/struct/struct.util.ts new file mode 100644 index 00000000..435dcb7a --- /dev/null +++ b/packages/win32-def/src/lib/struct/struct.util.ts @@ -0,0 +1,74 @@ +import assert from 'assert' + +import type { StructFactoryResult } from '##/lib/types.js' + +import { + PPRINTER_INFO_1, + PPRINTER_INFO_4, + PPRINTER_INFO_5, + PPRINTER_INFO_6, + PPRINTER_INFO_8, + PPRINTER_INFO_9, + PRINTER_INFO_1_Factory, + PRINTER_INFO_4_Factory, + PRINTER_INFO_5_Factory, + PRINTER_INFO_6_Factory, + PRINTER_INFO_8_Factory, + PRINTER_INFO_9_Factory, +} from './struct.index.js' +import type { PRINTER_INFO_LEVEL, PRINTER_INFO_X_Type } from './winspool/helper.types.js' + + +export type PRINTER_INFO_X_Ptr_Type = X extends 1 + ? typeof PPRINTER_INFO_1 + : X extends 4 + ? typeof PPRINTER_INFO_4 + : X extends 5 + ? typeof PPRINTER_INFO_5 + : X extends 8 + ? typeof PPRINTER_INFO_8 + : X extends 9 + ? typeof PPRINTER_INFO_9 + : never + + +export function getPRINTER_INFO_X_Ptr(level: X): PRINTER_INFO_X_Ptr_Type { + switch (level) { + case 1: return PPRINTER_INFO_1 as PRINTER_INFO_X_Ptr_Type + + case 4: return PPRINTER_INFO_4 as PRINTER_INFO_X_Ptr_Type + + case 5: return PPRINTER_INFO_5 as PRINTER_INFO_X_Ptr_Type + + case 6: return PPRINTER_INFO_6 as PRINTER_INFO_X_Ptr_Type + + case 8: return PPRINTER_INFO_8 as PRINTER_INFO_X_Ptr_Type + + case 9: return PPRINTER_INFO_9 as PRINTER_INFO_X_Ptr_Type + + /* c8 ignore next 2 */ + default: + assert(false, `getPRINTER_INFO_X_Ptr(): level not supported: ${level}`) + } +} + +export function PRINTER_INFO_X_Factory(level: X): StructFactoryResult> { + switch (level) { + case 1: return PRINTER_INFO_1_Factory() as StructFactoryResult> + + case 4: return PRINTER_INFO_4_Factory() as StructFactoryResult> + + case 5: return PRINTER_INFO_5_Factory() as StructFactoryResult> + + case 6: return PRINTER_INFO_6_Factory() as StructFactoryResult> + + case 8: return PRINTER_INFO_8_Factory() as StructFactoryResult> + + case 9: return PRINTER_INFO_9_Factory() as StructFactoryResult> + + /* c8 ignore next 2 */ + default: + assert(false, `level not supported: ${level}`) + } +} + diff --git a/packages/win32-def/src/lib/struct/struct.var.def.ts b/packages/win32-def/src/lib/struct/struct.var.def.ts deleted file mode 100644 index 4171124a..00000000 --- a/packages/win32-def/src/lib/struct/struct.var.def.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Def } from '../def.enum.js' - - -/** https://msdn.microsoft.com/en-us/library/windows/desktop/dd162805(v=vs.85).aspx */ -export const POINT = Def.ptr - -/** - * @link https://docs.microsoft.com/en-us/windows/win32/api/windef/ns-windef-pointl - */ -export const POINTL = Def.ptr -export const PPOINTL = Def.ptr - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-alttabinfo */ -export const ALTTABINFO = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-copydatastruct */ -export const COPYDATASTRUCT = Def.ptr - - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-taghardwareinput */ -export const HARDWAREINPUT = Def.ptr - -export const INITCOMMONCONTROLSEX = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagkeybdinput */ -export const KEYBDINPUT = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagmouseinput */ -export const MOUSEINPUT = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg */ -export const MSG = Def.ptr - - -export const PROCESS_BASIC_INFORMATION = Def.ptr - -export const UNICODE_STRING = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawhid */ -export const RAWHID = Def.ptr - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-rawinputdevicelist */ -export const RAWINPUTDEVICELIST = Def.ptr -export const PRAWINPUTDEVICELIST = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawinputheader */ -export const RAWINPUTHEADER = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawkeyboard */ -export const RAWKEYBOARD = Def.ptr - - -/** https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms633577(v=vs.85).aspx */ -export const WNDCLASSEX = Def.ptr - -export const RECT = Def.ptr - -export const WINDOWINFO = Def.ptr - -/** https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime */ -export const FILETIME = Def.ptr - diff --git a/packages/win32-def/src/lib/struct/windef/POINT.ts b/packages/win32-def/src/lib/struct/windef/POINT.ts new file mode 100644 index 00000000..fd10398e --- /dev/null +++ b/packages/win32-def/src/lib/struct/windef/POINT.ts @@ -0,0 +1,36 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'POINT' +const ptr = `${key}*` as const +const init: StructInitType = { + x: D.LONG, + y: D.LONG, +} as const + + +/** + * POINT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-point + */ +export function POINT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * POINT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-point + */ +export interface POINT_Type { + x: T.LONG + y: T.LONG +} + +export const LPPOINT = ptr +export const POINT_Name = key +export const POINT_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/windef/RECT.ts b/packages/win32-def/src/lib/struct/windef/RECT.ts new file mode 100644 index 00000000..36617737 --- /dev/null +++ b/packages/win32-def/src/lib/struct/windef/RECT.ts @@ -0,0 +1,40 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RECT' +const ptr = `${key}*` as const +const init: StructInitType = { + left: D.LONG, + top: D.LONG, + right: D.LONG, + bottom: D.LONG, +} as const + + +/** + * RECT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-RECT + */ +export function RECT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RECT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/windef/ns-windef-RECT + */ +export interface RECT_Type { + left: T.LONG + top: T.LONG + right: T.LONG + bottom: T.LONG +} + +export const LPRECT = ptr +export const RECT_Name = key +export const RECT_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/windef/windef.index.ts b/packages/win32-def/src/lib/struct/windef/windef.index.ts new file mode 100644 index 00000000..e02b04fe --- /dev/null +++ b/packages/win32-def/src/lib/struct/windef/windef.index.ts @@ -0,0 +1,4 @@ + +export * from './POINT.js' +export * from './RECT.js' + diff --git a/packages/win32-def/src/lib/struct/wingdi.def.ts b/packages/win32-def/src/lib/struct/wingdi.def.ts deleted file mode 100644 index 384f1921..00000000 --- a/packages/win32-def/src/lib/struct/wingdi.def.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { DWORD, SHORT, WORD } from '../common.def.js' -import { wcharBuffer } from '../fixed-buffer.js' -import { UnionType } from '../helper.js' -import { - DEVMODEW_DUMMYUNIONNAME, - DEVMODEW_DUMMYUNIONNAME2, -} from '../union/winspool.union.def.js' - - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew */ -export const DISPLAY_DEVICEW = { - cb: DWORD, - DeviceName: wcharBuffer(32), - DeviceString: wcharBuffer(128), - StateFlags: DWORD, - DeviceID: wcharBuffer(128), - DeviceKey: wcharBuffer(128), -} - - -/** - * Used for specifying characteristics of display and print devices in the Unicode (wide) character set. - * @link https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodew - */ -export const DEVMODEW = { - dmDeviceName: wcharBuffer(128), - dmSpecVersion: WORD, - dmDriverVersion: WORD, - dmSize: WORD, - dmDriverExtra: WORD, - dmFields: DWORD, - DUMMYUNIONNAME: UnionType(DEVMODEW_DUMMYUNIONNAME), - dmColor: SHORT, - dmDuplex: SHORT, - dmYResolution: SHORT, - dmTTOption: SHORT, - dmCollate: SHORT, - /** - * For printers, specifies the name of the form to use; such as "Letter" or "Legal". - * This must be a name that can be obtain by calling the Win32 EnumForms function - * (described in the Microsoft Window SDK documentation). - */ - dmFormName: wcharBuffer(32), - dmLogPixels: WORD, - dmBitsPerPel: DWORD, - dmPelsWidth: DWORD, - dmPelsHeight: DWORD, - DUMMYUNIONNAME2: UnionType(DEVMODEW_DUMMYUNIONNAME2), - dmDisplayFrequency: DWORD, - dmICMMethod: DWORD, - dmICMIntent: DWORD, - dmMediaType: DWORD, - dmDitherType: DWORD, - dmReserved1: DWORD, - dmReserved2: DWORD, - dmPanningWidth: DWORD, - dmPanningHeight: DWORD, -} - - diff --git a/packages/win32-def/src/lib/struct/wingdi.types.ts b/packages/win32-def/src/lib/struct/wingdi.types.ts deleted file mode 100644 index 5979dea0..00000000 --- a/packages/win32-def/src/lib/struct/wingdi.types.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { - _POINTER, - DWORD, - StructInstanceBase, - WCHAR_String, - WORD, - SHORT, -} from '../common.types.js' -import { DEVMODEW_DUMMYUNIONNAME, DEVMODEW_DUMMYUNIONNAME2 } from '../union/winspool.union.types.js' - - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew */ -export interface DISPLAY_DEVICEW extends StructInstanceBase { - cb: DWORD - DeviceName: WCHAR_String - DeviceString: WCHAR_String - StateFlags: DWORD - DeviceID: WCHAR_String - DeviceKey: WCHAR_String -} -/** A pointer to DISPLAY_DEVICEW */ -export type PDISPLAY_DEVICEW = _POINTER -/** A pointer to DISPLAY_DEVICEW */ -export type LPDISPLAY_DEVICEW = _POINTER - - -/** - * Used for specifying characteristics of display and print devices in the Unicode (wide) character set. - * @link https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodew - */ -export interface DEVMODEW extends StructInstanceBase { - dmDeviceName: WCHAR_String - dmSpecVersion: WORD - dmDriverVersion: WORD - dmSize: WORD - dmDriverExtra: WORD - dmFields: DWORD - // union { - // struct { - // short dmOrientation; - // short dmPaperSize; - // short dmPaperLength; - // short dmPaperWidth; - // short dmScale; - // short dmCopies; - // short dmDefaultSource; - // short dmPrintQuality - // } DUMMYSTRUCTNAME; - // dmPosition: POINTL - // struct { - // POINTL dmPosition; - // DWORD dmDisplayOrientation; - // DWORD dmDisplayFixedOutput - // } DUMMYSTRUCTNAME2 - // } DUMMYUNIONNAME; - DUMMYUNIONNAME: DEVMODEW_DUMMYUNIONNAME - dmColor: SHORT - dmDuplex: SHORT - dmYResolution: SHORT - dmTTOption: SHORT - dmCollate: SHORT - /** - * For printers, specifies the name of the form to use; such as "Letter" or "Legal". - * This must be a name that can be obtain by calling the Win32 EnumForms function - * (described in the Microsoft Window SDK documentation). - */ - dmFormName: WCHAR_String - dmLogPixels: WORD - dmBitsPerPel: DWORD - dmPelsWidth: DWORD - dmPelsHeight: DWORD - // union { - // DWORD dmDisplayFlags; - // DWORD dmNup - // } DUMMYUNIONNAME2; - DUMMYUNIONNAME2: DEVMODEW_DUMMYUNIONNAME2 - dmDisplayFrequency: DWORD - dmICMMethod: DWORD - dmICMIntent: DWORD - dmMediaType: DWORD - dmDitherType: DWORD - dmReserved1: DWORD - dmReserved2: DWORD - dmPanningWidth: DWORD - dmPanningHeight: DWORD -} -export type PDEVMODEW = _POINTER -export type NPDEVMODEW = _POINTER -export type LPDEVMODEW = _POINTER diff --git a/packages/win32-def/src/lib/struct/wingdi.var.def.ts b/packages/win32-def/src/lib/struct/wingdi.var.def.ts deleted file mode 100644 index 2ac45362..00000000 --- a/packages/win32-def/src/lib/struct/wingdi.var.def.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Def } from '../def.enum.js' - - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew */ -export const DISPLAY_DEVICEW = Def.ptr - -/** - * Used for specifying characteristics of display and print devices in the Unicode (wide) character set. - * @link https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodew - */ -export const DEVMODEW = Def.ptr - -/** - * Specifies the name of an installed print processor. - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/printprocessor-info-1 - */ -export const PRINTPROCESSOR_INFO_1 = Def.ptr - diff --git a/packages/win32-def/src/lib/struct/wingdi/DEVMODEW.ts b/packages/win32-def/src/lib/struct/wingdi/DEVMODEW.ts new file mode 100644 index 00000000..39b161ad --- /dev/null +++ b/packages/win32-def/src/lib/struct/wingdi/DEVMODEW.ts @@ -0,0 +1,126 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genFixedInt16Array, genStruct } from '../struct.helper.js' +import { POINT_Factory, POINT_Type } from '../windef/POINT.js' + + +const key = 'DEVMODEW' +const ptr = `${key}*` as const +const init: StructInitType = { + dmDeviceName: genFixedInt16Array(32), + dmSpecVersion: D.WORD, + dmDriverVersion: D.WORD, + dmSize: D.WORD, + dmDriverExtra: D.WORD, + dmFields: D.DWORD, + u1: { + s1: { + dmOrientation: D.SHORT, + dmPaperSize: D.SHORT, + dmPaperLength: D.SHORT, + dmPaperWidth: D.SHORT, + dmScale: D.SHORT, + dmCopies: D.SHORT, + dmDefaultSource: D.SHORT, + dmPrintQuality: D.SHORT, + }, + dmPosition: POINT_Factory, + s2: { + dmPosition: POINT_Factory, + dmDisplayOrientation: D.DWORD, + dmDisplayFixedOutput: D.DWORD, + }, + }, + dmColor: D.SHORT, + dmDuplex: D.SHORT, + dmYResolution: D.SHORT, + dmTTOption: D.SHORT, + dmCollate: D.SHORT, + dmFormName: genFixedInt16Array(32), + dmLogPixels: D.WORD, + dmBitsPerPel: D.DWORD, + dmPelsWidth: D.DWORD, + dmPelsHeight: D.DWORD, + u2: { + dmDisplayFlags: D.DWORD, + dmNup: D.DWORD, + }, + dmDisplayFrequency: D.DWORD, + dmICMMethod: D.DWORD, + dmICMIntent: D.DWORD, + dmMediaType: D.DWORD, + dmDitherType: D.DWORD, + dmReserved1: D.DWORD, + dmReserved2: D.DWORD, + dmPanningWidth: D.DWORD, + dmPanningHeight: D.DWORD, +} as const + +/** + * DEVMODEW structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodew + */ +export function DEVMODEW_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['dmSize']) +} + +/** + * DEVMODEW structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-devmodew + */ +export interface DEVMODEW_Type { + dmDeviceName: T.WCHAR + dmSpecVersion: T.WORD + dmDriverVersion: T.WORD + dmSize: T.WORD + dmDriverExtra: T.WORD + dmFields: T.DWORD + u1: { + s1: { + dmOrientation: T.SHORT, + dmPaperSize: T.SHORT, + dmPaperLength: T.SHORT, + dmPaperWidth: T.SHORT, + dmScale: T.SHORT, + dmCopies: T.SHORT, + dmDefaultSource: T.SHORT, + dmPrintQuality: T.SHORT, + }, + dmPosition: POINT_Type, + s2: { + dmPosition: POINT_Type, + dmDisplayOrientation: T.DWORD, + dmDisplayFixedOutput: T.DWORD, + }, + } + dmColor: T.SHORT + dmDuplex: T.SHORT + dmYResolution: T.SHORT + dmTTOption: T.SHORT + dmCollate: T.SHORT + dmFormName: T.WCHAR + dmLogPixels: T.WORD + dmBitsPerPel: T.DWORD + dmPelsWidth: T.DWORD + dmPelsHeight: T.DWORD + u2: { + dmDisplayFlags: T.DWORD, + dmNup: T.DWORD, + } + dmDisplayFrequency: T.DWORD + dmICMMethod: T.DWORD + dmICMIntent: T.DWORD + dmMediaType: T.DWORD + dmDitherType: T.DWORD + dmReserved1: T.DWORD + dmReserved2: T.DWORD + dmPanningWidth: T.DWORD + dmPanningHeight: T.DWORD +} + +export const LPDEVMODEW = ptr +export const DEVMODEW_Name = key +export const DEVMODEW_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/wingdi/DISPLAY_DEVICEW.ts b/packages/win32-def/src/lib/struct/wingdi/DISPLAY_DEVICEW.ts new file mode 100644 index 00000000..3cb02998 --- /dev/null +++ b/packages/win32-def/src/lib/struct/wingdi/DISPLAY_DEVICEW.ts @@ -0,0 +1,43 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genFixedInt16Array, genStruct } from '../struct.helper.js' + + +const key = 'DISPLAY_DEVICEW' +const ptr = `${key}*` as const +const init: StructInitType = { + cb: D.DWORD, + DeviceName: genFixedInt16Array(32), + DeviceString: genFixedInt16Array(128), + StateFlags: D.DWORD, + DeviceID: genFixedInt16Array(128), + DeviceKey: genFixedInt16Array(128), +} as const + +/** + * DISPLAY_DEVICEW structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-display_devicew + */ +export function DISPLAY_DEVICEW_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['cb']) +} + +/** + * DISPLAY_DEVICEW structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-display_devicew + */ +export interface DISPLAY_DEVICEW_Type { + cb: T.DWORD + DeviceName: T.WCHAR_Array + DeviceString: T.WCHAR_Array + StateFlags: T.DWORD + DeviceID: T.WCHAR_Array + DeviceKey: T.WCHAR_Array +} + +export const LPDISPLAY_DEVICEW = ptr +export const DISPLAY_DEVICEW_Name = key +export const DISPLAY_DEVICEW_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/wingdi/wingdi.index.ts b/packages/win32-def/src/lib/struct/wingdi/wingdi.index.ts new file mode 100644 index 00000000..a30a893d --- /dev/null +++ b/packages/win32-def/src/lib/struct/wingdi/wingdi.index.ts @@ -0,0 +1,4 @@ + +export * from './DEVMODEW.js' +export * from './DISPLAY_DEVICEW.js' + diff --git a/packages/win32-def/src/lib/struct/winspool.def.ts b/packages/win32-def/src/lib/struct/winspool.def.ts deleted file mode 100644 index b7b87a1a..00000000 --- a/packages/win32-def/src/lib/struct/winspool.def.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { - ACCESS_MASK, - DWORD, - LPTSTR, -} from '../common.def.js' -import { StructType } from '../helper.js' - -import { DEVMODEW } from './wingdi.def.js' - - -/** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/datatypes-info-1 - */ -export const DATATYPES_INFO_1 = { - pName: LPTSTR, -} as const - -/** - * Describes a document that will be printed. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/doc-info-1 - */ -export const DOC_INFO_1 = { - pDocName: LPTSTR, - pOutputFile: LPTSTR, - pDatatype: LPTSTR, -} as const - -/** - * Specifies the name of an installed print processor. - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/printprocessor-info-1 - */ -export const PRINTPROCESSOR_INFO_1 = { - pName: LPTSTR, -} as const - -/** - * Specifies the default data type, environment, initialization data, and access rights for a printer. - * @link https://docs.microsoft.com/zh-cn/windows/win32/printdocs/printer-defaults - */ -export const PRINTER_DEFAULTS = { - /** - * Pointer to a null-terminated string that specifies the default data type for a printer. - */ - pDatatype: LPTSTR, - /** - * Pointer to a DEVMODE structure that identifies the default environment and initialization data for a printer. - */ - pDevMode: StructType(DEVMODEW), - // pDevMode: LPDEVMODE, - DesiredAccess: ACCESS_MASK, -} as const - - -/** - * Specifies general printer information - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-1 - */ -export const PRINTER_INFO_1 = { - Flags: DWORD, - pDescription: LPTSTR, - pName: LPTSTR, - pComment: LPTSTR, -} as const - - -/** - * Specifies general printer information - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-4 - * @description The structure can be used to retrieve minimal printer information on a call to EnumPrinters. - * Such a call is a fast and easy way to retrieve the names and attributes of all locally installed printers - * on a system and all remote printer connections that a user has established. - */ -export const PRINTER_INFO_4 = { - pPrinterName: LPTSTR, - pServerName: LPTSTR, - Attributes: DWORD, -} as const - diff --git a/packages/win32-def/src/lib/struct/winspool.types.ts b/packages/win32-def/src/lib/struct/winspool.types.ts deleted file mode 100644 index a02b6031..00000000 --- a/packages/win32-def/src/lib/struct/winspool.types.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { - _POINTER, - StructInstanceBase, - ACCESS_MASK, - DWORD, - WCHAR_String, - LPTSTR, -} from '../common.types.js' - -import { DEVMODEW } from './wingdi.types.js' - - - -/** - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/datatypes-info-1 - */ -export interface DATATYPES_INFO_1 extends StructInstanceBase { - pName: WCHAR_String -} -export type PDATATYPES_INFO_1 = _POINTER - -/** - * Describes a document that will be printed. - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/doc-info-1 - */ -export interface DOC_INFO_1 extends StructInstanceBase { - pDocName: LPTSTR - pOutputFile: LPTSTR - pDatatype: LPTSTR -} -export type PDOC_INFO_1 = _POINTER - -/** - * Specifies the name of an installed print processor. - * @docs https://docs.microsoft.com/zh-cn/windows/win32/printdocs/printprocessor-info-1 - */ -export interface PRINTPROCESSOR_INFO_1 extends StructInstanceBase { - pName: WCHAR_String -} -export type PPRINTPROCESSOR_INFO_1 = _POINTER - - -/** - * Specifies the default data type, environment, initialization data, and access rights for a printer. - * @link https://docs.microsoft.com/zh-cn/windows/win32/printdocs/printer-defaults - */ -export interface PRINTER_DEFAULTS extends StructInstanceBase { - /** - * Pointer to a null-terminated string that specifies the default data type for a printer. - */ - pDatatype: WCHAR_String - /** - * Pointer to a DEVMODE structure that identifies the default environment and initialization data for a printer. - */ - // pDevMode: LPDEVMODEW - pDevMode: DEVMODEW - DesiredAccess: ACCESS_MASK -} -/** A pointer to PRINTER_DEFAULTS */ -export type PPRINTER_DEFAULTS = _POINTER -export type LPPRINTER_DEFAULTS = _POINTER - - -/** - * Specifies general printer information - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/getprinter#parameters - */ -export interface PRINTER_INFO_X { - 1: PRINTER_INFO_1 - 4: PRINTER_INFO_4 - [key: number]: StructInstanceBase -} - -/** - * Specifies general printer information - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-1 - */ -export interface PRINTER_INFO_1 extends StructInstanceBase { - Flags: DWORD - pDescription: WCHAR_String - pName: WCHAR_String - pComment: WCHAR_String - // pDescription: LPTSTR - // pName: LPTSTR - // pComment: LPTSTR -} -export type PPRINTER_INFO_1 = _POINTER - -/** - * Specifies general printer information - * @docs https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-4 - * @description The structure can be used to retrieve minimal printer information on a call to EnumPrinters. - * Such a call is a fast and easy way to retrieve the names and attributes of all locally installed printers - * on a system and all remote printer connections that a user has established. - */ -export interface PRINTER_INFO_4 extends StructInstanceBase { - pPrinterName: WCHAR_String - pServerName: WCHAR_String - Attributes: DWORD -} -export type PPRINTER_INFO_4 = _POINTER - diff --git a/packages/win32-def/src/lib/struct/winspool.var.def.ts b/packages/win32-def/src/lib/struct/winspool.var.def.ts deleted file mode 100644 index 435686ca..00000000 --- a/packages/win32-def/src/lib/struct/winspool.var.def.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Def } from '../def.enum.js' - - -export const DOC_INFO_1 = Def.ptr - -/** - * @link https://docs.microsoft.com/zh-cn/windows/win32/printdocs/printer-defaults - */ -export const PRINTER_DEFAULTS = Def.ptr -export const LPRINTER_DEFAULTS = Def.ptr - -export const PRINTER_INFO_1 = Def.ptr -export const PPRINTER_INFO_1 = Def.ptr - -export const PRINTER_INFO_2 = Def.ptr -export const PPRINTER_INFO_2 = Def.ptr -export const PRINTER_INFO_3 = Def.ptr -export const PPRINTER_INFO_3 = Def.ptr -export const PRINTER_INFO_4 = Def.ptr -export const PPRINTER_INFO_4 = Def.ptr -export const PRINTER_INFO_5 = Def.ptr -export const PPRINTER_INFO_5 = Def.ptr -export const PRINTER_INFO_6 = Def.ptr -export const PPRINTER_INFO_6 = Def.ptr -export const PRINTER_INFO_7 = Def.ptr -export const PPRINTER_INFO_7 = Def.ptr -export const PRINTER_INFO_8 = Def.ptr -export const PPRINTER_INFO_8 = Def.ptr -export const PRINTER_INFO_9 = Def.ptr -export const PPRINTER_INFO_9 = Def.ptr - diff --git a/packages/win32-def/src/lib/struct/winspool/DOC_INFO_1.ts b/packages/win32-def/src/lib/struct/winspool/DOC_INFO_1.ts new file mode 100644 index 00000000..851ea294 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/DOC_INFO_1.ts @@ -0,0 +1,39 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'DOC_INFO_1' +const ptr = `${key}*` as const +const init: StructInitType = { + pDocName: D.WString, + pOutputFile: D.WString, + pDatatype: D.WString, +} as const + +/** + * DOC_INFO_1 structure, + * Describes a document that will be printed. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/doc-info-1 + */ +export function DOC_INFO_1_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * DOC_INFO_1 structure, + * Describes a document that will be printed. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/doc-info-1 + */ +export interface DOC_INFO_1_Type { + pDocName: T.WString + pOutputFile: T.WString | null + pDatatype: T.WString +} + +export const LPDOC_INFO_1 = ptr +export const DOC_INFO_1_Name = key +export const DOC_INFO_1_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/JOB_INFO_1.ts b/packages/win32-def/src/lib/struct/winspool/JOB_INFO_1.ts new file mode 100644 index 00000000..bcc97857 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/JOB_INFO_1.ts @@ -0,0 +1,61 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { SYSTEMTIME_Factory, type SYSTEMTIME_Type } from '../minwinbase/SYSTEMTIME.js' +import { genStruct } from '../struct.helper.js' + + + +const key = 'JOB_INFO_1' +const ptr = `${key}*` as const +const init: StructInitType = { + JobId: D.DWORD, + pPrinterName: D.LPTSTR, + pMachineName: D.LPTSTR, + pUserName: D.LPTSTR, + pDocument: D.LPTSTR, + pDatatype: D.LPTSTR, + pStatus: D.LPTSTR, + Status: D.DWORD, + Priority: D.DWORD, + Position: D.DWORD, + TotalPages: D.DWORD, + PagesPrinted: D.DWORD, + Submitted: SYSTEMTIME_Factory, +} as const + +/** + * JOB_INFO_1 structure, + * The JOB_INFO_1 structure specifies print-job information such as the job-identifier value + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/job-info-1 + */ +export function JOB_INFO_1_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * JOB_INFO_1 structure, + * The JOB_INFO_1 structure specifies print-job information such as the job-identifier value + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/job-info-1 + */ +export interface JOB_INFO_1_Type { + JobId: T.DWORD + pPrinterName: T.LPTSTR + pMachineName: T.LPTSTR + pUserName: T.LPTSTR + pDocument: T.LPTSTR + pDatatype: T.LPTSTR + pStatus: T.LPTSTR + Status: T.DWORD + Priority: T.DWORD + Position: T.DWORD + TotalPages: T.DWORD + PagesPrinted: T.DWORD + Submitted: SYSTEMTIME_Type +} + +export const PJOB_INFO_1 = ptr +export const JOB_INFO_1_Name = key +export const JOB_INFO_1_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_DEFAULTS.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_DEFAULTS.ts new file mode 100644 index 00000000..acb8fa04 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_DEFAULTS.ts @@ -0,0 +1,46 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' +import { DEVMODEW_Factory, DEVMODEW_Type } from '../wingdi/DEVMODEW.js' + + +const key = 'PRINTER_DEFAULTS' +const ptr = `${key}*` as const +const init: StructInitType = { + pDatatype: D.LPTSTR, + pDevMode: DEVMODEW_Factory, + DesiredAccess: D.ACCESS_MASK, +} as const + +/** + * PRINTER_DEFAULTS structure, + * Specifies the default data type, environment, initialization data, and access rights for a printer. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/printer-defaults + */ +export function PRINTER_DEFAULTS_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_DEFAULTS structure, + * Specifies the default data type, environment, initialization data, and access rights for a printer. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/printer-defaults + */ +export interface PRINTER_DEFAULTS_Type { + /** + * Pointer to a null-terminated string that specifies the default data type for a printer. + */ + pDatatype: T.LPTSTR + /** + * Pointer to a DEVMODE structure that identifies the default environment and initialization data for a printer. + */ + pDevMode: DEVMODEW_Type + DesiredAccess: T.ACCESS_MASK +} + +export const PPRINTER_DEFAULTS = ptr +export const PRINTER_DEFAULTS_Name = key +export const PRINTER_DEFAULTS_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_1.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_1.ts new file mode 100644 index 00000000..6ecc22b7 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_1.ts @@ -0,0 +1,41 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'PRINTER_INFO_1' +const ptr = `${key}*` as const +const init: StructInitType = { + Flags: D.DWORD, + pDescription: D.WString, + pName: D.WString, + pComment: D.WString, +} as const + +/** + * PRINTER_INFO_1 structure, + * Specifies general printer information + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-1 + */ +export function PRINTER_INFO_1_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_INFO_1 structure, + * Specifies general printer information + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-1 + */ +export interface PRINTER_INFO_1_Type { + Flags: T.DWORD + pDescription: T.WString + pName: T.WString + pComment: T.WString +} + +export const PPRINTER_INFO_1 = ptr +export const PRINTER_INFO_1_Name = key +export const PRINTER_INFO_1_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_4.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_4.ts new file mode 100644 index 00000000..d6b9adf0 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_4.ts @@ -0,0 +1,45 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'PRINTER_INFO_4' +const ptr = `${key}*` as const +const init: StructInitType = { + pPrinterName: D.WString, + pServerName: D.WString, + Attributes: D.DWORD, +} as const + +/** + * PRINTER_INFO_4 structure, + * Specifies general printer information + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-4 + * @description The structure can be used to retrieve minimal printer information on a call to EnumPrinters. + * Such a call is a fast and easy way to retrieve the names and attributes of all locally installed printers + * on a system and all remote printer connections that a user has established. + */ +export function PRINTER_INFO_4_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_INFO_4 structure, + * Specifies general printer information + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-4 + * @description The structure can be used to retrieve minimal printer information on a call to EnumPrinters. + * Such a call is a fast and easy way to retrieve the names and attributes of all locally installed printers + * on a system and all remote printer connections that a user has established. + */ +export interface PRINTER_INFO_4_Type { + pPrinterName: T.WString + pServerName: T.WString | null + Attributes: T.DWORD +} + +export const PPRINTER_INFO_4 = ptr +export const PRINTER_INFO_4_Name = key +export const PRINTER_INFO_4_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_5.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_5.ts new file mode 100644 index 00000000..f9bccbea --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_5.ts @@ -0,0 +1,43 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'PRINTER_INFO_5' +const ptr = `${key}*` as const +const init: StructInitType = { + pPrinterName: D.WString, + pPortName: D.WString, + Attributes: D.DWORD, + DeviceNotSelectedTimeout: D.DWORD, + TransmissionRetryTimeout: D.DWORD, +} as const + +/** + * PRINTER_INFO_5 structure, + * structure specifies detailed printer information. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-5 + */ +export function PRINTER_INFO_5_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_INFO_5 structure, + * structure specifies detailed printer information. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-5 + */ +export interface PRINTER_INFO_5_Type { + pPrinterName: T.WString + pPortName: T.WString + Attributes: T.DWORD + DeviceNotSelectedTimeout: T.DWORD + TransmissionRetryTimeout: T.DWORD +} + +export const PPRINTER_INFO_5 = ptr +export const PRINTER_INFO_5_Name = key +export const PRINTER_INFO_5_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_6.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_6.ts new file mode 100644 index 00000000..f84f5b9b --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_6.ts @@ -0,0 +1,35 @@ +import * as D from '##/lib/common.def.js' +import { PRINTER_STATUS } from '##/lib/consts/index.consts.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'PRINTER_INFO_6' +const ptr = `${key}*` as const +const init: StructInitType = { + dwStatus: D.DWORD, +} as const + +/** + * PRINTER_INFO_6 structure, + * structure specifies detailed printer information. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-6 + */ +export function PRINTER_INFO_6_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_INFO_6 structure, + * structure specifies detailed printer information. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-6 + */ +export interface PRINTER_INFO_6_Type { + dwStatus: PRINTER_STATUS +} + +export const PPRINTER_INFO_6 = ptr +export const PRINTER_INFO_6_Name = key +export const PRINTER_INFO_6_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_8.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_8.ts new file mode 100644 index 00000000..38c0f7e3 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_8.ts @@ -0,0 +1,35 @@ +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' +import { DEVMODEW_Factory, type DEVMODEW_Type } from '../wingdi/wingdi.index.js' + + + +const key = 'PRINTER_INFO_8' +const ptr = `${key}*` as const +const init: StructInitType = { + pDevMode: DEVMODEW_Factory, +} as const + +/** + * PRINTER_INFO_8 structure, + * specifies the global default printer settings. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-8 + */ +export function PRINTER_INFO_8_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_INFO_8 structure, + * specifies the global default printer settings. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-8 + */ +export interface PRINTER_INFO_8_Type { + pDevMode: DEVMODEW_Type +} + +export const PPRINTER_INFO_8 = ptr +export const PRINTER_INFO_8_Name = key +export const PRINTER_INFO_8_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_9.ts b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_9.ts new file mode 100644 index 00000000..e4aaab93 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTER_INFO_9.ts @@ -0,0 +1,34 @@ +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' +import { DEVMODEW_Factory, type DEVMODEW_Type } from '../wingdi/wingdi.index.js' + + +const key = 'PRINTER_INFO_9' +const ptr = `${key}*` as const +const init: StructInitType = { + pDevMode: DEVMODEW_Factory, +} as const + +/** + * PRINTER_INFO_9 structure, + * structure specifies the per-user default printer settings. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-9 + */ +export function PRINTER_INFO_9_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTER_INFO_9 structure, + * structure specifies the per-user default printer settings. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/PRINTER-INFO-9 + */ +export interface PRINTER_INFO_9_Type { + pDevMode: DEVMODEW_Type +} + +export const PPRINTER_INFO_9 = ptr +export const PRINTER_INFO_9_Name = key +export const PRINTER_INFO_9_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/PRINTPROCESSOR_INFO_1.ts b/packages/win32-def/src/lib/struct/winspool/PRINTPROCESSOR_INFO_1.ts new file mode 100644 index 00000000..58fef9d9 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/PRINTPROCESSOR_INFO_1.ts @@ -0,0 +1,35 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'PRINTPROCESSOR_INFO_1' +const ptr = `${key}*` as const +const init: StructInitType = { + pName: D.LPTSTR, +} as const + +/** + * PRINTPROCESSOR_INFO_1 structure, + * Specifies the name of an installed print processor. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/printprocessor-info-1 + */ +export function PRINTPROCESSOR_INFO_1_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * PRINTPROCESSOR_INFO_1 structure, + * Specifies the name of an installed print processor. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/printprocessor-info-1 + */ +export interface PRINTPROCESSOR_INFO_1_Type { + pName: T.LPTSTR +} + +export const PPRINTPROCESSOR_INFO_1 = ptr +export const PRINTPROCESSOR_INFO_1_Name = key +export const PRINTPROCESSOR_INFO_1_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winspool/helper.types.ts b/packages/win32-def/src/lib/struct/winspool/helper.types.ts new file mode 100644 index 00000000..512cb551 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/helper.types.ts @@ -0,0 +1,84 @@ +import type { PRINTER_INFO_1_Type } from './PRINTER_INFO_1.js' +import type { PRINTER_INFO_4_Type } from './PRINTER_INFO_4.js' +import type { PRINTER_INFO_5_Type } from './PRINTER_INFO_5.js' +import type { PRINTER_INFO_6_Type } from './PRINTER_INFO_6.js' +import type { PRINTER_INFO_8_Type } from './PRINTER_INFO_8.js' +import type { PRINTER_INFO_9_Type } from './PRINTER_INFO_9.js' + + +export * from './DOC_INFO_1.js' +export * from './PRINTER_DEFAULTS.js' +export * from './PRINTER_INFO_1.js' +export * from './PRINTER_INFO_4.js' +export * from './PRINTER_INFO_5.js' +export * from './PRINTER_INFO_6.js' +export * from './PRINTER_INFO_8.js' +export * from './PRINTER_INFO_9.js' +export * from './PRINTPROCESSOR_INFO_1.js' + +// #region EnumPrinters + +/** + * For GetPrinter() + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter#parameters + * @todo 2, 3, 6, 7 + */ +export type PRINTER_INFO_LEVEL = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 + +/** + * For GetPrinter() + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter#parameters + * @todo 2, 3, 6, 7 + */ +export type PRINTER_INFO_Type = PRINTER_INFO_1_Type | PRINTER_INFO_4_Type | PRINTER_INFO_5_Type | PRINTER_INFO_8_Type | PRINTER_INFO_9_Type + +/** + * For GetPrinter() + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter#parameters + * @todo 2, 3, 7 + */ +export type PRINTER_INFO_X_Type = X extends 1 + ? PRINTER_INFO_1_Type + : X extends 4 + ? PRINTER_INFO_4_Type + : X extends 5 + ? PRINTER_INFO_5_Type + : X extends 6 + ? PRINTER_INFO_6_Type + : X extends 8 + ? PRINTER_INFO_8_Type + : X extends 9 + ? PRINTER_INFO_9_Type + : never + + +// #region EnumPrinters + +/** + * For EnumPrinters() + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/enumprinters + * @todo 2 + */ +export type EnumPrinters_Level = 1 | 4 | 5 + +/** + * For EnumPrinters() + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/enumprinters + * @todo 2 + */ +export type EnumPrinters_Level_Type = PRINTER_INFO_1_Type | PRINTER_INFO_4_Type | PRINTER_INFO_5_Type + +/** + * For EnumPrinters() + * @link https://learn.microsoft.com/zh-cn/windows/win32/printdocs/enumprinters + * @todo 2 + */ +export type EnumPrinters_Level_X_Type = X extends 1 + ? PRINTER_INFO_1_Type + : X extends 4 + ? PRINTER_INFO_4_Type + : X extends 5 + ? PRINTER_INFO_5_Type + : never + + diff --git a/packages/win32-def/src/lib/struct/winspool/winspool.index.ts b/packages/win32-def/src/lib/struct/winspool/winspool.index.ts new file mode 100644 index 00000000..2f184b52 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winspool/winspool.index.ts @@ -0,0 +1,13 @@ + +export * from './DOC_INFO_1.js' +export * from './JOB_INFO_1.js' +export * from './PRINTER_DEFAULTS.js' +export * from './PRINTER_INFO_1.js' +export * from './PRINTER_INFO_4.js' +export * from './PRINTER_INFO_5.js' +export * from './PRINTER_INFO_8.js' +export * from './PRINTER_INFO_9.js' +export * from './PRINTPROCESSOR_INFO_1.js' + +export * from './helper.types.js' + diff --git a/packages/win32-def/src/lib/struct/winuser.def.ts b/packages/win32-def/src/lib/struct/winuser.def.ts deleted file mode 100644 index 97ce274d..00000000 --- a/packages/win32-def/src/lib/struct/winuser.def.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - DWORD, - HWND, - UINT, -} from '../common.def.js' -import { UnionType } from '../helper.js' -import { RID_DEVICE_INFO_DUMMYUNIONNAME } from '../union/union.def.js' -// import * as UT from '../union/union.types.js' - - -/** - * @link https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-flashwinfo - */ -export const FLASHWINFO = { - cbSize: UINT, - hwnd: HWND, - dwFlags: DWORD, - uCount: UINT, - dwTimeout: DWORD, -} as const - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-rid_device_info */ -export const RID_DEVICE_INFO = { - cbSize: DWORD, - dwType: DWORD, - // DUMMYUNIONNAME: UnionType(RID_DEVICE_INFO_DUMMYUNIONNAME), - DUMMYUNIONNAME: UnionType(RID_DEVICE_INFO_DUMMYUNIONNAME), -} as const - diff --git a/packages/win32-def/src/lib/struct/winuser.types.ts b/packages/win32-def/src/lib/struct/winuser.types.ts deleted file mode 100644 index 09b67a1f..00000000 --- a/packages/win32-def/src/lib/struct/winuser.types.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { - DWORD, - HWND, - StructInstanceBase, - UINT, - _POINTER, -} from '../common.types.js' -import { RID_DEVICE_INFO_DUMMYUNIONNAME } from '../union/union.types.js' - - -/** - * @link https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-flashwinfo - */ -export interface FLASHWINFO extends StructInstanceBase { - cbSize: UINT - hwnd: HWND - dwFlags: DWORD - uCount: UINT - dwTimeout: DWORD -} -export type PFLASHWINFO = _POINTER - - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/ns-winuser-rid_device_info */ -export interface RID_DEVICE_INFO extends StructInstanceBase { - cbSize: DWORD - dwType: DWORD - // DUMMYUNIONNAME: BufferType - DUMMYUNIONNAME: RID_DEVICE_INFO_DUMMYUNIONNAME -} -export type PRID_DEVICE_INFO = _POINTER - diff --git a/packages/win32-def/src/lib/struct/winuser.var.def.ts b/packages/win32-def/src/lib/struct/winuser.var.def.ts deleted file mode 100644 index c83f10fa..00000000 --- a/packages/win32-def/src/lib/struct/winuser.var.def.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Def } from '../def.enum.js' - - -/** - * @link https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-flashwinfo - */ -export const FLASHWINFO = Def.ptr - -/** https://docs.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-display_devicew */ -export const RID_DEVICE_INFO = Def.ptr - - diff --git a/packages/win32-def/src/lib/struct/winuser/ALTTABINFO.ts b/packages/win32-def/src/lib/struct/winuser/ALTTABINFO.ts new file mode 100644 index 00000000..7dffbdbd --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/ALTTABINFO.ts @@ -0,0 +1,50 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' +import { POINT_Factory, type POINT_Type } from '../windef/POINT.js' + + +const key = 'ALTTABINFO' +const ptr = `${key}*` as const +const init: StructInitType = { + cbSize: D.DWORD, + cItems: D.INT, + cColumns: D.INT, + cRows: D.INT, + iColFocus: D.INT, + iRowFocus: D.INT, + cxItem: D.INT, + cyItem: D.INT, + ptStart: POINT_Factory, +} as const + +/** + * ALTTABINFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-alttabinfo + */ +export function ALTTABINFO_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['cbSize']) +} + +/** + * ALTTABINFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-alttabinfo + */ +export interface ALTTABINFO_Type { + cbSize: T.DWORD + cItems: T.INT + cColumns: T.INT + cRows: T.INT + iColFocus: T.INT + iRowFocus: T.INT + cxItem: T.INT + cyItem: T.INT + ptStart: POINT_Type +} + +export const LPALTTABINFO = ptr +export const ALTTABINFO_Name = key +export const ALTTABINFO_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/COPYDATASTRUCT.ts b/packages/win32-def/src/lib/struct/winuser/COPYDATASTRUCT.ts new file mode 100644 index 00000000..a7bff01f --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/COPYDATASTRUCT.ts @@ -0,0 +1,38 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'COPYDATASTRUCT' +const ptr = `${key}*` as const +const init: StructInitType = { + dwData: D.ULONG_PTR, + cbData: D.DWORD, + lpData: D.PVOID, +} as const + + +/** + * COPYDATASTRUCT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-copydatastruct + */ +export function COPYDATASTRUCT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * POINT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-copydatastruct + */ +export interface COPYDATASTRUCT_Type { + dwData: T.ULONG_PTR + cbData: T.DWORD + lpData: T.PVOID +} + +export const LPCOPYDATASTRUCT = ptr +export const COPYDATASTRUCT_Name = key +export const COPYDATASTRUCT_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/FLASHWINFO.ts b/packages/win32-def/src/lib/struct/winuser/FLASHWINFO.ts new file mode 100644 index 00000000..cf9e1669 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/FLASHWINFO.ts @@ -0,0 +1,42 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'FLASHWINFO' +const ptr = `${key}*` as const +const init: StructInitType = { + cbSize: D.UINT, + hwnd: D.HWND, + dwFlags: D.DWORD, + uCount: D.UINT, + dwTimeout: D.DWORD, +} as const + + +/** + * FLASHWINFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-FLASHWINFO + */ +export function FLASHWINFO_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['cbSize']) +} + +/** + * FLASHWINFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-FLASHWINFO + */ +export interface FLASHWINFO_Type { + cbSize: T.UINT + hwnd: T.HWND + dwFlags: T.DWORD + uCount: T.UINT + dwTimeout: T.DWORD +} + +export const PFLASHWINFO = ptr +export const FLASHWINFO_Name = key +export const FLASHWINFO_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/HARDWAREINPUT.ts b/packages/win32-def/src/lib/struct/winuser/HARDWAREINPUT.ts new file mode 100644 index 00000000..adce6b24 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/HARDWAREINPUT.ts @@ -0,0 +1,36 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'HARDWAREINPUT' +const ptr = `${key}*` as const +const init: StructInitType = { + uMsg: D.UINT32, + wParamL: D.UINT16, + wParamH: D.UINT16, +} as const + +/** + * HARDWAREINPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-hardwareinput + */ +export function HARDWAREINPUT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} +/** + * HARDWAREINPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-hardwareinput + */ +export interface HARDWAREINPUT_TYPE { + uMsg: T.UINT32 + wParamL: T.UINT16 + wParamH: T.UINT16 +} + +export const LPHARDWAREINPUT = ptr +export const HARDWAREINPUT_Name = key +export const HARDWAREINPUT_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/INPUT.ts b/packages/win32-def/src/lib/struct/winuser/INPUT.ts new file mode 100644 index 00000000..799d0ac8 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/INPUT.ts @@ -0,0 +1,58 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + +import { HARDWAREINPUT_Factory, type HARDWAREINPUT_TYPE } from './HARDWAREINPUT.js' +import { KEYBDINPUT_Factory, type KEYBDINPUT_Type } from './KEYBDINPUT.js' +import { MOUSEINPUT_Factory, type MOUSEINPUT_Type } from './MOUSEINPUT.js' + + +const key = 'INPUT' +const ptr = `${key}*` as const +const init: StructInitType = { + type: D.UINT32, + u: { + mi: MOUSEINPUT_Factory, + ki: KEYBDINPUT_Factory, + hi: HARDWAREINPUT_Factory, + }, +} as const + + +/** + * INPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-input + */ +export function INPUT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * INPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-input + */ +export interface INPUT_Type { + type: T.UINT32 + u: { + mi?: MOUSEINPUT_Type, + ki?: KEYBDINPUT_Type, + hi?: HARDWAREINPUT_TYPE, + } +} + +export const LPINPUT = ptr +export const INPUT_Name = key +export const INPUT_Init: typeof init = init + +// export const INPUT = koffi.struct('INPUT', { +// type: W.UINT32, +// u: koffi.union({ +// mi: MOUSEINPUT, +// ki: KEYBDINPUT, +// hi: HARDWAREINPUT, +// }), +// }) + + diff --git a/packages/win32-def/src/lib/struct/winuser/KEYBDINPUT.ts b/packages/win32-def/src/lib/struct/winuser/KEYBDINPUT.ts new file mode 100644 index 00000000..6e4c6836 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/KEYBDINPUT.ts @@ -0,0 +1,42 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'KEYBDINPUT' +const ptr = `${key}*` as const +const init: StructInitType = { + wVk: D.UINT16, + wScan: D.UINT16, + dwFlags: D.UINT32, + time: D.UINT32, + dwExtraInfo: D.PUINT, +} as const + + +/** + * KEYBDINPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput + */ +export function KEYBDINPUT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * KEYBDINPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput + */ +export interface KEYBDINPUT_Type { + wVk: T.WORD + wScan: T.WORD + dwFlags: T.DWORD + time: T.DWORD + dwExtraInfo: T.ULONG_PTR +} + +export const LPKEYBDINPUT = ptr +export const KEYBDINPUT_Name = key +export const KEYBDINPUT_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/MOUSEINPUT.ts b/packages/win32-def/src/lib/struct/winuser/MOUSEINPUT.ts new file mode 100644 index 00000000..0b061120 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/MOUSEINPUT.ts @@ -0,0 +1,44 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'MOUSEINPUT' +const ptr = `${key}*` as const +const init: StructInitType = { + dx: D.LONG, + dy: D.LONG, + mouseData: D.UINT32, + dwFlags: D.UINT32, + time: D.UINT32, + dwExtraInfo: D.PUINT, +} as const + + +/** + * MOUSEINPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput + */ +export function MOUSEINPUT_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * MOUSEINPUT structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput + */ +export interface MOUSEINPUT_Type { + dx: T.LONG + dy: T.LONG + mouseData: T.UINT32 + dwFlags: T.UINT32 + time: T.UINT32 + dwExtraInfo: T.PUINT +} + +export const LPMOUSEINPUT = ptr +export const MOUSEINPUT_Name = key +export const MOUSEINPUT_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/MSG.ts b/packages/win32-def/src/lib/struct/winuser/MSG.ts new file mode 100644 index 00000000..774726a8 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/MSG.ts @@ -0,0 +1,47 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' +import { POINT_Factory, type POINT_Type } from '../windef/POINT.js' + + +const key = 'MSG' +const ptr = `${key}*` as const +const init: StructInitType = { + hwnd: D.HWND, + message: D.UINT, + wParam: D.WPARAM, + lParam: D.LPARAM, + time: D.DWORD, + pt: POINT_Factory, + lPrivate: D.DWORD, +} as const + + +/** + * MSG structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg + */ +export function MSG_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * MSG structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-msg + */ +export interface MSG_Type { + hwnd: T.HWND + message: T.UINT + wParam: T.WPARAM + lParam: T.LPARAM + time: T.DWORD + pt: POINT_Type + lPrivate: T.DWORD +} + +export const LPMSG = ptr +export const MSG_Name = key +export const MSG_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RAWHID.ts b/packages/win32-def/src/lib/struct/winuser/RAWHID.ts new file mode 100644 index 00000000..52a50b11 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RAWHID.ts @@ -0,0 +1,40 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RAWHID' +const ptr = `${key}*` as const +const init: StructInitType = { + dwSizeHid: D.DWORD, + dwCount: D.DWORD, + /** bRawData[1] */ + bRawData: D.BYTE, +} as const + + +/** + * RAWHID structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawhid + */ +export function RAWHID_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RAWHID structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawhid + */ +export interface RAWHID_Type { + dwSizeHid: T.DWORD + dwCount: T.DWORD + /** bRawData[1] */ + bRawData: T.BYTE +} + +export const LPRAWHID = ptr +export const RAWHID_Name = key +export const RAWHID_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RAWINPUTDEVICELIST.ts b/packages/win32-def/src/lib/struct/winuser/RAWINPUTDEVICELIST.ts new file mode 100644 index 00000000..99b60a01 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RAWINPUTDEVICELIST.ts @@ -0,0 +1,36 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RAWINPUTDEVICELIST' +const ptr = `${key}*` as const +const init: StructInitType = { + hDevice: D.HANDLE, + dwType: D.DWORD, +} as const + + +/** + * RAWINPUTDEVICELIST structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RAWINPUTDEVICELIST + */ +export function RAWINPUTDEVICELIST_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RAWINPUTDEVICELIST structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RAWINPUTDEVICELIST + */ +export interface RAWINPUTDEVICELIST_Type { + hDevice: T.HANDLE + dwType: T.DWORD +} + +export const LPRAWINPUTDEVICELIST = ptr +export const RAWINPUTDEVICELIST_Name = key +export const RAWINPUTDEVICELIST_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RAWINPUTHEADER.ts b/packages/win32-def/src/lib/struct/winuser/RAWINPUTHEADER.ts new file mode 100644 index 00000000..440010c4 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RAWINPUTHEADER.ts @@ -0,0 +1,40 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RAWINPUTHEADER' +const ptr = `${key}*` as const +const init: StructInitType = { + dwType: D.DWORD, + dwSize: D.DWORD, + hDevice: D.HANDLE, + wParam: D.WPARAM, +} as const + + +/** + * RAWINPUTHEADER structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RAWINPUTHEADER + */ +export function RAWINPUTHEADER_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RAWINPUTHEADER structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RAWINPUTHEADER + */ +export interface RAWINPUTHEADER_Type { + dwType: T.DWORD + dwSize: T.DWORD + hDevice: T.HANDLE + wParam: T.WPARAM +} + +export const LPRAWINPUTHEADER = ptr +export const RAWINPUTHEADER_Name = key +export const RAWINPUTHEADER_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RAWKEYBOARD.ts b/packages/win32-def/src/lib/struct/winuser/RAWKEYBOARD.ts new file mode 100644 index 00000000..7de2ddfd --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RAWKEYBOARD.ts @@ -0,0 +1,44 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RAWKEYBOARD' +const ptr = `${key}*` as const +const init: StructInitType = { + MakeCode: D.USHORT, + Flags: D.USHORT, + Reserved: D.USHORT, + VKey: D.USHORT, + Message: D.UINT, + ExtraInformation: D.ULONG, +} as const + + +/** + * RAWKEYBOARD structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RAWKEYBOARD + */ +export function RAWKEYBOARD_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RAWKEYBOARD structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RAWKEYBOARD + */ +export interface RAWKEYBOARD_Type { + MakeCode: T.USHORT + Flags: T.USHORT + Reserved: T.USHORT + VKey: T.USHORT + Message: T.UINT + ExtraInformation: T.ULONG +} + +export const LPRAWKEYBOARD = ptr +export const RAWKEYBOARD_Name = key +export const RAWKEYBOARD_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO.ts b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO.ts new file mode 100644 index 00000000..6c3d16c9 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO.ts @@ -0,0 +1,50 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + +import { RID_DEVICE_INFO_HID_Factory, type RID_DEVICE_INFO_HID_Type } from './RID_DEVICE_INFO_HID.js' +import { RID_DEVICE_INFO_KEYBOARD_Factory, type RID_DEVICE_INFO_KEYBOARD_Type } from './RID_DEVICE_INFO_KEYBOARD.js' +import { RID_DEVICE_INFO_MOUSE_Factory, type RID_DEVICE_INFO_MOUSE_Type } from './RID_DEVICE_INFO_MOUSE.js' + + +const key = 'RID_DEVICE_INFO' +const ptr = `${key}*` as const +const init: StructInitType = { + cbSize: D.DWORD, + dwType: D.DWORD, + u: { + mouse: RID_DEVICE_INFO_MOUSE_Factory, + keyboard: RID_DEVICE_INFO_KEYBOARD_Factory, + hid: RID_DEVICE_INFO_HID_Factory, + }, +} as const + + +/** + * RID_DEVICE_INFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO + */ +export function RID_DEVICE_INFO_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['cbSize']) +} + +/** + * RID_DEVICE_INFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO + */ +export interface RID_DEVICE_INFO_Type { + cbSize: T.DWORD + dwType: T.DWORD + u: { + mouse: RID_DEVICE_INFO_MOUSE_Type, + keyboard: RID_DEVICE_INFO_KEYBOARD_Type, + hid: RID_DEVICE_INFO_HID_Type, + } +} + +export const LPRID_DEVICE_INFO = ptr +export const RID_DEVICE_INFO_Name = key +export const RID_DEVICE_INFO_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_HID.ts b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_HID.ts new file mode 100644 index 00000000..893da117 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_HID.ts @@ -0,0 +1,42 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RID_DEVICE_INFO_HID' +const ptr = `${key}*` as const +const init: StructInitType = { + dwVendorId: D.DWORD, + dwProductId: D.DWORD, + dwVersionNumber: D.DWORD, + usUsagePage: D.USHORT, + usUsage: D.USHORT, +} as const + + +/** + * RID_DEVICE_INFO_HID structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO_HID + */ +export function RID_DEVICE_INFO_HID_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RID_DEVICE_INFO_HID structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO_HID + */ +export interface RID_DEVICE_INFO_HID_Type { + dwVendorId: T.DWORD + dwProductId: T.DWORD + dwVersionNumber: T.DWORD + usUsagePage: T.USHORT + usUsage: T.USHORT +} + +export const PRID_DEVICE_INFO_HID = ptr +export const RID_DEVICE_INFO_HID_Name = key +export const RID_DEVICE_INFO_HID_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_KEYBOARD.ts b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_KEYBOARD.ts new file mode 100644 index 00000000..f4c778d6 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_KEYBOARD.ts @@ -0,0 +1,44 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RID_DEVICE_INFO_KEYBOARD' +const ptr = `${key}*` as const +const init: StructInitType = { + dwType: D.DWORD, + dwSubType: D.DWORD, + dwKeyboardMode: D.DWORD, + dwNumberOfFunctionKeys: D.DWORD, + dwNumberOfIndicators: D.DWORD, + dwNumberOfKeysTotal: D.DWORD, +} as const + + +/** + * RID_DEVICE_INFO_KEYBOARD structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO_KEYBOARD + */ +export function RID_DEVICE_INFO_KEYBOARD_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RID_DEVICE_INFO_KEYBOARD structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO_KEYBOARD + */ +export interface RID_DEVICE_INFO_KEYBOARD_Type { + dwType: T.DWORD + dwSubType: T.DWORD + dwKeyboardMode: T.DWORD + dwNumberOfFunctionKeys: T.DWORD + dwNumberOfIndicators: T.DWORD + dwNumberOfKeysTotal: T.DWORD +} + +export const PRID_DEVICE_INFO_KEYBOARD = ptr +export const RID_DEVICE_INFO_KEYBOARD_Name = key +export const RID_DEVICE_INFO_KEYBOARD_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_MOUSE.ts b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_MOUSE.ts new file mode 100644 index 00000000..4f3ad0fb --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/RID_DEVICE_INFO_MOUSE.ts @@ -0,0 +1,40 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'RID_DEVICE_INFO_MOUSE' +const ptr = `${key}*` as const +const init: StructInitType = { + dwId: D.DWORD, + dwNumberOfButtons: D.DWORD, + dwSampleRate: D.DWORD, + fHasHorizontalWheel: D.BOOL, +} as const + + +/** + * RID_DEVICE_INFO_MOUSE structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO_MOUSE + */ +export function RID_DEVICE_INFO_MOUSE_Factory(): StructFactoryResult { + return genStruct(init, key, ptr) +} + +/** + * RID_DEVICE_INFO_MOUSE structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-RID_DEVICE_INFO_MOUSE + */ +export interface RID_DEVICE_INFO_MOUSE_Type { + dwId: T.DWORD + dwNumberOfButtons: T.DWORD + dwSampleRate: T.DWORD + fHasHorizontalWheel: T.BOOL +} + +export const PRID_DEVICE_INFO_MOUSE = ptr +export const RID_DEVICE_INFO_MOUSE_Name = key +export const RID_DEVICE_INFO_MOUSE_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/WINDOWINFO.ts b/packages/win32-def/src/lib/struct/winuser/WINDOWINFO.ts new file mode 100644 index 00000000..961abf0f --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/WINDOWINFO.ts @@ -0,0 +1,53 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' +import { RECT_Factory, type RECT_Type } from '../windef/RECT.js' + + +const key = 'WINDOWINFO' +const ptr = `${key}*` as const +const init: StructInitType = { + cbSize: D.DWORD, + rcWindow: RECT_Factory, + rcClient: RECT_Factory, + dwStyle: D.DWORD, + dwExStyle: D.DWORD, + dwWindowStatus: D.DWORD, + cxWindowBorders: D.UINT, + cyWindowBorders: D.UINT, + atomWindowType: D.ATOM, + wCreatorVersion: D.WORD, +} as const + + +/** + * WINDOWINFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-WINDOWINFO + */ +export function WINDOWINFO_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['cbSize']) +} + +/** + * WINDOWINFO structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-WINDOWINFO + */ +export interface WINDOWINFO_Type { + cbSize: T.DWORD + rcWindow: RECT_Type + rcClient: RECT_Type + dwStyle: T.DWORD + dwExStyle: T.DWORD + dwWindowStatus: T.DWORD + cxWindowBorders: T.UINT + cyWindowBorders: T.UINT + atomWindowType: T.ATOM + wCreatorVersion: T.WORD +} + +export const LPWINDOWINFO = ptr +export const WINDOWINFO_Name = key +export const WINDOWINFO_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/WNDCLASSEXW.ts b/packages/win32-def/src/lib/struct/winuser/WNDCLASSEXW.ts new file mode 100644 index 00000000..8b148d52 --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/WNDCLASSEXW.ts @@ -0,0 +1,58 @@ +import * as D from '##/lib/common.def.js' +import * as T from '##/lib/common.types.js' +import type { StructFactoryResult, StructInitType } from '##/lib/types.js' + +import { genStruct } from '../struct.helper.js' + + +const key = 'WNDCLASSEXW' +const ptr = `${key}*` as const +const init: StructInitType = { + cbSize: D.UINT, + style: D.UINT, + // 'lpfnWndProc': ffi.Function('int32', ['pointer', 'uint32', 'int32', 'uint32']) , + lpfnWndProc: D.WNDPROC, + cbClsExtra: D.INT, + cbWndExtra: D.INT, + hInstance: D.HINSTANCE, + hIcon: D.HICON, + hCursor: D.HCURSOR, + hbrBackground: D.HBRUSH, + lpszMenuName: D.LPCTSTR, + lpszClassName: D.LPCTSTR, + hIconSm: D.HICON, +} as const + + +/** + * WNDCLASSEXW structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexw + */ +export function WNDCLASSEXW_Factory(): StructFactoryResult { + return genStruct(init, key, ptr, ['cbSize']) +} + +/** + * WNDCLASSEXW structure + * @link https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexw + */ +export interface WNDCLASSEXW_Type { + cbSize: T.UINT + style: T.UINT + // 'lpfnWndProc': ffi.Function('int32', ['pointer', 'uint32', 'int32', 'uint32']) , + lpfnWndProc: T.WNDPROC + cbClsExtra: T.INT + cbWndExtra: T.INT + hInstance: T.HINSTANCE + hIcon: T.HICON + hCursor: T.HCURSOR + hbrBackground: T.HBRUSH + lpszMenuName: T.LPCTSTR + lpszClassName: T.LPCTSTR + hIconSm: T.HICON +} + +export const LPWNDCLASSEXW = ptr +export const WNDCLASSEXW_Name = key +export const WNDCLASSEXW_Init: typeof init = init + diff --git a/packages/win32-def/src/lib/struct/winuser/winuser.index.ts b/packages/win32-def/src/lib/struct/winuser/winuser.index.ts new file mode 100644 index 00000000..9169e47e --- /dev/null +++ b/packages/win32-def/src/lib/struct/winuser/winuser.index.ts @@ -0,0 +1,20 @@ + +export * from './ALTTABINFO.js' +export * from './COPYDATASTRUCT.js' +export * from './FLASHWINFO.js' +export * from './HARDWAREINPUT.js' +export * from './INPUT.js' +export * from './KEYBDINPUT.js' +export * from './MOUSEINPUT.js' +export * from './MSG.js' +export * from './RAWHID.js' +export * from './RAWINPUTDEVICELIST.js' +export * from './RAWINPUTHEADER.js' +export * from './RAWKEYBOARD.js' +export * from './RID_DEVICE_INFO.js' +export * from './RID_DEVICE_INFO_HID.js' +export * from './RID_DEVICE_INFO_KEYBOARD.js' +export * from './RID_DEVICE_INFO_MOUSE.js' +export * from './WNDCLASSEXW.js' +export * from './WINDOWINFO.js' + diff --git a/packages/win32-def/src/lib/types.ts b/packages/win32-def/src/lib/types.ts new file mode 100644 index 00000000..d61a06b8 --- /dev/null +++ b/packages/win32-def/src/lib/types.ts @@ -0,0 +1,119 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { ToAsyncFunction } from '@waiting/shared-types' +import type { IKoffiLib, IKoffiCType, TypeSpecWithAlignment } from 'koffi' + +import type { + CallingConvention, + DllFuncsType, + FnDefName, + FnDefFullParams, + FuncDefList, +} from './ffi.types.js' + + +export type { KoffiFunction } from 'koffi' +export type { IKoffiLib } + + +export interface LoadOptions { + dll: string + dllFuncs: FuncDefList + usedFuncNames?: FnDefName[] | undefined + _WIN64?: boolean // default from process.arch + /** + * Calling convention + * @default 'Cdecl' + * @link https://koffi.dev/functions#calling-conventions + */ + convention?: CallingConvention + /** + * Create struct automatically from parameters of function definition list + * @description param like 'POINT*' or 'POINT *', POINT_Factory() will be called + * @default true + */ + autoCreateStruct?: boolean // for load() + /** + * Multiple choice mapper for function parameters + */ + multipleChoiceMapperList?: MultipleChoiceMapperList + /** + * Force re-register the library, overwriting the existing one + * @default false + */ + forceRegister?: boolean +} + + +export type LibDefBase = Record +export type LibDef2Type = Record, (...args: any) => unknown> + +/** + * FFI library containing functions + */ +export type FLib = T & FLibExtMethods & { + [K in keyof T as K extends `${string}_Async` ? K : `${K & string}_Async`]: T[K] extends (...args: any) => unknown + ? ToAsyncFunction + : never +} + +export interface FLibExtMethods { + /** + * @note Unload the library + * - On windows, it may cause later calls to functions in the library to fail! + * - On some platforms (such as with the musl C library on Linux), shared libraries cannot be unloaded, + * so the library will remain loaded and memory mapped after the call to lib.unload(). + */ + unload: () => void + updateMultipleChoiceMapper: (options: UpdateMultipleChoiceMapperOptions) => void +} + +export interface UpdateMultipleChoiceMapperOptions { + /** update using name+Set */ + fnName?: string + mapperSet?: MultipleChoiceMapperSet + /** update using Map (contains name+Set) */ + mapperList?: MultipleChoiceMapperList +} + +/** + * Multiple choice parameter mapper + * return the matched function definition arguments if matched, + * otherwise return undefined (will then match the next mapper) + */ +export type _MultipleChoiceMapper = ( + fnName: string, + runtimeArgs: TRuntimeArgs, + fnDefCallParamsExpanded: (Readonly | TFnDefArgs)[] +) => TFnDefArgs | string[] | readonly string[] | undefined + +export type MultipleChoiceMapper + = _MultipleChoiceMapper & { name: string } + +export type MultipleChoiceMapperList = Map +export type MultipleChoiceMapperSet = Set + + +/** + * The return value of payload always be new one after each call of the struct factory function or access payload + */ +export interface StructFactoryResult extends StructDetail { + /** + * Struct payload for _Out_ or _Inout_ parameter + */ + readonly payload: T + readonly sizeColumns?: PropertyKey[] +} + +export interface StructDetail { + readonly name: string + readonly pointer: string + readonly CType: IKoffiCType + readonly size: number +} +export type StructFactory = () => StructFactoryResult + +export interface StructInitType { + [key: string]: string | IKoffiCType | StructFactory | StructInitType +} + +export type StructInitPlainType = Record diff --git a/packages/win32-def/src/lib/union/index.union.types.ts b/packages/win32-def/src/lib/union/index.union.types.ts deleted file mode 100644 index 2b49b81b..00000000 --- a/packages/win32-def/src/lib/union/index.union.types.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export * from './union.types.js' -export * from './winspool.union.types.js' - - diff --git a/packages/win32-def/src/lib/union/union.def.ts b/packages/win32-def/src/lib/union/union.def.ts deleted file mode 100644 index 1b2634ca..00000000 --- a/packages/win32-def/src/lib/union/union.def.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DWORD } from '../common.def.js' - - -export const RID_DEVICE_INFO_DUMMYUNIONNAME = { - mouse: DWORD, - keyboard: DWORD, - hid: DWORD, -} - diff --git a/packages/win32-def/src/lib/union/union.types.ts b/packages/win32-def/src/lib/union/union.types.ts deleted file mode 100644 index f9f4bbee..00000000 --- a/packages/win32-def/src/lib/union/union.types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DWORD, UnionInstanceBase } from '../common.types.js' - - -export interface RID_DEVICE_INFO_DUMMYUNIONNAME extends UnionInstanceBase { - mouse: DWORD - keyboard: DWORD - hid: DWORD -} - diff --git a/packages/win32-def/src/lib/union/union.var.def.ts b/packages/win32-def/src/lib/union/union.var.def.ts deleted file mode 100644 index 238a9c9f..00000000 --- a/packages/win32-def/src/lib/union/union.var.def.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Def } from '../def.enum.js' - - -export const RID_DEVICE_INFO_DUMMYUNIONNAME = Def.ptr - diff --git a/packages/win32-def/src/lib/union/winspool.union.def.ts b/packages/win32-def/src/lib/union/winspool.union.def.ts deleted file mode 100644 index ae476175..00000000 --- a/packages/win32-def/src/lib/union/winspool.union.def.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { DWORD, SHORT } from '../common.def.js' -import { StructType } from '../helper.js' -import { POINTL } from '../struct/struct.def.js' - - -const DEVMODEW_DUMMYSTRUCTNAME = { - dmOrientation: SHORT, - dmPaperSize: SHORT, - dmPaperLength: SHORT, - dmPaperWidth: SHORT, - dmScale: SHORT, - dmCopies: SHORT, - dmDefaultSource: SHORT, - dmPrintQuality: SHORT, -} -const DEVMODEW_DUMMYSTRUCTNAME2 = { - dmPosition: StructType(POINTL), - dmDisplayOrientation: DWORD, - dmDisplayFixedOutput: DWORD, -} -export const DEVMODEW_DUMMYUNIONNAME = { - DUMMYSTRUCTNAME: StructType(DEVMODEW_DUMMYSTRUCTNAME), - dmPosition: StructType(POINTL), - DUMMYSTRUCTNAME2: StructType(DEVMODEW_DUMMYSTRUCTNAME2), -} -export const DEVMODEW_DUMMYUNIONNAME2 = { - dmDisplayFlags: DWORD, - dmNup: DWORD, -} - diff --git a/packages/win32-def/src/lib/union/winspool.union.types.ts b/packages/win32-def/src/lib/union/winspool.union.types.ts deleted file mode 100644 index b1036369..00000000 --- a/packages/win32-def/src/lib/union/winspool.union.types.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { - DWORD, - SHORT, - StructInstanceBase, - UnionInstanceBase, -} from '../common.types.js' -import { POINTL } from '../struct/struct.types.js' - - -export interface DEVMODEW_DUMMYUNIONNAME extends UnionInstanceBase { - DUMMYSTRUCTNAME: DEVMODEW_DUMMYSTRUCTNAME - dmPosition: POINTL - DUMMYSTRUCTNAME2: DEVMODEW_DUMMYSTRUCTNAME2 -} -interface DEVMODEW_DUMMYSTRUCTNAME extends StructInstanceBase { - dmOrientation: SHORT - dmPaperSize: SHORT - dmPaperLength: SHORT - dmPaperWidth: SHORT - dmScale: SHORT - dmCopies: SHORT - dmDefaultSource: SHORT - dmPrintQuality: SHORT -} -interface DEVMODEW_DUMMYSTRUCTNAME2 extends StructInstanceBase { - dmPosition: POINTL - dmDisplayOrientation: DWORD - dmDisplayFixedOutput: DWORD -} -export interface DEVMODEW_DUMMYUNIONNAME2 extends UnionInstanceBase { - dmDisplayFlags: DWORD - dmNup: DWORD -} diff --git a/packages/win32-def/src/lib/union/winspool.union.var.def.ts b/packages/win32-def/src/lib/union/winspool.union.var.def.ts deleted file mode 100644 index d5a1c891..00000000 --- a/packages/win32-def/src/lib/union/winspool.union.var.def.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Def } from '../def.enum.js' - - -export const DEVMODEW_DUMMYUNIONNAME = Def.ptr -export const DEVMODEW_DUMMYUNIONNAME2 = Def.ptr - diff --git a/packages/win32-def/src/lib/util.ts b/packages/win32-def/src/lib/util.ts new file mode 100644 index 00000000..8b05172d --- /dev/null +++ b/packages/win32-def/src/lib/util.ts @@ -0,0 +1,48 @@ +import assert from 'assert' + +import ffi from 'koffi' + +import { WCHAR_Array } from './common.types.js' + + +export function decodeInt16Array(input: WCHAR_Array, length = -1): string { + assert(input, 'input must be an object') + assert(typeof input.buffer === 'object', 'input.buffer must be an object') + assert(typeof input.byteLength === 'number', 'input.byteLength must be a number') + assert(typeof input.byteOffset === 'number', 'input.byteOffset must be a number') + assert(typeof input.length === 'number', 'input.length must be a number') + // const str = Buffer.from(input.buffer).toString('ucs2') + // return str + const str = ffi.decode(input, 'char16_t', length) as string + return str || '' +} + +/** + * Convert a Buffer to string with UCS2 encoding, and remove the last '\0'. + */ +export function ucsBufferToString(input: Buffer, charNum = 0): string { + // read the last 2 bytes to check if it is '\0' + const last = input.readUInt16LE(input.length - 2) + + if (charNum > 0) { + const n2 = input.length / 2 + const offset = Math.min(charNum, n2) + const txt = input.toString('ucs2', 0, offset * 2) + return last === 0 && charNum >= n2 ? txt.slice(0, -1) : txt + } + + if (last === 0) { // remove the last '\0' + return input.toString('ucs2').slice(0, -1) + } + return input.toString('ucs2') +} + + +/** + * Convert a string to Buffer with UCS2 encoding, and append a '\0' at the end. + */ +export function ucsBufferFrom(str: string): Buffer { + assert(typeof str === 'string', 'str must be a string ') + return Buffer.from(str + '\0', 'ucs2') +} + diff --git a/packages/win32-def/test/.eslintrc.yml b/packages/win32-def/test/.eslintrc.yml deleted file mode 100644 index 809c7469..00000000 --- a/packages/win32-def/test/.eslintrc.yml +++ /dev/null @@ -1,14 +0,0 @@ -extends: '@waiting/eslint-config/recommended' -parserOptions: - project: 'tsconfig.eslint.json' - -rules: - "@typescript-eslint/no-unused-vars": 0 - "node/no-extraneous-import": 0 - "unicorn/filename-case": 0 - "@typescript-eslint/prefer-ts-expect-error": 0 - "linebreak-style": 0 - -ignorePatterns: - - fixtures - diff --git a/packages/win32-def/test/01.loader-no-autoCreateStruct.test.ts b/packages/win32-def/test/01.loader-no-autoCreateStruct.test.ts new file mode 100644 index 00000000..34ef65db --- /dev/null +++ b/packages/win32-def/test/01.loader-no-autoCreateStruct.test.ts @@ -0,0 +1,37 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { LoadOptions, load } from '##/index.js' +import { LPDISPLAY_DEVICEW, LPPOINT } from '##/index.struct.js' +import { type Win32, DefWin32 } from '#@/def.class/api.helper.js' + + +// Make sure this suit run as early as possible, for testing Struct not created case ! + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'user32.dll', + dllFuncs: DefWin32, + } + + describe('load() run first', () => { + // run first + it('autoCreateStruct=false', async () => { + try { + load({ + ...options, + autoCreateStruct: false, + }) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes(LPDISPLAY_DEVICEW) || ex.message.includes(LPPOINT), ex.message) + return + } + assert(false, 'Should throw Error') + }) + + }) +}) + diff --git a/packages/win32-def/test/10.index.test.ts b/packages/win32-def/test/10.index.test.ts index d5dd5cac..ac026be8 100644 --- a/packages/win32-def/test/10.index.test.ts +++ b/packages/win32-def/test/10.index.test.ts @@ -2,9 +2,14 @@ import assert from 'node:assert/strict' import { fileShortPath } from '@waiting/shared-core' -import { Def } from '../src/index.js' +import { Def } from '##/index.js' +import * as S from '##/index.struct.js' +import * as T from '##/index.types.js' +void S.DOC_INFO_1_Factory // for test coverage +void T.CallingConvention + describe(fileShortPath(import.meta.url), () => { describe('should index work', () => { diff --git a/packages/win32-def/test/11.index.def.test.ts b/packages/win32-def/test/12.index.def.test.ts similarity index 67% rename from packages/win32-def/test/11.index.def.test.ts rename to packages/win32-def/test/12.index.def.test.ts index 1bb66aab..c83cc442 100644 --- a/packages/win32-def/test/11.index.def.test.ts +++ b/packages/win32-def/test/12.index.def.test.ts @@ -2,7 +2,7 @@ import assert from 'node:assert/strict' import { fileShortPath } from '@waiting/shared-core' -import { Def, POINT } from '../src/index.def.js' +import { Def } from '../src/index.def.js' describe(fileShortPath(import.meta.url), () => { @@ -12,11 +12,6 @@ describe(fileShortPath(import.meta.url), () => { assert(Def) assert(Object.keys(Def).length > 0) }) - - it('POINT', () => { - assert(POINT) - assert(POINT === Def.ptr) - }) }) }) diff --git a/packages/win32-def/test/12.index.struct.test.ts b/packages/win32-def/test/12.index.struct.test.ts deleted file mode 100644 index 54dc071f..00000000 --- a/packages/win32-def/test/12.index.struct.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { Def } from '../src/index.def.js' -import { StringBuffer } from '../src/index.js' -import { - DISPLAY_DEVICEW, - POINT, - -} from '../src/index.struct.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('should work', () => { - it('POINT', () => { - assert(POINT) - assert(Object.keys(POINT).length > 0) - assert(POINT.x === Def.long) - assert(POINT.y === Def.long) - }) - - it('DISPLAY_DEVICEW', () => { - assert(DISPLAY_DEVICEW) - assert(Object.keys(DISPLAY_DEVICEW).length > 0) - assert(DISPLAY_DEVICEW.cb === Def.uint32) - assert(typeof DISPLAY_DEVICEW.DeviceName === 'object') - assert(DISPLAY_DEVICEW.DeviceName.size > 0) - assert(DISPLAY_DEVICEW.DeviceName.encoding === 'ucs2') - }) - }) - -}) - - diff --git a/packages/win32-def/test/20.helper.struct.test.ts b/packages/win32-def/test/20.helper.struct.test.ts deleted file mode 100644 index 9896ec8f..00000000 --- a/packages/win32-def/test/20.helper.struct.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - POINT, - RID_DEVICE_INFO, - StructFactory, - StructType, -} from '../src/index.js' -import * as DS from '../src/index.struct.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('StructType() should work', () => { - it('normal', () => { - const rnd = Math.round(Math.random() * 1000000) - - const typeinit = StructType(DS.POINT) - assert(typeinit) - const keys = Object.keys(DS.POINT) - keys.forEach((key) => { - assert(! Object.hasOwn(typeinit, key)) - }) - - const point = new typeinit() - assert(point) - point.x = 101 - point.y = rnd - - assert(point.x === 101) - assert(point.y === rnd) - }) - }) - - describe('StructFactory() should work', () => { - it('normal', () => { - const rnd = Math.round(Math.random() * 1000000) - const point = StructFactory(DS.POINT) - assert(point) - point.x = 101 - point.y = rnd - - const keys = Object.keys(DS.POINT) - keys.forEach((key) => { - assert(typeof point[key] !== undefined) - }) - - assert(point.x === 101) - assert(point.y === rnd) - }) - - it('with union property', () => { - const pData = StructFactory(DS.RID_DEVICE_INFO) - assert(pData) - assert(pData.cbSize === 0) - pData.cbSize = pData.ref().byteLength - assert(pData.cbSize > 0) - - const { DUMMYUNIONNAME } = pData - assert(DUMMYUNIONNAME) - assert(DUMMYUNIONNAME.hid === 0) - assert(DUMMYUNIONNAME.mouse === 0) - assert(DUMMYUNIONNAME.hid === 0) - }) - }) - -}) - diff --git a/packages/win32-def/test/21.helper.union.test.ts b/packages/win32-def/test/21.helper.union.test.ts deleted file mode 100644 index 10226625..00000000 --- a/packages/win32-def/test/21.helper.union.test.ts +++ /dev/null @@ -1,45 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - POINT, - UnionFactory, - UnionType, -} from '../src/index.js' -import * as DS from '../src/index.struct.js' -import * as DU from '../src/index.union.js' -import * as UT from '../src/lib/union/union.types.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('UnionType() should work', () => { - it('normal', () => { - - const typeinit = UnionType(DU.RID_DEVICE_INFO_DUMMYUNIONNAME) - assert(typeinit) - assert(! Object.hasOwn(typeinit, 'mouse')) - assert(! Object.hasOwn(typeinit, 'keyboard')) - assert(! Object.hasOwn(typeinit, 'hid')) - - const DUMMYUNIONNAME = new typeinit() as UT.RID_DEVICE_INFO_DUMMYUNIONNAME - assert(DUMMYUNIONNAME) - assert(DUMMYUNIONNAME.mouse === 0) - assert(DUMMYUNIONNAME.keyboard === 0) - assert(DUMMYUNIONNAME.hid === 0) - }) - }) - - describe('UnionFactory() should work', () => { - it('normal', () => { - const union = UnionFactory(DU.RID_DEVICE_INFO_DUMMYUNIONNAME) - assert(union) - assert(union.mouse === 0) - assert(union.keyboard === 0) - assert(union.hid === 0) - }) - }) - -}) - diff --git a/packages/win32-def/test/30.fixed-buffer.test.ts b/packages/win32-def/test/30.fixed-buffer.test.ts deleted file mode 100644 index 74b6331e..00000000 --- a/packages/win32-def/test/30.fixed-buffer.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { wcharBuffer, BufferTypeFactory } from '../src/index.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('wcharBuffer() should work', () => { - it('normal', () => { - const deviceName = wcharBuffer(4) - assert(deviceName) - assert(typeof deviceName === 'object') - assert(typeof deviceName.get === 'function') - assert(typeof deviceName.set === 'function') - assert(typeof deviceName.size === 'number') - }) - - it('get()', () => { - const buf = Buffer.alloc(8) - const deviceName = wcharBuffer(4) - assert(deviceName) - const str = deviceName.get(buf, 0) - assert(str === '') - }) - - it('set()', () => { - const len = 32 - const buf = Buffer.alloc(len) - const deviceName = wcharBuffer(len / 2) - assert(deviceName) - const rnd = Math.random().toString().slice(-2) + '汉𠮷' - deviceName.set(buf, 0, rnd) - const str = deviceName.get(buf, 0) - assert(str === rnd) - assertString(rnd, buf) - }) - }) - - describe('BufferTypeFactory() should work w/o ucs2', () => { - it('normal', () => { - const deviceName = BufferTypeFactory(4) - assert(deviceName) - assert(typeof deviceName === 'object') - assert(typeof deviceName.get === 'function') - assert(typeof deviceName.set === 'function') - }) - - it('get()', () => { - const len = 32 - const buf = Buffer.alloc(len) - const deviceName = BufferTypeFactory(len / 2) - const size = deviceName.size - assert(deviceName) - - const buf2 = deviceName.get(buf, 0) - assert(Buffer.isBuffer(buf2)) - assert(buf2.length === size) - - const buf3 = deviceName.get(buf, 2) - assert(Buffer.isBuffer(buf3)) - assert(buf3.length === size) - }) - - it('set() string w/o encoding', () => { - const len = 32 - const buf = Buffer.alloc(len) - const deviceName = BufferTypeFactory(len / 2) - assert(deviceName) - - const rnd = Math.random().toString().slice(-2) + '汉' - try { - deviceName.set(buf, 0, rnd) - } - catch (ex) { - assert(ex instanceof Error) - assert(ex.message.includes('BufferType')) - return - } - assert(false, 'should throw error') - }) - - it('set() string with encoding', () => { - const len = 32 - const buf = Buffer.alloc(len) - const deviceName = BufferTypeFactory(len / 2) - assert(deviceName) - deviceName.encoding = 'ucs2' - - const rnd = Math.random().toString().slice(-2) + '汉𠮷' - deviceName.set(buf, 0, rnd) - assert(deviceName) - - const str = deviceName.get(buf, 0) - assert(str === rnd) - assertString(rnd, buf) - }) - - it('set() buffer', () => { - const len = 32 - const buf = Buffer.alloc(len) - const deviceName = BufferTypeFactory(len / 2) - assert(deviceName) - - const rnd = Math.random().toString().slice(-2) + '汉𠮷' - const buf2 = Buffer.from(rnd, 'ucs2') - deviceName.set(buf, 0, buf2) - assert(deviceName) - - const buf3 = deviceName.get(buf, 0) - assert(Buffer.isBuffer(buf3)) - assertString(rnd, buf) - }) - }) -}) - - -function assertString(rnd: string, buf: Buffer): void { - const p0 = rnd.codePointAt(0) - const p1 = rnd.codePointAt(1) - const p2 = rnd.codePointAt(2) - assert(buf.readUInt16LE(0) === p0) - assert(buf.readUInt16LE(2) === p1) - assert(buf.readUInt16LE(4) === p2) - - const p3 = rnd.codePointAt(3) - if (p3) { - const p3a = buf.toString('ucs2').slice(3).replace(/\0/ug, '') - assert(p3a === rnd.slice(3)) - } -} diff --git a/packages/win32-def/test/31.StructFactory.test.ts b/packages/win32-def/test/31.StructFactory.test.ts deleted file mode 100644 index a955f894..00000000 --- a/packages/win32-def/test/31.StructFactory.test.ts +++ /dev/null @@ -1,149 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - StructCharOptions, - StructFactory, - StructInstanceBase, - WCHAR_String, - LPCTSTR, -} from '../src/index.js' -import * as DS from '../src/index.struct.js' -import * as DU from '../src/index.union.js' -import { DWORD, LPTSTR } from '../src/lib/common.def.js' -import * as ST from '../src/lib/struct/index.struct.types.js' - -import { ast_PRINTER_INFO_1 } from './asserts/asserts.PRINTER_DEFAULTS.js' - - -describe(fileShortPath(import.meta.url), () => { - describe('PRINTER_INFO_1 struct should work', () => { - it('nomal', () => { - const struct = StructFactory(DS.PRINTER_INFO_1) - assert(struct) - ast_PRINTER_INFO_1(struct) - - const { Flags, pDescription, pName, pComment } = struct - assert(typeof Flags === 'number') - assert(typeof pDescription === 'string') - assert(typeof pName === 'string') - assert(typeof pComment === 'string') - - assert(pName.length === 0) - const rnd = 'foo' - struct.pName = rnd - assert(pName.length === 0) - assert(struct.pName.length === 3) - assert(struct.pName === rnd) - }) - }) - - describe('PRINTER_INFO_1 struct should work with options', () => { - it('useStringBuffer: false', () => { - const opts: StructCharOptions = { - useStringBuffer: false, - } - const struct = StructFactory(DS.PRINTER_INFO_1, opts) - assert(struct) - - const { Flags, pDescription, pName, pComment } = struct - assert(typeof Flags === 'number') - assert(typeof pDescription === 'object') // vsc type hint show 'string' - assert(typeof pName === 'object') // vsc type hint show 'string' - assert(typeof pComment === 'object') // vsc type hint show 'string' - }) - - it('maxCharLength', () => { - const opts: StructCharOptions = { - maxCharLength: 2, - } - const struct = StructFactory(DS.PRINTER_INFO_1, opts) - assert(struct) - ast_PRINTER_INFO_1(struct) - - const p1 = struct.pName - assert(p1.length === 0) - - struct.pName = 'fo' - assert(struct.pName.length === 2) - - const { pName } = struct - assert(pName.length === 2) - - try { - struct.pName = 'foo' - } - catch { - return - } - assert(false, 'should throw Error but not') - }) - - it('useStringBuffer, invalid CharDefs', () => { - const opts: StructCharOptions = { - useStringBuffer: true, - CharDefs: [DWORD], - } - const struct = StructFactory(DS.PRINTER_INFO_1, opts) - assert(struct) - - const { Flags, pDescription, pName, pComment } = struct - assert(typeof Flags === 'string', typeof Flags) - assert(typeof pDescription === 'object', typeof pDescription) - assert(typeof pName === 'object') - assert(typeof pComment === 'object') - }) - }) - - describe('struct should work type _POINTER', () => { - it('nomal', () => { - interface User extends StructInstanceBase { - name: WCHAR_String - address: LPCTSTR - } - const user = { - name: LPTSTR, - address: LPTSTR, - } as const - - const struct = StructFactory(user) - assert(struct) - - const { name, address } = struct - assert(typeof name === 'string') - assert(typeof address === 'string', typeof address) // hint show 'Buffer' - }) - - it('Buffer encoding only support ucs2', () => { - interface User extends StructInstanceBase { - name: WCHAR_String - address: LPCTSTR - } - const user = { - name: LPTSTR, - address: LPTSTR, - } as const - - const struct = StructFactory(user) - assert(struct) - - struct.name = 'foo' - assert(struct.name === 'foo') - - struct.address = Buffer.from('bar', 'ucs2') - const p1 = struct.address.toString('ucs2') - assert(p1 === 'bar', p1) - - const p2 = 'bar1' - struct.address = Buffer.from(p2, 'utf8') - const p3 = struct.address.toString('utf8') - assert(p3 !== p2, p3) - - const p4 = struct.address.toString('ucs2') - assert(p4 !== p2, p4) - }) - }) - -}) - diff --git a/packages/win32-def/test/asserts/asserts.PRINTER_DEFAULTS.ts b/packages/win32-def/test/asserts/asserts.PRINTER_DEFAULTS.ts deleted file mode 100644 index b557ef24..00000000 --- a/packages/win32-def/test/asserts/asserts.PRINTER_DEFAULTS.ts +++ /dev/null @@ -1,96 +0,0 @@ -import assert from 'node:assert/strict' - - -import * as DS from '../../src/index.struct.js' -import * as DU from '../../src/index.union.js' -import * as ST from '../../src/lib/struct/index.struct.types.js' -import * as UT from '../../src/lib/union/index.union.types.js' - - -export function ast_PRINTER_DEFAULTS(struct: ST.PRINTER_DEFAULTS): void { - assert(struct) - - Object.keys(struct).forEach((key) => { - assert(typeof struct[key] !== 'undefined') - }) - - const { pDatatype, pDevMode, DesiredAccess } = struct - assert(pDatatype === '') - assert(DesiredAccess === 0) - - ast_DEVMODEWStruct(pDevMode) -} - -export function ast_DEVMODEWStruct(struct: ST.DEVMODEW): void { - assert(struct) - - Object.keys(struct).forEach((key) => { - assert(typeof struct[key] !== 'undefined') - }) - - const { dmDeviceName, dmSpecVersion } = struct - console.log({ dmDeviceName, dmSpecVersion }) - assert(dmDeviceName === '') - assert(dmSpecVersion === 0) - - ast_pDevMode_DUMMYUNIONNAME(struct.DUMMYUNIONNAME) - ast_pDevMode_DUMMYUNIONNAME2(struct.DUMMYUNIONNAME2) -} - - -export function ast_pDevMode_DUMMYUNIONNAME(union: UT.DEVMODEW_DUMMYUNIONNAME): void { - assert(union) - - Object.keys(union).forEach((key) => { - assert(typeof union[key] !== 'undefined') - }) - - const { DUMMYSTRUCTNAME, DUMMYSTRUCTNAME2, dmPosition } = union - - assert(DUMMYSTRUCTNAME) - assert(DUMMYSTRUCTNAME2) - assert(dmPosition) - - assert(DUMMYSTRUCTNAME.dmCopies === 0) - - assert(DUMMYSTRUCTNAME2.dmPosition.x === 0) - assert(DUMMYSTRUCTNAME2.dmDisplayFixedOutput === 0) - - assert(dmPosition.x === 0) - assert(dmPosition.y === 0) -} - - -export function ast_pDevMode_DUMMYUNIONNAME2(union: UT.DEVMODEW_DUMMYUNIONNAME2): void { - assert(union) - - Object.keys(union).forEach((key) => { - assert(typeof union[key] !== 'undefined') - }) - - assert(union.dmDisplayFlags === 0) - assert(union.dmNup === 0) -} - - - -export function ast_PRINTER_INFO_1(struct: ST.PRINTER_INFO_1): void { - assert(struct) - - Object.keys(struct).forEach((key) => { - assert(typeof struct[key] !== 'undefined') - }) - - - const { - Flags, - pDescription, - pName, - pComment, - } = struct - - assert(Flags === 0) - assert(pDescription === '') - assert(pName === '') - assert(pComment === '') -} diff --git a/packages/win32-def/test/def.class/20.loader.test.ts b/packages/win32-def/test/def.class/20.loader.test.ts new file mode 100644 index 00000000..58985b1d --- /dev/null +++ b/packages/win32-def/test/def.class/20.loader.test.ts @@ -0,0 +1,133 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { CallingConvention, LoadOptions, load } from '##/index.js' +import { POINT_Factory, POINT_Type } from '##/index.struct.js' + +import { type Win32, DefWin32Fake, DefWin32 } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'user32.dll', + dllFuncs: DefWin32, + } + + describe('load()', () => { + it('normal', async () => { + const lib = load(options) + const { payload: pos } = POINT_Factory() + + const res = await lib.GetCursorPos_Async(pos) + assert(res > 0) + console.info({ res, pos }) + assert(pos.x >= 0 && pos.y >= 0) + }) + + it('usedFuncNames', async () => { + const { payload: pos } = POINT_Factory() + const lib = load({ + ...options, + usedFuncNames: ['GetCursorPos'], + }) + + const res = lib.GetCursorPos(pos) + assert(res > 0) + assert(pos.x >= 0 && pos.y >= 0) + + assert(typeof lib.FindWindowExW === 'undefined') + assert(typeof lib.FindWindowExW_Async === 'undefined') + }) + + it('usedFuncNames _Async', async () => { + const { payload: pos } = POINT_Factory() + const lib = load({ + ...options, + usedFuncNames: ['GetCursorPos_Async'], + }) + + const res = await lib.GetCursorPos_Async(pos) + assert(res > 0) + assert(pos.x >= 0 && pos.y >= 0) + + assert(typeof lib.FindWindowExW === 'undefined') + assert(typeof lib.FindWindowExW_Async === 'undefined') + }) + + + it('sync + async', async () => { + const { payload: pos } = POINT_Factory() + const lib = load(options) + + const res = lib.GetCursorPos(pos) + assert(res > 0) + assert(pos.x >= 0 && pos.y >= 0) + + const pos2 = {} as POINT_Type + await lib.GetCursorPos_Async(pos2) + assert(pos2.x >= 0 && pos2.y >= 0, `pos2.x: ${pos2.x}, pos2.y: ${pos2.y}`) + + assert.deepEqual(pos, pos2) + }) + + it('sync + async with different inst', async () => { + const comb = POINT_Factory() + const pos = comb.payload + const lib = load(options) + + lib.GetCursorPos(pos) + assert(pos.x >= 0 && pos.y >= 0) + + const lib2 = load(options) + const pos2 = comb.payload + assert(typeof pos2.x === 'undefined') + await lib2.GetCursorPos_Async(pos2) + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + assert(pos2.x >= 0 && pos2.y >= 0, `pos2.x: ${pos2.x}, pos2.y: ${pos2.y}`) + + assert.deepEqual(pos, pos2) + }) + + it('convention', async () => { + const comb = POINT_Factory() + const pos = comb.payload + + const options2: LoadOptions = { + dll: 'user32.dll', + dllFuncs: DefWin32, + convention: CallingConvention.Stdcall, + } + const lib = load(options2) + + lib.GetCursorPos(pos) + assert(pos.x >= 0 && pos.y >= 0) + + const lib2 = load(options) + const pos2 = comb.payload + assert(typeof pos2.x === 'undefined') + await lib2.GetCursorPos_Async(pos2) + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + assert(pos2.x >= 0 && pos2.y >= 0, `pos2.x: ${pos2.x}, pos2.y: ${pos2.y}`) + + assert.deepEqual(pos, pos2) + }) + + it('fake struct in param', async () => { + try { + load({ + ...options, + dllFuncs: DefWin32Fake, + }) + } + catch (ex) { + assert(ex instanceof Error) + // console.info('test err:', ex.message) + assert(ex.message.includes('FAKE_POINT'), ex.message) + return + } + assert(false, 'Should throw Error') + }) + }) +}) + diff --git a/packages/win32-def/test/def.class/21.loader-multiple-choice.test.ts b/packages/win32-def/test/def.class/21.loader-multiple-choice.test.ts new file mode 100644 index 00000000..103bfb79 --- /dev/null +++ b/packages/win32-def/test/def.class/21.loader-multiple-choice.test.ts @@ -0,0 +1,261 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { CallingConvention, load } from '##/index.js' +import type { + PRINTER_INFO_1_Type, + PRINTER_INFO_4_Type, + PRINTER_INFO_5_Type, +} from '##/index.struct.js' +import { multipleChoiceMapperList, multipleChoiceMapperSet } from '#@/mapper/index.mapper.js' +import { expectPrinterInfo } from '#@/test.config.js' + +import { DefWinspool, Winspool } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const name = '' + const cbBuf = 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + + describe('load()', () => { + it('using Map (before)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ mapperList: multipleChoiceMapperList }) + + const level = 1 + const printerInfo = {} as PRINTER_INFO_1_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + assert(ret, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo.pName === expectPrinterInfo.name) + assert(printerInfo.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo.pComment === '') + assert(printerInfo.Flags === 8388608) + }) + + it('using fnName+Map (before)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ + fnName: 'EnumPrintersW', + mapperSet: multipleChoiceMapperSet, + }) + + + const level = 1 + const printerInfo = {} as PRINTER_INFO_1_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + assert(ret, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo.pName === expectPrinterInfo.name) + assert(printerInfo.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo.pComment === '') + assert(printerInfo.Flags === expectPrinterInfo.flags) + }) + + it('multi params Level=1', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 1 + const printerInfo = {} as PRINTER_INFO_1_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret, level, printerInfo }) + assert(ret, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo.pName === expectPrinterInfo.name) + assert(printerInfo.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo.pComment === '') + assert(printerInfo.Flags === expectPrinterInfo.flags) + }) + + it('multi params Level=4', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 4 + const printerInfo = {} as PRINTER_INFO_4_Type + + const ret = lib.EnumPrintersW( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret, level, printerInfo }) + assert(ret, 'EnumPrintersW(PRINTER_INFO_4) failed') + + assert(printerInfo.pPrinterName === expectPrinterInfo.name) + assert(printerInfo.pServerName === null) + assert(printerInfo.Attributes === 576) + }) + + it('multi params Level=5', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 5 + const printerInfo = {} as PRINTER_INFO_5_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret, level, printerInfo }) + assert(ret, 'EnumPrintersW(PRINTER_INFO_5) failed') + + assert(printerInfo.pPrinterName === expectPrinterInfo.name) + assert(printerInfo.pPortName === 'PORTPROMPT:') + assert(printerInfo.Attributes === 576) + assert(printerInfo.DeviceNotSelectedTimeout === 45000) + assert(printerInfo.TransmissionRetryTimeout === 45000) + }) + + it('multi params Level=2(not support)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 2 + const printerInfo = {} as PRINTER_INFO_5_Type + + try { + await lib.EnumPrintersW_Async( + flags, + name, + // @ts-expect-error test invalid level + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes('level not supported')) + assert(ex.message.includes(level.toString())) + return + } + assert(false, 'should throw Error') + }) + + it('multi params Level=999(invalid)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 999 + const printerInfo = {} as PRINTER_INFO_5_Type + + try { + await lib.EnumPrintersW_Async( + flags, + name, + // @ts-expect-error test invalid level + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes('level not supported')) + assert(ex.message.includes(level.toString())) + return + } + assert(false, 'should throw Error') + }) + + it('multi params invalid param', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + convention: CallingConvention.Cdecl, + }) + + const level = 4 + + try { + await lib.EnumPrintersW_Async( + flags, + name, + level, + // @ts-expect-error test invalid param + 'fake', + cbBuf, + pcbNeeded, + pcReturned, + ) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes('Unexpected String value, expected PRINTER_INFO_4 *')) + return + } + assert(false, 'should throw Error') + }) + }) +}) + diff --git a/packages/win32-def/test/def.class/22.loader-updateMultipleChoiceMapper.map.test.ts b/packages/win32-def/test/def.class/22.loader-updateMultipleChoiceMapper.map.test.ts new file mode 100644 index 00000000..f389c8c0 --- /dev/null +++ b/packages/win32-def/test/def.class/22.loader-updateMultipleChoiceMapper.map.test.ts @@ -0,0 +1,67 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { load } from '##/index.js' +import { PRINTER_INFO_1_Type, PRINTER_INFO_4_Type } from '##/index.struct.js' +import { multipleChoiceMapperList } from '#@/mapper/index.mapper.js' +import { expectPrinterInfo } from '#@/test.config.js' + +import { DefWinspool, Winspool } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const name = '' + const cbBuf = 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + const printerInfo1 = {} as PRINTER_INFO_1_Type + const printerInfo4 = {} as PRINTER_INFO_4_Type + + describe('load()', () => { + it('using Map', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ mapperList: multipleChoiceMapperList }) + + const ret1 = await lib.EnumPrintersW_Async( + flags, + name, + 1, + printerInfo1, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret1, printerInfo1 }) + assert(ret1, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo1.pName === expectPrinterInfo.name) + assert(printerInfo1.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo1.pComment === '') + assert(printerInfo1.Flags === expectPrinterInfo.flags) + + const ret4 = await lib.EnumPrintersW_Async( + flags, + name, + 4, + printerInfo4, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret4, printerInfo4 }) + assert(ret4, 'EnumPrintersW(PRINTER_INFO_4) failed') + + assert(printerInfo4.pPrinterName === expectPrinterInfo.name) + assert(printerInfo4.pServerName === null) + assert(printerInfo4.Attributes === 576) + }) + }) +}) + diff --git a/packages/win32-def/test/def.class/23.loader-updateMultipleChoiceMapper.set.test.ts b/packages/win32-def/test/def.class/23.loader-updateMultipleChoiceMapper.set.test.ts new file mode 100644 index 00000000..03cbf4ed --- /dev/null +++ b/packages/win32-def/test/def.class/23.loader-updateMultipleChoiceMapper.set.test.ts @@ -0,0 +1,71 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { load } from '##/index.js' +import { PRINTER_INFO_1_Type, PRINTER_INFO_4_Type } from '##/index.struct.js' +import { funcName } from '#@/mapper/EnumPrintersW.mapper.js' +import { multipleChoiceMapperSet } from '#@/mapper/index.mapper.js' +import { expectPrinterInfo } from '#@/test.config.js' + +import { DefWinspool, Winspool } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const name = '' + const cbBuf = 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + const printerInfo1 = {} as PRINTER_INFO_1_Type + const printerInfo4 = {} as PRINTER_INFO_4_Type + + describe('load()', () => { + it('using Set', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: DefWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ + fnName: funcName, + mapperSet: multipleChoiceMapperSet, + }) + + const ret1 = await lib.EnumPrintersW_Async( + flags, + name, + 1, + printerInfo1, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret1, printerInfo1 }) + assert(ret1, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo1.pName === expectPrinterInfo.name) + assert(printerInfo1.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo1.pComment === '') + assert(printerInfo1.Flags === expectPrinterInfo.flags) + + const ret4 = lib.EnumPrintersW( + flags, + name, + 4, + printerInfo4, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret4, printerInfo4 }) + assert(ret4, 'EnumPrintersW(PRINTER_INFO_4) failed') + + assert(printerInfo4.pPrinterName === expectPrinterInfo.name) + assert(printerInfo4.pServerName === null) + assert(printerInfo4.Attributes === 576) + }) + }) +}) + diff --git a/packages/win32-def/test/def.class/25.loader.GetTickCount.test.ts b/packages/win32-def/test/def.class/25.loader.GetTickCount.test.ts new file mode 100644 index 00000000..86223c85 --- /dev/null +++ b/packages/win32-def/test/def.class/25.loader.GetTickCount.test.ts @@ -0,0 +1,29 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { LoadOptions, load } from '##/index.js' + +import { type Kernel32, DefKernel32 } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'kernel32.dll', + dllFuncs: DefKernel32, + } + + describe('load()', () => { + it('GetTickCount', async () => { + const lib = load(options) + + const res = lib.GetTickCount() + assert(res > 0) + + // test only, not necessary under windows + lib.unload() + }) + + }) +}) + diff --git a/packages/win32-def/test/def.class/api.helper.ts b/packages/win32-def/test/def.class/api.helper.ts new file mode 100644 index 00000000..ab5a8f0d --- /dev/null +++ b/packages/win32-def/test/def.class/api.helper.ts @@ -0,0 +1,200 @@ +import * as D from '##/index.def.js' +import * as S from '##/index.struct.js' +import * as T from '##/index.types.js' + + +// #region Win32 + +export type LibWin32 = T.FLib + +class Def_A { + static ClientToScreen = [D.BOOL, [D.HWND, `_Inout_ ${S.LPPOINT}`]] + static EnumDisplayDevicesW = [D.BOOL, [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD]] +} + +class Def_B extends Def_A { + static FindWindowExW = [D.HWND, [D.HWND, D.HWND, D.LPCTSTR, D.LPCTSTR]] + static GetCursorPos = [D.BOOL, [`_Out_ ${S.LPPOINT}`]] +} + +export class DefWin32 extends Def_B implements T.LibDefBase { + [x: string]: T.FnDefFullParams +} + + +export class DefWin32Fake implements T.LibDefBase { + [x: string]: T.FnDefFullParams + static ClientToScreen = [D.BOOL, [D.HWND, `_Inout_ FAKE_${S.LPPOINT}`]] +} + +export class Win32 implements T.LibDef2Type { + // test fake struct LPPOINT + ClientToScreen: (hWnd: T.HWND, lpPoint: T.LPPOINT) => T.BOOL + + EnumDisplayDevicesW: ( + lpDevice: T.LPCWSTR | null, + iDevNum: T.DWORD, + lpDisplayDevice: S.DISPLAY_DEVICEW_Type, + dwFlags: T.DWORD, + ) => T.BOOL + + FindWindowExW: ( + hwndParent: T.HWND, + hwndChildAfter: T.HWND, + lpszClass: T.LPCTSTR | null, + lpszWindow: T.LPCTSTR | null, + ) => T.HWND + + GetCursorPos: (lpPoint: S.POINT_Type) => T.BOOL +} + +// #region Winspool + +export type LibWinspool = T.FLib + +export class DefWinspool implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + static EnumPrintersW = [D.BOOL, + [ + D.DWORD, + D.WString, + D.DWORD, + // test multiple choice only. It should be D.LPBYTE + [ + `_Out_ ${S.PPRINTER_INFO_1}`, + `_Out_ ${S.PPRINTER_INFO_4}`, + `_Out_ ${S.PPRINTER_INFO_5}`, + ], + D.DWORD, + D.LPDWORD, + D.LPDWORD, + ]] as const + + + /** + * Retrieves information about a specified printer. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter + */ + static GetPrinterW = [D.BOOL, [ + D.HANDLE, + D.DWORD, + // multiple choice instead of `_Out_ ${D.LPBYTE}`, + // @TODO 2|7 + [ + `_Out_ ${S.PPRINTER_INFO_1}`, + `_Out_ ${S.PPRINTER_INFO_4}`, + `_Out_ ${S.PPRINTER_INFO_5}`, + `_Out_ ${S.PPRINTER_INFO_6}`, + `_Out_ ${S.PPRINTER_INFO_8}`, + `_Out_ ${S.PPRINTER_INFO_9}`, + ], + D.DWORD, + `_Out_ ${D.LPDWORD}`, + ]] as const // `as const` is required for multipleChoice + +} + +export class Winspool implements T.LibDef2Type { + /** + * Enumerates available printers, print servers, domains, or print providers. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprinters + */ + EnumPrintersW: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + // test multiple choice only. It should be T.LPBYTE(Buffer) and ffi.decode to S.EnumPrinters_Level_X_Type[] + pPrinterEnum: S.EnumPrinters_Level_X_Type, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => T.BOOL + + EnumPrintersW_Async: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + // test multiple choice only. It should be T.LPBYTE(Buffer) and ffi.decode to S.EnumPrinters_Level_X_Type[] + pPrinterEnum: S.EnumPrinters_Level_X_Type, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => Promise + + /** + * Retrieves information about a specified printer. + * @docs https://learn.microsoft.com/en-us/windows/win32/printdocs/getprinter + * @docs https://learn.microsoft.com/zh-cn/windows/win32/printdocs/getprinter + */ + GetPrinterW: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pPrinter: S.PRINTER_INFO_X_Type, // multiple choice + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => T.BOOL + + GetPrinterW_Async: ( + hPrinter: T.HANDLE, + Level: T.DWORD, + pPrinter: S.PRINTER_INFO_X_Type, // multiple choice + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + ) => Promise + +} + +// #region Winspool2 + +export type LibWinspool2 = T.FLib + +export class DefWinspool2 implements T.LibDefBase { + [x: string]: T.FnDefFullParams + + static EnumPrintersW = [D.BOOL, [ + D.DWORD, + D.WString, + D.DWORD, + `_Out_ ${D.LPBYTE}`, + D.DWORD, + D.LPDWORD, + D.LPDWORD, + ]] as const +} + +export class Winspool2 implements T.LibDef2Type { + EnumPrintersW: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + pPrinterEnum: T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => T.BOOL + + EnumPrintersW_Async: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + pPrinterEnum: T.LPBYTE, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => Promise +} + +// #region kernel32 + +export type LibKernel32 = T.FLib + +export class DefKernel32 implements T.LibDefBase { + [x: string]: T.FnDefFullParams + static GetTickCount = [D.DWORD, []] +} + +export class Kernel32 implements T.LibDef2Type { + GetTickCount: () => T.DWORD +} + diff --git a/packages/win32-def/test/def.const/20c.loader.test.ts b/packages/win32-def/test/def.const/20c.loader.test.ts new file mode 100644 index 00000000..22948d1a --- /dev/null +++ b/packages/win32-def/test/def.const/20c.loader.test.ts @@ -0,0 +1,108 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { LoadOptions, load } from '##/index.js' +import { POINT_Factory, POINT_Type } from '##/index.struct.js' + +import { type Win32Fns, defWin32Fake, defWin32 } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'user32.dll', + dllFuncs: defWin32, + } + + describe('load()', () => { + it('normal', async () => { + const lib = load(options) + const { payload: pos } = POINT_Factory() + + const res = lib.GetCursorPos(pos) + assert(res > 0) + console.info({ res, pos }) + assert(pos.x >= 0 && pos.y >= 0) + }) + + it('usedFuncNames', async () => { + const { payload: pos } = POINT_Factory() + const lib = load({ + ...options, + usedFuncNames: ['GetCursorPos'], + }) + + const res = lib.GetCursorPos(pos) + assert(res > 0) + assert(pos.x >= 0 && pos.y >= 0) + + assert(typeof lib.FindWindowExW === 'undefined') + assert(typeof lib.FindWindowExW_Async === 'undefined') + }) + + it('usedFuncNames _Async', async () => { + const { payload: pos } = POINT_Factory() + const lib = load({ + ...options, + usedFuncNames: ['GetCursorPos_Async'], + }) + + const res = await lib.GetCursorPos_Async(pos) + assert(res > 0) + assert(pos.x >= 0 && pos.y >= 0) + + assert(typeof lib.FindWindowExW === 'undefined') + assert(typeof lib.FindWindowExW_Async === 'undefined') + }) + + it('sync + async', async () => { + const { payload: pos } = POINT_Factory() + const lib = load(options) + + const res = lib.GetCursorPos(pos) + assert(res > 0) + assert(pos.x >= 0 && pos.y >= 0) + + const pos2 = {} as POINT_Type + await lib.GetCursorPos_Async(pos2) + assert(pos2.x >= 0 && pos2.y >= 0, `pos2.x: ${pos2.x}, pos2.y: ${pos2.y}`) + + assert.deepEqual(pos, pos2) + }) + + it('sync + async with different inst', async () => { + const comb = POINT_Factory() + const pos = comb.payload + const lib = load(options) + + lib.GetCursorPos(pos) + assert(pos.x >= 0 && pos.y >= 0) + + const lib2 = load(options) + const pos2 = comb.payload + assert(typeof pos2.x === 'undefined') + await lib2.GetCursorPos_Async(pos2) + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + assert(pos2.x >= 0 && pos2.y >= 0, `pos2.x: ${pos2.x}, pos2.y: ${pos2.y}`) + + assert.deepEqual(pos, pos2) + }) + + it('fake struct in param', async () => { + try { + load({ + ...options, + dllFuncs: defWin32Fake, + }) + } + catch (ex) { + assert(ex instanceof Error) + // console.info('test err:', ex.message) + assert(ex.message.includes('FAKE_POINT'), ex.message) + return + } + assert(false, 'Should throw Error') + }) + }) +}) + diff --git a/packages/win32-def/test/def.const/21c.loader-multiple-choice.test.ts b/packages/win32-def/test/def.const/21c.loader-multiple-choice.test.ts new file mode 100644 index 00000000..3ed9077a --- /dev/null +++ b/packages/win32-def/test/def.const/21c.loader-multiple-choice.test.ts @@ -0,0 +1,260 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { CallingConvention, load } from '##/index.js' +import type { + PRINTER_INFO_1_Type, + PRINTER_INFO_4_Type, + PRINTER_INFO_5_Type, +} from '##/index.struct.js' +import { multipleChoiceMapperList, multipleChoiceMapperSet } from '#@/mapper/index.mapper.js' +import { expectPrinterInfo } from '#@/test.config.js' + +import { defWinspool, WinspoolFns } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const name = '' + const cbBuf = 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + + describe('load()', () => { + it('using Map (before)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ mapperList: multipleChoiceMapperList }) + + const level = 1 + const printerInfo = {} as PRINTER_INFO_1_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + assert(ret, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo.pName === expectPrinterInfo.name) + assert(printerInfo.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo.pComment === '') + assert(printerInfo.Flags === expectPrinterInfo.flags) + }) + + it('using fnName+Map (before)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ + fnName: 'EnumPrintersW', + mapperSet: multipleChoiceMapperSet, + }) + + const level = 1 + const printerInfo = {} as PRINTER_INFO_1_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + assert(ret, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo.pName === expectPrinterInfo.name) + assert(printerInfo.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo.pComment === '') + assert(printerInfo.Flags === expectPrinterInfo.flags) + }) + + it('multi params Level=1', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 1 + const printerInfo = {} as PRINTER_INFO_1_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret, level, printerInfo }) + assert(ret, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo.pName === expectPrinterInfo.name) + assert(printerInfo.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo.pComment === '') + assert(printerInfo.Flags === expectPrinterInfo.flags) + }) + + it('multi params Level=4', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 4 + const printerInfo = {} as PRINTER_INFO_4_Type + + const ret = lib.EnumPrintersW( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret, level, printerInfo }) + assert(ret, 'EnumPrintersW(PRINTER_INFO_4) failed') + + assert(printerInfo.pPrinterName === expectPrinterInfo.name) + assert(printerInfo.pServerName === null) + assert(printerInfo.Attributes === 576) + }) + + it('multi params Level=5', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 5 + const printerInfo = {} as PRINTER_INFO_5_Type + + const ret = await lib.EnumPrintersW_Async( + flags, + name, + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret, level, printerInfo }) + assert(ret, 'EnumPrintersW(PRINTER_INFO_5) failed') + + assert(printerInfo.pPrinterName === expectPrinterInfo.name) + assert(printerInfo.pPortName === 'PORTPROMPT:') + assert(printerInfo.Attributes === 576) + assert(printerInfo.DeviceNotSelectedTimeout === 45000) + assert(printerInfo.TransmissionRetryTimeout === 45000) + }) + + it('multi params Level=2(not support)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 2 + const printerInfo = {} as PRINTER_INFO_5_Type + + try { + await lib.EnumPrintersW_Async( + flags, + name, + // @ts-expect-error test invalid level + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes('level not supported')) + assert(ex.message.includes(level.toString())) + return + } + assert(false, 'should throw Error') + }) + + it('multi params Level=999(invalid)', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + }) + + const level = 999 + const printerInfo = {} as PRINTER_INFO_5_Type + + try { + await lib.EnumPrintersW_Async( + flags, + name, + // @ts-expect-error test invalid level + level, + printerInfo, + cbBuf, + pcbNeeded, + pcReturned, + ) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes('level not supported')) + assert(ex.message.includes(level.toString())) + return + } + assert(false, 'should throw Error') + }) + + it('multi params invalid param', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + multipleChoiceMapperList: multipleChoiceMapperList, + convention: CallingConvention.Cdecl, + }) + + const level = 4 + + try { + await lib.EnumPrintersW_Async( + flags, + name, + level, + // @ts-expect-error test invalid param + 'fake', + cbBuf, + pcbNeeded, + pcReturned, + ) + } + catch (ex) { + assert(ex instanceof Error) + assert(ex.message.includes('Unexpected String value, expected PRINTER_INFO_4 *')) + return + } + assert(false, 'should throw Error') + }) + }) +}) + diff --git a/packages/win32-def/test/def.const/22c.loader-updateMultipleChoiceMapper.map.test.ts b/packages/win32-def/test/def.const/22c.loader-updateMultipleChoiceMapper.map.test.ts new file mode 100644 index 00000000..ab939fd7 --- /dev/null +++ b/packages/win32-def/test/def.const/22c.loader-updateMultipleChoiceMapper.map.test.ts @@ -0,0 +1,67 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { load } from '##/index.js' +import { PRINTER_INFO_1_Type, PRINTER_INFO_4_Type } from '##/index.struct.js' +import { multipleChoiceMapperList } from '#@/mapper/index.mapper.js' +import { expectPrinterInfo } from '#@/test.config.js' + +import { defWinspool, WinspoolFns } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const name = '' + const cbBuf = 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + const printerInfo1 = {} as PRINTER_INFO_1_Type + const printerInfo4 = {} as PRINTER_INFO_4_Type + + describe('load()', () => { + it('using Map', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ mapperList: multipleChoiceMapperList }) + + const ret1 = await lib.EnumPrintersW_Async( + flags, + name, + 1, + printerInfo1, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret1, printerInfo1 }) + assert(ret1, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo1.pName === expectPrinterInfo.name) + assert(printerInfo1.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo1.pComment === '') + assert(printerInfo1.Flags === expectPrinterInfo.flags) + + const ret4 = lib.EnumPrintersW( + flags, + name, + 4, + printerInfo4, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret4, printerInfo4 }) + assert(ret4, 'EnumPrintersW(PRINTER_INFO_4) failed') + + assert(printerInfo4.pPrinterName === expectPrinterInfo.name) + assert(printerInfo4.pServerName === null) + assert(printerInfo4.Attributes === 576) + }) + }) +}) + diff --git a/packages/win32-def/test/def.const/23c.loader-updateMultipleChoiceMapper.set.test.ts b/packages/win32-def/test/def.const/23c.loader-updateMultipleChoiceMapper.set.test.ts new file mode 100644 index 00000000..62a95ca1 --- /dev/null +++ b/packages/win32-def/test/def.const/23c.loader-updateMultipleChoiceMapper.set.test.ts @@ -0,0 +1,71 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { load } from '##/index.js' +import { PRINTER_INFO_1_Type, PRINTER_INFO_4_Type } from '##/index.struct.js' +import { funcName } from '#@/mapper/EnumPrintersW.mapper.js' +import { multipleChoiceMapperSet } from '#@/mapper/index.mapper.js' +import { expectPrinterInfo } from '#@/test.config.js' + +import { defWinspool, WinspoolFns } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const name = '' + const cbBuf = 4096 + assert(cbBuf > 2, 'cbBuf must be > 2') + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + const printerInfo1 = {} as PRINTER_INFO_1_Type + const printerInfo4 = {} as PRINTER_INFO_4_Type + + describe('load()', () => { + it('using Set', async () => { + const lib = load({ + dll: 'winspool.drv', + dllFuncs: defWinspool, + // multipleChoiceMapperList: multipleChoiceMapperList, // using lib.updateMultipleChoiceMapper() method instead + }) + lib.updateMultipleChoiceMapper({ + fnName: funcName, + mapperSet: multipleChoiceMapperSet, + }) + + const ret1 = lib.EnumPrintersW( + flags, + name, + 1, + printerInfo1, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret1, printerInfo1 }) + assert(ret1, 'EnumPrintersW(PRINTER_INFO_1) failed') + assert(printerInfo1.pName === expectPrinterInfo.name) + assert(printerInfo1.pDescription.includes(expectPrinterInfo.name)) + assert(printerInfo1.pComment === '') + assert(printerInfo1.Flags === expectPrinterInfo.flags) + + const ret4 = lib.EnumPrintersW( + flags, + name, + 4, + printerInfo4, + cbBuf, + pcbNeeded, + pcReturned, + ) + console.log({ ret4, printerInfo4 }) + assert(ret4, 'EnumPrintersW(PRINTER_INFO_4) failed') + + assert(printerInfo4.pPrinterName === expectPrinterInfo.name) + assert(printerInfo4.pServerName === null) + assert(printerInfo4.Attributes === 576) + }) + }) +}) + diff --git a/packages/win32-def/test/def.const/25c.loader.GetTickCount.test.ts b/packages/win32-def/test/def.const/25c.loader.GetTickCount.test.ts new file mode 100644 index 00000000..b30b29a2 --- /dev/null +++ b/packages/win32-def/test/def.const/25c.loader.GetTickCount.test.ts @@ -0,0 +1,29 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { LoadOptions, load } from '##/index.js' + +import { type Kernel32Fns, defKernel32 } from './api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'kernel32.dll', + dllFuncs: defKernel32, + } + + describe('load()', () => { + it('GetTickCount', async () => { + const lib = load(options) + + const res = lib.GetTickCount() + assert(res > 0) + + // test only, not necessary under windows + lib.unload() + }) + + }) +}) + diff --git a/packages/win32-def/test/def.const/api.helper.ts b/packages/win32-def/test/def.const/api.helper.ts new file mode 100644 index 00000000..d4c68624 --- /dev/null +++ b/packages/win32-def/test/def.const/api.helper.ts @@ -0,0 +1,104 @@ +import * as D from '##/index.def.js' +import * as S from '##/index.struct.js' +import * as T from '##/index.types.js' + + +// #region Win32 + +export type LibWin32 = T.FLib + +export interface Win32Fns { + GetCursorPos: (lpPoint: S.POINT_Type) => T.BOOL + FindWindowExW: ( + hwndParent: T.HWND, + hwndChildAfter: T.HWND, + lpszClass: T.LPCTSTR | null, + lpszWindow: T.LPCTSTR | null, + ) => T.HWND + + EnumDisplayDevicesW: ( + lpDevice: T.LPCWSTR | null, + iDevNum: T.DWORD, + lpDisplayDevice: S.DISPLAY_DEVICEW_Type, + dwFlags: T.DWORD, + ) => T.BOOL + + // test fake struct + ClientToScreen: (hWnd: T.HWND, lpPoint: T.LPPOINT) => T.BOOL +} + +// skip ClientToScreen +export const defWin32 = { + GetCursorPos: [D.BOOL, [`_Out_ ${S.LPPOINT}`]], + FindWindowExW: [D.HWND, [D.HWND, D.HWND, D.LPCTSTR, D.LPCTSTR]], + EnumDisplayDevicesW: [D.BOOL, [D.LPCWSTR, D.DWORD, `_Inout_ ${S.LPDISPLAY_DEVICEW}`, D.DWORD]], + ClientToScreen: [D.BOOL, [D.HWND, `_Inout_ ${S.LPPOINT}`]], +} as const + +export const defWin32Fake = { + ClientToScreen: [D.BOOL, [D.HWND, `_Inout_ FAKE_${S.LPPOINT}`]], +} as const + +// #region WinspoolFns + +export type LibSpool = T.FLib + +export interface WinspoolFns { + /** + * Enumerates available printers, print servers, domains, or print providers. + * @link https://learn.microsoft.com/en-us/windows/win32/printdocs/enumprinters + */ + EnumPrintersW: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + // test multiple choice only. It should be T.LPBYTE(Buffer) and ffi.decode to S.EnumPrinters_Level_X_Type[] + pPrinterEnum: S.EnumPrinters_Level_X_Type, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => T.BOOL + + EnumPrintersW_Async: ( + Flags: T.DWORD, + Name: T.WString, + Level: Level, + // test multiple choice only. It should be T.LPBYTE(Buffer) and ffi.decode to S.EnumPrinters_Level_X_Type[] + pPrinterEnum: S.EnumPrinters_Level_X_Type, + cbBuf: T.DWORD, + pcbNeeded: T.LPDWORD, + pcReturned: T.LPDWORD, + ) => Promise +} + +export const defWinspool = { + EnumPrintersW: [D.BOOL, + [ + D.DWORD, + D.WString, + D.DWORD, + // test multiple choice only. It should be D.LPBYTE + [ + `_Out_ ${S.PPRINTER_INFO_1}`, + `_Out_ ${S.PPRINTER_INFO_4}`, + `_Out_ ${S.PPRINTER_INFO_5}`, + ], + D.DWORD, + D.LPDWORD, + D.LPDWORD, + ]], +} as const + + + +// #region kernel32 + + +export interface Kernel32Fns { + GetTickCount: () => T.DWORD +} + +export const defKernel32 = { + GetTickCount: [D.DWORD, []], +} as const + diff --git a/packages/win32-def/test/helper.ts b/packages/win32-def/test/helper.ts new file mode 100644 index 00000000..61311498 --- /dev/null +++ b/packages/win32-def/test/helper.ts @@ -0,0 +1,14 @@ +import assert from 'node:assert' + +import { StructDetail } from '##/index.js' + + +type ExpectData = Omit + +export function assertStructUnion(src: StructDetail, expect: ExpectData): void { + assert(src) + assert(src.name === expect.name, `name: ${src.name}`) + assert(src.pointer === expect.pointer, `pointer: ${src.pointer}`) + assert(src.size === expect.size, `size: ${src.size}`) +} + diff --git a/packages/win32-def/test/lib/24.LoaderCache.test.ts b/packages/win32-def/test/lib/24.LoaderCache.test.ts new file mode 100644 index 00000000..3993718d --- /dev/null +++ b/packages/win32-def/test/lib/24.LoaderCache.test.ts @@ -0,0 +1,65 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import type { KoffiFunction } from '##/index.js' +import type { MultipleChoiceMapperList, MultipleChoiceMapper, MultipleChoiceMapperSet } from '##/index.types.js' +import { LoaderCache } from '##/lib/loader/loader.cache.js' +import { loadIKoffiLib } from '##/lib/loader/loader.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const dll = 'acledit.dll' + const fnName = 'ACLEDIT' + const mapper: MultipleChoiceMapper = () => { return } + + const multipleChoiceMapperList: MultipleChoiceMapperList = new Map() + const multipleChoiceMapperSet: MultipleChoiceMapperSet = new Set() + multipleChoiceMapperList.set(fnName, multipleChoiceMapperSet) + multipleChoiceMapperSet.add(mapper) + + describe('LoaderCache', () => { + it('lib', async () => { + assert(! LoaderCache.getLibByName(dll)) + + const ffiLIb = loadIKoffiLib(dll) + assert(ffiLIb) + assert(LoaderCache.getLibByName(dll) === ffiLIb) + + LoaderCache.removeLibByName(dll) + assert(! LoaderCache.getLibByName(dll)) + }) + + it('RegisteredFunc', async () => { + + const ffiLIb = loadIKoffiLib(dll) + assert(! LoaderCache.getRegisteredFuncMap(ffiLIb, fnName)) + + const fn = (() => { return }) as KoffiFunction + LoaderCache.setRegisteredFuncToCache(ffiLIb, fnName, fn, []) + + assert(LoaderCache.getRegisteredFunc(ffiLIb, fnName) === fn) + + LoaderCache.removeRegisteredFuncFromCache(ffiLIb, fnName) + assert(! LoaderCache.getRegisteredFuncMap(ffiLIb, fnName)) + }) + + it('eMultipleChoiceListMapper', async () => { + const ffiLIb = loadIKoffiLib(dll) + assert(! LoaderCache.getMultipleChoiceListMapperSet(ffiLIb, fnName)) + + LoaderCache.updateMultipleChoiceListMapper(ffiLIb, multipleChoiceMapperList) + + const res = LoaderCache.getMultipleChoiceListMapperSet(ffiLIb, fnName) + assert(res === multipleChoiceMapperSet) + + LoaderCache.updateMultipleChoiceListMapper(ffiLIb, new Map()) + const res2 = LoaderCache.getMultipleChoiceListMapperSet(ffiLIb, fnName) + assert(res2 === multipleChoiceMapperSet) + + LoaderCache.removeMultipleChoiceListMapper(ffiLIb, fnName) + assert(! LoaderCache.getMultipleChoiceListMapperSet(ffiLIb, fnName)) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/30.ucsBufferFrom.test.ts b/packages/win32-def/test/lib/30.ucsBufferFrom.test.ts new file mode 100644 index 00000000..2efeb354 --- /dev/null +++ b/packages/win32-def/test/lib/30.ucsBufferFrom.test.ts @@ -0,0 +1,18 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { ucsBufferFrom } from '##/lib/util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('ucsBufferFrom()', () => { + it('normal', async () => { + const str = '联通' + const buf = ucsBufferFrom(str) + assert(buf.length === 6) + assert(buf.byteLength === 6) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/31.ucsBufferToString.test.ts b/packages/win32-def/test/lib/31.ucsBufferToString.test.ts new file mode 100644 index 00000000..64c24b95 --- /dev/null +++ b/packages/win32-def/test/lib/31.ucsBufferToString.test.ts @@ -0,0 +1,54 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { ucsBufferToString, ucsBufferFrom } from '##/lib/util.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('bufferToString()', () => { + it('normal', async () => { + const str = '联通' + const buf = ucsBufferFrom(str) + const ret = ucsBufferToString(buf) + assert(ret === str) + }) + + it('charNum=0', async () => { + const str = '联通' + const buf = ucsBufferFrom(str) + const ret = ucsBufferToString(buf, 0) + assert(ret === str) + }) + + it('charNum=2', async () => { + const str = '联通' + const buf = ucsBufferFrom(str) + const ret = ucsBufferToString(buf, 2) + assert(ret === str, `"${ret}" !== "${str}"`) + }) + + it('charNum=1', async () => { + const str = '联通' + const buf = ucsBufferFrom(str) + const ret = ucsBufferToString(buf, 1) + assert(ret === str.slice(0, 1)) + }) + + it('charNum=3', async () => { + const str = '联通' + const buf = ucsBufferFrom(str) + const ret = ucsBufferToString(buf, 3) + assert(ret === str, `ret: "${ret}", str: "${str}"`) + }) + + it('using Buffer contains no \0', async () => { + const str = '联通' + const buf = Buffer.from(str, 'ucs2') + const ret = ucsBufferToString(buf) + assert(ret === str) + }) + + }) +}) + diff --git a/packages/win32-def/test/consts/40.consts.wingdi.test.ts b/packages/win32-def/test/lib/consts/40.consts.wingdi.test.ts similarity index 76% rename from packages/win32-def/test/consts/40.consts.wingdi.test.ts rename to packages/win32-def/test/lib/consts/40.consts.wingdi.test.ts index 17705e5c..7931a2cb 100644 --- a/packages/win32-def/test/consts/40.consts.wingdi.test.ts +++ b/packages/win32-def/test/lib/consts/40.consts.wingdi.test.ts @@ -1,8 +1,9 @@ +/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ import assert from 'node:assert/strict' import { fileShortPath } from '@waiting/shared-core' -import * as consts from '../../src/index.consts.js' +import * as consts from '##/index.consts.js' describe(fileShortPath(import.meta.url), () => { diff --git a/packages/win32-def/test/consts/41.consts.key-mouse-vk.test.ts b/packages/win32-def/test/lib/consts/41.consts.key-mouse-vk.test.ts similarity index 74% rename from packages/win32-def/test/consts/41.consts.key-mouse-vk.test.ts rename to packages/win32-def/test/lib/consts/41.consts.key-mouse-vk.test.ts index 1522b81c..0fe529ca 100644 --- a/packages/win32-def/test/consts/41.consts.key-mouse-vk.test.ts +++ b/packages/win32-def/test/lib/consts/41.consts.key-mouse-vk.test.ts @@ -1,8 +1,9 @@ +/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ import assert from 'node:assert/strict' import { fileShortPath } from '@waiting/shared-core' -import { VirtualKey } from '../../src/index.consts.js' +import { VirtualKey } from '##/index.consts.js' describe(fileShortPath(import.meta.url), () => { diff --git a/packages/win32-def/test/consts/42.winuser.test.ts b/packages/win32-def/test/lib/consts/42.winuser.test.ts similarity index 86% rename from packages/win32-def/test/consts/42.winuser.test.ts rename to packages/win32-def/test/lib/consts/42.winuser.test.ts index f31e33d7..a163f623 100644 --- a/packages/win32-def/test/consts/42.winuser.test.ts +++ b/packages/win32-def/test/lib/consts/42.winuser.test.ts @@ -2,7 +2,7 @@ import assert from 'node:assert/strict' import { fileShortPath } from '@waiting/shared-core' -import * as consts from '../../src/index.consts.js' +import * as consts from '##/index.consts.js' describe(fileShortPath(import.meta.url), () => { diff --git a/packages/win32-def/test/lib/struct/41.genSimpleStruct.test.ts b/packages/win32-def/test/lib/struct/41.genSimpleStruct.test.ts new file mode 100644 index 00000000..931ba97b --- /dev/null +++ b/packages/win32-def/test/lib/struct/41.genSimpleStruct.test.ts @@ -0,0 +1,80 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { StructInitPlainType } from '##/index.js' +import { POINT_Init, LPPOINT, genSimpleStruct } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('genSimpleStruct()', () => { + const expectSize = 8 + + it('normal', async () => { + const key = 'POINT' + const ptr = `${key}*` as const + const { name, pointer, CType, size } = genSimpleStruct(POINT_Init as StructInitPlainType, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass empty ptr', async () => { + const key = 'POINT' + const ptr = '' + const { name, pointer, CType, size } = genSimpleStruct(POINT_Init as StructInitPlainType, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass space key,ptr', async () => { + const key = 'POINT ' + const ptr = ' ' + const { name, pointer, CType, size } = genSimpleStruct(POINT_Init as StructInitPlainType, `${key} `, ptr) + + assert(name === key.trim(), `name: ${name}, key: "${key.trim()}"`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass no ptr', async () => { + const key = 'POINT' + const { name, pointer, CType, size } = genSimpleStruct(POINT_Init as StructInitPlainType, key) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass no key, ptr', async () => { + const { name, pointer, CType, size } = genSimpleStruct(POINT_Init as StructInitPlainType) + + assert(name === '', `name: ${name}`) + assert(pointer === '', `pointer: ${pointer}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + // it('cache', async () => { + // const key = 'POINT' + // const ptr = `${key} *` as const + // genSimpleStruct(POINT_Init as StructInitPlainType, key, ptr) + // const { name, pointer, CType, size } = genSimpleStruct(POINT_Init as StructInitPlainType, key, 'fake') + + // assert(name === key, `name: ${name}, key: ${key}`) + // assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + // assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + // assert(CType) + // assert(size === expectSize, `size: ${size} !== ${expectSize}`) + // }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/42.genComplexStruct.test.ts b/packages/win32-def/test/lib/struct/42.genComplexStruct.test.ts new file mode 100644 index 00000000..45f3d728 --- /dev/null +++ b/packages/win32-def/test/lib/struct/42.genComplexStruct.test.ts @@ -0,0 +1,80 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { POINT_Init, LPPOINT, genComplexStruct } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('genComplexStruct()', () => { + const expectSize = 8 + + it('normal', async () => { + const key = 'POINT' + const ptr = `${key}*` as const + const { name, pointer, CType, size } = genComplexStruct(POINT_Init, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass empty ptr', async () => { + const key = 'POINT' + const ptr = '' + const { name, pointer, CType, size } = genComplexStruct(POINT_Init, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass space key,ptr', async () => { + const key = 'POINT ' + const ptr = ' ' + const { name, pointer, CType, size } = genComplexStruct(POINT_Init, `${key} `, ptr) + + assert(name === key.trim(), `name: "${name}", key: "${key.trim()}"`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass no ptr', async () => { + const key = 'POINT' + const { name, pointer, CType, size } = genComplexStruct(POINT_Init, key) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass no key, ptr', async () => { + const { name, pointer, CType, size } = genComplexStruct(POINT_Init) + + assert(name === '', `name: ${name}`) + assert(pointer === '', `pointer: ${pointer}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('cache', async () => { + const key = 'POINT' + const ptr = `${key}*` as const + const info = genComplexStruct(POINT_Init, key, ptr) + assert(info) + const { name, pointer, CType, size } = genComplexStruct(POINT_Init, key, 'fake') + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + assert(pointer === LPPOINT, `pointer: ${pointer}, LPPOINT: ${LPPOINT}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/43.genSimpleUnion.test.ts b/packages/win32-def/test/lib/struct/43.genSimpleUnion.test.ts new file mode 100644 index 00000000..7437c808 --- /dev/null +++ b/packages/win32-def/test/lib/struct/43.genSimpleUnion.test.ts @@ -0,0 +1,62 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import * as D from '##/index.def.js' +import { genSimpleUnion } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('genSimpleUnion()', () => { + const expectSize = 4 + const u2 = { + dmDisplayFlags: D.DWORD, + dmNup: D.DWORD, + } + + it('normal', async () => { + const key = 'uu' + const ptr = `${key}*` as const + const { name, pointer, CType, size } = genSimpleUnion(u2, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass empty ptr', async () => { + const key = 'uu1' + const ptr = '' + const { name, pointer, CType, size } = genSimpleUnion(u2, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === `${key} *`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass space key,ptr', async () => { + const key = 'uu1 ' + const ptr = ' ' + const { name, pointer, CType, size } = genSimpleUnion(u2, key, ptr) + + assert(name === key.trim(), `name: ${name}, key: "${key}"`) + assert(pointer === `${key.trim()} *`, `pointer: ${pointer}, key: "${key.trim()} *"`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass no ptr', async () => { + const key = 'uu2' + const { name, pointer, CType, size } = genSimpleUnion(u2, key) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === `${key} *`, `pointer: ${pointer}, key: "${key} *"`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + }) +}) + diff --git a/packages/win32-def/test/lib/struct/44.genUnion.test.ts b/packages/win32-def/test/lib/struct/44.genUnion.test.ts new file mode 100644 index 00000000..d00d4b79 --- /dev/null +++ b/packages/win32-def/test/lib/struct/44.genUnion.test.ts @@ -0,0 +1,75 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import * as D from '##/index.def.js' +import { genUnion } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('genUnion()', () => { + const expectSize = 4 + const u2 = { + dmDisplayFlags: D.DWORD, + dmNup: D.DWORD, + } + + it('normal', async () => { + const key = 'uu' + const ptr = `${key}*` as const + const { name, pointer, CType, size } = genUnion(u2, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass empty ptr', async () => { + const key = 'uu1' + const ptr = '' + const { name, pointer, CType, size } = genUnion(u2, key, ptr) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === `${key}*`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass space key,ptr', async () => { + const key = 'uu1 ' + const ptr = ' ' + const { name, pointer, CType, size } = genUnion(u2, key, ptr) + + assert(name === key.trim(), `name: ${name}, key: "${key}"`) + assert(pointer === `${key.trim()}*`, `pointer: ${pointer}, key: "${key.trim()}*"`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('pass no ptr', async () => { + const key = 'uu2' + const { name, pointer, CType, size } = genUnion(u2, key) + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === `${key}*`, `pointer: ${pointer}, key: "${key}*"`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + + it('cache', async () => { + const key = 'uu2' + const ptr = `${key}*` as const + const info = genUnion(u2, key, ptr) + assert(info) + + const { name, pointer, CType, size } = genUnion(u2, key, 'fake') + + assert(name === key, `name: ${name}, key: ${key}`) + assert(pointer === ptr, `pointer: ${pointer}, ptr: ${ptr}`) + assert(CType) + assert(size === expectSize, `size: ${size} !== ${expectSize}`) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/45.StructUnionCache.test.ts b/packages/win32-def/test/lib/struct/45.StructUnionCache.test.ts new file mode 100644 index 00000000..a91fe955 --- /dev/null +++ b/packages/win32-def/test/lib/struct/45.StructUnionCache.test.ts @@ -0,0 +1,58 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import * as D from '##/index.def.js' +import { StructInitPlainType } from '##/index.js' +import { genSimpleStruct, genUnion, POINT_Init } from '##/index.struct.js' +import { StructUnionCache } from '##/lib/struct/struct.cache.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('StructUnionCache', () => { + + it('getStruct', async () => { + const key = 'POINT-test' + const info = genSimpleStruct(POINT_Init as StructInitPlainType, key) + const s1 = StructUnionCache.getStruct(key) + assert(s1 === info) + }) + it('removeStruct', async () => { + const key = 'POINT-test' + genSimpleStruct(POINT_Init as StructInitPlainType, key) + + StructUnionCache.removeStruct(key) + const s1 = StructUnionCache.getStruct(key) + assert(! s1) + }) + + it('getUnion', async () => { + const u2 = { + dmDisplayFlags: D.DWORD, + dmNup: D.DWORD, + } + const key = 'uu' + const ptr = `${key} *` as const + const info = genUnion(u2, key, ptr) + + const u1 = StructUnionCache.getUnion(key) + assert(u1 === info) + }) + it('removeUnion', async () => { + const expectSize = 4 + const u2 = { + dmDisplayFlags: D.DWORD, + dmNup: D.DWORD, + } + const key = 'uu' + const ptr = `${key}*` as const + genUnion(u2, key, ptr) + + StructUnionCache.removeUnion(key) + const u1 = StructUnionCache.getUnion(key) + assert(! u1) + }) + + }) +}) + diff --git a/packages/win32-def/test/lib/struct/46.genFixedArray.test.ts b/packages/win32-def/test/lib/struct/46.genFixedArray.test.ts new file mode 100644 index 00000000..d5ee5472 --- /dev/null +++ b/packages/win32-def/test/lib/struct/46.genFixedArray.test.ts @@ -0,0 +1,24 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' +import ffi from 'koffi' + +import { genFixedArray } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('genFixedArray()', () => { + it('normal', async () => { + const arr = genFixedArray(4) + assert(arr) + + const info = ffi.introspect(arr) + assert(info.name === 'int16_t[4]') + assert(info.alignment === 2) + assert(info.hint === 'Array') + assert(info.length === 4) + assert(info.size === 8) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/47.genFixedInt16Array.test.ts b/packages/win32-def/test/lib/struct/47.genFixedInt16Array.test.ts new file mode 100644 index 00000000..9cea3d32 --- /dev/null +++ b/packages/win32-def/test/lib/struct/47.genFixedInt16Array.test.ts @@ -0,0 +1,24 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' +import ffi from 'koffi' + +import { genFixedInt16Array } from '##/index.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('genFixedInt16Array()', () => { + it('normal', async () => { + const arr = genFixedInt16Array(4) + assert(arr) + + const info = ffi.introspect(arr) + assert(info.name === 'int16_t[4]') + assert(info.alignment === 2) + assert(info.hint === 'Typed') + assert(info.length === 4) + assert(info.size === 8) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/48.decodeInt16Array.test.ts b/packages/win32-def/test/lib/struct/48.decodeInt16Array.test.ts new file mode 100644 index 00000000..3e9527ee --- /dev/null +++ b/packages/win32-def/test/lib/struct/48.decodeInt16Array.test.ts @@ -0,0 +1,39 @@ +import assert from 'node:assert' + +import { fileShortPath, sleep } from '@waiting/shared-core' + +import { LoadOptions, load, decodeInt16Array } from '##/index.js' +import { DISPLAY_DEVICEW_Factory } from '##/index.struct.js' +import { type Win32, DefWin32 } from '#@/def.class/api.helper.js' + + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'user32.dll', + dllFuncs: DefWin32, + } + + describe('decodeInt16Array()', () => { + it('normal', async () => { + const lib = load(options) + const { payload } = DISPLAY_DEVICEW_Factory() + + const res = await lib.EnumDisplayDevicesW_Async(null, 0, payload, 1) + + const DeviceID = decodeInt16Array(payload.DeviceID) + const DeviceKey = decodeInt16Array(payload.DeviceKey) + const DeviceName = decodeInt16Array(payload.DeviceName) + const DeviceString = decodeInt16Array(payload.DeviceString) + + console.info({ res, DeviceID, DeviceKey, DeviceName, DeviceString }) + + assert(DeviceID.startsWith('PCI\\VEN_') || DeviceID.includes('VMBUS') || DeviceID === '', DeviceID) + assert(typeof DeviceKey === 'string', DeviceKey) + assert(DeviceName === '\\\\.\\DISPLAY1', DeviceName) + assert(DeviceString.length > 0) + const flag = ['Microsoft Hyper-V', 'Intel', 'AMD', 'Radeon'].some(val => DeviceString.includes(val)) + assert(flag, DeviceString) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/50.POINT_Factory.test.ts b/packages/win32-def/test/lib/struct/50.POINT_Factory.test.ts new file mode 100644 index 00000000..43f33f67 --- /dev/null +++ b/packages/win32-def/test/lib/struct/50.POINT_Factory.test.ts @@ -0,0 +1,75 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { POINT_Factory, POINT_Type, LPPOINT } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + describe('POINT_Factory()', () => { + it('normal', async () => { + const { payload } = POINT_Factory() + assert(payload) + assert(typeof payload.x === 'undefined') + assert(typeof payload.y === 'undefined') + + payload.x = 1 + payload.y = 2 + assert(payload.x === 1) + assert(payload.y === 2) + void 0 + }) + + it('not same', async () => { + const comb = POINT_Factory() + const p1 = comb.payload + const p2 = comb.payload + assert(p1 !== p2) + + const { payload: p3 } = comb + const { payload: p4 } = comb + assert(p3 !== p4) + assert(p3 !== p1) + assert(p3 !== p2) + + p1.x = 1 + assert(typeof p2.x === 'undefined') + assert(typeof p3.x === 'undefined') + assert(typeof p4.x === 'undefined') + }) + + it('not same 2', async () => { + const { payload } = POINT_Factory() + const { payload: p2 } = POINT_Factory() + assert(payload !== p2) + }) + + it('not same 3', async () => { + const { payload } = POINT_Factory() + assert(payload) + assert(typeof payload.x === 'undefined') + assert(typeof payload.y === 'undefined') + payload.x = 1 + payload.y = 2 + + const { payload: p2 } = POINT_Factory() + assert(typeof p2.x === 'undefined') + assert(typeof p2.y === 'undefined') + + p2.x = 10 + p2.y = 20 + assert(p2.x === 10) + assert(p2.y === 20) + void 0 + }) + + it('re-run', async () => { + const data = POINT_Factory() + assert(data) + + const data2 = POINT_Factory() + assert(data2) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/51.DISPLAY_DEVICEW_Factory.test.ts b/packages/win32-def/test/lib/struct/51.DISPLAY_DEVICEW_Factory.test.ts new file mode 100644 index 00000000..9687c001 --- /dev/null +++ b/packages/win32-def/test/lib/struct/51.DISPLAY_DEVICEW_Factory.test.ts @@ -0,0 +1,29 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { DISPLAY_DEVICEW_Factory } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('DISPLAY_DEVICEW_Factory()', () => { + it('normal', async () => { + const { size, payload, sizeColumns } = DISPLAY_DEVICEW_Factory() + assert(sizeColumns?.length === 1) + assert(sizeColumns?.[0] === 'cb') + assert(payload.cb === size) + try { + payload.cb = 10 + } + catch (ex) { + assert(ex instanceof TypeError) + assert(ex.message.includes('Cannot assign to read only property'), ex.message) + assert(ex.message.includes('cb'), ex.message) + return + } + assert(false, 'should throw TypeError') + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/52.PRINTER_INFO_X_Factory.test.ts b/packages/win32-def/test/lib/struct/52.PRINTER_INFO_X_Factory.test.ts new file mode 100644 index 00000000..42aa0ccd --- /dev/null +++ b/packages/win32-def/test/lib/struct/52.PRINTER_INFO_X_Factory.test.ts @@ -0,0 +1,33 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_X_Factory } from '##/index.struct.js' + + +describe(fileShortPath(import.meta.url), () => { + + describe('PRINTER_INFO_X_Factory()', () => { + it('level 1', async () => { + const { size } = PRINTER_INFO_X_Factory(1) + assert(size === 32) + }) + it('level 4', async () => { + const { size } = PRINTER_INFO_X_Factory(4) + assert(size === 24) + }) + it('level 5', async () => { + const { size } = PRINTER_INFO_X_Factory(5) + assert(size === 32) + }) + it('level 8', async () => { + const { size } = PRINTER_INFO_X_Factory(8) + assert(size === 220) + }) + it('level 9', async () => { + const { size } = PRINTER_INFO_X_Factory(9) + assert(size === 220) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/comctl/201.INITCOMMONCONTROLSEX.test.ts b/packages/win32-def/test/lib/struct/comctl/201.INITCOMMONCONTROLSEX.test.ts new file mode 100644 index 00000000..b93584ee --- /dev/null +++ b/packages/win32-def/test/lib/struct/comctl/201.INITCOMMONCONTROLSEX.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { INITCOMMONCONTROLSEX_Factory, LPINITCOMMONCONTROLSEX } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'INITCOMMONCONTROLSEX' +const pointer = LPINITCOMMONCONTROLSEX +const factory = INITCOMMONCONTROLSEX_Factory +const size = 8 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/minwinbase/401.FILETIME.test.ts b/packages/win32-def/test/lib/struct/minwinbase/401.FILETIME.test.ts new file mode 100644 index 00000000..d3fac2df --- /dev/null +++ b/packages/win32-def/test/lib/struct/minwinbase/401.FILETIME.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { FILETIME_Factory, LPFILETIME } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'FILETIME' +const pointer = LPFILETIME +const factory = FILETIME_Factory +const size = 8 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/minwinbase/402.SYSTEMTIME.test.ts b/packages/win32-def/test/lib/struct/minwinbase/402.SYSTEMTIME.test.ts new file mode 100644 index 00000000..31af5dd3 --- /dev/null +++ b/packages/win32-def/test/lib/struct/minwinbase/402.SYSTEMTIME.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { SYSTEMTIME_Factory, LPSYSTEMTIME } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'SYSTEMTIME' +const pointer = LPSYSTEMTIME +const factory = SYSTEMTIME_Factory +const size = 16 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/windef/301.RECT.test.ts b/packages/win32-def/test/lib/struct/windef/301.RECT.test.ts new file mode 100644 index 00000000..ef5f5d86 --- /dev/null +++ b/packages/win32-def/test/lib/struct/windef/301.RECT.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RECT_Factory, LPRECT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RECT' +const pointer = LPRECT +const factory = RECT_Factory +const size = 16 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/windef/302.POINT.test.ts b/packages/win32-def/test/lib/struct/windef/302.POINT.test.ts new file mode 100644 index 00000000..b6f9c7df --- /dev/null +++ b/packages/win32-def/test/lib/struct/windef/302.POINT.test.ts @@ -0,0 +1,28 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { POINT_Factory, LPPOINT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'POINT' +const pointer = LPPOINT +const factory = POINT_Factory +const size = 8 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + + it('point cache', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/wingdi/501.DISPLAY_DEVICEW.test.ts b/packages/win32-def/test/lib/struct/wingdi/501.DISPLAY_DEVICEW.test.ts new file mode 100644 index 00000000..254881c7 --- /dev/null +++ b/packages/win32-def/test/lib/struct/wingdi/501.DISPLAY_DEVICEW.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { DISPLAY_DEVICEW_Factory, LPDISPLAY_DEVICEW } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'DISPLAY_DEVICEW' +const pointer = LPDISPLAY_DEVICEW +const factory = DISPLAY_DEVICEW_Factory +const size = 840 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/wingdi/502.DEVMODEW.test.ts b/packages/win32-def/test/lib/struct/wingdi/502.DEVMODEW.test.ts new file mode 100644 index 00000000..df75ad5a --- /dev/null +++ b/packages/win32-def/test/lib/struct/wingdi/502.DEVMODEW.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { DEVMODEW_Factory, LPDEVMODEW } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'DEVMODEW' +const pointer = LPDEVMODEW +const factory = DEVMODEW_Factory +const size = 220 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/601.PRINTPROCESSOR_INFO_1.test.ts b/packages/win32-def/test/lib/struct/winspool/601.PRINTPROCESSOR_INFO_1.test.ts new file mode 100644 index 00000000..75d2a74f --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/601.PRINTPROCESSOR_INFO_1.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTPROCESSOR_INFO_1_Factory, PPRINTPROCESSOR_INFO_1 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTPROCESSOR_INFO_1' +const pointer = PPRINTPROCESSOR_INFO_1 +const factory = PRINTPROCESSOR_INFO_1_Factory +const size = 8 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/602.DOC_INFO_1.test.ts b/packages/win32-def/test/lib/struct/winspool/602.DOC_INFO_1.test.ts new file mode 100644 index 00000000..2670e5b5 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/602.DOC_INFO_1.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { DOC_INFO_1_Factory, LPDOC_INFO_1 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'DOC_INFO_1' +const pointer = LPDOC_INFO_1 +const factory = DOC_INFO_1_Factory +const size = 24 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/603.PRINTER_DEFAULTS.test.ts b/packages/win32-def/test/lib/struct/winspool/603.PRINTER_DEFAULTS.test.ts new file mode 100644 index 00000000..07b9b5f0 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/603.PRINTER_DEFAULTS.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_DEFAULTS_Factory, PPRINTER_DEFAULTS } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_DEFAULTS' +const pointer = PPRINTER_DEFAULTS +const factory = PRINTER_DEFAULTS_Factory +const size = 232 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/604.PRINTER_INFO_1.test.ts b/packages/win32-def/test/lib/struct/winspool/604.PRINTER_INFO_1.test.ts new file mode 100644 index 00000000..18afff18 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/604.PRINTER_INFO_1.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_1_Factory, PPRINTER_INFO_1 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_INFO_1' +const pointer = PPRINTER_INFO_1 +const factory = PRINTER_INFO_1_Factory +const size = 32 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/605.PRINTER_INFO_4.test.ts b/packages/win32-def/test/lib/struct/winspool/605.PRINTER_INFO_4.test.ts new file mode 100644 index 00000000..d487ecc0 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/605.PRINTER_INFO_4.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_4_Factory, PPRINTER_INFO_4 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_INFO_4' +const pointer = PPRINTER_INFO_4 +const factory = PRINTER_INFO_4_Factory +const size = 24 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/606.PRINTER_INFO_5.test.ts b/packages/win32-def/test/lib/struct/winspool/606.PRINTER_INFO_5.test.ts new file mode 100644 index 00000000..52b0be0d --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/606.PRINTER_INFO_5.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_5_Factory, PPRINTER_INFO_5 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_INFO_5' +const pointer = PPRINTER_INFO_5 +const factory = PRINTER_INFO_5_Factory +const size = 32 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/607.PRINTER_INFO_6.test.ts b/packages/win32-def/test/lib/struct/winspool/607.PRINTER_INFO_6.test.ts new file mode 100644 index 00000000..116040b0 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/607.PRINTER_INFO_6.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_6_Factory, PPRINTER_INFO_6 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_INFO_6' +const pointer = PPRINTER_INFO_6 +const factory = PRINTER_INFO_6_Factory +const size = 4 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/608.PRINTER_INFO_8.test.ts b/packages/win32-def/test/lib/struct/winspool/608.PRINTER_INFO_8.test.ts new file mode 100644 index 00000000..9120d2ce --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/608.PRINTER_INFO_8.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_8_Factory, PPRINTER_INFO_8 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_INFO_8' +const pointer = PPRINTER_INFO_8 +const factory = PRINTER_INFO_8_Factory +const size = 220 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/609.PRINTER_INFO_9.test.ts b/packages/win32-def/test/lib/struct/winspool/609.PRINTER_INFO_9.test.ts new file mode 100644 index 00000000..1ca25f40 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/609.PRINTER_INFO_9.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { PRINTER_INFO_9_Factory, PPRINTER_INFO_9 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'PRINTER_INFO_9' +const pointer = PPRINTER_INFO_9 +const factory = PRINTER_INFO_9_Factory +const size = 220 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winspool/610.JOB_INFO_1.test.ts b/packages/win32-def/test/lib/struct/winspool/610.JOB_INFO_1.test.ts new file mode 100644 index 00000000..22a85e9e --- /dev/null +++ b/packages/win32-def/test/lib/struct/winspool/610.JOB_INFO_1.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { JOB_INFO_1_Factory, PJOB_INFO_1 } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'JOB_INFO_1' +const pointer = PJOB_INFO_1 +const factory = JOB_INFO_1_Factory +const size = 96 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/101.HARDWAREINPUT.test.ts b/packages/win32-def/test/lib/struct/winuser/101.HARDWAREINPUT.test.ts new file mode 100644 index 00000000..d7088069 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/101.HARDWAREINPUT.test.ts @@ -0,0 +1,21 @@ +import { fileShortPath } from '@waiting/shared-core' + +import { HARDWAREINPUT_Factory, LPHARDWAREINPUT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'HARDWAREINPUT' +const pointer = LPHARDWAREINPUT +const factory = HARDWAREINPUT_Factory +const size = 8 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/102.KEYBDINPUT.test.ts b/packages/win32-def/test/lib/struct/winuser/102.KEYBDINPUT.test.ts new file mode 100644 index 00000000..e11ac7ae --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/102.KEYBDINPUT.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { KEYBDINPUT_Factory, LPKEYBDINPUT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'KEYBDINPUT' +const pointer = LPKEYBDINPUT +const factory = KEYBDINPUT_Factory +const size = 24 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/103.MOUSEINPUT.test.ts b/packages/win32-def/test/lib/struct/winuser/103.MOUSEINPUT.test.ts new file mode 100644 index 00000000..f1ff8e9b --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/103.MOUSEINPUT.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { MOUSEINPUT_Factory, LPMOUSEINPUT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'MOUSEINPUT' +const pointer = LPMOUSEINPUT +const factory = MOUSEINPUT_Factory +const size = 32 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/105.FLASHWINFO.ts.test.ts b/packages/win32-def/test/lib/struct/winuser/105.FLASHWINFO.ts.test.ts new file mode 100644 index 00000000..382e30ed --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/105.FLASHWINFO.ts.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { FLASHWINFO_Factory, PFLASHWINFO } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'FLASHWINFO' +const pointer = PFLASHWINFO +const factory = FLASHWINFO_Factory +const size = 32 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/106.ALTTABINFO.test.ts b/packages/win32-def/test/lib/struct/winuser/106.ALTTABINFO.test.ts new file mode 100644 index 00000000..ba681e3c --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/106.ALTTABINFO.test.ts @@ -0,0 +1,28 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { ALTTABINFO_Factory, LPALTTABINFO } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'ALTTABINFO' +const pointer = LPALTTABINFO +const factory = ALTTABINFO_Factory +const size = 40 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + + it('point cache', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/107.COPYDATASTRUCT.test.ts b/packages/win32-def/test/lib/struct/winuser/107.COPYDATASTRUCT.test.ts new file mode 100644 index 00000000..229efcf2 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/107.COPYDATASTRUCT.test.ts @@ -0,0 +1,24 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { COPYDATASTRUCT_Factory, LPCOPYDATASTRUCT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'COPYDATASTRUCT' +const pointer = LPCOPYDATASTRUCT +const factory = COPYDATASTRUCT_Factory +const size = 24 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/109.MSG.test.ts b/packages/win32-def/test/lib/struct/winuser/109.MSG.test.ts new file mode 100644 index 00000000..6586a732 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/109.MSG.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { MSG_Factory, LPMSG } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'MSG' +const pointer = LPMSG +const factory = MSG_Factory +const size = 48 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/110.RAWHID.test.ts b/packages/win32-def/test/lib/struct/winuser/110.RAWHID.test.ts new file mode 100644 index 00000000..46c91d22 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/110.RAWHID.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RAWHID_Factory, LPRAWHID } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RAWHID' +const pointer = LPRAWHID +const factory = RAWHID_Factory +const size = 16 // ? 12 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/111.RAWINPUTDEVICELIST.test.ts b/packages/win32-def/test/lib/struct/winuser/111.RAWINPUTDEVICELIST.test.ts new file mode 100644 index 00000000..6b0f6c10 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/111.RAWINPUTDEVICELIST.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RAWINPUTDEVICELIST_Factory, LPRAWINPUTDEVICELIST } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RAWINPUTDEVICELIST' +const pointer = LPRAWINPUTDEVICELIST +const factory = RAWINPUTDEVICELIST_Factory +const size = 16 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/112.RAWINPUTHEADER.test.ts b/packages/win32-def/test/lib/struct/winuser/112.RAWINPUTHEADER.test.ts new file mode 100644 index 00000000..da63a6c8 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/112.RAWINPUTHEADER.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RAWINPUTHEADER_Factory, LPRAWINPUTHEADER } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RAWINPUTHEADER' +const pointer = LPRAWINPUTHEADER +const factory = RAWINPUTHEADER_Factory +const size = 24 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/113.RAWKEYBOARD.test.ts b/packages/win32-def/test/lib/struct/winuser/113.RAWKEYBOARD.test.ts new file mode 100644 index 00000000..a69d2dbd --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/113.RAWKEYBOARD.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RAWKEYBOARD_Factory, LPRAWKEYBOARD } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RAWKEYBOARD' +const pointer = LPRAWKEYBOARD +const factory = RAWKEYBOARD_Factory +const size = 16 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/114.WNDCLASSEXW.test.ts b/packages/win32-def/test/lib/struct/winuser/114.WNDCLASSEXW.test.ts new file mode 100644 index 00000000..33665736 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/114.WNDCLASSEXW.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { WNDCLASSEXW_Factory, LPWNDCLASSEXW } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'WNDCLASSEXW' +const pointer = LPWNDCLASSEXW +const factory = WNDCLASSEXW_Factory +const size = 80 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/116.WINDOWINFO.test.ts b/packages/win32-def/test/lib/struct/winuser/116.WINDOWINFO.test.ts new file mode 100644 index 00000000..0e925aff --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/116.WINDOWINFO.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { WINDOWINFO_Factory, LPWINDOWINFO } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'WINDOWINFO' +const pointer = LPWINDOWINFO +const factory = WINDOWINFO_Factory +const size = 60 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/117.RID_DEVICE_INFO_MOUSE.test.ts b/packages/win32-def/test/lib/struct/winuser/117.RID_DEVICE_INFO_MOUSE.test.ts new file mode 100644 index 00000000..22769f98 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/117.RID_DEVICE_INFO_MOUSE.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RID_DEVICE_INFO_MOUSE_Factory, PRID_DEVICE_INFO_MOUSE } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RID_DEVICE_INFO_MOUSE' +const pointer = PRID_DEVICE_INFO_MOUSE +const factory = RID_DEVICE_INFO_MOUSE_Factory +const size = 16 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/118.RID_DEVICE_INFO_KEYBOARD.test.ts b/packages/win32-def/test/lib/struct/winuser/118.RID_DEVICE_INFO_KEYBOARD.test.ts new file mode 100644 index 00000000..359b1fb0 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/118.RID_DEVICE_INFO_KEYBOARD.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RID_DEVICE_INFO_KEYBOARD_Factory, PRID_DEVICE_INFO_KEYBOARD } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RID_DEVICE_INFO_KEYBOARD' +const pointer = PRID_DEVICE_INFO_KEYBOARD +const factory = RID_DEVICE_INFO_KEYBOARD_Factory +const size = 24 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/119.RID_DEVICE_INFO_HID.test.ts b/packages/win32-def/test/lib/struct/winuser/119.RID_DEVICE_INFO_HID.test.ts new file mode 100644 index 00000000..d7c7b90d --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/119.RID_DEVICE_INFO_HID.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RID_DEVICE_INFO_HID_Factory, PRID_DEVICE_INFO_HID } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RID_DEVICE_INFO_HID' +const pointer = PRID_DEVICE_INFO_HID +const factory = RID_DEVICE_INFO_HID_Factory +const size = 16 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/120.RID_DEVICE_INFO.test.ts b/packages/win32-def/test/lib/struct/winuser/120.RID_DEVICE_INFO.test.ts new file mode 100644 index 00000000..0848069d --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/120.RID_DEVICE_INFO.test.ts @@ -0,0 +1,23 @@ +import assert from 'node:assert/strict' + +import { fileShortPath } from '@waiting/shared-core' + +import { RID_DEVICE_INFO_Factory, LPRID_DEVICE_INFO } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'RID_DEVICE_INFO' +const pointer = LPRID_DEVICE_INFO +const factory = RID_DEVICE_INFO_Factory +const size = 32 +const fn = `${name}_Factory` + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + }) +}) + diff --git a/packages/win32-def/test/lib/struct/winuser/990.INPUT.test.ts b/packages/win32-def/test/lib/struct/winuser/990.INPUT.test.ts new file mode 100644 index 00000000..2dd5ed72 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/990.INPUT.test.ts @@ -0,0 +1,83 @@ +import assert from 'node:assert/strict' + +import { fileShortPath, sleep } from '@waiting/shared-core' +import ffi from 'koffi' +import { INPUT, KEYBDINPUT, VirtualKey } from 'win32-def/consts' + +import { INPUT_Factory, INPUT_Type, LPINPUT } from '##/index.struct.js' +import { assertStructUnion } from '#@/helper.js' + + +const name = 'INPUT' +const pointer = LPINPUT +const factory = INPUT_Factory +const size = 40 +const fn = `${name}_Factory` + +const INPUT_KEYBOARD = INPUT.INPUT_KEYBOARD +const KEYEVENTF_KEYUP = KEYBDINPUT.KEYEVENTF_KEYUP +const VK_RWIN = VirtualKey.VK_RWIN +const VK_D = VirtualKey.VK_D + +describe(fileShortPath(import.meta.url), () => { + describe(fn, () => { + it('normal', () => { + const data = factory() + assertStructUnion(data, { name, pointer, size }) + }) + + it('Show/hide desktop with Win+D shortcut', async () => { + const user32 = ffi.load('user32.dll') + + const events: unknown[] = [ + make_keyboard_event(VK_RWIN, true), + make_keyboard_event(VK_D, true), + make_keyboard_event(VK_D, false), + make_keyboard_event(VK_RWIN, false), + ] + + try { + const input = factory() + assert(input.size === size, `size: ${input.size}`) + + const SendInput = user32.func('__stdcall', 'SendInput', 'uint', ['uint', input.pointer, 'int']) + const res = SendInput(events.length, events, size) as number + assert(res === events.length, `res: ${res}`) + + await sleep(2000) + + await SendInput.async(events.length, events, size, (err: Error | undefined, res2: number) => { + if (err) { + console.error(err) + throw err + } + assert(res2 === events.length, `res2: ${res2}`) + }) as number + + user32.unload() // not necessary under windows + } + finally { + user32.unload() // not necessary under windows + } + }) + + }) +}) + +// Utility +function make_keyboard_event(vk: VirtualKey, down: boolean) { + const event: INPUT_Type = { + type: INPUT_KEYBOARD, + u: { + ki: { + wVk: vk, + wScan: 0, + dwFlags: down ? 0 : KEYEVENTF_KEYUP, + time: 0, + dwExtraInfo: 0, + }, + }, + } + return event +} + diff --git a/packages/win32-def/test/lib/struct/winuser/999.loader.forceRegister.test.ts b/packages/win32-def/test/lib/struct/winuser/999.loader.forceRegister.test.ts new file mode 100644 index 00000000..674e5ce4 --- /dev/null +++ b/packages/win32-def/test/lib/struct/winuser/999.loader.forceRegister.test.ts @@ -0,0 +1,57 @@ +import assert from 'node:assert' + +import { fileShortPath } from '@waiting/shared-core' +import ffi from 'koffi' + +import { PrinterEnumFlags } from '##/index.consts.js' +import { LoadOptions, load } from '##/index.js' +import * as S from '##/index.struct.js' +import { Winspool2 as Winspool, DefWinspool2 as DefWinspool } from '#@/def.class/api.helper.js' + +// run as last as possible + +describe(fileShortPath(import.meta.url), () => { + const options: LoadOptions = { + dll: 'winspool.drv', + dllFuncs: DefWinspool, + forceRegister: true, + } + + const flags = PrinterEnumFlags.PRINTER_ENUM_LOCAL + const pcbNeeded = Buffer.alloc(4) + const pcReturned = Buffer.alloc(4) + + const cbBuf = 4096 + const buf = Buffer.alloc(cbBuf) + + describe('forceRegister', () => { + it('EnumPrintersW() after MultipleChoiceMapper', async () => { + S.PRINTER_INFO_1_Factory() + + const lib = load(options) + + const level = 1 + const name = '' + + const ret = lib.EnumPrintersW( + flags, + name, + level, + buf, + cbBuf, + pcbNeeded, + pcReturned, + ) + assert(ret) + + const count = pcReturned.readUInt32LE() + + const decodeType1 = `${S.PRINTER_INFO_1_Name}[${count}]` + const infoArr = ffi.decode(buf, decodeType1) as S.PRINTER_INFO_1_Type[] + + console.info({ ret, level, infoArr }) + }) + + }) +}) + diff --git a/packages/win32-def/test/mapper/EnumPrintersW.mapper.ts b/packages/win32-def/test/mapper/EnumPrintersW.mapper.ts new file mode 100644 index 00000000..fb3e6853 --- /dev/null +++ b/packages/win32-def/test/mapper/EnumPrintersW.mapper.ts @@ -0,0 +1,33 @@ +import assert from 'assert' + +import type { FlattenNestedTuple } from '@waiting/shared-types' + +import { getPRINTER_INFO_X_Ptr } from '##/index.struct.js' +import type { MultipleChoiceMapper } from '##/index.types.js' +import { type Winspool, DefWinspool } from '#@/def.class/api.helper.js' + + +export const funcName = 'EnumPrintersW' +type Func = Winspool[typeof funcName] +type Params = Parameters + +type DefFunc = typeof DefWinspool[typeof funcName] +type DefParams = FlattenNestedTuple + +export const EnumPrintersW_mapper: MultipleChoiceMapper = (name, runtimeArgs, defParamsArray) => { + if (name !== funcName) { return } + const argLevel = runtimeArgs[2] + const argPtr = getPRINTER_INFO_X_Ptr(argLevel) + assert(argPtr, `getPRINTER_INFO_X_Ptr(${argLevel}) failed`) + + for (const row of defParamsArray) { + assert(Array.isArray(row)) + const defPtr = row[3] as typeof argPtr + if (defPtr.endsWith(argPtr)) { + return row + } + } + // return [] // will throw Error +} + + diff --git a/packages/win32-def/test/mapper/GetPrinterW.mapper.ts b/packages/win32-def/test/mapper/GetPrinterW.mapper.ts new file mode 100644 index 00000000..a22e05a5 --- /dev/null +++ b/packages/win32-def/test/mapper/GetPrinterW.mapper.ts @@ -0,0 +1,33 @@ +import assert from 'assert' + +import type { FlattenNestedTuple } from '@waiting/shared-types' +import { getPRINTER_INFO_X_Ptr } from 'win32-def/struct' +import type { EnumPrinters_Level, MultipleChoiceMapper } from 'win32-def/types' + +import { type Winspool, DefWinspool } from '#@/def.class/api.helper.js' + + +export const funcName = 'GetPrinterW' +type Func = Winspool[typeof funcName] +type Params = Parameters + +type DefFunc = typeof DefWinspool[typeof funcName] +type DefParams = FlattenNestedTuple + +export const GetPrinterW_mapper: MultipleChoiceMapper = (name, runtimeArgs, defParamsArray) => { + if (name !== funcName) { return } + const argLevel = runtimeArgs[1] as EnumPrinters_Level + const argPtr = getPRINTER_INFO_X_Ptr(argLevel) + assert(argPtr, `getPRINTER_INFO_X_Ptr(${argLevel}) failed`) + + for (const row of defParamsArray) { + assert(Array.isArray(row)) + const defPtr = row[2] as typeof argPtr + if (defPtr.endsWith(argPtr)) { + return row + } + } + // return [] // will throw Error +} + + diff --git a/packages/win32-def/test/mapper/index.mapper.ts b/packages/win32-def/test/mapper/index.mapper.ts new file mode 100644 index 00000000..b186143e --- /dev/null +++ b/packages/win32-def/test/mapper/index.mapper.ts @@ -0,0 +1,15 @@ +import type { MultipleChoiceMapperList, MultipleChoiceMapperSet } from 'win32-def/types' + +import * as EnumPrintersW from './EnumPrintersW.mapper.js' +import * as GetPrinterW from './GetPrinterW.mapper.js' + + +export const multipleChoiceMapperList: MultipleChoiceMapperList = new Map() +export const multipleChoiceMapperSet: MultipleChoiceMapperSet = new Set() + +multipleChoiceMapperList.set(EnumPrintersW.funcName, multipleChoiceMapperSet) +multipleChoiceMapperSet.add(EnumPrintersW.EnumPrintersW_mapper) + +multipleChoiceMapperList.set(GetPrinterW.funcName, multipleChoiceMapperSet) +multipleChoiceMapperSet.add(GetPrinterW.GetPrinterW_mapper) + diff --git a/packages/win32-def/test/root.config.ts b/packages/win32-def/test/root.config.ts new file mode 100644 index 00000000..b55cd037 --- /dev/null +++ b/packages/win32-def/test/root.config.ts @@ -0,0 +1,34 @@ +import { join } from 'node:path' + +import { genCurrentDirname } from '@waiting/shared-core' + + +export const testDir = genCurrentDirname(import.meta.url) +export const baseDir = join(testDir, '..') + +export const CI = !! process.env['CI'] // GithubAction +export const TEST = !! (CI + || process.env['MIDWAY_SERVER_ENV'] === 'unittest' + || process.env['MIDWAY_SERVER_ENV'] === 'local' + || process.env['NODE_ENV'] === 'unittest' + || process.env['NODE_ENV'] === 'local' +) + +export interface TestConfig { + baseDir: string + testDir: string + testAppDir: string + CI: boolean + TEST: boolean + isWinChinese: boolean +} + +const testAppDir = join(testDir, 'fixtures', 'base-app') +export const testConfig = { + baseDir, + testDir, + testAppDir, + CI, + TEST, +} as TestConfig + diff --git a/packages/win32-def/test/root.hooks.ts b/packages/win32-def/test/root.hooks.ts deleted file mode 100644 index 04af7d24..00000000 --- a/packages/win32-def/test/root.hooks.ts +++ /dev/null @@ -1,27 +0,0 @@ - -/** - * @see https://mochajs.org/#root-hook-plugins - * beforeAll: - * - In serial mode(Mocha’s default ), before all tests begin, once only - * - In parallel mode, run before all tests begin, for each file - * beforeEach: - * - In both modes, run before each test - */ -export const mochaHooks = async () => { - // avoid run multi times - if (! process.env['mochaRootHookFlag']) { - process.env['mochaRootHookFlag'] = 'true' - } - - return { - beforeAll: async () => { - return - }, - - afterAll: async () => { - return - }, - } - -} - diff --git a/packages/win32-def/test/setup.ts b/packages/win32-def/test/setup.ts new file mode 100644 index 00000000..bce5a4f0 --- /dev/null +++ b/packages/win32-def/test/setup.ts @@ -0,0 +1,13 @@ +// https://mochajs.org/#global-fixtures +import assert from 'node:assert/strict' +import { join } from 'node:path' + + +export async function mochaGlobalSetup(): Promise { + void 0 +} + +export async function mochaGlobalTeardown(): Promise { + void 0 +} + diff --git a/packages/win32-def/test/struct/101.ALTTABINFO.test.ts b/packages/win32-def/test/struct/101.ALTTABINFO.test.ts deleted file mode 100644 index 31ffe5df..00000000 --- a/packages/win32-def/test/struct/101.ALTTABINFO.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { - ALTTABINFO, - StructFactory, - StructType, -} from '../../src/index.js' -import * as DS from '../../src/index.struct.js' - - -describe(fileShortPath(import.meta.url), () => { - - describe('ALTTABINFO should work', () => { - it('StructType()', () => { - const rnd = Math.round(Math.random() * 1000000) - - const typeinit = StructType(DS.ALTTABINFO) - assert(typeinit) - - const keys = Object.keys(DS.ALTTABINFO) - keys.forEach((key) => { - assert(! Object.hasOwn(typeinit, key)) - }) - - const struct = new typeinit() as unknown as ALTTABINFO - assert(struct) - keys.forEach((key) => { - assert(typeof struct[key] !== undefined) - }) - - const len = struct.ref().byteLength - struct.cbSize = len - assert(struct.cbSize === len) - }) - - it('StructFactory()', () => { - const struct = StructFactory(DS.ALTTABINFO) - assert(struct) - - const keys = Object.keys(struct) - keys.forEach((key) => { - assert(typeof struct[key] !== undefined) - }) - - const len = struct.ref().byteLength - struct.cbSize = len - assert(struct.cbSize === len) - }) - }) -}) - diff --git a/packages/win32-def/test/struct/102.DEVMODEW.test.ts b/packages/win32-def/test/struct/102.DEVMODEW.test.ts deleted file mode 100644 index 3c2d5e3d..00000000 --- a/packages/win32-def/test/struct/102.DEVMODEW.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { StructFactory } from '../../src/index.js' -import * as DS from '../../src/index.struct.js' -import * as DU from '../../src/index.union.js' -import * as ST from '../../src/lib/struct/index.struct.types.js' -import { ast_DEVMODEWStruct } from '../asserts/asserts.PRINTER_DEFAULTS.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('DEVMODEW struct should work', () => { - const struct = StructFactory(DS.DEVMODEW) - ast_DEVMODEWStruct(struct) - }) - -}) - diff --git a/packages/win32-def/test/struct/103.PRINTER_DEFAULTS.test.ts b/packages/win32-def/test/struct/103.PRINTER_DEFAULTS.test.ts deleted file mode 100644 index a908c071..00000000 --- a/packages/win32-def/test/struct/103.PRINTER_DEFAULTS.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { StructFactory } from '../../src/index.js' -import * as DS from '../../src/index.struct.js' -import * as DU from '../../src/index.union.js' -import * as ST from '../../src/lib/struct/index.struct.types.js' -import { ast_PRINTER_DEFAULTS } from '../asserts/asserts.PRINTER_DEFAULTS.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('PRINTER_DEFAULTS struct should work', () => { - const struct = StructFactory(DS.PRINTER_DEFAULTS) - ast_PRINTER_DEFAULTS(struct) - - }) - -}) - diff --git a/packages/win32-def/test/struct/104.PRINTER_INFO_X.test.ts b/packages/win32-def/test/struct/104.PRINTER_INFO_X.test.ts deleted file mode 100644 index b16a0046..00000000 --- a/packages/win32-def/test/struct/104.PRINTER_INFO_X.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { StructFactory } from '../../src/index.js' -import * as DS from '../../src/index.struct.js' -import * as DU from '../../src/index.union.js' -import * as ST from '../../src/lib/struct/index.struct.types.js' -import { ast_PRINTER_INFO_1 } from '../asserts/asserts.PRINTER_DEFAULTS.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('PRINTER_INFO_1 struct should work', () => { - const struct = StructFactory(DS.PRINTER_INFO_1) - ast_PRINTER_INFO_1(struct) - }) - -}) - diff --git a/packages/win32-def/test/test.config.ts b/packages/win32-def/test/test.config.ts new file mode 100644 index 00000000..73add6d9 --- /dev/null +++ b/packages/win32-def/test/test.config.ts @@ -0,0 +1,11 @@ +import assert from 'node:assert' + +import { testConfig } from '#@/root.config.js' + + +export const expectPrinterInfo = { + name: testConfig.CI ? 'Microsoft XPS Document Writer' : 'Microsoft Print to PDF', + description: testConfig.CI ? 'Microsoft XPS Document Writer,Microsoft XPS Document Writer v4,' : 'Microsoft Print to PDF', + flags: testConfig.CI ? 8388608 : 8388608, +} + diff --git a/packages/win32-def/test/tsconfig.json b/packages/win32-def/test/tsconfig.json index 16ed73e6..c2f79e68 100644 --- a/packages/win32-def/test/tsconfig.json +++ b/packages/win32-def/test/tsconfig.json @@ -1,24 +1,15 @@ { - "extends": "../tsconfig.json", + "extends": "../tsconfig.base.json", "compilerOptions": { - "declaration": false, - "declarationMap": false, - "inlineSourceMap": false, "noEmit": true, "noImplicitAny": false, "noImplicitThis": false, + "noPropertyAccessFromIndexSignature": false, "noUnusedLocals": false, - "sourceMap": false, - "target": "ESNEXT" + "rootDir": ".." }, "include": [ - "**/*.ts" - ], - "exclude": [ - "asset/", - "fixtures/", - "node_modules*", - "**/*.d.ts", - "**/*.spec.ts" + "../src", + "." ] } diff --git a/packages/win32-def/test/union/202.DEVMODEW.test.ts b/packages/win32-def/test/union/202.DEVMODEW.test.ts deleted file mode 100644 index e3770836..00000000 --- a/packages/win32-def/test/union/202.DEVMODEW.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import assert from 'node:assert/strict' - -import { fileShortPath } from '@waiting/shared-core' - -import { UnionFactory } from '../../src/index.js' -import * as DS from '../../src/index.struct.js' -import * as DU from '../../src/index.union.js' -import * as UT from '../../src/lib/union/index.union.types.js' -import { - ast_pDevMode_DUMMYUNIONNAME, - ast_pDevMode_DUMMYUNIONNAME2, -} from '../asserts/asserts.PRINTER_DEFAULTS.js' - - -describe(fileShortPath(import.meta.url), () => { - - it('DEVMODEW_DUMMYUNIONNAME should work', () => { - const union = UnionFactory(DU.DEVMODEW_DUMMYUNIONNAME) - ast_pDevMode_DUMMYUNIONNAME(union) - }) - - it('DEVMODEW_DUMMYUNIONNAME2 should work', () => { - const union = UnionFactory(DU.DEVMODEW_DUMMYUNIONNAME2) - ast_pDevMode_DUMMYUNIONNAME2(union) - }) - -}) - diff --git a/packages/win32-def/tsconfig.eslint.json b/packages/win32-def/tsconfig.eslint.json deleted file mode 100644 index b1910adb..00000000 --- a/packages/win32-def/tsconfig.eslint.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": true - }, - "include": [ - "src/**/*.ts", - "test/**/*.ts", - "test_browser/**/*.ts" - ], - "exclude": [ - "asset", - "app/public", - "app/views", - "dist", - "node_modules*", - "test/fixtures", - "**/*.d.ts" - ] -} diff --git a/packages/win32-def/tsconfig.json b/packages/win32-def/tsconfig.json index 18a5e65e..320b868a 100644 --- a/packages/win32-def/tsconfig.json +++ b/packages/win32-def/tsconfig.json @@ -1,58 +1,5 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "baseUrl": ".", - "declaration": true, - "declarationMap": true, - "emitDecoratorMetadata": true, - "esModuleInterop": true, - "exactOptionalPropertyTypes": true, - "experimentalDecorators": true, - "forceConsistentCasingInFileNames": true, - "incremental": true, - "module": "NodeNext", - "moduleResolution": "NodeNext", - "newLine": "lf", - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "outDir": "dist", - "paths": { - "~/*": ["./src/*"], - "@/*": ["./test/*"] - }, - "preserveConstEnums": true, - "pretty": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "strictPropertyInitialization": false, - "stripInternal": true, - "target": "ES2022", - "tsBuildInfoFile": ".vscode/.tsbuildinfo", - "types" : ["mocha", "node"] - }, - "ts-node": { - "esm": true, - "experimentalResolver": true, - "experimentalSpecifierResolution": "node", - "preferTsExts": true, - "transpileOnly": false - }, - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "asset", - "app/public", - "app/views", - "dist", - "node_modules*", - "test", - "**/*.d.ts", - "**/*.spec.ts" - ] + } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000..cfe54a54 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,147 @@ +import { basename, dirname } from 'node:path' +import assert from 'node:assert' + +import pkg from './package.json' with { type: 'json' } + +// `npm run build` -> `production` is true +// `npm run dev` -> `production` is false +const production = ! process.env.ROLLUP_WATCH +let name = pkg.name + +if (name.slice(0, 1) === '@') { + name = name.split('/')[1] + if (! name) { + throw new TypeError('pkg.name invalid') + } +} +name = parseName(name) +console.log({ name }) + +const deps = pkg.dependencies +const peerDeps = pkg.peerDependencies + +const banner = ` +/** + * ${pkg.name} + * ${pkg.description} + * + * @version ${pkg.version} + * @author ${pkg.author} + * @license ${pkg.license} + * @link ${pkg.homepage} + */ +`.trimStart() +const uglifyOpts = { + mangle: true, + compress: { + unused: false, + sequences: true, + dead_code: true, + conditionals: true, + booleans: true, + if_return: true, + join_vars: true, + drop_console: false, + drop_debugger: false, + typeofs: false, + }, + output: { + preamble: banner, + }, +} + +const globals = { + 'rxjs/operators': 'rxjs.operators', + 'rxjs/websocket': 'rxjs.websocket', +} +let external = [ + 'rxjs', 'rxjs/operators', 'rxjs/websocket', 'rxjs/ajax', +] +const nodeModule = [ + 'fs', 'path', 'util', 'os', +] + +if (deps && Object.keys(deps).length) { + for (const depName of Object.keys(deps)) { + external.push(depName) + } +} +if (peerDeps && Object.keys(peerDeps).length) { + for (const depName of Object.keys(peerDeps)) { + external.push(depName) + } +} +external = [...new Set(external)] + +const config = [] + + +if (pkg.bin) { + // const shebang = `#!/usr/bin/env node\n\n${banner}` + // const shebang = `#!/usr/bin/env ts-node-esm\n\n${banner}` + const shebang = `#!/usr/bin/env tsx\n\n${banner}` + + for (const binPath of Object.values(pkg.bin)) { + if (! binPath) { + continue + } + const binSrcPath = binPath.includes('bin/') && ! binPath.includes('dist/bin/') + ? binPath.replace('bin/', 'dist/bin/') + : binPath + + config.push({ + external: external.concat(nodeModule), + input: binSrcPath, + output: [ + { + file: binPath, + banner: shebang, + format: 'esm', + globals, + }, + ], + }) + } + +} + + + +// remove pkg.name extension if exists +function parseName(name) { + if (typeof name === 'string' && name) { + return basename(name) + } + else { + throw new TypeError('name invalid') + } + return name +} + +function genFileNamesForCTS(row) { + const path = row.import + assert(path, 'path is required') + assert(typeof path === 'string', 'path must be a string') + + let srcPath = row.types + let baseName = '' + let prefixDir = dirname(path).split('/').slice(2).join('/') + + if (path.startsWith('./src/') && path.endsWith('.ts')) { + baseName = basename(path, '.ts') + srcPath = srcPath ?? path + } + else if (path.startsWith('./dist/') && path.endsWith('.js')) { + baseName = basename(path, '.js') + srcPath = srcPath ?? `./src/${prefixDir}/${baseName}.ts` + } + + const ctsPath = `./dist/${prefixDir}/${baseName}.d.cts` + return { + srcPath, + ctsPath, + } +} + +export default config + diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 00000000..d5118b1d --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,58 @@ +{ + "compilerOptions": { + "baseUrl": "${configDir}", + "declaration": true, + "declarationMap": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "exactOptionalPropertyTypes": true, + "experimentalDecorators": true, + "forceConsistentCasingInFileNames": true, + "incremental": true, + "module": "NodeNext", + "moduleResolution": "NodeNext", + "newLine": "lf", + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist", + "paths": { + "##/*": ["src/*"], + "#a/*": ["src/app/*"], + "#@/*": ["test/*"] + }, + "preserveConstEnums": true, + "pretty": true, + "resolveJsonModule": true, + "rootDir": "${configDir}/src", + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "strictPropertyInitialization": false, + "stripInternal": true, + "target": "ES2022", + "tsBuildInfoFile": ".tsbuildinfo", + "types" : ["mocha", "node"] + }, + "include": [ + "${configDir}/src/**/*.ts" + ], + "exclude": [ + "${configDir}/asset", + "${configDir}/app/public", + "${configDir}/app/views", + "${configDir}/dist", + "${configDir}/fixtures", + "node_modules*", + "**/*.d.ts", + "**/*.spec.ts" + ], + "ts-node": { + "esm": true, + "experimentalResolver": true, + "experimentalSpecifierResolution": "node" + } +} diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 65952b61..10dc5f2b 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -4,17 +4,14 @@ "noEmit": true }, "include": [ - "src/**/*.ts", - "test/**/*.ts", - "packages/*/src/**/*.ts", - "packages/*/test/**/*.ts" - ], - "exclude": [ - "asset", - "app/public", - "app/views", - "dist", - "node_modules*", - "**/*.d.ts" + "${configDir}/demo/**/*.mts", + "${configDir}/demo/**/*.ts", + "${configDir}/src/**/*.ts", + "${configDir}/src/**/*.mts", + "${configDir}/test/**/*.ts", + "${configDir}/test/**/*.mts", + "${configDir}/test_browser/**/*.ts", + "${configDir}/packages/*/src/**/*.ts", + "${configDir}/packages/*/test/**/*.ts" ] } diff --git a/tsconfig.json b/tsconfig.json index 3a3c040f..1b3379ad 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,51 +1,7 @@ { - "compilerOptions": { - "baseUrl": ".", - "declaration": true, - "declarationMap": true, - "emitDecoratorMetadata": true, - "esModuleInterop": true, - "exactOptionalPropertyTypes": true, - "experimentalDecorators": true, - "forceConsistentCasingInFileNames": true, - "incremental": true, - "module": "NodeNext", - "moduleResolution": "NodeNext", - "newLine": "lf", - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "outDir": "dist", - "paths": { - "~/*": ["./src/*"], - "@/*": ["./test/*"] - }, - "preserveConstEnums": true, - "pretty": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "strictPropertyInitialization": false, - "stripInternal": true, - "target": "ES2022", - "types" : ["mocha", "node"] - }, + "extends": "./tsconfig.base.json", "include": [ - "src/**/*.ts", - "packages/**/*.ts" - ], - "exclude": [ - "asset", - "app/public", - "app/views", - "dist", - "node_modules*", - "test", - "**/*.d.ts", - "**/*.spec.ts" + "${configDir}/src/**/*.ts", + "${configDir}/packages/**/*.ts" ] }