Skip to content

Commit 35ba4ff

Browse files
committed
refactor(all): Implement lazy bindings, providing lower memory usage as well as enhanced code readability
1 parent b4f70ae commit 35ba4ff

File tree

19 files changed

+587
-384
lines changed

19 files changed

+587
-384
lines changed

source/demos/createwindow.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import {
44
CreateWindowEx, ShowWindow, UpdateWindow, DefWindowProc,
55
GetMessage, TranslateMessage, DispatchMessage, PostQuitMessage,
66
MessageBox,
7-
type HINSTANCE, type WPARAM, type LPARAM, type HWND, type MSG
7+
type HINSTANCE, type WPARAM, type LPARAM, type HWND, type MSG,
8+
FormatMessage
89
} from 'libwin32'
9-
import { CS_, CW_, IDC_, IDI_, MB_, SW_, WM_, WS_, WS_EX_ } from 'libwin32/consts'
10+
import { CS_, CW_, FORMAT_MESSAGE_, IDC_, IDI_, MB_, SW_, WM_, WS_, WS_EX_ } from 'libwin32/consts'
1011

1112
const windowClass = "NodeApp"
1213
const windowName = "Window Demo!"
@@ -17,15 +18,16 @@ function wndProc(hWnd: HWND, uMmsg: WM_, wParam: WPARAM, lParam: LPARAM) {
1718
let ret: number
1819
switch (uMmsg) {
1920
case WM_.DESTROY:
21+
console.log('WM_DESTROY')
2022
PostQuitMessage(0)
2123
ret = 0
2224
break
2325

2426
default:
25-
ret = DefWindowProc(hWnd, uMmsg, wParam, lParam)
27+
// console.log(uMmsg)
28+
ret = DefWindowProc(hWnd, uMmsg, wParam, lParam) as number
2629
break
2730
}
28-
// console.log(hWnd, { uMmsg, wParam, lParam }, ret)
2931
return ret
3032
}
3133

@@ -55,8 +57,9 @@ function WinMain(hInstance: HINSTANCE, nCmdShow: SW_): number {
5557
)
5658
if (!hWnd) {
5759
const err = GetLastError()
58-
MessageBox(null, "Call to CreateWindow failed!\n" + err.toString(16), appTitle, MB_.OK | MB_.ICONERROR)
59-
return -1
60+
const msg = FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, err, 0)
61+
MessageBox(null, "Call to CreateWindow failed!\n" + msg, appTitle, MB_.OK | MB_.ICONERROR)
62+
return err
6063
}
6164

6265
ShowWindow(hWnd, nCmdShow)
@@ -72,4 +75,9 @@ function WinMain(hInstance: HINSTANCE, nCmdShow: SW_): number {
7275
return 0
7376
}
7477

75-
process.exitCode = WinMain(GetModuleHandle(null), SW_.NORMAL)
78+
const hInstance = GetModuleHandle(null)
79+
if (!hInstance) {
80+
throw new Error('GetModuleHandle() failed.')
81+
}
82+
83+
process.exitCode = WinMain(hInstance, SW_.NORMAL)

source/win32/consts/BSF.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ export enum BSF_ {
1414
RETURNHDESK = 0x00000200,
1515
LUID = 0x00000400
1616
}
17+
18+
/** Return this value to deny a query. */
19+
export const BROADCAST_QUERY_DENY = 0x424D5144

source/win32/ctypes.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export type DLGPROC = (hWnd: HWND, msg: number, wParam: WPARAM, lParam: LPAR
6565
export const cPOINT = koffi.struct({
6666
x: cLONG,
6767
y: cLONG
68-
}), cPPOINT = koffi.pointer(cPOINT), cLPPOINT = koffi.pointer(cPOINT)
68+
})
6969

7070
export interface POINT {
7171
x: number
@@ -75,7 +75,7 @@ export interface POINT {
7575
export const cPOINTS = koffi.struct({
7676
x: cSHORT,
7777
y: cSHORT
78-
}), cPPOINTS = koffi.pointer(cPOINTS), cLPPOINTS = koffi.pointer(cPOINTS)
78+
})
7979

