diff --git a/source/demos/audit.ts b/source/demos/audit.ts new file mode 100644 index 0000000..f743409 --- /dev/null +++ b/source/demos/audit.ts @@ -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))) +} diff --git a/source/demos/createwindow.ts b/source/demos/createwindow.ts index 8508e13..e35a433 100644 --- a/source/demos/createwindow.ts +++ b/source/demos/createwindow.ts @@ -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) diff --git a/source/demos/enumwindows.ts b/source/demos/enumwindows.ts index a67b2c1..d75818e 100644 --- a/source/demos/enumwindows.ts +++ b/source/demos/enumwindows.ts @@ -3,6 +3,7 @@ import { } from 'libwin32/user32' const filters = [ + // cSpell:disable-next-line 'MSCTFIME UI', 'Default IME' ] diff --git a/source/demos/gettokeninformation.ts b/source/demos/gettokeninformation.ts index 127c716..295b090 100644 --- a/source/demos/gettokeninformation.ts +++ b/source/demos/gettokeninformation.ts @@ -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())) diff --git a/source/demos/messagebox.ts b/source/demos/messagebox.ts index 29e67c0..88f0a9c 100644 --- a/source/demos/messagebox.ts +++ b/source/demos/messagebox.ts @@ -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 = { [IDYES]: 'YES', @@ -16,4 +13,5 @@ const button = MessageBox( 'libwin32', MB_.ICONINFORMATION | MB_.YESNOCANCEL ) + console.log(results[button]) diff --git a/source/demos/registry.ts b/source/demos/registry.ts index ff03282..f595ef8 100644 --- a/source/demos/registry.ts +++ b/source/demos/registry.ts @@ -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(hTestKey)) { +if (isHandle(hTestKey)) { QueryKey(hTestKey) RegCloseKey(hTestKey) } diff --git a/source/win32/advapi32/lsa/types.ts b/source/win32/advapi32/lsa/types.ts index da1975e..09a92a4 100644 --- a/source/win32/advapi32/lsa/types.ts +++ b/source/win32/advapi32/lsa/types.ts @@ -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. diff --git a/source/win32/internals.ts b/source/win32/internals.ts index b144e41..d732baa 100644 --- a/source/win32/internals.ts +++ b/source/win32/internals.ts @@ -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)