winevt_c 0.9.1 → 0.10.0
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.
- checksums.yaml +4 -4
- data/.clang-format +4 -4
- data/.github/workflows/linux.yml +26 -0
- data/Gemfile +6 -6
- data/LICENSE.txt +202 -202
- data/README.md +97 -97
- data/Rakefile +37 -37
- data/appveyor.yml +48 -26
- data/example/bookmark.rb +9 -9
- data/example/enumerate_channels.rb +13 -13
- data/example/eventlog.rb +13 -13
- data/example/locale.rb +13 -13
- data/example/rate_limit.rb +14 -14
- data/example/tailing.rb +21 -21
- data/ext/winevt/extconf.rb +24 -24
- data/ext/winevt/winevt.c +30 -30
- data/ext/winevt/winevt_bookmark.c +149 -149
- data/ext/winevt/winevt_c.h +133 -132
- data/ext/winevt/winevt_channel.c +327 -327
- data/ext/winevt/winevt_locale.c +92 -92
- data/ext/winevt/winevt_locale_info.c +68 -68
- data/ext/winevt/winevt_query.c +649 -650
- data/ext/winevt/winevt_session.c +425 -425
- data/ext/winevt/winevt_subscribe.c +756 -757
- data/ext/winevt/winevt_utils.cpp +790 -718
- data/lib/winevt/bookmark.rb +6 -6
- data/lib/winevt/query.rb +6 -6
- data/lib/winevt/session.rb +15 -15
- data/lib/winevt/subscribe.rb +18 -18
- data/lib/winevt/version.rb +3 -3
- data/lib/winevt.rb +14 -14
- data/winevt_c.gemspec +34 -34
- metadata +8 -9
- data/.travis.yml +0 -15
data/ext/winevt/winevt_utils.cpp
CHANGED
@@ -1,718 +1,790 @@
|
|
1
|
-
#include <winevt_c.h>
|
2
|
-
|
3
|
-
#include <sddl.h>
|
4
|
-
#include <stdlib.h>
|
5
|
-
#include <string>
|
6
|
-
#include <vector>
|
7
|
-
|
8
|
-
VALUE
|
9
|
-
wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen)
|
10
|
-
{
|
11
|
-
VALUE vstr;
|
12
|
-
CHAR* ptr;
|
13
|
-
int
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
{
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
case
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
rb_ary_push(userValues, rb_utf8_str_new_cstr(
|
249
|
-
}
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
rb_ary_push(userValues, rb_utf8_str_new_cstr(
|
276
|
-
} else {
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
}
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
cleanup
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
status
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
rb_hash_aset(hash,
|
699
|
-
rb_str_new2("
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
718
|
-
|
1
|
+
#include <winevt_c.h>
|
2
|
+
|
3
|
+
#include <sddl.h>
|
4
|
+
#include <stdlib.h>
|
5
|
+
#include <string>
|
6
|
+
#include <vector>
|
7
|
+
|
8
|
+
VALUE
|
9
|
+
wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen)
|
10
|
+
{
|
11
|
+
VALUE vstr;
|
12
|
+
CHAR* ptr;
|
13
|
+
int ret = -1;
|
14
|
+
DWORD err = ERROR_SUCCESS;
|
15
|
+
if (wstr == NULL) {
|
16
|
+
return rb_utf8_str_new_cstr("");
|
17
|
+
}
|
18
|
+
|
19
|
+
int len = WideCharToMultiByte(cp, 0, wstr, clen, nullptr, 0, nullptr, nullptr);
|
20
|
+
ptr = ALLOCV_N(CHAR, vstr, len);
|
21
|
+
// For memory safety.
|
22
|
+
ZeroMemory(ptr, sizeof(CHAR) * len);
|
23
|
+
ret = WideCharToMultiByte(cp, 0, wstr, clen, ptr, len, nullptr, nullptr);
|
24
|
+
// return 0 should be failure.
|
25
|
+
// ref: https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte#return-value
|
26
|
+
if (ret == 0) {
|
27
|
+
err = GetLastError();
|
28
|
+
ALLOCV_END(vstr);
|
29
|
+
raise_system_error(rb_eRuntimeError, err);
|
30
|
+
}
|
31
|
+
VALUE str = rb_utf8_str_new_cstr(ptr);
|
32
|
+
ALLOCV_END(vstr);
|
33
|
+
|
34
|
+
return str;
|
35
|
+
}
|
36
|
+
|
37
|
+
void
|
38
|
+
raise_system_error(VALUE error, DWORD errorCode)
|
39
|
+
{
|
40
|
+
WCHAR msgBuf[256] = { 0 };
|
41
|
+
VALUE errorMessage;
|
42
|
+
|
43
|
+
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
44
|
+
NULL,
|
45
|
+
errorCode,
|
46
|
+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
47
|
+
msgBuf,
|
48
|
+
_countof(msgBuf),
|
49
|
+
NULL);
|
50
|
+
errorMessage = wstr_to_rb_str(CP_UTF8, msgBuf, -1);
|
51
|
+
|
52
|
+
#pragma GCC diagnostic push
|
53
|
+
#pragma GCC diagnostic ignored "-Wformat="
|
54
|
+
#pragma GCC diagnostic ignored "-Wformat-extra-args"
|
55
|
+
rb_raise(error, "ErrorCode: %lu\nError: %" PRIsVALUE "\n", errorCode, errorMessage);
|
56
|
+
#pragma GCC diagnostic pop
|
57
|
+
}
|
58
|
+
|
59
|
+
VALUE
|
60
|
+
render_to_rb_str(EVT_HANDLE handle, DWORD flags)
|
61
|
+
{
|
62
|
+
VALUE vbuffer;
|
63
|
+
WCHAR* buffer;
|
64
|
+
ULONG bufferSize = 0;
|
65
|
+
ULONG bufferSizeUsed = 0;
|
66
|
+
ULONG count;
|
67
|
+
BOOL succeeded;
|
68
|
+
VALUE result;
|
69
|
+
|
70
|
+
if (flags != EvtRenderEventXml && flags != EvtRenderBookmark) {
|
71
|
+
return Qnil;
|
72
|
+
}
|
73
|
+
|
74
|
+
// Get the size of the buffer
|
75
|
+
EvtRender(nullptr, handle, flags, 0, NULL, &bufferSize, &count);
|
76
|
+
|
77
|
+
// bufferSize is in bytes, not characters
|
78
|
+
buffer = (WCHAR*)ALLOCV(vbuffer, bufferSize);
|
79
|
+
|
80
|
+
succeeded =
|
81
|
+
EvtRender(nullptr, handle, flags, bufferSize, buffer, &bufferSizeUsed, &count);
|
82
|
+
if (!succeeded) {
|
83
|
+
DWORD status = GetLastError();
|
84
|
+
ALLOCV_END(vbuffer);
|
85
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
86
|
+
}
|
87
|
+
|
88
|
+
result = wstr_to_rb_str(CP_UTF8, buffer, -1);
|
89
|
+
ALLOCV_END(vbuffer);
|
90
|
+
|
91
|
+
return result;
|
92
|
+
}
|
93
|
+
|
94
|
+
EVT_HANDLE
|
95
|
+
connect_to_remote(LPWSTR computerName, LPWSTR domain, LPWSTR username, LPWSTR password,
|
96
|
+
EVT_RPC_LOGIN_FLAGS flags, DWORD *error_code)
|
97
|
+
{
|
98
|
+
EVT_HANDLE hRemote = NULL;
|
99
|
+
EVT_RPC_LOGIN Credentials;
|
100
|
+
|
101
|
+
RtlZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
|
102
|
+
|
103
|
+
Credentials.Server = computerName;
|
104
|
+
Credentials.Domain = domain;
|
105
|
+
Credentials.User = username;
|
106
|
+
Credentials.Password = password;
|
107
|
+
Credentials.Flags = flags;
|
108
|
+
|
109
|
+
hRemote = EvtOpenSession(EvtRpcLogin, &Credentials, 0, 0);
|
110
|
+
if (!hRemote) {
|
111
|
+
*error_code = GetLastError();
|
112
|
+
return hRemote;
|
113
|
+
}
|
114
|
+
|
115
|
+
SecureZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
|
116
|
+
|
117
|
+
return hRemote;
|
118
|
+
}
|
119
|
+
|
120
|
+
static std::wstring
|
121
|
+
guid_to_wstr(const GUID& guid)
|
122
|
+
{
|
123
|
+
LPOLESTR p = nullptr;
|
124
|
+
if (FAILED(StringFromCLSID(guid, &p))) {
|
125
|
+
return nullptr;
|
126
|
+
}
|
127
|
+
std::wstring s(p);
|
128
|
+
CoTaskMemFree(p);
|
129
|
+
return s;
|
130
|
+
}
|
131
|
+
|
132
|
+
static VALUE
|
133
|
+
make_displayable_binary_string(PBYTE bin, size_t length)
|
134
|
+
{
|
135
|
+
const char *HEX_TABLE = "0123456789ABCDEF";
|
136
|
+
CHAR *buffer;
|
137
|
+
int size = length * 2 + 1;
|
138
|
+
size_t i, j;
|
139
|
+
unsigned int idx = 0;
|
140
|
+
VALUE vbuffer;
|
141
|
+
|
142
|
+
if (length == 0) {
|
143
|
+
return rb_str_new2("(NULL)");
|
144
|
+
}
|
145
|
+
|
146
|
+
buffer = ALLOCV_N(CHAR, vbuffer, size);
|
147
|
+
|
148
|
+
for (i = 0; i < length; i++) {
|
149
|
+
for (j = 0; j < 2; j++) {
|
150
|
+
idx = (unsigned int)(bin[i] >> (j * 4) & 0x0F);
|
151
|
+
buffer[2*i+(1-j)] = HEX_TABLE[idx];
|
152
|
+
}
|
153
|
+
}
|
154
|
+
buffer[size - 1] = '\0';
|
155
|
+
|
156
|
+
VALUE str = rb_str_new2(buffer);
|
157
|
+
ALLOCV_END(vbuffer);
|
158
|
+
|
159
|
+
return str;
|
160
|
+
}
|
161
|
+
|
162
|
+
static VALUE
|
163
|
+
extract_user_evt_variants(PEVT_VARIANT pRenderedValues, DWORD propCount)
|
164
|
+
{
|
165
|
+
VALUE userValues = rb_ary_new();
|
166
|
+
VALUE rbObj;
|
167
|
+
|
168
|
+
for (DWORD i = 0; i < propCount; i++) {
|
169
|
+
switch (pRenderedValues[i].Type) {
|
170
|
+
case EvtVarTypeNull:
|
171
|
+
rb_ary_push(userValues, Qnil);
|
172
|
+
break;
|
173
|
+
case EvtVarTypeString:
|
174
|
+
if (pRenderedValues[i].StringVal == nullptr) {
|
175
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
|
176
|
+
} else {
|
177
|
+
std::wstring wStr(pRenderedValues[i].StringVal);
|
178
|
+
rbObj = wstr_to_rb_str(CP_UTF8, &wStr[0], -1);
|
179
|
+
rb_ary_push(userValues, rbObj);
|
180
|
+
}
|
181
|
+
break;
|
182
|
+
case EvtVarTypeAnsiString:
|
183
|
+
if (pRenderedValues[i].AnsiStringVal == nullptr) {
|
184
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
|
185
|
+
} else {
|
186
|
+
rb_ary_push(
|
187
|
+
userValues,
|
188
|
+
rb_utf8_str_new_cstr(const_cast<char*>(pRenderedValues[i].AnsiStringVal)));
|
189
|
+
}
|
190
|
+
break;
|
191
|
+
case EvtVarTypeSByte:
|
192
|
+
rbObj = INT2NUM(static_cast<UINT32>(pRenderedValues[i].SByteVal));
|
193
|
+
rb_ary_push(userValues, rbObj);
|
194
|
+
break;
|
195
|
+
case EvtVarTypeByte:
|
196
|
+
rbObj = INT2NUM(static_cast<UINT32>(pRenderedValues[i].ByteVal));
|
197
|
+
rb_ary_push(userValues, rbObj);
|
198
|
+
break;
|
199
|
+
case EvtVarTypeInt16:
|
200
|
+
rbObj = INT2NUM(static_cast<INT32>(pRenderedValues[i].Int16Val));
|
201
|
+
rb_ary_push(userValues, rbObj);
|
202
|
+
break;
|
203
|
+
case EvtVarTypeUInt16:
|
204
|
+
rbObj = UINT2NUM(static_cast<UINT32>(pRenderedValues[i].UInt16Val));
|
205
|
+
rb_ary_push(userValues, rbObj);
|
206
|
+
break;
|
207
|
+
case EvtVarTypeInt32:
|
208
|
+
rbObj = INT2NUM(pRenderedValues[i].Int32Val);
|
209
|
+
rb_ary_push(userValues, rbObj);
|
210
|
+
break;
|
211
|
+
case EvtVarTypeUInt32:
|
212
|
+
rbObj = UINT2NUM(pRenderedValues[i].UInt32Val);
|
213
|
+
rb_ary_push(userValues, rbObj);
|
214
|
+
break;
|
215
|
+
case EvtVarTypeInt64:
|
216
|
+
rbObj = LONG2NUM(pRenderedValues[i].Int64Val);
|
217
|
+
rb_ary_push(userValues, rbObj);
|
218
|
+
break;
|
219
|
+
case EvtVarTypeUInt64:
|
220
|
+
rbObj = ULONG2NUM(pRenderedValues[i].UInt64Val);
|
221
|
+
rb_ary_push(userValues, rbObj);
|
222
|
+
break;
|
223
|
+
case EvtVarTypeSingle: {
|
224
|
+
CHAR sResult[256];
|
225
|
+
_snprintf_s(
|
226
|
+
sResult, _countof(sResult), _TRUNCATE, "%f", pRenderedValues[i].SingleVal);
|
227
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr(sResult));
|
228
|
+
break;
|
229
|
+
}
|
230
|
+
case EvtVarTypeDouble: {
|
231
|
+
CHAR sResult[256];
|
232
|
+
_snprintf_s(
|
233
|
+
sResult, _countof(sResult), _TRUNCATE, "%lf", pRenderedValues[i].DoubleVal);
|
234
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr(sResult));
|
235
|
+
break;
|
236
|
+
}
|
237
|
+
case EvtVarTypeBoolean:
|
238
|
+
rbObj = pRenderedValues[i].BooleanVal ? Qtrue : Qfalse;
|
239
|
+
rb_ary_push(userValues, rbObj);
|
240
|
+
break;
|
241
|
+
case EvtVarTypeGuid:
|
242
|
+
if (pRenderedValues[i].GuidVal != nullptr) {
|
243
|
+
const GUID guid = *pRenderedValues[i].GuidVal;
|
244
|
+
std::wstring wstr = guid_to_wstr(guid);
|
245
|
+
rbObj = wstr_to_rb_str(CP_UTF8, wstr.c_str(), -1);
|
246
|
+
rb_ary_push(userValues, rbObj);
|
247
|
+
} else {
|
248
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
|
249
|
+
}
|
250
|
+
break;
|
251
|
+
case EvtVarTypeSizeT:
|
252
|
+
rbObj = SIZET2NUM(pRenderedValues[i].SizeTVal);
|
253
|
+
rb_ary_push(userValues, rbObj);
|
254
|
+
break;
|
255
|
+
case EvtVarTypeFileTime: {
|
256
|
+
LARGE_INTEGER timestamp;
|
257
|
+
CHAR strTime[128];
|
258
|
+
FILETIME ft;
|
259
|
+
SYSTEMTIME st;
|
260
|
+
timestamp.QuadPart = pRenderedValues[i].FileTimeVal;
|
261
|
+
ft.dwHighDateTime = timestamp.HighPart;
|
262
|
+
ft.dwLowDateTime = timestamp.LowPart;
|
263
|
+
if (FileTimeToSystemTime(&ft, &st)) {
|
264
|
+
_snprintf_s(strTime,
|
265
|
+
_countof(strTime),
|
266
|
+
_TRUNCATE,
|
267
|
+
"%04d-%02d-%02d %02d:%02d:%02d.%dZ",
|
268
|
+
st.wYear,
|
269
|
+
st.wMonth,
|
270
|
+
st.wDay,
|
271
|
+
st.wHour,
|
272
|
+
st.wMinute,
|
273
|
+
st.wSecond,
|
274
|
+
st.wMilliseconds);
|
275
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr(strTime));
|
276
|
+
} else {
|
277
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
|
278
|
+
}
|
279
|
+
break;
|
280
|
+
}
|
281
|
+
case EvtVarTypeSysTime: {
|
282
|
+
CHAR strTime[128];
|
283
|
+
SYSTEMTIME st;
|
284
|
+
if (pRenderedValues[i].SysTimeVal != nullptr) {
|
285
|
+
st = *pRenderedValues[i].SysTimeVal;
|
286
|
+
_snprintf_s(strTime,
|
287
|
+
_countof(strTime),
|
288
|
+
_TRUNCATE,
|
289
|
+
"%04d-%02d-%02d %02d:%02d:%02d.%dZ",
|
290
|
+
st.wYear,
|
291
|
+
st.wMonth,
|
292
|
+
st.wDay,
|
293
|
+
st.wHour,
|
294
|
+
st.wMinute,
|
295
|
+
st.wSecond,
|
296
|
+
st.wMilliseconds);
|
297
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr(strTime));
|
298
|
+
} else {
|
299
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
|
300
|
+
}
|
301
|
+
break;
|
302
|
+
}
|
303
|
+
case EvtVarTypeSid: {
|
304
|
+
WCHAR* tmpWChar = nullptr;
|
305
|
+
if (ConvertSidToStringSidW(pRenderedValues[i].SidVal, &tmpWChar)) {
|
306
|
+
rbObj = wstr_to_rb_str(CP_UTF8, tmpWChar, -1);
|
307
|
+
rb_ary_push(userValues, rbObj);
|
308
|
+
LocalFree(tmpWChar);
|
309
|
+
} else {
|
310
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
|
311
|
+
}
|
312
|
+
break;
|
313
|
+
}
|
314
|
+
case EvtVarTypeHexInt32:
|
315
|
+
rbObj = rb_sprintf("%#x", pRenderedValues[i].UInt32Val);
|
316
|
+
rb_ary_push(userValues, rbObj);
|
317
|
+
break;
|
318
|
+
case EvtVarTypeHexInt64:
|
319
|
+
uint32_t high;
|
320
|
+
uint32_t low;
|
321
|
+
|
322
|
+
high = pRenderedValues[i].UInt64Val >> 32;
|
323
|
+
low = pRenderedValues[i].UInt64Val & 0x00000000FFFFFFFF;
|
324
|
+
rbObj = rb_sprintf("0x%08x%08x", high, low);
|
325
|
+
rb_ary_push(userValues, rbObj);
|
326
|
+
break;
|
327
|
+
case EvtVarTypeEvtXml:
|
328
|
+
if (pRenderedValues[i].XmlVal == nullptr) {
|
329
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
|
330
|
+
} else {
|
331
|
+
rbObj = wstr_to_rb_str(CP_UTF8, pRenderedValues[i].XmlVal, -1);
|
332
|
+
rb_ary_push(userValues, rbObj);
|
333
|
+
}
|
334
|
+
break;
|
335
|
+
case EvtVarTypeBinary:
|
336
|
+
if (pRenderedValues[i].BinaryVal == nullptr) {
|
337
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
|
338
|
+
} else {
|
339
|
+
rbObj = make_displayable_binary_string(pRenderedValues[i].BinaryVal, pRenderedValues[i].Count);
|
340
|
+
rb_ary_push(userValues, rbObj);
|
341
|
+
}
|
342
|
+
break;
|
343
|
+
default:
|
344
|
+
rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
|
345
|
+
break;
|
346
|
+
}
|
347
|
+
}
|
348
|
+
|
349
|
+
return userValues;
|
350
|
+
}
|
351
|
+
|
352
|
+
VALUE
|
353
|
+
get_values(EVT_HANDLE handle)
|
354
|
+
{
|
355
|
+
VALUE vbuffer;
|
356
|
+
PEVT_VARIANT pRenderedValues;
|
357
|
+
ULONG bufferSize = 0;
|
358
|
+
ULONG bufferSizeUsed = 0;
|
359
|
+
DWORD propCount = 0;
|
360
|
+
BOOL succeeded;
|
361
|
+
VALUE userValues = Qnil;
|
362
|
+
|
363
|
+
EVT_HANDLE renderContext = EvtCreateRenderContext(0, nullptr, EvtRenderContextUser);
|
364
|
+
if (renderContext == nullptr) {
|
365
|
+
rb_raise(rb_eWinevtQueryError, "Failed to create renderContext");
|
366
|
+
}
|
367
|
+
|
368
|
+
// Get the size of the buffer
|
369
|
+
EvtRender(
|
370
|
+
renderContext, handle, EvtRenderEventValues, 0, NULL, &bufferSize, &propCount);
|
371
|
+
|
372
|
+
// bufferSize is in bytes, not array size
|
373
|
+
pRenderedValues = (PEVT_VARIANT)ALLOCV(vbuffer, bufferSize);
|
374
|
+
|
375
|
+
succeeded = EvtRender(renderContext,
|
376
|
+
handle,
|
377
|
+
EvtRenderEventValues,
|
378
|
+
bufferSize,
|
379
|
+
pRenderedValues,
|
380
|
+
&bufferSizeUsed,
|
381
|
+
&propCount);
|
382
|
+
if (!succeeded) {
|
383
|
+
DWORD status = GetLastError();
|
384
|
+
ALLOCV_END(vbuffer);
|
385
|
+
EvtClose(renderContext);
|
386
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
387
|
+
}
|
388
|
+
|
389
|
+
userValues = extract_user_evt_variants(pRenderedValues, propCount);
|
390
|
+
|
391
|
+
ALLOCV_END(vbuffer);
|
392
|
+
EvtClose(renderContext);
|
393
|
+
|
394
|
+
return userValues;
|
395
|
+
}
|
396
|
+
|
397
|
+
static std::vector<WCHAR>
|
398
|
+
get_message(EVT_HANDLE hMetadata, EVT_HANDLE handle)
|
399
|
+
{
|
400
|
+
#define BUFSIZE 4096
|
401
|
+
std::vector<WCHAR> result;
|
402
|
+
ULONG status;
|
403
|
+
ULONG bufferSizeNeeded = 0;
|
404
|
+
LPVOID lpMsgBuf;
|
405
|
+
std::vector<WCHAR> message(BUFSIZE);
|
406
|
+
|
407
|
+
if (!EvtFormatMessage(hMetadata,
|
408
|
+
handle,
|
409
|
+
0xffffffff,
|
410
|
+
0,
|
411
|
+
nullptr,
|
412
|
+
EvtFormatMessageEvent,
|
413
|
+
message.size(),
|
414
|
+
&message[0],
|
415
|
+
&bufferSizeNeeded)) {
|
416
|
+
status = GetLastError();
|
417
|
+
|
418
|
+
if (status != ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
|
419
|
+
switch (status) {
|
420
|
+
case ERROR_EVT_MESSAGE_NOT_FOUND:
|
421
|
+
case ERROR_EVT_MESSAGE_ID_NOT_FOUND:
|
422
|
+
case ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
|
423
|
+
case ERROR_RESOURCE_DATA_NOT_FOUND:
|
424
|
+
case ERROR_RESOURCE_TYPE_NOT_FOUND:
|
425
|
+
case ERROR_RESOURCE_NAME_NOT_FOUND:
|
426
|
+
case ERROR_RESOURCE_LANG_NOT_FOUND:
|
427
|
+
case ERROR_MUI_FILE_NOT_FOUND:
|
428
|
+
case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: {
|
429
|
+
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
430
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
431
|
+
nullptr,
|
432
|
+
status,
|
433
|
+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
434
|
+
reinterpret_cast<WCHAR*>(&lpMsgBuf),
|
435
|
+
0,
|
436
|
+
nullptr) == 0)
|
437
|
+
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
|
438
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
439
|
+
nullptr,
|
440
|
+
status,
|
441
|
+
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
442
|
+
reinterpret_cast<WCHAR*>(&lpMsgBuf),
|
443
|
+
0,
|
444
|
+
nullptr);
|
445
|
+
|
446
|
+
std::wstring ret(reinterpret_cast<WCHAR*>(lpMsgBuf));
|
447
|
+
std::copy(ret.begin(), ret.end(), std::back_inserter(result));
|
448
|
+
LocalFree(lpMsgBuf);
|
449
|
+
|
450
|
+
goto cleanup;
|
451
|
+
}
|
452
|
+
}
|
453
|
+
|
454
|
+
if (status != ERROR_INSUFFICIENT_BUFFER)
|
455
|
+
rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu", status);
|
456
|
+
}
|
457
|
+
|
458
|
+
if (status == ERROR_INSUFFICIENT_BUFFER) {
|
459
|
+
message.resize(bufferSizeNeeded);
|
460
|
+
message.shrink_to_fit();
|
461
|
+
|
462
|
+
if (!EvtFormatMessage(hMetadata,
|
463
|
+
handle,
|
464
|
+
0xffffffff,
|
465
|
+
0,
|
466
|
+
nullptr,
|
467
|
+
EvtFormatMessageEvent,
|
468
|
+
message.size(),
|
469
|
+
&message.front(),
|
470
|
+
&bufferSizeNeeded)) {
|
471
|
+
status = GetLastError();
|
472
|
+
|
473
|
+
if (status != ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
|
474
|
+
switch (status) {
|
475
|
+
case ERROR_EVT_MESSAGE_NOT_FOUND:
|
476
|
+
case ERROR_EVT_MESSAGE_ID_NOT_FOUND:
|
477
|
+
case ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
|
478
|
+
case ERROR_RESOURCE_DATA_NOT_FOUND:
|
479
|
+
case ERROR_RESOURCE_TYPE_NOT_FOUND:
|
480
|
+
case ERROR_RESOURCE_NAME_NOT_FOUND:
|
481
|
+
case ERROR_RESOURCE_LANG_NOT_FOUND:
|
482
|
+
case ERROR_MUI_FILE_NOT_FOUND:
|
483
|
+
case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT:
|
484
|
+
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
485
|
+
FORMAT_MESSAGE_FROM_SYSTEM |
|
486
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
487
|
+
nullptr,
|
488
|
+
status,
|
489
|
+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
490
|
+
reinterpret_cast<WCHAR*>(&lpMsgBuf),
|
491
|
+
0,
|
492
|
+
nullptr) == 0)
|
493
|
+
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
494
|
+
FORMAT_MESSAGE_FROM_SYSTEM |
|
495
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
496
|
+
nullptr,
|
497
|
+
status,
|
498
|
+
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
|
499
|
+
reinterpret_cast<WCHAR*>(&lpMsgBuf),
|
500
|
+
0,
|
501
|
+
nullptr);
|
502
|
+
|
503
|
+
std::wstring ret(reinterpret_cast<WCHAR*>(lpMsgBuf));
|
504
|
+
std::copy(ret.begin(), ret.end(), std::back_inserter(result));
|
505
|
+
LocalFree(lpMsgBuf);
|
506
|
+
|
507
|
+
goto cleanup;
|
508
|
+
}
|
509
|
+
|
510
|
+
rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu", status);
|
511
|
+
}
|
512
|
+
}
|
513
|
+
}
|
514
|
+
}
|
515
|
+
|
516
|
+
result = message;
|
517
|
+
|
518
|
+
cleanup:
|
519
|
+
|
520
|
+
return result;
|
521
|
+
|
522
|
+
#undef BUFSIZE
|
523
|
+
}
|
524
|
+
|
525
|
+
WCHAR*
|
526
|
+
get_description(EVT_HANDLE handle, LANGID langID, EVT_HANDLE hRemote)
|
527
|
+
{
|
528
|
+
#define BUFSIZE 4096
|
529
|
+
std::vector<WCHAR> buffer(BUFSIZE);
|
530
|
+
ULONG bufferSizeNeeded = 0;
|
531
|
+
ULONG status, count;
|
532
|
+
std::vector<WCHAR> result;
|
533
|
+
EVT_HANDLE hMetadata = nullptr;
|
534
|
+
|
535
|
+
static PCWSTR eventProperties[] = { L"Event/System/Provider/@Name" };
|
536
|
+
EVT_HANDLE renderContext =
|
537
|
+
EvtCreateRenderContext(1, eventProperties, EvtRenderContextValues);
|
538
|
+
if (renderContext == nullptr) {
|
539
|
+
rb_raise(rb_eWinevtQueryError, "Failed to create renderContext");
|
540
|
+
}
|
541
|
+
|
542
|
+
if (EvtRender(renderContext,
|
543
|
+
handle,
|
544
|
+
EvtRenderEventValues,
|
545
|
+
buffer.size(),
|
546
|
+
&buffer.front(),
|
547
|
+
&bufferSizeNeeded,
|
548
|
+
&count) != FALSE) {
|
549
|
+
status = ERROR_SUCCESS;
|
550
|
+
} else {
|
551
|
+
status = GetLastError();
|
552
|
+
}
|
553
|
+
|
554
|
+
if (status != ERROR_SUCCESS) {
|
555
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
556
|
+
}
|
557
|
+
|
558
|
+
// Obtain buffer as EVT_VARIANT pointer. To avoid ErrorCide 87 in EvtRender.
|
559
|
+
const PEVT_VARIANT values = reinterpret_cast<PEVT_VARIANT>(&buffer.front());
|
560
|
+
|
561
|
+
// Open publisher metadata
|
562
|
+
hMetadata = EvtOpenPublisherMetadata(
|
563
|
+
hRemote,
|
564
|
+
values[0].StringVal,
|
565
|
+
nullptr,
|
566
|
+
MAKELCID(langID, SORT_DEFAULT),
|
567
|
+
0);
|
568
|
+
if (hMetadata == nullptr) {
|
569
|
+
// When winevt_c cannot open metadata, then give up to obtain
|
570
|
+
// message file and clean up immediately.
|
571
|
+
goto cleanup;
|
572
|
+
}
|
573
|
+
|
574
|
+
result = get_message(hMetadata, handle);
|
575
|
+
|
576
|
+
#undef BUFSIZE
|
577
|
+
|
578
|
+
cleanup:
|
579
|
+
|
580
|
+
if (renderContext)
|
581
|
+
EvtClose(renderContext);
|
582
|
+
|
583
|
+
if (hMetadata)
|
584
|
+
EvtClose(hMetadata);
|
585
|
+
|
586
|
+
return _wcsdup(result.data());
|
587
|
+
}
|
588
|
+
|
589
|
+
VALUE
|
590
|
+
render_system_event(EVT_HANDLE hEvent, BOOL preserve_qualifiers)
|
591
|
+
{
|
592
|
+
DWORD status = ERROR_SUCCESS;
|
593
|
+
EVT_HANDLE hContext = NULL;
|
594
|
+
DWORD dwBufferSize = 0;
|
595
|
+
DWORD dwBufferUsed = 0;
|
596
|
+
DWORD dwPropertyCount = 0;
|
597
|
+
VALUE vRenderedValues;
|
598
|
+
PEVT_VARIANT pRenderedValues = NULL;
|
599
|
+
WCHAR wsGuid[50];
|
600
|
+
LPSTR pwsSid = NULL;
|
601
|
+
ULONGLONG ullTimeStamp = 0;
|
602
|
+
ULONGLONG ullNanoseconds = 0;
|
603
|
+
SYSTEMTIME st;
|
604
|
+
FILETIME ft;
|
605
|
+
CHAR buffer[32];
|
606
|
+
VALUE rbstr;
|
607
|
+
DWORD EventID;
|
608
|
+
VALUE hash = rb_hash_new();
|
609
|
+
|
610
|
+
hContext = EvtCreateRenderContext(0, NULL, EvtRenderContextSystem);
|
611
|
+
if (NULL == hContext) {
|
612
|
+
rb_raise(
|
613
|
+
rb_eWinevtQueryError, "Failed to create renderContext with %lu\n", GetLastError());
|
614
|
+
}
|
615
|
+
|
616
|
+
if (!EvtRender(hContext,
|
617
|
+
hEvent,
|
618
|
+
EvtRenderEventValues,
|
619
|
+
dwBufferSize,
|
620
|
+
pRenderedValues,
|
621
|
+
&dwBufferUsed,
|
622
|
+
&dwPropertyCount)) {
|
623
|
+
status = GetLastError();
|
624
|
+
if (ERROR_INSUFFICIENT_BUFFER == status) {
|
625
|
+
dwBufferSize = dwBufferUsed;
|
626
|
+
pRenderedValues = (PEVT_VARIANT)ALLOCV(vRenderedValues, dwBufferSize);
|
627
|
+
if (pRenderedValues) {
|
628
|
+
EvtRender(hContext,
|
629
|
+
hEvent,
|
630
|
+
EvtRenderEventValues,
|
631
|
+
dwBufferSize,
|
632
|
+
pRenderedValues,
|
633
|
+
&dwBufferUsed,
|
634
|
+
&dwPropertyCount);
|
635
|
+
status = GetLastError();
|
636
|
+
} else {
|
637
|
+
EvtClose(hContext);
|
638
|
+
rb_raise(rb_eRuntimeError, "Failed to malloc memory with %lu\n", status);
|
639
|
+
}
|
640
|
+
}
|
641
|
+
|
642
|
+
if (ERROR_SUCCESS != status) {
|
643
|
+
EvtClose(hContext);
|
644
|
+
ALLOCV_END(vRenderedValues);
|
645
|
+
|
646
|
+
rb_raise(rb_eWinevtQueryError, "EvtRender failed with %lu\n", status);
|
647
|
+
}
|
648
|
+
}
|
649
|
+
|
650
|
+
// EVT_VARIANT value with EvtRenderContextSystem will be decomposed
|
651
|
+
// as the following enum definition:
|
652
|
+
// https://docs.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_system_property_id
|
653
|
+
rbstr = wstr_to_rb_str(CP_UTF8, pRenderedValues[EvtSystemProviderName].StringVal, -1);
|
654
|
+
rb_hash_aset(hash, rb_str_new2("ProviderName"), rbstr);
|
655
|
+
if (NULL != pRenderedValues[EvtSystemProviderGuid].GuidVal) {
|
656
|
+
const GUID* Guid = pRenderedValues[EvtSystemProviderGuid].GuidVal;
|
657
|
+
StringFromGUID2(*Guid, wsGuid, _countof(wsGuid));
|
658
|
+
rbstr = wstr_to_rb_str(CP_UTF8, wsGuid, -1);
|
659
|
+
rb_hash_aset(hash, rb_str_new2("ProviderGuid"), rbstr);
|
660
|
+
} else {
|
661
|
+
rb_hash_aset(hash, rb_str_new2("ProviderGuid"), Qnil);
|
662
|
+
}
|
663
|
+
|
664
|
+
EventID = pRenderedValues[EvtSystemEventID].UInt16Val;
|
665
|
+
if (preserve_qualifiers) {
|
666
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemQualifiers].Type) {
|
667
|
+
rb_hash_aset(hash, rb_str_new2("Qualifiers"),
|
668
|
+
INT2NUM(pRenderedValues[EvtSystemQualifiers].UInt16Val));
|
669
|
+
} else {
|
670
|
+
rb_hash_aset(hash, rb_str_new2("Qualifiers"), rb_str_new2(""));
|
671
|
+
}
|
672
|
+
|
673
|
+
rb_hash_aset(hash, rb_str_new2("EventID"), INT2NUM(EventID));
|
674
|
+
} else {
|
675
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemQualifiers].Type) {
|
676
|
+
EventID = MAKELONG(pRenderedValues[EvtSystemEventID].UInt16Val,
|
677
|
+
pRenderedValues[EvtSystemQualifiers].UInt16Val);
|
678
|
+
}
|
679
|
+
|
680
|
+
rb_hash_aset(hash, rb_str_new2("EventID"), ULONG2NUM(EventID));
|
681
|
+
}
|
682
|
+
|
683
|
+
rb_hash_aset(hash,
|
684
|
+
rb_str_new2("Version"),
|
685
|
+
(EvtVarTypeNull == pRenderedValues[EvtSystemVersion].Type)
|
686
|
+
? INT2NUM(0)
|
687
|
+
: INT2NUM(pRenderedValues[EvtSystemVersion].ByteVal));
|
688
|
+
rb_hash_aset(hash,
|
689
|
+
rb_str_new2("Level"),
|
690
|
+
(EvtVarTypeNull == pRenderedValues[EvtSystemLevel].Type)
|
691
|
+
? INT2NUM(0)
|
692
|
+
: INT2NUM(pRenderedValues[EvtSystemLevel].ByteVal));
|
693
|
+
rb_hash_aset(hash,
|
694
|
+
rb_str_new2("Task"),
|
695
|
+
(EvtVarTypeNull == pRenderedValues[EvtSystemTask].Type)
|
696
|
+
? INT2NUM(0)
|
697
|
+
: INT2NUM(pRenderedValues[EvtSystemTask].UInt16Val));
|
698
|
+
rb_hash_aset(hash,
|
699
|
+
rb_str_new2("Opcode"),
|
700
|
+
(EvtVarTypeNull == pRenderedValues[EvtSystemOpcode].Type)
|
701
|
+
? INT2NUM(0)
|
702
|
+
: INT2NUM(pRenderedValues[EvtSystemOpcode].ByteVal));
|
703
|
+
_snprintf_s(buffer,
|
704
|
+
_countof(buffer),
|
705
|
+
_TRUNCATE,
|
706
|
+
"0x%llx",
|
707
|
+
pRenderedValues[EvtSystemKeywords].UInt64Val);
|
708
|
+
rb_hash_aset(hash,
|
709
|
+
rb_str_new2("Keywords"),
|
710
|
+
(EvtVarTypeNull == pRenderedValues[EvtSystemKeywords].Type)
|
711
|
+
? Qnil
|
712
|
+
: rb_str_new2(buffer));
|
713
|
+
|
714
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemTimeCreated].Type) {
|
715
|
+
ullTimeStamp = pRenderedValues[EvtSystemTimeCreated].FileTimeVal;
|
716
|
+
ft.dwHighDateTime = (DWORD)((ullTimeStamp >> 32) & 0xFFFFFFFF);
|
717
|
+
ft.dwLowDateTime = (DWORD)(ullTimeStamp & 0xFFFFFFFF);
|
718
|
+
|
719
|
+
FileTimeToSystemTime(&ft, &st);
|
720
|
+
ullNanoseconds =
|
721
|
+
(ullTimeStamp % 10000000) *
|
722
|
+
100; // Display nanoseconds instead of milliseconds for higher resolution
|
723
|
+
_snprintf_s(buffer,
|
724
|
+
_countof(buffer),
|
725
|
+
_TRUNCATE,
|
726
|
+
"%02d/%02d/%02d %02d:%02d:%02d.%llu",
|
727
|
+
st.wYear,
|
728
|
+
st.wMonth,
|
729
|
+
st.wDay,
|
730
|
+
st.wHour,
|
731
|
+
st.wMinute,
|
732
|
+
st.wSecond,
|
733
|
+
ullNanoseconds);
|
734
|
+
rb_hash_aset(hash,
|
735
|
+
rb_str_new2("TimeCreated"),
|
736
|
+
rb_str_new2(buffer));
|
737
|
+
} else {
|
738
|
+
rb_hash_aset(hash,
|
739
|
+
rb_str_new2("TimeCreated"),
|
740
|
+
Qnil);
|
741
|
+
}
|
742
|
+
_snprintf_s(buffer,
|
743
|
+
_countof(buffer),
|
744
|
+
_TRUNCATE,
|
745
|
+
"%llu",
|
746
|
+
pRenderedValues[EvtSystemEventRecordId].UInt64Val);
|
747
|
+
rb_hash_aset(hash,
|
748
|
+
rb_str_new2("EventRecordID"),
|
749
|
+
(EvtVarTypeNull == pRenderedValues[EvtSystemEventRecordId].UInt64Val)
|
750
|
+
? Qnil
|
751
|
+
: rb_str_new2(buffer));
|
752
|
+
|
753
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemActivityID].Type) {
|
754
|
+
const GUID* Guid = pRenderedValues[EvtSystemActivityID].GuidVal;
|
755
|
+
StringFromGUID2(*Guid, wsGuid, _countof(wsGuid));
|
756
|
+
rbstr = wstr_to_rb_str(CP_UTF8, wsGuid, -1);
|
757
|
+
rb_hash_aset(hash, rb_str_new2("ActivityID"), rbstr);
|
758
|
+
}
|
759
|
+
|
760
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemRelatedActivityID].Type) {
|
761
|
+
const GUID* Guid = pRenderedValues[EvtSystemRelatedActivityID].GuidVal;
|
762
|
+
StringFromGUID2(*Guid, wsGuid, _countof(wsGuid));
|
763
|
+
rbstr = wstr_to_rb_str(CP_UTF8, wsGuid, -1);
|
764
|
+
rb_hash_aset(hash, rb_str_new2("RelatedActivityID"), rbstr);
|
765
|
+
}
|
766
|
+
|
767
|
+
rb_hash_aset(hash,
|
768
|
+
rb_str_new2("ProcessID"),
|
769
|
+
UINT2NUM(pRenderedValues[EvtSystemProcessID].UInt32Val));
|
770
|
+
rb_hash_aset(hash,
|
771
|
+
rb_str_new2("ThreadID"),
|
772
|
+
UINT2NUM(pRenderedValues[EvtSystemThreadID].UInt32Val));
|
773
|
+
rbstr = wstr_to_rb_str(CP_UTF8, pRenderedValues[EvtSystemChannel].StringVal, -1);
|
774
|
+
rb_hash_aset(hash, rb_str_new2("Channel"), rbstr);
|
775
|
+
rbstr = wstr_to_rb_str(CP_UTF8, pRenderedValues[EvtSystemComputer].StringVal, -1);
|
776
|
+
rb_hash_aset(hash, rb_str_new2("Computer"), rbstr);
|
777
|
+
|
778
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemUserID].Type) {
|
779
|
+
if (ConvertSidToStringSid(pRenderedValues[EvtSystemUserID].SidVal, &pwsSid)) {
|
780
|
+
rbstr = rb_utf8_str_new_cstr(pwsSid);
|
781
|
+
rb_hash_aset(hash, rb_str_new2("UserID"), rbstr);
|
782
|
+
LocalFree(pwsSid);
|
783
|
+
}
|
784
|
+
}
|
785
|
+
|
786
|
+
EvtClose(hContext);
|
787
|
+
ALLOCV_END(vRenderedValues);
|
788
|
+
|
789
|
+
return hash;
|
790
|
+
}
|