mirror of
https://github.com/Septh/libwin32
synced 2026-08-09 12:19:58 +00:00
refactor(user32): rework WNDCLASS[EX] registration
This commit is contained in:
+35
-62
@@ -26,12 +26,8 @@ import type {
|
||||
*/
|
||||
export class ACL {
|
||||
readonly AclRevision = Internals.ACL_REVISION
|
||||
readonly Sbsz1 = 0 // Used for alignment
|
||||
readonly Sbsz2 = 0 // Used for alignment
|
||||
constructor(
|
||||
public AceCount: number = 0,
|
||||
public AclSize: number = 0
|
||||
) {}
|
||||
public AceCount!: number
|
||||
public AclSize!: number
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -63,15 +59,9 @@ export const cSID_IDENTIFIER_AUTHORITY = koffi.array(cBYTE, 6, 'Array')
|
||||
*/
|
||||
export class SID {
|
||||
readonly Revision = Internals.SID_REVISION
|
||||
public SubAuthorityCount: number
|
||||
public SubAuthority: number[]
|
||||
constructor(
|
||||
public IdentifierAuthority: SID_IDENTIFIER_AUTHORITY,
|
||||
...SubAuthority: number[]
|
||||
) {
|
||||
this.SubAuthorityCount = SubAuthority.length
|
||||
this.SubAuthority = SubAuthority.slice()
|
||||
}
|
||||
public SubAuthorityCount!: number
|
||||
public SubAuthority!: number[]
|
||||
public IdentifierAuthority!: SID_IDENTIFIER_AUTHORITY
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -156,32 +146,17 @@ export const cCLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE = koffi.struct({
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-claim_security_attribute_v1
|
||||
*/
|
||||
export class CLAIM_SECURITY_ATTRIBUTE_V1 {
|
||||
readonly Reserved = 0
|
||||
public Values = new koffi.Union('CLAIM_SECURITY_ATTRIBUTE_V1_Values') as {
|
||||
public Name!: string
|
||||
public ValueType!: CLAIM_SECURITY_ATTRIBUTE_TYPE_
|
||||
public Flags!: CLAIM_SECURITY_ATTRIBUTE_
|
||||
public ValueCount!: number
|
||||
public Values = new koffi.Union('CSA_V1_Values') as {
|
||||
pInt64?: BigInt[]
|
||||
pUint64?: BigInt[]
|
||||
ppString?: string[]
|
||||
pFqbn?: CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE[]
|
||||
pOctetString?: CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE[]
|
||||
}
|
||||
constructor(
|
||||
public Name: string = null!,
|
||||
public Flags: CLAIM_SECURITY_ATTRIBUTE_ = 0 as CLAIM_SECURITY_ATTRIBUTE_,
|
||||
public ValueType: CLAIM_SECURITY_ATTRIBUTE_TYPE_ = 0,
|
||||
public ValueCount = 0,
|
||||
{ pInt64, pUint64, ppString, pFqbn, pOctetString }: CLAIM_SECURITY_ATTRIBUTE_V1['Values'] = {}
|
||||
) {
|
||||
if (pInt64)
|
||||
this.Values.pInt64 = pInt64
|
||||
else if (pUint64)
|
||||
this.Values.pInt64 = pUint64
|
||||
else if (ppString)
|
||||
this.Values.ppString = ppString
|
||||
else if (pFqbn)
|
||||
this.Values.pFqbn = pFqbn
|
||||
else if (pOctetString)
|
||||
this.Values.pOctetString = pOctetString
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -191,7 +166,7 @@ export const cCLAIM_SECURITY_ATTRIBUTE_V1 = koffi.struct({
|
||||
Reserved: cWORD,
|
||||
Flags: cDWORD,
|
||||
ValueCount: cDWORD,
|
||||
Values: koffi.union('CLAIM_SECURITY_ATTRIBUTE_V1_Values', {
|
||||
Values: koffi.union('CSA_V1_Values', {
|
||||
pInt64: koffi.pointer(cLONG64, Internals.ANYSIZE_ARRAY),
|
||||
pUint64: koffi.pointer(cDWORD64, Internals.ANYSIZE_ARRAY),
|
||||
ppString: koffi.pointer(cSTR, Internals.ANYSIZE_ARRAY),
|
||||
@@ -217,7 +192,7 @@ export const cCLAIM_SECURITY_ATTRIBUTES_INFORMATION = koffi.struct({
|
||||
Version: cWORD,
|
||||
Reserved: cWORD,
|
||||
AttributeCount: cDWORD,
|
||||
Attribute: koffi.struct({ // Should be a union, but there is only one member...
|
||||
Attribute: koffi.struct({ // Should be a union, but since there is only one member...
|
||||
pAttributeV1: koffi.pointer(cCLAIM_SECURITY_ATTRIBUTE_V1, Internals.ANYSIZE_ARRAY)
|
||||
})
|
||||
})
|
||||
@@ -645,19 +620,17 @@ export const cDLGPROC = koffi.pointer(koffi.proto('DLG', cLRESULT, [ cHANDLE, cU
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassw
|
||||
*/
|
||||
export class WNDCLASS {
|
||||
constructor(
|
||||
public hInstance: HINSTANCE | null = null,
|
||||
public lpszClassName: string = '',
|
||||
public style: CS_ = 0,
|
||||
public lpfnWndProc: WNDPROC | null = null,
|
||||
public hCursor: HCURSOR | null = null,
|
||||
public hIcon: HICON | null = null,
|
||||
public hbrBackground: HBRUSH | null = null,
|
||||
public lpszMenuName: string | null = null,
|
||||
public cbClsExtra: number = 0,
|
||||
public cwWndExtra: number = 0
|
||||
) {}
|
||||
export interface WNDCLASS {
|
||||
hInstance: HINSTANCE | null
|
||||
lpszClassName: string | null
|
||||
style: CS_
|
||||
lpfnWndProc: WNDPROC | null
|
||||
hCursor: HCURSOR | null
|
||||
hIcon: HICON | null
|
||||
hbrBackground: HBRUSH | null
|
||||
lpszMenuName: string | null
|
||||
cbClsExtra: number
|
||||
cwWndExtra: number
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -683,16 +656,16 @@ export class WNDCLASSEX {
|
||||
readonly cbSize = SIZEOF_WNDCLASSEX
|
||||
constructor(
|
||||
public hInstance: HINSTANCE | null = null,
|
||||
public lpszClassName: string = '',
|
||||
public style: CS_ = 0,
|
||||
public lpfnWndProc: WNDPROC | null = null,
|
||||
public hCursor: HCURSOR | null = null,
|
||||
public hIcon: HICON | null = null,
|
||||
public hIconSm: HICON | null = null,
|
||||
public hbrBackground: HBRUSH | null = null,
|
||||
public lpszMenuName: string | null = null,
|
||||
public cbClsExtra: number = 0,
|
||||
public cwWndExtra: number = 0
|
||||
public lpszClassName: string | null = null,
|
||||
public style: CS_ = 0,
|
||||
public lpfnWndProc: WNDPROC | null = null,
|
||||
public hCursor: HCURSOR | null = null,
|
||||
public hIcon: HICON | null = null,
|
||||
public hIconSm: HICON | null = null,
|
||||
public hbrBackground: HBRUSH | null = null,
|
||||
public lpszMenuName: string | null = null,
|
||||
public cbClsExtra: number = 0,
|
||||
public cwWndExtra: number = 0
|
||||
) {}
|
||||
}
|
||||
|
||||
@@ -1108,7 +1081,7 @@ export const cPOLICY_ACCOUNT_DOMAIN_INFO = koffi.struct({
|
||||
/**
|
||||
* Used to set and query the system's auditing rules.
|
||||
*
|
||||
* learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-policy_audit_events_info
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-policy_audit_events_info
|
||||
*/
|
||||
export interface POLICY_AUDIT_EVENTS_INFO {
|
||||
AuditingMode: boolean
|
||||
@@ -1119,7 +1092,7 @@ export interface POLICY_AUDIT_EVENTS_INFO {
|
||||
/** @internal */
|
||||
export const cPOLICY_AUDIT_EVENTS_INFO = koffi.struct({
|
||||
AuditingMode: cBOOL,
|
||||
EventAuditingOptions: koffi.array(cULONG, 'MaximumAuditEventCount', Internals.POLICY_AUDIT_EVENTS_INFO_MAX_OPTIONS),
|
||||
EventAuditingOptions: koffi.pointer(null, cULONG, 'MaximumAuditEventCount'),
|
||||
MaximumAuditEventCount: cULONG
|
||||
})
|
||||
|
||||
|
||||
@@ -5,56 +5,40 @@ import {
|
||||
cATOM, type ATOM, cHANDLE, type HINSTANCE, type HWND
|
||||
} from '../ctypes.js'
|
||||
import {
|
||||
cWNDCLASS, WNDCLASS,
|
||||
cWNDCLASS, type WNDCLASS,
|
||||
cWNDCLASSEX, WNDCLASSEX,
|
||||
cWNDPROC
|
||||
} from '../structs.js'
|
||||
import { user32 } from './lib.js'
|
||||
|
||||
const wndProcs = new Map<string | ATOM, koffi.IKoffiRegisteredCallback>()
|
||||
const wndProcs = new Map<ATOM, koffi.IKoffiRegisteredCallback | undefined>()
|
||||
|
||||
/**
|
||||
* Retrieves information about a window class.
|
||||
*
|
||||
* FIXME: at the moment, libwin32 does not support passing an ATOM for `className`.
|
||||
* Note: libwin32 only supports querying by class name (string).
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassinfow
|
||||
*/
|
||||
export function GetClassInfo(hInstance: HINSTANCE | null, className: string): WNDCLASS | null {
|
||||
const wndClass = new WNDCLASS()
|
||||
return typeof className === 'number' ? info_by_atom() : info_by_string()
|
||||
GetClassInfo.native ??= user32.func('GetClassInfoW', cBOOL, [ cHANDLE, cSTR, koffi.out(koffi.pointer(cWNDCLASS)) ])
|
||||
|
||||
function info_by_atom() {
|
||||
info_by_atom.native ??= user32.func('GetClassInfoW', cBOOL, [ cHANDLE, cATOM, koffi.out(koffi.pointer(cWNDCLASS)) ])
|
||||
return info_by_atom.native(hInstance, className, wndClass) !== 0 ? wndClass : null
|
||||
}
|
||||
|
||||
function info_by_string() {
|
||||
info_by_string.native ??= user32.func('GetClassInfoW', cBOOL, [ cHANDLE, cSTR, koffi.out(koffi.pointer(cWNDCLASS)) ])
|
||||
return info_by_string.native(hInstance, className, wndClass) !== 0 ? wndClass : null
|
||||
}
|
||||
const wndClass = {} as WNDCLASS
|
||||
return GetClassInfo.native(hInstance, className, wndClass) !== 0 ? wndClass : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information about a window class, including a handle to the small icon associated with the window class.
|
||||
*
|
||||
* FIXME: at the moment, libwin32 does not support passing an ATOM for `className`.
|
||||
* Note: libwin32 only supports querying by class name (string).
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassinfoexw
|
||||
*/
|
||||
export function GetClassInfoEx(hInstance: HINSTANCE | null, className: string): WNDCLASSEX | null {
|
||||
GetClassInfoEx.native ??= user32.func('GetClassInfoExW', cBOOL, [ cHANDLE, cSTR, koffi.out(koffi.pointer(cWNDCLASSEX)) ])
|
||||
|
||||
const wndClassEx = new WNDCLASSEX()
|
||||
return typeof className === 'number' ? info_by_atom() : info_by_string()
|
||||
|
||||
function info_by_atom() {
|
||||
info_by_atom.native ??= user32.func('GetClassInfoExW', cBOOL, [ cHANDLE, cATOM, koffi.out(koffi.pointer(cWNDCLASSEX)) ])
|
||||
return info_by_atom.native(hInstance, className, wndClassEx) !== 0 ? wndClassEx : null
|
||||
}
|
||||
|
||||
function info_by_string() {
|
||||
info_by_string.native ??= user32.func('GetClassInfoExW', cBOOL, [ cHANDLE, cSTR, koffi.out(koffi.pointer(cWNDCLASSEX)) ])
|
||||
return info_by_string.native(hInstance, className, wndClassEx) !== 0 ? wndClassEx : null
|
||||
}
|
||||
return GetClassInfoEx.native(hInstance, className, wndClassEx) !== 0 ? wndClassEx : null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,12 +46,12 @@ export function GetClassInfoEx(hInstance: HINSTANCE | null, className: string):
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclassnamew
|
||||
*/
|
||||
export function GetClassName(hWnd: HWND): string {
|
||||
export function GetClassName(hWnd: HWND): string | null {
|
||||
GetClassName.native ??= user32.func('GetClassNameW', cINT, [ cHANDLE, koffi.out(cPVOID), cINT ])
|
||||
|
||||
const className = new StringOutputBuffer(256)
|
||||
const len = GetClassName.native(hWnd, className.buffer, className.length)
|
||||
return className.decode(len)
|
||||
return len ? className.decode(len) : null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,10 +59,10 @@ export function GetClassName(hWnd: HWND): string {
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclassw
|
||||
*/
|
||||
export function RegisterClass(wndClass: WNDCLASS): ATOM {
|
||||
export function RegisterClass(wndClass: WNDCLASS): ATOM | null {
|
||||
RegisterClass.native ??= user32.func('RegisterClassW', cATOM, [ koffi.pointer(cWNDCLASS) ])
|
||||
|
||||
let wndProc: koffi.IKoffiRegisteredCallback | undefined = undefined
|
||||
let wndProc: koffi.IKoffiRegisteredCallback | undefined
|
||||
if (typeof wndClass.lpfnWndProc === 'function') {
|
||||
wndProc = koffi.register(wndClass.lpfnWndProc, cWNDPROC)
|
||||
wndClass = {
|
||||
@@ -88,15 +72,9 @@ export function RegisterClass(wndClass: WNDCLASS): ATOM {
|
||||
}
|
||||
|
||||
const atom = RegisterClass.native(wndClass)
|
||||
if (atom && wndProc) {
|
||||
wndProcs.set(atom, wndProc)
|
||||
if (wndClass.lpszClassName)
|
||||
wndProcs.set(wndClass.lpszClassName, wndProc)
|
||||
}
|
||||
else if (wndProc)
|
||||
koffi.unregister(wndProc)
|
||||
|
||||
return atom
|
||||
? (wndProcs.set(atom, wndProc), atom)
|
||||
: (wndProc && koffi.unregister(wndProc), null)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,10 +82,10 @@ export function RegisterClass(wndClass: WNDCLASS): ATOM {
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclassexw
|
||||
*/
|
||||
export function RegisterClassEx(wndClassEx: WNDCLASSEX): ATOM {
|
||||
export function RegisterClassEx(wndClassEx: WNDCLASSEX): ATOM | null {
|
||||
RegisterClassEx.native ??= user32.func('RegisterClassExW', cATOM, [ koffi.pointer(cWNDCLASSEX) ])
|
||||
|
||||
let wndProc: koffi.IKoffiRegisteredCallback | undefined = undefined
|
||||
let wndProc: koffi.IKoffiRegisteredCallback | undefined
|
||||
if (typeof wndClassEx.lpfnWndProc === 'function') {
|
||||
wndProc = koffi.register(wndClassEx.lpfnWndProc, cWNDPROC)
|
||||
wndClassEx = {
|
||||
@@ -117,38 +95,30 @@ export function RegisterClassEx(wndClassEx: WNDCLASSEX): ATOM {
|
||||
}
|
||||
|
||||
const atom = RegisterClassEx.native(wndClassEx)
|
||||
if (atom && wndProc) {
|
||||
wndProcs.set(atom, wndProc)
|
||||
if (wndClassEx.lpszClassName)
|
||||
wndProcs.set(wndClassEx.lpszClassName, wndProc)
|
||||
}
|
||||
else if (wndProc)
|
||||
koffi.unregister(wndProc)
|
||||
|
||||
return atom
|
||||
? (wndProcs.set(atom, wndProc), atom)
|
||||
: (wndProc && koffi.unregister(wndProc), null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a window class, freeing the memory required for the class.
|
||||
*
|
||||
* Note: despite the parameter being named `className`, as in the native API,
|
||||
* libwin32 only supports unregistering by ATOM -- the one you received
|
||||
* from RegisterClass/RegisterClassEx.
|
||||
*
|
||||
* https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-unregisterclassw
|
||||
*/
|
||||
export function UnregisterClass(className: ATOM | string, hInstance: HINSTANCE | null = null): boolean {
|
||||
const wndProc = wndProcs.get(className)
|
||||
const ret = typeof className === 'number' ? unregister_by_atom() : unregister_by_string()
|
||||
if (wndProc) {
|
||||
koffi.unregister(wndProc)
|
||||
wndProcs.forEach((v, k) => v === wndProc && wndProcs.delete(k))
|
||||
export function UnregisterClass(className: ATOM, hInstance: HINSTANCE | null = null): boolean {
|
||||
UnregisterClass.native ??= user32.func('UnregisterClassW', cBOOL, [ cATOM, cHANDLE ])
|
||||
|
||||
const ret = UnregisterClass.native(className, hInstance) !== 0
|
||||
if (ret) {
|
||||
const wndProc = wndProcs.get(className)
|
||||
if (wndProc) {
|
||||
koffi.unregister(wndProc)
|
||||
wndProcs.delete(className)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
|
||||
function unregister_by_atom() {
|
||||
unregister_by_atom.native ??= user32.func('UnregisterClassW', cBOOL, [ cATOM, cHANDLE ])
|
||||
return unregister_by_atom.native(className, hInstance) !== 0
|
||||
}
|
||||
|
||||
function unregister_by_string() {
|
||||
unregister_by_string.native ??= user32.func('UnregisterClassW', cBOOL, [ cSTR, cHANDLE ])
|
||||
return unregister_by_string.native(className, hInstance) !== 0
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user