@logtape/windows-eventlog 1.4.0-dev.428 → 1.4.0-dev.438
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -0
- package/dist/ffi.bun.cjs +13 -13
- package/dist/ffi.bun.js +13 -13
- package/dist/ffi.bun.js.map +1 -1
- package/dist/ffi.deno.cjs +21 -20
- package/dist/ffi.deno.js +21 -17
- package/dist/ffi.deno.js.map +1 -1
- package/dist/ffi.node.cjs +10 -15
- package/dist/ffi.node.js +10 -15
- package/dist/ffi.node.js.map +1 -1
- package/dist/formatter.cjs +38 -0
- package/dist/formatter.js +38 -0
- package/dist/formatter.js.map +1 -0
- package/dist/sink.bun.cjs +3 -70
- package/dist/sink.bun.d.cts.map +1 -1
- package/dist/sink.bun.d.ts.map +1 -1
- package/dist/sink.bun.js +4 -70
- package/dist/sink.bun.js.map +1 -1
- package/dist/sink.cjs +84 -0
- package/dist/sink.deno.cjs +3 -84
- package/dist/sink.deno.d.cts.map +1 -1
- package/dist/sink.deno.d.ts.map +1 -1
- package/dist/sink.deno.js +4 -84
- package/dist/sink.deno.js.map +1 -1
- package/dist/sink.js +84 -0
- package/dist/sink.js.map +1 -0
- package/dist/sink.node.cjs +3 -81
- package/dist/sink.node.d.cts.map +1 -1
- package/dist/sink.node.d.ts.map +1 -1
- package/dist/sink.node.js +4 -81
- package/dist/sink.node.js.map +1 -1
- package/dist/types.cjs +16 -7
- package/dist/types.d.cts +6 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +16 -8
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -100,6 +100,34 @@ await configure({
|
|
|
100
100
|
> This is the standard location for application events and does not require
|
|
101
101
|
> administrator privileges.
|
|
102
102
|
|
|
103
|
+
> [!NOTE]
|
|
104
|
+
> The event ID is used to lookup a string resource from a dynamic link library.
|
|
105
|
+
> If you do not register a library, “the system cannot open the file” will be
|
|
106
|
+
> printed as description in the Event Log regardless of the parameters passed.
|
|
107
|
+
|
|
108
|
+
If you want to log only the text supplied by the formatter into the event log,
|
|
109
|
+
you can register the system generic string library using this command:
|
|
110
|
+
|
|
111
|
+
~~~~ powershell
|
|
112
|
+
New-Item `
|
|
113
|
+
-Path HKLM:\SYSTEM\CurrentControlSet\Services\EventLog\Application `
|
|
114
|
+
-Name MyApplication `
|
|
115
|
+
| New-ItemProperty `
|
|
116
|
+
-Name EventMessageFile `
|
|
117
|
+
-PropertyType ExpandString `
|
|
118
|
+
-Value %SystemRoot%\System32\netmsg.dll
|
|
119
|
+
~~~~
|
|
120
|
+
|
|
121
|
+
Replacing `MyApplication` with the name you passed as `sourceName` to the sink,
|
|
122
|
+
and use the `NELOG_OEM_Code` (the default) as the event ID. Note that there is
|
|
123
|
+
no quotation marks around the data part of that command, as this trips up the
|
|
124
|
+
escaping of the percentage signs.
|
|
125
|
+
|
|
126
|
+
> [!NOTE]
|
|
127
|
+
> Event Viewer will cache the event message file when it is open. If you change
|
|
128
|
+
> the entry in the registry, it will not be updated until Event Viewer is
|
|
129
|
+
> restarted.
|
|
130
|
+
|
|
103
131
|
|
|
104
132
|
Runtime support
|
|
105
133
|
---------------
|
package/dist/ffi.bun.cjs
CHANGED
|
@@ -6,23 +6,21 @@ const bun_ffi = require_rolldown_runtime.__toESM(require("bun:ffi"));
|
|
|
6
6
|
/**
|
|
7
7
|
* Bun FFI implementation for Windows Event Log API
|
|
8
8
|
*/
|
|
9
|
-
var
|
|
9
|
+
var WindowsEventLogBunFFI = class {
|
|
10
10
|
eventSource = null;
|
|
11
11
|
lib = null;
|
|
12
|
-
sourceName;
|
|
12
|
+
sourceName = "";
|
|
13
13
|
initialized = false;
|
|
14
14
|
metaLogger = (0, __logtape_logtape.getLogger)([
|
|
15
15
|
"logtape",
|
|
16
16
|
"meta",
|
|
17
17
|
"windows-eventlog"
|
|
18
18
|
]);
|
|
19
|
-
constructor(sourceName) {
|
|
20
|
-
this.sourceName = sourceName;
|
|
21
|
-
}
|
|
22
19
|
/**
|
|
23
20
|
* Initialize the FFI bindings and register event source
|
|
24
21
|
*/
|
|
25
|
-
initialize() {
|
|
22
|
+
initialize(sourceName) {
|
|
23
|
+
this.sourceName = sourceName;
|
|
26
24
|
if (this.initialized) return;
|
|
27
25
|
try {
|
|
28
26
|
this.lib = (0, bun_ffi.dlopen)("advapi32.dll", {
|
|
@@ -62,15 +60,17 @@ var WindowsEventLogFFI = class {
|
|
|
62
60
|
/**
|
|
63
61
|
* Write an event to Windows Event Log
|
|
64
62
|
*/
|
|
65
|
-
writeEvent(eventType, eventId,
|
|
63
|
+
writeEvent(eventType, eventId, params) {
|
|
66
64
|
if (!this.initialized || !this.eventSource || !this.lib) return;
|
|
67
65
|
try {
|
|
66
|
+
const ptrArray = new BigUint64Array(params.length + 1);
|
|
68
67
|
const encoder = new TextEncoder();
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
for (let i = 0; i < params.length; i++) {
|
|
69
|
+
const paramBuffer = encoder.encode(params[i] + "\0");
|
|
70
|
+
ptrArray[i] = BigInt((0, bun_ffi.ptr)(paramBuffer));
|
|
71
|
+
}
|
|
72
|
+
ptrArray[params.length] = 0n;
|
|
73
|
+
const success = this.lib.symbols.ReportEventA(this.eventSource, eventType, 0, eventId, null, params.length, 0, ptrArray, null);
|
|
74
74
|
if (!success) throw new Error(`ReportEventA returned false`);
|
|
75
75
|
} catch (error) {
|
|
76
76
|
throw error;
|
|
@@ -99,4 +99,4 @@ var WindowsEventLogFFI = class {
|
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
//#endregion
|
|
102
|
-
exports.
|
|
102
|
+
exports.WindowsEventLogBunFFI = WindowsEventLogBunFFI;
|
package/dist/ffi.bun.js
CHANGED
|
@@ -5,23 +5,21 @@ import { FFIType, dlopen, ptr } from "bun:ffi";
|
|
|
5
5
|
/**
|
|
6
6
|
* Bun FFI implementation for Windows Event Log API
|
|
7
7
|
*/
|
|
8
|
-
var
|
|
8
|
+
var WindowsEventLogBunFFI = class {
|
|
9
9
|
eventSource = null;
|
|
10
10
|
lib = null;
|
|
11
|
-
sourceName;
|
|
11
|
+
sourceName = "";
|
|
12
12
|
initialized = false;
|
|
13
13
|
metaLogger = getLogger([
|
|
14
14
|
"logtape",
|
|
15
15
|
"meta",
|
|
16
16
|
"windows-eventlog"
|
|
17
17
|
]);
|
|
18
|
-
constructor(sourceName) {
|
|
19
|
-
this.sourceName = sourceName;
|
|
20
|
-
}
|
|
21
18
|
/**
|
|
22
19
|
* Initialize the FFI bindings and register event source
|
|
23
20
|
*/
|
|
24
|
-
initialize() {
|
|
21
|
+
initialize(sourceName) {
|
|
22
|
+
this.sourceName = sourceName;
|
|
25
23
|
if (this.initialized) return;
|
|
26
24
|
try {
|
|
27
25
|
this.lib = dlopen("advapi32.dll", {
|
|
@@ -61,15 +59,17 @@ var WindowsEventLogFFI = class {
|
|
|
61
59
|
/**
|
|
62
60
|
* Write an event to Windows Event Log
|
|
63
61
|
*/
|
|
64
|
-
writeEvent(eventType, eventId,
|
|
62
|
+
writeEvent(eventType, eventId, params) {
|
|
65
63
|
if (!this.initialized || !this.eventSource || !this.lib) return;
|
|
66
64
|
try {
|
|
65
|
+
const ptrArray = new BigUint64Array(params.length + 1);
|
|
67
66
|
const encoder = new TextEncoder();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
67
|
+
for (let i = 0; i < params.length; i++) {
|
|
68
|
+
const paramBuffer = encoder.encode(params[i] + "\0");
|
|
69
|
+
ptrArray[i] = BigInt(ptr(paramBuffer));
|
|
70
|
+
}
|
|
71
|
+
ptrArray[params.length] = 0n;
|
|
72
|
+
const success = this.lib.symbols.ReportEventA(this.eventSource, eventType, 0, eventId, null, params.length, 0, ptrArray, null);
|
|
73
73
|
if (!success) throw new Error(`ReportEventA returned false`);
|
|
74
74
|
} catch (error) {
|
|
75
75
|
throw error;
|
|
@@ -98,5 +98,5 @@ var WindowsEventLogFFI = class {
|
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
//#endregion
|
|
101
|
-
export {
|
|
101
|
+
export { WindowsEventLogBunFFI };
|
|
102
102
|
//# sourceMappingURL=ffi.bun.js.map
|
package/dist/ffi.bun.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffi.bun.js","names":["sourceName: string","eventType: EventType","eventId: number","
|
|
1
|
+
{"version":3,"file":"ffi.bun.js","names":["sourceName: string","eventType: EventType","eventId: number","params: string[]"],"sources":["../src/ffi.bun.ts"],"sourcesContent":["import { getLogger } from \"@logtape/logtape\";\n// @ts-types=\"npm:@types/bun@^1.2.16\"\nimport { dlopen, FFIType, ptr } from \"bun:ffi\";\nimport type { WindowsEventLogFFI } from \"./ffi.ts\";\nimport type { EventType } from \"./types.ts\";\n\n/**\n * Bun FFI implementation for Windows Event Log API\n */\nexport class WindowsEventLogBunFFI implements WindowsEventLogFFI {\n private eventSource: number | null = null;\n // deno-lint-ignore no-explicit-any\n private lib: any = null;\n private sourceName: string = \"\"; // immediately overwritten in initialize\n private initialized = false;\n private metaLogger = getLogger([\"logtape\", \"meta\", \"windows-eventlog\"]);\n\n /**\n * Initialize the FFI bindings and register event source\n */\n initialize(sourceName: string): void {\n this.sourceName = sourceName;\n if (this.initialized) return;\n\n try {\n // Load advapi32.dll using Bun FFI\n this.lib = dlopen(\"advapi32.dll\", {\n RegisterEventSourceA: {\n args: [FFIType.ptr, FFIType.cstring],\n returns: FFIType.ptr,\n },\n ReportEventA: {\n args: [\n FFIType.ptr, // hEventLog\n FFIType.u16, // wType\n FFIType.u16, // wCategory\n FFIType.u32, // dwEventID\n FFIType.ptr, // lpUserSid\n FFIType.u16, // wNumStrings\n FFIType.u32, // dwDataSize\n FFIType.ptr, // lpStrings - pointer to array of string pointers\n FFIType.ptr, // lpRawData\n ],\n returns: FFIType.bool,\n },\n DeregisterEventSource: {\n args: [FFIType.ptr],\n returns: FFIType.bool,\n },\n });\n\n // Register event source using cstring\n // Create a buffer for the source name\n const encoder = new TextEncoder();\n const sourceNameBuffer = encoder.encode(this.sourceName + \"\\0\");\n\n const result = this.lib.symbols.RegisterEventSourceA(\n null,\n sourceNameBuffer,\n );\n this.eventSource = typeof result === \"number\" ? result : null;\n\n if (!this.eventSource || this.eventSource === 0) {\n throw new Error(\n `Failed to register event source: ${this.sourceName}`,\n );\n }\n\n this.initialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize Windows Event Log FFI: ${error}`,\n );\n }\n }\n\n /**\n * Write an event to Windows Event Log\n */\n writeEvent(eventType: EventType, eventId: number, params: string[]): void {\n if (!this.initialized || !this.eventSource || !this.lib) {\n return;\n }\n\n try {\n // Create pointer array for strings\n const ptrArray = new BigUint64Array(params.length + 1);\n\n // Use string array approach which works with Bun FFI\n const encoder = new TextEncoder();\n for (let i = 0; i < params.length; i++) {\n const paramBuffer = encoder.encode(params[i] + \"\\0\");\n ptrArray[i] = BigInt(ptr(paramBuffer));\n }\n ptrArray[params.length] = 0n; // null terminator\n\n const success = this.lib.symbols.ReportEventA(\n this.eventSource,\n eventType,\n 0, // category\n eventId,\n null, // user SID (null)\n params.length, // number of strings\n 0, // data size\n ptrArray, // pointer to array of string pointers\n null, // raw data (null)\n );\n\n if (!success) {\n throw new Error(`ReportEventA returned false`);\n }\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n if (this.initialized && this.eventSource && this.lib) {\n try {\n this.lib.symbols.DeregisterEventSource(this.eventSource);\n } catch (error) {\n this.metaLogger.error(\n \"Failed to deregister event source during cleanup: {error}\",\n { error },\n );\n }\n this.eventSource = null;\n this.initialized = false;\n\n try {\n this.lib.close();\n } catch (error) {\n this.metaLogger.error(\n \"Failed to close FFI library during cleanup: {error}\",\n { error },\n );\n }\n this.lib = null;\n }\n }\n}\n\n// cSpell: ignore cstring\n"],"mappings":";;;;;;;AASA,IAAa,wBAAb,MAAiE;CAC/D,AAAQ,cAA6B;CAErC,AAAQ,MAAW;CACnB,AAAQ,aAAqB;CAC7B,AAAQ,cAAc;CACtB,AAAQ,aAAa,UAAU;EAAC;EAAW;EAAQ;CAAmB,EAAC;;;;CAKvE,WAAWA,YAA0B;AACnC,OAAK,aAAa;AAClB,MAAI,KAAK,YAAa;AAEtB,MAAI;AAEF,QAAK,MAAM,OAAO,gBAAgB;IAChC,sBAAsB;KACpB,MAAM,CAAC,QAAQ,KAAK,QAAQ,OAAQ;KACpC,SAAS,QAAQ;IAClB;IACD,cAAc;KACZ,MAAM;MACJ,QAAQ;MACR,QAAQ;MACR,QAAQ;MACR,QAAQ;MACR,QAAQ;MACR,QAAQ;MACR,QAAQ;MACR,QAAQ;MACR,QAAQ;KACT;KACD,SAAS,QAAQ;IAClB;IACD,uBAAuB;KACrB,MAAM,CAAC,QAAQ,GAAI;KACnB,SAAS,QAAQ;IAClB;GACF,EAAC;GAIF,MAAM,UAAU,IAAI;GACpB,MAAM,mBAAmB,QAAQ,OAAO,KAAK,aAAa,KAAK;GAE/D,MAAM,SAAS,KAAK,IAAI,QAAQ,qBAC9B,MACA,iBACD;AACD,QAAK,qBAAqB,WAAW,WAAW,SAAS;AAEzD,QAAK,KAAK,eAAe,KAAK,gBAAgB,EAC5C,OAAM,IAAI,OACP,mCAAmC,KAAK,WAAW;AAIxD,QAAK,cAAc;EACpB,SAAQ,OAAO;AACd,SAAM,IAAI,OACP,8CAA8C,MAAM;EAExD;CACF;;;;CAKD,WAAWC,WAAsBC,SAAiBC,QAAwB;AACxE,OAAK,KAAK,gBAAgB,KAAK,gBAAgB,KAAK,IAClD;AAGF,MAAI;GAEF,MAAM,WAAW,IAAI,eAAe,OAAO,SAAS;GAGpD,MAAM,UAAU,IAAI;AACpB,QAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IACtC,MAAM,cAAc,QAAQ,OAAO,OAAO,KAAK,KAAK;AACpD,aAAS,KAAK,OAAO,IAAI,YAAY,CAAC;GACvC;AACD,YAAS,OAAO,UAAU;GAE1B,MAAM,UAAU,KAAK,IAAI,QAAQ,aAC/B,KAAK,aACL,WACA,GACA,SACA,MACA,OAAO,QACP,GACA,UACA,KACD;AAED,QAAK,QACH,OAAM,IAAI,OAAO;EAEpB,SAAQ,OAAO;AACd,SAAM;EACP;CACF;;;;CAKD,UAAgB;AACd,MAAI,KAAK,eAAe,KAAK,eAAe,KAAK,KAAK;AACpD,OAAI;AACF,SAAK,IAAI,QAAQ,sBAAsB,KAAK,YAAY;GACzD,SAAQ,OAAO;AACd,SAAK,WAAW,MACd,6DACA,EAAE,MAAO,EACV;GACF;AACD,QAAK,cAAc;AACnB,QAAK,cAAc;AAEnB,OAAI;AACF,SAAK,IAAI,OAAO;GACjB,SAAQ,OAAO;AACd,SAAK,WAAW,MACd,uDACA,EAAE,MAAO,EACV;GACF;AACD,QAAK,MAAM;EACZ;CACF;AACF"}
|
package/dist/ffi.deno.cjs
CHANGED
|
@@ -3,9 +3,6 @@ const require_types = require('./types.cjs');
|
|
|
3
3
|
const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
|
|
4
4
|
|
|
5
5
|
//#region src/ffi.deno.ts
|
|
6
|
-
const EVENTLOG_ERROR_TYPE = 1;
|
|
7
|
-
const EVENTLOG_WARNING_TYPE = 2;
|
|
8
|
-
const EVENTLOG_INFORMATION_TYPE = 4;
|
|
9
6
|
const FFI_SYMBOLS = {
|
|
10
7
|
RegisterEventSourceA: {
|
|
11
8
|
parameters: ["pointer", "pointer"],
|
|
@@ -36,28 +33,30 @@ const FFI_SYMBOLS = {
|
|
|
36
33
|
*
|
|
37
34
|
* @since 1.0.0
|
|
38
35
|
*/
|
|
39
|
-
var
|
|
36
|
+
var WindowsEventLogDenoFFI = class {
|
|
40
37
|
lib = null;
|
|
41
38
|
eventSource = null;
|
|
39
|
+
sourceName = "";
|
|
40
|
+
initialized = false;
|
|
42
41
|
encoder = new TextEncoder();
|
|
43
42
|
metaLogger = (0, __logtape_logtape.getLogger)([
|
|
44
43
|
"logtape",
|
|
45
44
|
"meta",
|
|
46
45
|
"windows-eventlog"
|
|
47
46
|
]);
|
|
48
|
-
constructor(sourceName) {
|
|
49
|
-
this.sourceName = sourceName;
|
|
50
|
-
}
|
|
51
47
|
/**
|
|
52
48
|
* Initializes the FFI library and registers the event source.
|
|
53
49
|
* @throws {WindowsEventLogError} If initialization fails
|
|
54
50
|
*/
|
|
55
|
-
initialize() {
|
|
51
|
+
initialize(sourceName) {
|
|
52
|
+
this.sourceName = sourceName;
|
|
53
|
+
if (this.initialized) return;
|
|
56
54
|
try {
|
|
57
55
|
this.lib = Deno.dlopen("advapi32.dll", FFI_SYMBOLS);
|
|
58
56
|
const sourceNamePtr = Deno.UnsafePointer.of(this.encoder.encode(this.sourceName + "\0"));
|
|
59
57
|
this.eventSource = this.lib.symbols.RegisterEventSourceA(null, sourceNamePtr);
|
|
60
58
|
if (!this.eventSource) throw new require_types.WindowsEventLogError(`Failed to register event source '${this.sourceName}'.`);
|
|
59
|
+
this.initialized = true;
|
|
61
60
|
} catch (error) {
|
|
62
61
|
if (error instanceof require_types.WindowsEventLogError) throw error;
|
|
63
62
|
throw new require_types.WindowsEventLogError(`Failed to initialize Windows Event Log FFI: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : void 0);
|
|
@@ -67,19 +66,23 @@ var WindowsEventLogFFI = class {
|
|
|
67
66
|
* Writes a message to the Windows Event Log.
|
|
68
67
|
*
|
|
69
68
|
* @param eventType Event type (error, warning, info)
|
|
70
|
-
* @param eventId Event ID number
|
|
71
|
-
* @param
|
|
69
|
+
* @param eventId Event ID number that gives us formatting string
|
|
70
|
+
* @param params Message parameter strings to log
|
|
72
71
|
* @throws {WindowsEventLogError} If the write operation fails
|
|
73
72
|
*/
|
|
74
|
-
writeEvent(eventType, eventId,
|
|
73
|
+
writeEvent(eventType, eventId, params) {
|
|
75
74
|
if (!this.lib || !this.eventSource) throw new require_types.WindowsEventLogError("FFI not initialized. Call initialize() first.");
|
|
76
75
|
try {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
const unsafePointersToStrings = [];
|
|
77
|
+
for (let i = 0; i < params.length; i++) {
|
|
78
|
+
const paramBuffer = this.encoder.encode(params[i] + "\0");
|
|
79
|
+
const paramPtr = Deno.UnsafePointer.of(paramBuffer);
|
|
80
|
+
const paramPtrValue = paramPtr ? Deno.UnsafePointer.value(paramPtr) : 0n;
|
|
81
|
+
unsafePointersToStrings.push(paramPtrValue);
|
|
82
|
+
}
|
|
83
|
+
const stringsArray = new BigUint64Array(unsafePointersToStrings);
|
|
81
84
|
const stringsPtr = Deno.UnsafePointer.of(stringsArray);
|
|
82
|
-
const result = this.lib.symbols.ReportEventA(this.eventSource, eventType, 0, eventId, null,
|
|
85
|
+
const result = this.lib.symbols.ReportEventA(this.eventSource, eventType, 0, eventId, null, stringsArray.length, 0, stringsPtr, null);
|
|
83
86
|
if (result === 0) throw new require_types.WindowsEventLogError(`Failed to write event to Event Log.`);
|
|
84
87
|
} catch (error) {
|
|
85
88
|
if (error instanceof require_types.WindowsEventLogError) throw error;
|
|
@@ -106,11 +109,9 @@ var WindowsEventLogFFI = class {
|
|
|
106
109
|
}
|
|
107
110
|
this.lib = null;
|
|
108
111
|
}
|
|
112
|
+
this.initialized = false;
|
|
109
113
|
}
|
|
110
114
|
};
|
|
111
115
|
|
|
112
116
|
//#endregion
|
|
113
|
-
exports.
|
|
114
|
-
exports.EVENTLOG_INFORMATION_TYPE = EVENTLOG_INFORMATION_TYPE;
|
|
115
|
-
exports.EVENTLOG_WARNING_TYPE = EVENTLOG_WARNING_TYPE;
|
|
116
|
-
exports.WindowsEventLogFFI = WindowsEventLogFFI;
|
|
117
|
+
exports.WindowsEventLogDenoFFI = WindowsEventLogDenoFFI;
|
package/dist/ffi.deno.js
CHANGED
|
@@ -2,9 +2,6 @@ import { WindowsEventLogError } from "./types.js";
|
|
|
2
2
|
import { getLogger } from "@logtape/logtape";
|
|
3
3
|
|
|
4
4
|
//#region src/ffi.deno.ts
|
|
5
|
-
const EVENTLOG_ERROR_TYPE = 1;
|
|
6
|
-
const EVENTLOG_WARNING_TYPE = 2;
|
|
7
|
-
const EVENTLOG_INFORMATION_TYPE = 4;
|
|
8
5
|
const FFI_SYMBOLS = {
|
|
9
6
|
RegisterEventSourceA: {
|
|
10
7
|
parameters: ["pointer", "pointer"],
|
|
@@ -35,28 +32,30 @@ const FFI_SYMBOLS = {
|
|
|
35
32
|
*
|
|
36
33
|
* @since 1.0.0
|
|
37
34
|
*/
|
|
38
|
-
var
|
|
35
|
+
var WindowsEventLogDenoFFI = class {
|
|
39
36
|
lib = null;
|
|
40
37
|
eventSource = null;
|
|
38
|
+
sourceName = "";
|
|
39
|
+
initialized = false;
|
|
41
40
|
encoder = new TextEncoder();
|
|
42
41
|
metaLogger = getLogger([
|
|
43
42
|
"logtape",
|
|
44
43
|
"meta",
|
|
45
44
|
"windows-eventlog"
|
|
46
45
|
]);
|
|
47
|
-
constructor(sourceName) {
|
|
48
|
-
this.sourceName = sourceName;
|
|
49
|
-
}
|
|
50
46
|
/**
|
|
51
47
|
* Initializes the FFI library and registers the event source.
|
|
52
48
|
* @throws {WindowsEventLogError} If initialization fails
|
|
53
49
|
*/
|
|
54
|
-
initialize() {
|
|
50
|
+
initialize(sourceName) {
|
|
51
|
+
this.sourceName = sourceName;
|
|
52
|
+
if (this.initialized) return;
|
|
55
53
|
try {
|
|
56
54
|
this.lib = Deno.dlopen("advapi32.dll", FFI_SYMBOLS);
|
|
57
55
|
const sourceNamePtr = Deno.UnsafePointer.of(this.encoder.encode(this.sourceName + "\0"));
|
|
58
56
|
this.eventSource = this.lib.symbols.RegisterEventSourceA(null, sourceNamePtr);
|
|
59
57
|
if (!this.eventSource) throw new WindowsEventLogError(`Failed to register event source '${this.sourceName}'.`);
|
|
58
|
+
this.initialized = true;
|
|
60
59
|
} catch (error) {
|
|
61
60
|
if (error instanceof WindowsEventLogError) throw error;
|
|
62
61
|
throw new WindowsEventLogError(`Failed to initialize Windows Event Log FFI: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : void 0);
|
|
@@ -66,19 +65,23 @@ var WindowsEventLogFFI = class {
|
|
|
66
65
|
* Writes a message to the Windows Event Log.
|
|
67
66
|
*
|
|
68
67
|
* @param eventType Event type (error, warning, info)
|
|
69
|
-
* @param eventId Event ID number
|
|
70
|
-
* @param
|
|
68
|
+
* @param eventId Event ID number that gives us formatting string
|
|
69
|
+
* @param params Message parameter strings to log
|
|
71
70
|
* @throws {WindowsEventLogError} If the write operation fails
|
|
72
71
|
*/
|
|
73
|
-
writeEvent(eventType, eventId,
|
|
72
|
+
writeEvent(eventType, eventId, params) {
|
|
74
73
|
if (!this.lib || !this.eventSource) throw new WindowsEventLogError("FFI not initialized. Call initialize() first.");
|
|
75
74
|
try {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
const unsafePointersToStrings = [];
|
|
76
|
+
for (let i = 0; i < params.length; i++) {
|
|
77
|
+
const paramBuffer = this.encoder.encode(params[i] + "\0");
|
|
78
|
+
const paramPtr = Deno.UnsafePointer.of(paramBuffer);
|
|
79
|
+
const paramPtrValue = paramPtr ? Deno.UnsafePointer.value(paramPtr) : 0n;
|
|
80
|
+
unsafePointersToStrings.push(paramPtrValue);
|
|
81
|
+
}
|
|
82
|
+
const stringsArray = new BigUint64Array(unsafePointersToStrings);
|
|
80
83
|
const stringsPtr = Deno.UnsafePointer.of(stringsArray);
|
|
81
|
-
const result = this.lib.symbols.ReportEventA(this.eventSource, eventType, 0, eventId, null,
|
|
84
|
+
const result = this.lib.symbols.ReportEventA(this.eventSource, eventType, 0, eventId, null, stringsArray.length, 0, stringsPtr, null);
|
|
82
85
|
if (result === 0) throw new WindowsEventLogError(`Failed to write event to Event Log.`);
|
|
83
86
|
} catch (error) {
|
|
84
87
|
if (error instanceof WindowsEventLogError) throw error;
|
|
@@ -105,9 +108,10 @@ var WindowsEventLogFFI = class {
|
|
|
105
108
|
}
|
|
106
109
|
this.lib = null;
|
|
107
110
|
}
|
|
111
|
+
this.initialized = false;
|
|
108
112
|
}
|
|
109
113
|
};
|
|
110
114
|
|
|
111
115
|
//#endregion
|
|
112
|
-
export {
|
|
116
|
+
export { WindowsEventLogDenoFFI };
|
|
113
117
|
//# sourceMappingURL=ffi.deno.js.map
|
package/dist/ffi.deno.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffi.deno.js","names":["sourceName: string","eventType: number","eventId: number","
|
|
1
|
+
{"version":3,"file":"ffi.deno.js","names":["sourceName: string","eventType: number","eventId: number","params: string[]","unsafePointersToStrings: bigint[]"],"sources":["../src/ffi.deno.ts"],"sourcesContent":["import { getLogger } from \"@logtape/logtape\";\nimport type { WindowsEventLogFFI } from \"./ffi.ts\";\nimport { WindowsEventLogError } from \"./types.ts\";\n\n/**\n * Windows Event Log API constants and types for FFI.\n * @since 1.0.0\n */\n\n// Event Log types\nexport const EVENTLOG_SUCCESS = 0x0000;\nexport const EVENTLOG_ERROR_TYPE = 0x0001;\nexport const EVENTLOG_WARNING_TYPE = 0x0002;\nexport const EVENTLOG_INFORMATION_TYPE = 0x0004;\n\n// FFI symbol definitions for Windows Event Log APIs\nconst FFI_SYMBOLS = {\n RegisterEventSourceA: {\n parameters: [\"pointer\", \"pointer\"] as const,\n result: \"pointer\" as const,\n },\n DeregisterEventSource: {\n parameters: [\"pointer\"] as const,\n result: \"u32\" as const,\n },\n ReportEventA: {\n parameters: [\n \"pointer\", // hEventLog\n \"u16\", // wType\n \"u16\", // wCategory\n \"u32\", // dwEventID\n \"pointer\", // lpUserSid\n \"u16\", // wNumStrings\n \"u32\", // dwDataSize\n \"pointer\", // lpStrings\n \"pointer\", // lpRawData\n ] as const,\n result: \"u32\" as const,\n },\n} as const;\n\n/**\n * Windows Event Log FFI wrapper class for Deno.\n * Provides direct access to Windows Event Log APIs through Deno's FFI.\n *\n * @since 1.0.0\n */\nexport class WindowsEventLogDenoFFI implements WindowsEventLogFFI {\n private lib: Deno.DynamicLibrary<typeof FFI_SYMBOLS> | null = null;\n private eventSource: Deno.PointerValue | null = null;\n private sourceName: string = \"\"; // immediately overwritten in initialize\n private initialized = false;\n private encoder = new TextEncoder();\n private metaLogger = getLogger([\"logtape\", \"meta\", \"windows-eventlog\"]);\n\n /**\n * Initializes the FFI library and registers the event source.\n * @throws {WindowsEventLogError} If initialization fails\n */\n initialize(sourceName: string): void {\n this.sourceName = sourceName;\n if (this.initialized) return;\n\n try {\n // Load advapi32.dll\n this.lib = Deno.dlopen(\"advapi32.dll\", FFI_SYMBOLS);\n\n // Register event source\n const sourceNamePtr = Deno.UnsafePointer.of(\n this.encoder.encode(this.sourceName + \"\\0\"),\n );\n this.eventSource = this.lib.symbols.RegisterEventSourceA(\n null,\n sourceNamePtr,\n );\n\n if (!this.eventSource) {\n throw new WindowsEventLogError(\n `Failed to register event source '${this.sourceName}'.`,\n );\n }\n\n this.initialized = true;\n } catch (error) {\n if (error instanceof WindowsEventLogError) {\n throw error;\n }\n throw new WindowsEventLogError(\n `Failed to initialize Windows Event Log FFI: ${\n error instanceof Error ? error.message : String(error)\n }`,\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Writes a message to the Windows Event Log.\n *\n * @param eventType Event type (error, warning, info)\n * @param eventId Event ID number that gives us formatting string\n * @param params Message parameter strings to log\n * @throws {WindowsEventLogError} If the write operation fails\n */\n writeEvent(eventType: number, eventId: number, params: string[]): void {\n if (!this.lib || !this.eventSource) {\n throw new WindowsEventLogError(\n \"FFI not initialized. Call initialize() first.\",\n );\n }\n\n try {\n const unsafePointersToStrings: bigint[] = [];\n for (let i = 0; i < params.length; i++) {\n // Prepare message string\n const paramBuffer = this.encoder.encode(params[i] + \"\\0\");\n const paramPtr = Deno.UnsafePointer.of(paramBuffer);\n const paramPtrValue = paramPtr\n ? Deno.UnsafePointer.value(paramPtr)\n : 0n;\n unsafePointersToStrings.push(paramPtrValue);\n }\n const stringsArray = new BigUint64Array(unsafePointersToStrings);\n const stringsPtr = Deno.UnsafePointer.of(stringsArray);\n\n // Call ReportEventA\n const result = this.lib.symbols.ReportEventA(\n this.eventSource, // hEventLog\n eventType, // wType\n 0, // wCategory (0 = no category)\n eventId, // dwEventID\n null, // lpUserSid (null = current user)\n stringsArray.length, // wNumStrings\n 0, // dwDataSize (no additional data)\n stringsPtr, // lpStrings\n null, // lpRawData (no additional data)\n );\n\n if (result === 0) {\n throw new WindowsEventLogError(\n `Failed to write event to Event Log.`,\n );\n }\n } catch (error) {\n if (error instanceof WindowsEventLogError) {\n throw error;\n }\n throw new WindowsEventLogError(\n `Error writing to Event Log: ${\n error instanceof Error ? error.message : String(error)\n }`,\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Cleans up resources and deregisters the event source.\n */\n dispose(): void {\n if (this.lib && this.eventSource) {\n try {\n this.lib.symbols.DeregisterEventSource(this.eventSource);\n } catch (error) {\n this.metaLogger.error(\n \"Failed to deregister event source during cleanup: {error}\",\n { error },\n );\n }\n this.eventSource = null;\n }\n\n if (this.lib) {\n try {\n this.lib.close();\n } catch (error) {\n this.metaLogger.error(\n \"Failed to close FFI library during cleanup: {error}\",\n { error },\n );\n }\n this.lib = null;\n }\n\n this.initialized = false;\n }\n}\n"],"mappings":";;;;AAgBA,MAAM,cAAc;CAClB,sBAAsB;EACpB,YAAY,CAAC,WAAW,SAAU;EAClC,QAAQ;CACT;CACD,uBAAuB;EACrB,YAAY,CAAC,SAAU;EACvB,QAAQ;CACT;CACD,cAAc;EACZ,YAAY;GACV;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;EACD;EACD,QAAQ;CACT;AACF;;;;;;;AAQD,IAAa,yBAAb,MAAkE;CAChE,AAAQ,MAAsD;CAC9D,AAAQ,cAAwC;CAChD,AAAQ,aAAqB;CAC7B,AAAQ,cAAc;CACtB,AAAQ,UAAU,IAAI;CACtB,AAAQ,aAAa,UAAU;EAAC;EAAW;EAAQ;CAAmB,EAAC;;;;;CAMvE,WAAWA,YAA0B;AACnC,OAAK,aAAa;AAClB,MAAI,KAAK,YAAa;AAEtB,MAAI;AAEF,QAAK,MAAM,KAAK,OAAO,gBAAgB,YAAY;GAGnD,MAAM,gBAAgB,KAAK,cAAc,GACvC,KAAK,QAAQ,OAAO,KAAK,aAAa,KAAK,CAC5C;AACD,QAAK,cAAc,KAAK,IAAI,QAAQ,qBAClC,MACA,cACD;AAED,QAAK,KAAK,YACR,OAAM,IAAI,sBACP,mCAAmC,KAAK,WAAW;AAIxD,QAAK,cAAc;EACpB,SAAQ,OAAO;AACd,OAAI,iBAAiB,qBACnB,OAAM;AAER,SAAM,IAAI,sBACP,8CACC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CACvD,GACD,iBAAiB,QAAQ;EAE5B;CACF;;;;;;;;;CAUD,WAAWC,WAAmBC,SAAiBC,QAAwB;AACrE,OAAK,KAAK,QAAQ,KAAK,YACrB,OAAM,IAAI,qBACR;AAIJ,MAAI;GACF,MAAMC,0BAAoC,CAAE;AAC5C,QAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;IAEtC,MAAM,cAAc,KAAK,QAAQ,OAAO,OAAO,KAAK,KAAK;IACzD,MAAM,WAAW,KAAK,cAAc,GAAG,YAAY;IACnD,MAAM,gBAAgB,WAClB,KAAK,cAAc,MAAM,SAAS,GAClC;AACJ,4BAAwB,KAAK,cAAc;GAC5C;GACD,MAAM,eAAe,IAAI,eAAe;GACxC,MAAM,aAAa,KAAK,cAAc,GAAG,aAAa;GAGtD,MAAM,SAAS,KAAK,IAAI,QAAQ,aAC9B,KAAK,aACL,WACA,GACA,SACA,MACA,aAAa,QACb,GACA,YACA,KACD;AAED,OAAI,WAAW,EACb,OAAM,IAAI,sBACP;EAGN,SAAQ,OAAO;AACd,OAAI,iBAAiB,qBACnB,OAAM;AAER,SAAM,IAAI,sBACP,8BACC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CACvD,GACD,iBAAiB,QAAQ;EAE5B;CACF;;;;CAKD,UAAgB;AACd,MAAI,KAAK,OAAO,KAAK,aAAa;AAChC,OAAI;AACF,SAAK,IAAI,QAAQ,sBAAsB,KAAK,YAAY;GACzD,SAAQ,OAAO;AACd,SAAK,WAAW,MACd,6DACA,EAAE,MAAO,EACV;GACF;AACD,QAAK,cAAc;EACpB;AAED,MAAI,KAAK,KAAK;AACZ,OAAI;AACF,SAAK,IAAI,OAAO;GACjB,SAAQ,OAAO;AACd,SAAK,WAAW,MACd,uDACA,EAAE,MAAO,EACV;GACF;AACD,QAAK,MAAM;EACZ;AAED,OAAK,cAAc;CACpB;AACF"}
|
package/dist/ffi.node.cjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const __logtape_logtape = require_rolldown_runtime.__toESM(require("@logtape/logtape"));
|
|
3
|
+
const koffi = require_rolldown_runtime.__toESM(require("koffi"));
|
|
3
4
|
|
|
4
5
|
//#region src/ffi.node.ts
|
|
5
6
|
/**
|
|
6
7
|
* Node.js FFI implementation for Windows Event Log API using koffi
|
|
7
8
|
*/
|
|
8
|
-
var
|
|
9
|
+
var WindowsEventLogNodeFFI = class {
|
|
9
10
|
eventSource = null;
|
|
10
|
-
|
|
11
|
-
sourceName;
|
|
11
|
+
sourceName = "";
|
|
12
12
|
initialized = false;
|
|
13
13
|
lib = null;
|
|
14
14
|
metaLogger = (0, __logtape_logtape.getLogger)([
|
|
@@ -16,18 +16,14 @@ var WindowsEventLogFFI = class {
|
|
|
16
16
|
"meta",
|
|
17
17
|
"windows-eventlog"
|
|
18
18
|
]);
|
|
19
|
-
constructor(sourceName) {
|
|
20
|
-
this.sourceName = sourceName;
|
|
21
|
-
}
|
|
22
19
|
/**
|
|
23
20
|
* Initialize the FFI bindings and register event source
|
|
24
21
|
*/
|
|
25
|
-
|
|
22
|
+
initialize(sourceName) {
|
|
23
|
+
this.sourceName = sourceName;
|
|
26
24
|
if (this.initialized) return;
|
|
27
25
|
try {
|
|
28
|
-
|
|
29
|
-
this.koffi = koffiModule.default || koffiModule;
|
|
30
|
-
this.lib = this.koffi.load("advapi32.dll");
|
|
26
|
+
this.lib = koffi.default.load("advapi32.dll");
|
|
31
27
|
const RegisterEventSourceA = this.lib.func("uintptr __stdcall RegisterEventSourceA(uintptr lpUNCServerName, str lpSourceName)");
|
|
32
28
|
const ReportEventA = this.lib.func("bool __stdcall ReportEventA(uintptr hEventLog, uint16 wType, uint16 wCategory, uint32 dwEventID, uintptr lpUserSid, uint16 wNumStrings, uint32 dwDataSize, char** lpStrings, uint8* lpRawData)");
|
|
33
29
|
const DeregisterEventSource = this.lib.func("bool __stdcall DeregisterEventSource(uintptr hEventLog)");
|
|
@@ -47,12 +43,11 @@ var WindowsEventLogFFI = class {
|
|
|
47
43
|
/**
|
|
48
44
|
* Write an event to Windows Event Log
|
|
49
45
|
*/
|
|
50
|
-
writeEvent(eventType, eventId,
|
|
46
|
+
writeEvent(eventType, eventId, params) {
|
|
51
47
|
if (!this.initialized || !this.eventSource || !this.ReportEventA) return;
|
|
52
48
|
try {
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const success = this.ReportEventA(this.eventSource, eventType, 0, eventId, 0, 1, 0, messages, null);
|
|
49
|
+
const nullTerminatedParams = params.map((s) => s + "\0");
|
|
50
|
+
const success = this.ReportEventA(this.eventSource, eventType, 0, eventId, 0, nullTerminatedParams.length, 0, nullTerminatedParams, null);
|
|
56
51
|
if (!success) throw new Error("ReportEventA() returned false.");
|
|
57
52
|
} catch (error) {
|
|
58
53
|
throw error;
|
|
@@ -75,4 +70,4 @@ var WindowsEventLogFFI = class {
|
|
|
75
70
|
};
|
|
76
71
|
|
|
77
72
|
//#endregion
|
|
78
|
-
exports.
|
|
73
|
+
exports.WindowsEventLogNodeFFI = WindowsEventLogNodeFFI;
|
package/dist/ffi.node.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { getLogger } from "@logtape/logtape";
|
|
2
|
+
import koffi from "koffi";
|
|
2
3
|
|
|
3
4
|
//#region src/ffi.node.ts
|
|
4
5
|
/**
|
|
5
6
|
* Node.js FFI implementation for Windows Event Log API using koffi
|
|
6
7
|
*/
|
|
7
|
-
var
|
|
8
|
+
var WindowsEventLogNodeFFI = class {
|
|
8
9
|
eventSource = null;
|
|
9
|
-
|
|
10
|
-
sourceName;
|
|
10
|
+
sourceName = "";
|
|
11
11
|
initialized = false;
|
|
12
12
|
lib = null;
|
|
13
13
|
metaLogger = getLogger([
|
|
@@ -15,18 +15,14 @@ var WindowsEventLogFFI = class {
|
|
|
15
15
|
"meta",
|
|
16
16
|
"windows-eventlog"
|
|
17
17
|
]);
|
|
18
|
-
constructor(sourceName) {
|
|
19
|
-
this.sourceName = sourceName;
|
|
20
|
-
}
|
|
21
18
|
/**
|
|
22
19
|
* Initialize the FFI bindings and register event source
|
|
23
20
|
*/
|
|
24
|
-
|
|
21
|
+
initialize(sourceName) {
|
|
22
|
+
this.sourceName = sourceName;
|
|
25
23
|
if (this.initialized) return;
|
|
26
24
|
try {
|
|
27
|
-
|
|
28
|
-
this.koffi = koffiModule.default || koffiModule;
|
|
29
|
-
this.lib = this.koffi.load("advapi32.dll");
|
|
25
|
+
this.lib = koffi.load("advapi32.dll");
|
|
30
26
|
const RegisterEventSourceA = this.lib.func("uintptr __stdcall RegisterEventSourceA(uintptr lpUNCServerName, str lpSourceName)");
|
|
31
27
|
const ReportEventA = this.lib.func("bool __stdcall ReportEventA(uintptr hEventLog, uint16 wType, uint16 wCategory, uint32 dwEventID, uintptr lpUserSid, uint16 wNumStrings, uint32 dwDataSize, char** lpStrings, uint8* lpRawData)");
|
|
32
28
|
const DeregisterEventSource = this.lib.func("bool __stdcall DeregisterEventSource(uintptr hEventLog)");
|
|
@@ -46,12 +42,11 @@ var WindowsEventLogFFI = class {
|
|
|
46
42
|
/**
|
|
47
43
|
* Write an event to Windows Event Log
|
|
48
44
|
*/
|
|
49
|
-
writeEvent(eventType, eventId,
|
|
45
|
+
writeEvent(eventType, eventId, params) {
|
|
50
46
|
if (!this.initialized || !this.eventSource || !this.ReportEventA) return;
|
|
51
47
|
try {
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const success = this.ReportEventA(this.eventSource, eventType, 0, eventId, 0, 1, 0, messages, null);
|
|
48
|
+
const nullTerminatedParams = params.map((s) => s + "\0");
|
|
49
|
+
const success = this.ReportEventA(this.eventSource, eventType, 0, eventId, 0, nullTerminatedParams.length, 0, nullTerminatedParams, null);
|
|
55
50
|
if (!success) throw new Error("ReportEventA() returned false.");
|
|
56
51
|
} catch (error) {
|
|
57
52
|
throw error;
|
|
@@ -74,5 +69,5 @@ var WindowsEventLogFFI = class {
|
|
|
74
69
|
};
|
|
75
70
|
|
|
76
71
|
//#endregion
|
|
77
|
-
export {
|
|
72
|
+
export { WindowsEventLogNodeFFI };
|
|
78
73
|
//# sourceMappingURL=ffi.node.js.map
|
package/dist/ffi.node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ffi.node.js","names":["sourceName: string","eventType: EventType","eventId: number","
|
|
1
|
+
{"version":3,"file":"ffi.node.js","names":["sourceName: string","eventType: EventType","eventId: number","params: string[]"],"sources":["../src/ffi.node.ts"],"sourcesContent":["import { getLogger } from \"@logtape/logtape\";\nimport koffi from \"koffi\";\nimport type { WindowsEventLogFFI } from \"./ffi.ts\";\nimport type { EventType } from \"./types.ts\";\n\n/**\n * Node.js FFI implementation for Windows Event Log API using koffi\n */\nexport class WindowsEventLogNodeFFI implements WindowsEventLogFFI {\n private eventSource: unknown = null;\n private sourceName: string = \"\"; // immediately overwritten in initialize;\n private initialized = false;\n private lib: unknown = null;\n private metaLogger = getLogger([\"logtape\", \"meta\", \"windows-eventlog\"]);\n\n /**\n * Initialize the FFI bindings and register event source\n */\n initialize(sourceName: string): void {\n this.sourceName = sourceName;\n if (this.initialized) return;\n\n try {\n // Load advapi32.dll\n this.lib = koffi.load(\"advapi32.dll\");\n\n // Define Windows API functions with correct koffi types using __stdcall convention\n const RegisterEventSourceA =\n (this.lib as unknown as { func: (sig: string) => unknown }).func(\n \"uintptr __stdcall RegisterEventSourceA(uintptr lpUNCServerName, str lpSourceName)\",\n );\n // ReportEventA expects LPCSTR* (array of string pointers) for lpStrings\n // Use char** for null-terminated array of strings\n const ReportEventA =\n (this.lib as unknown as { func: (sig: string) => unknown }).func(\n \"bool __stdcall ReportEventA(uintptr hEventLog, uint16 wType, uint16 wCategory, uint32 dwEventID, uintptr lpUserSid, uint16 wNumStrings, uint32 dwDataSize, char** lpStrings, uint8* lpRawData)\",\n );\n const DeregisterEventSource =\n (this.lib as unknown as { func: (sig: string) => unknown }).func(\n \"bool __stdcall DeregisterEventSource(uintptr hEventLog)\",\n );\n\n // Store functions\n this.RegisterEventSourceA = RegisterEventSourceA;\n this.ReportEventA = ReportEventA;\n this.DeregisterEventSource = DeregisterEventSource;\n\n // Register event source\n this.eventSource = (this.RegisterEventSourceA as unknown as (\n ...args: unknown[]\n ) => unknown)(0, this.sourceName);\n\n if (!this.eventSource || this.eventSource === 0) {\n throw new Error(\n `Failed to register event source: ${this.sourceName}`,\n );\n }\n\n this.initialized = true;\n } catch (error) {\n throw new Error(\n `Failed to initialize Windows Event Log FFI: ${error}`,\n );\n }\n }\n\n private RegisterEventSourceA: unknown = null;\n private ReportEventA: unknown = null;\n private DeregisterEventSource: unknown = null;\n\n /**\n * Write an event to Windows Event Log\n */\n writeEvent(eventType: EventType, eventId: number, params: string[]): void {\n if (!this.initialized || !this.eventSource || !this.ReportEventA) {\n return;\n }\n\n try {\n // Create null-terminated strings\n // In koffi, we pass an array of strings for char**\n const nullTerminatedParams = params.map((s) => s + \"\\0\");\n\n // Report the event using strings array approach\n const success =\n (this.ReportEventA as unknown as (...args: unknown[]) => unknown)(\n this.eventSource,\n eventType,\n 0, // category\n eventId,\n 0, // user SID (null)\n nullTerminatedParams.length, // number of strings\n 0, // data size (0 - not using raw data)\n nullTerminatedParams, // strings array with our message\n null, // raw data (null - not using)\n );\n\n if (!success) {\n throw new Error(\"ReportEventA() returned false.\");\n }\n } catch (error) {\n throw error;\n }\n }\n\n /**\n * Clean up resources\n */\n dispose(): void {\n if (this.initialized && this.eventSource && this.DeregisterEventSource) {\n try {\n (this.DeregisterEventSource as unknown as (\n ...args: unknown[]\n ) => unknown)(this.eventSource);\n } catch (error) {\n this.metaLogger.error(\n \"Failed to deregister event source during cleanup: {error}\",\n { error },\n );\n }\n this.eventSource = null;\n this.initialized = false;\n }\n }\n}\n"],"mappings":";;;;;;;AAQA,IAAa,yBAAb,MAAkE;CAChE,AAAQ,cAAuB;CAC/B,AAAQ,aAAqB;CAC7B,AAAQ,cAAc;CACtB,AAAQ,MAAe;CACvB,AAAQ,aAAa,UAAU;EAAC;EAAW;EAAQ;CAAmB,EAAC;;;;CAKvE,WAAWA,YAA0B;AACnC,OAAK,aAAa;AAClB,MAAI,KAAK,YAAa;AAEtB,MAAI;AAEF,QAAK,MAAM,MAAM,KAAK,eAAe;GAGrC,MAAM,uBACJ,AAAC,KAAK,IAAsD,KAC1D,oFACD;GAGH,MAAM,eACJ,AAAC,KAAK,IAAsD,KAC1D,iMACD;GACH,MAAM,wBACJ,AAAC,KAAK,IAAsD,KAC1D,0DACD;AAGH,QAAK,uBAAuB;AAC5B,QAAK,eAAe;AACpB,QAAK,wBAAwB;AAG7B,QAAK,cAAc,AAAC,KAAK,qBAEX,GAAG,KAAK,WAAW;AAEjC,QAAK,KAAK,eAAe,KAAK,gBAAgB,EAC5C,OAAM,IAAI,OACP,mCAAmC,KAAK,WAAW;AAIxD,QAAK,cAAc;EACpB,SAAQ,OAAO;AACd,SAAM,IAAI,OACP,8CAA8C,MAAM;EAExD;CACF;CAED,AAAQ,uBAAgC;CACxC,AAAQ,eAAwB;CAChC,AAAQ,wBAAiC;;;;CAKzC,WAAWC,WAAsBC,SAAiBC,QAAwB;AACxE,OAAK,KAAK,gBAAgB,KAAK,gBAAgB,KAAK,aAClD;AAGF,MAAI;GAGF,MAAM,uBAAuB,OAAO,IAAI,CAAC,MAAM,IAAI,KAAK;GAGxD,MAAM,UACJ,AAAC,KAAK,aACJ,KAAK,aACL,WACA,GACA,SACA,GACA,qBAAqB,QACrB,GACA,sBACA,KACD;AAEH,QAAK,QACH,OAAM,IAAI,MAAM;EAEnB,SAAQ,OAAO;AACd,SAAM;EACP;CACF;;;;CAKD,UAAgB;AACd,MAAI,KAAK,eAAe,KAAK,eAAe,KAAK,uBAAuB;AACtE,OAAI;AACF,IAAC,KAAK,sBAEQ,KAAK,YAAY;GAChC,SAAQ,OAAO;AACd,SAAK,WAAW,MACd,6DACA,EAAE,MAAO,EACV;GACF;AACD,QAAK,cAAc;AACnB,QAAK,cAAc;EACpB;CACF;AACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/formatter.ts
|
|
3
|
+
/**
|
|
4
|
+
* Formats a log record message into a string suitable for Windows Event Log.
|
|
5
|
+
* Combines the template and arguments into a readable message.
|
|
6
|
+
*/
|
|
7
|
+
function formatMessage(record) {
|
|
8
|
+
let message = "";
|
|
9
|
+
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
10
|
+
else {
|
|
11
|
+
const arg = record.message[i];
|
|
12
|
+
if (typeof arg === "string") message += arg;
|
|
13
|
+
else message += JSON.stringify(arg);
|
|
14
|
+
}
|
|
15
|
+
return message;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Formats additional context information for the log entry.
|
|
19
|
+
* Includes category, properties, and other metadata.
|
|
20
|
+
*/
|
|
21
|
+
function formatContext(record) {
|
|
22
|
+
const context = [];
|
|
23
|
+
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
|
|
24
|
+
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
|
|
25
|
+
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
|
|
26
|
+
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Default way of rendering a record into text that goes in the event log.
|
|
30
|
+
*/
|
|
31
|
+
function defaultWindowsEventlogFormatter(record) {
|
|
32
|
+
const msg = formatMessage(record);
|
|
33
|
+
const ctx = formatContext(record);
|
|
34
|
+
return msg + ctx;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
//#endregion
|
|
38
|
+
exports.defaultWindowsEventlogFormatter = defaultWindowsEventlogFormatter;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//#region src/formatter.ts
|
|
2
|
+
/**
|
|
3
|
+
* Formats a log record message into a string suitable for Windows Event Log.
|
|
4
|
+
* Combines the template and arguments into a readable message.
|
|
5
|
+
*/
|
|
6
|
+
function formatMessage(record) {
|
|
7
|
+
let message = "";
|
|
8
|
+
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
9
|
+
else {
|
|
10
|
+
const arg = record.message[i];
|
|
11
|
+
if (typeof arg === "string") message += arg;
|
|
12
|
+
else message += JSON.stringify(arg);
|
|
13
|
+
}
|
|
14
|
+
return message;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Formats additional context information for the log entry.
|
|
18
|
+
* Includes category, properties, and other metadata.
|
|
19
|
+
*/
|
|
20
|
+
function formatContext(record) {
|
|
21
|
+
const context = [];
|
|
22
|
+
if (record.category && record.category.length > 0) context.push(`Category: ${record.category.join(".")}`);
|
|
23
|
+
if (record.properties && Object.keys(record.properties).length > 0) context.push(`Properties: ${JSON.stringify(record.properties)}`);
|
|
24
|
+
context.push(`Timestamp: ${new Date(record.timestamp).toISOString()}`);
|
|
25
|
+
return context.length > 0 ? `\n\n${context.join("\n")}` : "";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Default way of rendering a record into text that goes in the event log.
|
|
29
|
+
*/
|
|
30
|
+
function defaultWindowsEventlogFormatter(record) {
|
|
31
|
+
const msg = formatMessage(record);
|
|
32
|
+
const ctx = formatContext(record);
|
|
33
|
+
return msg + ctx;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { defaultWindowsEventlogFormatter };
|
|
38
|
+
//# sourceMappingURL=formatter.js.map
|