feat(demos): add audit demo, polish others

This commit is contained in:
Stephan Schreiber
2026-06-14 11:35:58 +02:00
parent cc04b9858e
commit 71237bdf3d
8 changed files with 84 additions and 21 deletions
+66
View File
@@ -0,0 +1,66 @@
/*
* This demo is based on MS's sample code "Managing the Audit Status"
* https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/security/authorization/audit
*
* This demo only queries the current audit status; it does not change it.
*/
import {
LsaOpenPolicy, LsaQueryInformationPolicy, LsaClose, LsaFreeMemory, LsaNtStatusToWinError,
FormatMessage, isHandle, isErrorStatus,
type POLICY_AUDIT_EVENT_OPTIONS, type LSA_HANDLE
} from 'libwin32'
import {
POLICY_, POLICY_AUDIT_EVENT_, POLICY_AUDIT_EVENT_TYPE,
NTSTATUS_, FORMAT_MESSAGE_,
POLICY_INFORMATION_CLASS,
} from 'libwin32/consts'
function displayAuditEventOption(eventTypeIndex: number, eventOption: POLICY_AUDIT_EVENT_OPTIONS) {
let output = 'AuditCategory: '
switch (eventTypeIndex) {
case POLICY_AUDIT_EVENT_TYPE.AuditCategorySystem: output += 'System'; break
case POLICY_AUDIT_EVENT_TYPE.AuditCategoryLogon: output += 'Logon'; break
case POLICY_AUDIT_EVENT_TYPE.AuditCategoryObjectAccess: output += 'ObjectAccess'; break
case POLICY_AUDIT_EVENT_TYPE.AuditCategoryPrivilegeUse: output += 'PrivilegeUse'; break
case POLICY_AUDIT_EVENT_TYPE.AuditCategoryDetailedTracking: output += 'DetailedTracking'; break
case POLICY_AUDIT_EVENT_TYPE.AuditCategoryPolicyChange: output += 'PolicyChange'; break
case POLICY_AUDIT_EVENT_TYPE.AuditCategoryAccountManagement: output += 'AccountManagement'; break
default: output += 'Unknown'
}
if (eventOption & POLICY_AUDIT_EVENT_.SUCCESS)
output += ' (AUDIT_EVENT_SUCCESS)'
if (eventOption & POLICY_AUDIT_EVENT_.FAILURE)
output += ' (AUDIT_EVENT_FAILURE)'
console.log(output)
}
function displayAudit(policy: LSA_HANDLE) {
const auditEvents = LsaQueryInformationPolicy(policy, POLICY_INFORMATION_CLASS.PolicyAuditEventsInformation)
if (isErrorStatus(auditEvents))
console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, LsaNtStatusToWinError(auditEvents)))
else {
if (auditEvents.AuditingMode)
console.log('Auditing enabled.')
else
console.log('Auditing disabled.')
for (let i = 0; i < auditEvents.MaximumAuditEventCount; i++)
displayAuditEventOption(i, auditEvents.EventAuditingOptions[i])
LsaFreeMemory(auditEvents)
}
}
const computerName = process.argv[2] || null
const policy = LsaOpenPolicy(computerName, POLICY_.VIEW_AUDIT_INFORMATION)
if (isHandle(policy)) {
displayAudit(policy)
LsaClose(policy)
}
else {
console.error('LsaOpenPolicy() returned NTSTATUS 0x%s (%s)', policy.toString(16), NTSTATUS_[policy])
console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, LsaNtStatusToWinError(policy)))
}
+6 -8
View File
@@ -3,10 +3,10 @@ import {
RegisterClassEx, LoadCursor, LoadIcon, WNDCLASSEX,
CreateWindowEx, ShowWindow, UpdateWindow, DefWindowProc,
GetMessage, TranslateMessage, DispatchMessage, PostQuitMessage,
FormatMessage, MessageBox,
FormatMessage,
type HINSTANCE, type MSG, type WPARAM, type LPARAM, type HWND, type HBRUSH
} from 'libwin32'
import { CS_, CW_USEDEFAULT, FORMAT_MESSAGE_, IDC_, IDI_, MB_, SW_, WM_, WS_, WS_EX_ } from 'libwin32/consts'
import { CS_, CW_USEDEFAULT, FORMAT_MESSAGE_, IDC_, IDI_, SW_, WM_, WS_, WS_EX_ } from 'libwin32/consts'
const windowClass = 'libwin32_app'
const windowName = 'libwin32 demo: CreateWindow'
@@ -22,7 +22,7 @@ function wndProc(hWnd: HWND, uMmsg: WM_, wParam: WPARAM, lParam: LPARAM) {
break
default:
// console.log(uMmsg)
// console.log(uMsg)
ret = DefWindowProc(hWnd, uMmsg, wParam, lParam) as number
break
}
@@ -44,7 +44,7 @@ function WinMain(hInstance: HINSTANCE, nCmdShow: SW_): number {
const atom = RegisterClassEx(wcex)
if (!atom) {
MessageBox(null, 'Call to RegisterClassEx failed!', 'libwin32', MB_.OK | MB_.ICONERROR)
console.error('Call to RegisterClassEx failed!')
return 1
}
@@ -57,8 +57,7 @@ function WinMain(hInstance: HINSTANCE, nCmdShow: SW_): number {
)
if (!hWnd) {
const err = GetLastError()
const msg = FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, err, 0)
MessageBox(null, 'Call to CreateWindowEx failed!\n' + msg, 'libwin32', MB_.OK | MB_.ICONERROR)
console.error('Call to CreateWindowEx failed:', FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, err, 0))
return err
}
@@ -76,8 +75,7 @@ function WinMain(hInstance: HINSTANCE, nCmdShow: SW_): number {
}
const hInstance = GetModuleHandle(null)
if (!hInstance) {
if (!hInstance)
throw new Error('GetModuleHandle() failed.')
}
process.exitCode = WinMain(hInstance, SW_.NORMAL)
+1
View File
@@ -3,6 +3,7 @@ import {
} from 'libwin32/user32'
const filters = [
// cSpell:disable-next-line
'MSCTFIME UI', 'Default IME'
]
+3 -4
View File
@@ -11,9 +11,7 @@ if (hToken) {
for (let i = TOKEN_INFORMATION_CLASS.TokenUser; i <= TOKEN_INFORMATION_CLASS.TokenIntegrityLevel; i++) {
console.group('\n****', TOKEN_INFORMATION_CLASS[i])
const info = GetTokenInformation(hToken, i)
if (info === null)
console.log(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
else {
if (info !== null) {
console.dir(info, { depth: 5 })
if (i === TOKEN_INFORMATION_CLASS.TokenLinkedToken) {
// "When you have finished using the handle, close it by calling the CloseHandle function."
@@ -21,8 +19,9 @@ if (hToken) {
CloseHandle((info as TOKEN_LINKED_TOKEN).LinkedToken)
}
}
else console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
console.groupEnd()
}
CloseHandle(hToken)
}
else console.log(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
else console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
+2 -4
View File
@@ -1,8 +1,5 @@
import { MessageBox } from 'libwin32'
import {
MB_,
IDYES, IDNO, IDCANCEL
} from 'libwin32/consts'
import { MB_, IDYES, IDNO, IDCANCEL } from 'libwin32/consts'
const results: Record<number, string> = {
[IDYES]: 'YES',
@@ -16,4 +13,5 @@ const button = MessageBox(
'libwin32',
MB_.ICONINFORMATION | MB_.YESNOCANCEL
)
console.log(results[button])
+4 -4
View File
@@ -15,7 +15,7 @@ function QueryKey(hKey: HKEY) {
// Get the class name and the value count.
const info = RegQueryInfoKey(hKey)
if (isErrorStatus(info)) {
console.log(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
return
}
@@ -24,7 +24,7 @@ function QueryKey(hKey: HKEY) {
for (let i = 0; i < info.subKeys; i++) {
const key = RegEnumKeyEx(hKey, i)
if (isErrorStatus(key)) {
console.log(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
break
}
console.log('(%d) %s', i + 1, key.name)
@@ -35,7 +35,7 @@ function QueryKey(hKey: HKEY) {
for (let i = 0; i < info.values; i++) {
const value = RegEnumValue(hKey, i)
if (isErrorStatus(value)) {
console.log(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
console.error(FormatMessage(FORMAT_MESSAGE_.FROM_SYSTEM, null, GetLastError()))
break
}
console.log('(%d) %s', i + 1, value.name)
@@ -43,7 +43,7 @@ function QueryKey(hKey: HKEY) {
}
const hTestKey = RegOpenKeyEx(HKEY_.CURRENT_USER, "SOFTWARE\\Microsoft", 0, KEY_.READ)
if (isHandle<HKEY>(hTestKey)) {
if (isHandle(hTestKey)) {
QueryKey(hTestKey)
RegCloseKey(hTestKey)
}
+1
View File
@@ -113,6 +113,7 @@ export interface POLICY_AUDIT_EVENTS_INFO {
MaximumAuditEventCount: number
}
export type POLICY_AUDIT_EVENT_OPTIONS = number
/**
* Used to set and query Domain Name System (DNS) information about the primary domain associated with a Policy object.
+1 -1
View File
@@ -30,7 +30,7 @@ export const cSIZE_T = koffi.types.uint64
export const cHANDLE = koffi.pointer(koffi.opaque())
export const cLSTATUS = koffi.types.int32
export const cNTSTATUS = koffi.types.int32
export const cNTSTATUS = koffi.types.uint32 // Defined a LONG in ntstatus.h but more useful as unsigned
export const cP_VOID = koffi.pointer(koffi.types.void)
export const cP_DWORD = koffi.pointer(cDWORD)