8080
export interface POINTS {
8181
x: number
@@ -87,7 +87,7 @@ export const cRECT = koffi.struct({
8787
top: cLONG,
8888
right: cLONG,
8989
bottom: cLONG
90-
}), cPRECT = koffi.pointer(cRECT), cLPRECT = koffi.pointer(cRECT)
90+
})
9191

9292
export interface RECT {
9393
left: number
@@ -99,7 +99,7 @@ export interface RECT {
9999
export const cSIZE = koffi.struct({
100100
cx: cLONG,
101101
yy: cLONG
102-
}), cPSIZE = koffi.pointer(cSIZE), cLPSIZE = koffi.pointer(cSIZE)
102+
})
103103

104104
export interface SIZE {
105105
x: number
@@ -112,7 +112,7 @@ export const cMINMAXINFO = koffi.struct({
112112
ptMaxPosition: cPOINT,
113113
ptMinTrackSize: cPOINT,
114114
ptMaxTrackSize: cPOINT
115-
}), cPMINMAXINFO = koffi.pointer(cMINMAXINFO), cLPMINMAXINFO = koffi.pointer(cMINMAXINFO)
115+
})
116116

117117
export interface MINMAXINFO {
118118
ptReserved: POINT
@@ -139,7 +139,7 @@ export interface GUID {
139139
export const cLUID = koffi.struct({
140140
LowPart: cDWORD,
141141
HighPart: cLONG,
142-
}), cPLUID = koffi.pointer(cLUID)
142+
})
143143

144144
export interface LUID {
145145
LowPart: number

source/win32/kernel32/console.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
import { kernel32 } from './_lib.js'
1+
import type { koffi } from '../private.js'
22
import { cHANDLE, type HWND } from '../ctypes.js'
3+
import { kernel32 } from './_lib.js'
34

45
/**
56
* Retrieves the window handle used by the console associated with the calling process.
67
*
78
* https://learn.microsoft.com/en-us/windows/console/getconsolewindow
89
*/
9-
export const GetConsoleWindow: () => HWND | null = /*#__PURE__*/kernel32.func('GetConsoleWindow', cHANDLE, [])
10+
export function GetConsoleWindow(): HWND | null {
11+
GetConsoleWindow.fn ??= kernel32.func('GetConsoleWindow', cHANDLE, [])
12+
return GetConsoleWindow.fn()
13+
}
14+
15+
/** @internal */
16+
export declare namespace GetConsoleWindow {
17+
export var fn: koffi.KoffiFunc<() => HWND | null>
18+
}

source/win32/kernel32/error.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { textDecoder } from '../private.js'
2-
import {
3-
cDWORD, cLPCVOID, cLPWSTR, cVOID,
4-
type HMODULE
5-
} from '../ctypes.js'
1+
import { textDecoder, type koffi } from '../private.js'
2+
import { cDWORD, cLPCVOID, cLPWSTR, cVOID, type HMODULE } from '../ctypes.js'
63
import type { FORMAT_MESSAGE_ } from '../consts.js'
74
import { kernel32 } from './_lib.js'
85

@@ -11,14 +8,30 @@ import { kernel32 } from './_lib.js'
118
*
129
* https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror
1310
*/
14-
export const GetLastError: () => number = /*#__PURE__*/kernel32.func('GetLastError', cDWORD, [])
11+
export function GetLastError(): number {
12+
GetLastError.fn ??= kernel32.func('GetLastError', cDWORD, [])
13+
return GetLastError.fn()
14+
}
15+
16+
/** @internal */
17+
export declare namespace GetLastError {
18+
export var fn: koffi.KoffiFunc<() => number>
19+
}
1520

1621
/**
1722
* Sets the last-error code for the calling thread.
1823
*
1924
* https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setlasterror
2025
*/
21-
export const SetLastError: (dwErrcode: number) => void = /*#__PURE__*/kernel32.func('SetLastError', cVOID, [ cDWORD ])
26+
export function SetLastError(dwErrcode: number): void {
27+
SetLastError.fn ??= kernel32.func('SetLastError', cVOID, [ cDWORD ])
28+
return SetLastError.fn(dwErrcode)
29+
}
30+
31+
/** @internal */
32+
export declare namespace SetLastError {
33+
export var fn: koffi.KoffiFunc<(dwErrcode: number) => void>
34+
}
2235

2336
/**
2437
* Formats a message string.
@@ -28,23 +41,19 @@ export const SetLastError: (dwErrcode: number) => void = /*#__PURE__*/kernel32.f
2841
*
2942
* https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessagew
3043
*/
31-
export function FormatMessage(
32-
dwFlags: FORMAT_MESSAGE_ | number,
33-
lpSource: HMODULE | string | null,
34-
dwMessageId: number,
35-
dwLanguageId: number
36-
): string {
44+
export function FormatMessage(dwFlags: FORMAT_MESSAGE_ | number, lpSource: HMODULE | string | null, dwMessageId: number, dwLanguageId: number): string {
45+
FormatMessage.fn ??= kernel32.func('FormatMessageW', cDWORD, [ cDWORD, cLPCVOID, cDWORD, cDWORD, cLPWSTR, cDWORD, '...' as any ])
46+
3747
const out = new Uint16Array(2048)
38-
const len = _FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, out, out.length, 'int', 0)
48+
const len = FormatMessage.fn(
49+
dwFlags, lpSource, dwMessageId, dwLanguageId,
50+
out, out.length,
51+
'int', 0 // Fake va_list
52+
)
3953
return textDecoder.decode(out.slice(0, len))
4054
}
4155

42-
const _FormatMessageW: (
43-
dwFlags: number,
44-
lpSource: HMODULE | string | null,
45-
dwMessageId: number,
46-
dwLanguageId: number,
47-
lpBuffer: Uint16Array,
48-
nSize: number,
49-
...args: any[]
50-
) => number = /*#__PURE__*/kernel32.func('FormatMessageW', cDWORD, [ cDWORD, cLPCVOID, cDWORD, cDWORD, cLPWSTR, cDWORD, '...' as any ])
56+
/** @internal */
57+
export declare namespace FormatMessage {
58+
export var fn: koffi.KoffiFunc<(dwFlags: number, lpSource: HMODULE | string | null, dwMessageId: number, dwLanguageId: number, lpBuffer: Uint16Array, nSize: number, ...args: any[]) => number>
59+
}

source/win32/kernel32/module.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { koffi } from '../private.js'
2-
import {
3-
cBOOL, cDWORD, cLPCWSTR,
4-
cHANDLE, type HMODULE
5-
} from '../ctypes.js'
1+
import { koffi, type POINTER } from '../private.js'
2+
import { cBOOL, cDWORD, cLPCWSTR, cHANDLE, type HMODULE } from '../ctypes.js'
63
import type { GET_MODULE_HANDLE_EX_FLAG_ } from '../consts.js'
74
import { kernel32 } from './_lib.js'
85

@@ -11,30 +8,34 @@ import { kernel32 } from './_lib.js'
118
*
129
* https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlew
1310
*/
14-
export const GetModuleHandle: (
15-
lpModuleName: string | null
16-
) => HMODULE = /*#__PURE__*/kernel32.func('GetModuleHandleW', cHANDLE, [ cLPCWSTR ])
11+
export function GetModuleHandle(lpModuleName: string | null): HMODULE | null {
12+
GetModuleHandle.fn ??= kernel32.func('GetModuleHandleW', cHANDLE, [ cLPCWSTR ])
13+
return GetModuleHandle.fn(lpModuleName)
14+
}
15+
16+
/** @internal */
17+
export declare namespace GetModuleHandle {
18+
export var fn: koffi.KoffiFunc<(lpModuleName: string | null) => HMODULE | null>
19+
}
1720

1821
/**
1922
* Retrieves a module handle for the specified module and increments the module's reference count
2023
* unless GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT is specified.
24+
*
2125
* The module must have been loaded by the calling process.
2226
*
2327
* https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandleexw
2428
*/
25-
/*#__NO_SIDE_EFFECTS__*/
26-
export function GetModuleHandleEx(
27-
dwFlags: GET_MODULE_HANDLE_EX_FLAG_,
28-
lpModuleName: string | null
29-
): HMODULE | null {
30-
const hModule: [ HMODULE | null ] = [ null ]
31-
return _GetModuleHandleExW(dwFlags, lpModuleName, hModule) === 0
29+
export function GetModuleHandleEx(dwFlags: GET_MODULE_HANDLE_EX_FLAG_, lpModuleName: string | null): HMODULE | null {
30+
GetModuleHandleEx.fn ??= kernel32.func('GetModuleHandleExW', cBOOL, [ cDWORD, cLPCWSTR, koffi.out(koffi.pointer(cHANDLE)) ])
31+
32+
const hModule: POINTER<HMODULE | null> = [ null ]
33+
return GetModuleHandleEx.fn(dwFlags, lpModuleName, hModule) === 0
3234
? null
3335
: hModule[0]
3436
}
3537

36-
const _GetModuleHandleExW:(
37-
dwFlags: GET_MODULE_HANDLE_EX_FLAG_,
38-
lpModuleName: string | null,
39-
phModule: [ HMODULE | null ]
40-
) => number = /*#__PURE__*/kernel32.func('GetModuleHandleExW', cBOOL, [ cDWORD, cLPCWSTR, koffi.out(koffi.pointer(cHANDLE)) ])
38+
/** @internal */
39+
export declare namespace GetModuleHandleEx {
40+
export var fn: koffi.KoffiFunc<(dwFlags: GET_MODULE_HANDLE_EX_FLAG_, lpModuleName: string | null, phModule: POINTER<HMODULE | null>) => number>
41+
}

source/win32/kernel32/process.ts

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { koffi, textDecoder } from '../private.js'
1+
import { koffi, textDecoder, type INT_PTR } from '../private.js'
22
import { cBOOL, cDWORD, cHANDLE, cLPDWORD, cLPWSTR, type HANDLE } from '../ctypes.js'
33
import type { PSAR_ } from '../consts.js'
44
import { kernel32 } from './_lib.js'
@@ -10,57 +10,62 @@ import { kernel32 } from './_lib.js'
1010
* https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
1111
*
1212
*/
13-
export const CloseHandle: (
14-
hObject: HANDLE
15-
) => number = /*#__PURE__*/kernel32.func('CloseHandle', cBOOL, [ cHANDLE ])
13+
export function CloseHandle(hObject: HANDLE): number {
14+
CloseHandle.fn ??= kernel32.func('CloseHandle', cBOOL, [ cHANDLE ])
15+
return CloseHandle.fn(hObject)
16+
}
17+
18+
/** @internal */
19+
export declare namespace CloseHandle {
20+
export var fn: koffi.KoffiFunc<(hObject: HANDLE) => number>
21+
}
1622

1723
/**
1824
* Opens an existing local process object.
1925
*
2026
* https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
2127
*/
22-
/*@__NO_SIDE_EFFECTS__*/
23-
export function OpenProcess(
24-
dwDesiredAccess: PSAR_ | number,
25-
bInheritHandle: boolean,
26-
dwProcessId: number
27-
): HANDLE | null {
28-
return _OpenProcess(dwDesiredAccess, Number(bInheritHandle), dwProcessId)
28+
export function OpenProcess(dwDesiredAccess: PSAR_ | number, bInheritHandle: boolean, dwProcessId: number): HANDLE | null {
29+
OpenProcess.fn ??= kernel32.func('OpenProcess', cHANDLE, [ cDWORD, cBOOL, cDWORD ])
30+
return OpenProcess.fn(dwDesiredAccess, Number(bInheritHandle), dwProcessId)
2931
}
3032

31-
const _OpenProcess: (
32-
dwDesiredAccess: PSAR_ | number,
33-
bInheritHandle: number,
34-
dwProcessId: number
35-
) => HANDLE = /*#__PURE__*/kernel32.func('OpenProcess', cHANDLE, [ cDWORD, cBOOL, cDWORD ])
33+
/** @internal */
34+
export declare namespace OpenProcess {
35+
export var fn: koffi.KoffiFunc<(dwDesiredAccess: PSAR_ | number, bInheritHandle: number, dwProcessId: number) => HANDLE>
36+
}
3637

3738
/**
3839
* Retrieves a pseudo handle for the current process.
3940
*
4041
* https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess
4142
*/
42-
export const GetCurrentProcess: () => HANDLE = /*#__PURE__*/kernel32.func('GetCurrentProcess', cHANDLE, [])
43+
export function GetCurrentProcess(): HANDLE {
44+
GetCurrentProcess.fn ??= kernel32.func('GetCurrentProcess', cHANDLE, [])
45+
return GetCurrentProcess.fn()
46+
}
47+
48+
/** @internal */
49+
export declare namespace GetCurrentProcess {
50+
export var fn: koffi.KoffiFunc<() => HANDLE>
51+
}
4352

4453
/**
4554
* Retrieves the full name of the executable image for the specified process.
4655
*
4756
* https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-queryfullprocessimagenamew
4857
*/
49-
/*#__NO_SIDE_EFFECTS__*/
50-
export function QueryFullProcessImageName(
51-
hProcess: HANDLE,
52-
dwFlags: number
53-
): string | null {
58+
export function QueryFullProcessImageName(hProcess: HANDLE, dwFlags: number): string | null {
59+
QueryFullProcessImageName.fn ??= kernel32.func('QueryFullProcessImageNameW', cBOOL, [ cHANDLE, cDWORD, koffi.out(cLPWSTR), koffi.inout(cLPDWORD) ])
60+
5461
const exeName = new Uint16Array(256)
55-
const dwSize: [ number ] = [ exeName.length ]
56-
return _QueryFullProcessImageNameW(hProcess, dwFlags, exeName, dwSize) === 0
62+
const dwSize: INT_PTR = [ exeName.length ]
63+
return QueryFullProcessImageName.fn(hProcess, dwFlags, exeName, dwSize) === 0
5764
? null
5865
: textDecoder.decode(exeName.slice(0, dwSize[0]))
5966
}
6067

61-
const _QueryFullProcessImageNameW: (
62-
hProcess: HANDLE,
63-
dwFlags: number,
64-
lpExeName: Uint16Array,
65-
lpdwSize: [ number ]
66-
) => number = /*#__PURE__*/kernel32.func('QueryFullProcessImageNameW', cBOOL, [ cHANDLE, cDWORD, koffi.out(cLPWSTR), koffi.inout(cLPDWORD) ])
68+
/** @internal */
69+
export declare namespace QueryFullProcessImageName {
70+
export var fn: koffi.KoffiFunc<(hProcess: HANDLE, dwFlags: number, lpExeName: Uint16Array, lpdwSize: INT_PTR) => number>
71+
}

source/win32/private.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ export class Win32Dll implements Disposable {
2828
return /*#__PURE__*/this.#lib.func(name, result, parameters)
2929
}
3030
}
31+
32+
export type POINTER<T> = [ T ]
33+
export type INT_PTR = POINTER<number>

source/win32/shell32/notifyicon.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ export const cNOTIFYICONDATA = koffi.struct({
5353
*
5454
* https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shell_notifyiconw
5555
*/
56-
export const Shell_NotifyIcon: (
57-
dwMessage: NIM_ | number,
58-
data: NOTIFYICONDATA
59-
) => number = /*#__PURE__*/shell32.func('Shell_NotifyIconW', cBOOL, [ cDWORD, cNOTIFYICONDATA ])
56+
export function Shell_NotifyIcon(dwMessage: NIM_ | number, data: NOTIFYICONDATA): number {
57+
Shell_NotifyIcon.fn ??= shell32.func('Shell_NotifyIconW', cBOOL, [ cDWORD, cNOTIFYICONDATA ])
58+
return Shell_NotifyIcon.fn(dwMessage, data)
59+
}
60+
61+
/** @internal */
62+
export declare namespace Shell_NotifyIcon {
63+
export var fn: koffi.KoffiFunc<(dwMessage: NIM_ | number, data: NOTIFYICONDATA) => number>
64+
}

0 commit comments

Comments
 (0)