winevt_c 0.7.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +55 -0
- data/Rakefile +1 -1
- data/example/eventlog.rb +7 -1
- data/example/locale.rb +13 -0
- data/example/rate_limit.rb +1 -1
- data/example/tailing.rb +10 -2
- data/ext/winevt/winevt.c +7 -0
- data/ext/winevt/winevt_bookmark.c +2 -0
- data/ext/winevt/winevt_c.h +46 -8
- data/ext/winevt/winevt_channel.c +2 -0
- data/ext/winevt/winevt_locale.c +92 -0
- data/ext/winevt/winevt_locale_info.c +68 -0
- data/ext/winevt/winevt_query.c +138 -9
- data/ext/winevt/winevt_session.c +425 -0
- data/ext/winevt/winevt_subscribe.c +136 -10
- data/ext/winevt/winevt_utils.cpp +42 -8
- data/lib/winevt.rb +1 -0
- data/lib/winevt/session.rb +15 -0
- data/lib/winevt/subscribe.rb +5 -2
- data/lib/winevt/version.rb +1 -1
- data/winevt_c.gemspec +1 -1
- metadata +9 -4
@@ -57,6 +57,9 @@ subscribe_free(void* ptr)
|
|
57
57
|
}
|
58
58
|
}
|
59
59
|
|
60
|
+
if (winevtSubscribe->remoteHandle)
|
61
|
+
EvtClose(winevtSubscribe->remoteHandle);
|
62
|
+
|
60
63
|
xfree(ptr);
|
61
64
|
}
|
62
65
|
|
@@ -89,6 +92,8 @@ rb_winevt_subscribe_initialize(VALUE self)
|
|
89
92
|
winevtSubscribe->currentRate = 0;
|
90
93
|
winevtSubscribe->renderAsXML = TRUE;
|
91
94
|
winevtSubscribe->readExistingEvents = TRUE;
|
95
|
+
winevtSubscribe->preserveQualifiers = FALSE;
|
96
|
+
winevtSubscribe->localeInfo = &default_locale;
|
92
97
|
|
93
98
|
return Qnil;
|
94
99
|
}
|
@@ -130,23 +135,27 @@ rb_winevt_subscribe_read_existing_events_p(VALUE self)
|
|
130
135
|
/*
|
131
136
|
* Subscribe into a Windows EventLog channel.
|
132
137
|
*
|
133
|
-
* @overload subscribe(path, query,
|
138
|
+
* @overload subscribe(path, query, bookmark=nil, session=nil)
|
134
139
|
* @param path [String] Subscribe Channel
|
135
140
|
* @param query [String] Query string for channel
|
136
|
-
* @
|
141
|
+
* @param bookmark [Bookmark] bookmark Bookmark class instance.
|
142
|
+
* @param session [Session] Session information for remoting access.
|
137
143
|
* @return [Boolean]
|
138
144
|
*
|
139
145
|
*/
|
140
146
|
static VALUE
|
141
147
|
rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
142
148
|
{
|
143
|
-
VALUE rb_path, rb_query, rb_bookmark;
|
149
|
+
VALUE rb_path, rb_query, rb_bookmark, rb_session;
|
144
150
|
EVT_HANDLE hSubscription = NULL, hBookmark = NULL;
|
145
151
|
HANDLE hSignalEvent;
|
152
|
+
EVT_HANDLE hRemoteHandle = NULL;
|
146
153
|
DWORD len, flags = 0L;
|
154
|
+
DWORD err = ERROR_SUCCESS;
|
147
155
|
VALUE wpathBuf, wqueryBuf, wBookmarkBuf;
|
148
156
|
PWSTR path, query, bookmarkXml;
|
149
157
|
DWORD status = ERROR_SUCCESS;
|
158
|
+
struct WinevtSession* winevtSession;
|
150
159
|
struct WinevtSubscribe* winevtSubscribe;
|
151
160
|
|
152
161
|
hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
@@ -154,7 +163,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
154
163
|
TypedData_Get_Struct(
|
155
164
|
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
156
165
|
|
157
|
-
rb_scan_args(argc, argv, "
|
166
|
+
rb_scan_args(argc, argv, "22", &rb_path, &rb_query, &rb_bookmark, &rb_session);
|
158
167
|
Check_Type(rb_path, T_STRING);
|
159
168
|
Check_Type(rb_query, T_STRING);
|
160
169
|
|
@@ -177,6 +186,19 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
177
186
|
raise_system_error(rb_eWinevtQueryError, status);
|
178
187
|
}
|
179
188
|
}
|
189
|
+
if (rb_obj_is_kind_of(rb_session, rb_cSession)) {
|
190
|
+
winevtSession = EventSession(rb_session);
|
191
|
+
hRemoteHandle = connect_to_remote(winevtSession->server,
|
192
|
+
winevtSession->domain,
|
193
|
+
winevtSession->username,
|
194
|
+
winevtSession->password,
|
195
|
+
winevtSession->flags);
|
196
|
+
|
197
|
+
err = GetLastError();
|
198
|
+
if (err != ERROR_SUCCESS) {
|
199
|
+
raise_system_error(rb_eRuntimeError, err);
|
200
|
+
}
|
201
|
+
}
|
180
202
|
|
181
203
|
// path : To wide char
|
182
204
|
len =
|
@@ -202,7 +224,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
202
224
|
}
|
203
225
|
|
204
226
|
hSubscription =
|
205
|
-
EvtSubscribe(
|
227
|
+
EvtSubscribe(hRemoteHandle, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
|
206
228
|
if (!hSubscription) {
|
207
229
|
if (hBookmark != NULL) {
|
208
230
|
EvtClose(hBookmark);
|
@@ -211,7 +233,11 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
211
233
|
CloseHandle(hSignalEvent);
|
212
234
|
}
|
213
235
|
status = GetLastError();
|
214
|
-
|
236
|
+
if (rb_obj_is_kind_of(rb_session, rb_cSession)) {
|
237
|
+
rb_raise(rb_eRemoteHandlerError, "Remoting subscription is not working. errCode: %ld\n", status);
|
238
|
+
} else {
|
239
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
240
|
+
}
|
215
241
|
}
|
216
242
|
|
217
243
|
if (winevtSubscribe->subscription != NULL) {
|
@@ -224,6 +250,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
224
250
|
|
225
251
|
winevtSubscribe->signalEvent = hSignalEvent;
|
226
252
|
winevtSubscribe->subscription = hSubscription;
|
253
|
+
winevtSubscribe->remoteHandle = hRemoteHandle;
|
227
254
|
if (hBookmark) {
|
228
255
|
winevtSubscribe->bookmark = hBookmark;
|
229
256
|
} else {
|
@@ -339,17 +366,17 @@ rb_winevt_subscribe_render(VALUE self, EVT_HANDLE event)
|
|
339
366
|
if (winevtSubscribe->renderAsXML) {
|
340
367
|
return render_to_rb_str(event, EvtRenderEventXml);
|
341
368
|
} else {
|
342
|
-
return render_system_event(event);
|
369
|
+
return render_system_event(event, winevtSubscribe->preserveQualifiers);
|
343
370
|
}
|
344
371
|
}
|
345
372
|
|
346
373
|
static VALUE
|
347
|
-
rb_winevt_subscribe_message(EVT_HANDLE event)
|
374
|
+
rb_winevt_subscribe_message(EVT_HANDLE event, LocaleInfo* localeInfo, EVT_HANDLE hRemote)
|
348
375
|
{
|
349
376
|
WCHAR* wResult;
|
350
377
|
VALUE utf8str;
|
351
378
|
|
352
|
-
wResult = get_description(event);
|
379
|
+
wResult = get_description(event, localeInfo->langID, hRemote);
|
353
380
|
utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
|
354
381
|
free(wResult);
|
355
382
|
|
@@ -392,7 +419,8 @@ rb_winevt_subscribe_each_yield(VALUE self)
|
|
392
419
|
for (int i = 0; i < winevtSubscribe->count; i++) {
|
393
420
|
rb_yield_values(3,
|
394
421
|
rb_winevt_subscribe_render(self, winevtSubscribe->hEvents[i]),
|
395
|
-
rb_winevt_subscribe_message(winevtSubscribe->hEvents[i]
|
422
|
+
rb_winevt_subscribe_message(winevtSubscribe->hEvents[i], winevtSubscribe->localeInfo,
|
423
|
+
winevtSubscribe->remoteHandle),
|
396
424
|
rb_winevt_subscribe_string_inserts(winevtSubscribe->hEvents[i]));
|
397
425
|
}
|
398
426
|
|
@@ -517,6 +545,84 @@ rb_winevt_subscribe_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
|
|
517
545
|
return Qnil;
|
518
546
|
}
|
519
547
|
|
548
|
+
/*
|
549
|
+
* This method specifies whether preserving qualifiers key or not.
|
550
|
+
*
|
551
|
+
* @since 0.7.3
|
552
|
+
* @param rb_preserve_qualifiers [Boolean]
|
553
|
+
*/
|
554
|
+
static VALUE
|
555
|
+
rb_winevt_subscribe_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
|
556
|
+
{
|
557
|
+
struct WinevtSubscribe* winevtSubscribe;
|
558
|
+
|
559
|
+
TypedData_Get_Struct(
|
560
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
561
|
+
|
562
|
+
winevtSubscribe->preserveQualifiers = RTEST(rb_preserve_qualifiers);
|
563
|
+
|
564
|
+
return Qnil;
|
565
|
+
}
|
566
|
+
|
567
|
+
/*
|
568
|
+
* This method returns whether preserving qualifiers or not.
|
569
|
+
*
|
570
|
+
* @since 0.7.3
|
571
|
+
* @return [Integer]
|
572
|
+
*/
|
573
|
+
static VALUE
|
574
|
+
rb_winevt_subscribe_get_preserve_qualifiers_p(VALUE self)
|
575
|
+
{
|
576
|
+
struct WinevtSubscribe* winevtSubscribe;
|
577
|
+
|
578
|
+
TypedData_Get_Struct(
|
579
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
580
|
+
|
581
|
+
return winevtSubscribe->preserveQualifiers ? Qtrue : Qfalse;
|
582
|
+
}
|
583
|
+
|
584
|
+
/*
|
585
|
+
* This method specifies locale with [String].
|
586
|
+
*
|
587
|
+
* @since 0.8.0
|
588
|
+
* @param rb_locale_str [String]
|
589
|
+
*/
|
590
|
+
static VALUE
|
591
|
+
rb_winevt_subscribe_set_locale(VALUE self, VALUE rb_locale_str)
|
592
|
+
{
|
593
|
+
struct WinevtSubscribe* winevtSubscribe;
|
594
|
+
LocaleInfo* locale_info = &default_locale;
|
595
|
+
|
596
|
+
TypedData_Get_Struct(
|
597
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
598
|
+
|
599
|
+
locale_info = get_locale_info_from_rb_str(rb_locale_str);
|
600
|
+
|
601
|
+
winevtSubscribe->localeInfo = locale_info;
|
602
|
+
|
603
|
+
return Qnil;
|
604
|
+
}
|
605
|
+
|
606
|
+
/*
|
607
|
+
* This method obtains specified locale with [String].
|
608
|
+
*
|
609
|
+
* @since 0.8.0
|
610
|
+
*/
|
611
|
+
static VALUE
|
612
|
+
rb_winevt_subscribe_get_locale(VALUE self)
|
613
|
+
{
|
614
|
+
struct WinevtSubscribe* winevtSubscribe;
|
615
|
+
|
616
|
+
TypedData_Get_Struct(
|
617
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
618
|
+
|
619
|
+
if (winevtSubscribe->localeInfo->langCode) {
|
620
|
+
return rb_str_new2(winevtSubscribe->localeInfo->langCode);
|
621
|
+
} else {
|
622
|
+
return rb_str_new2(default_locale.langCode);
|
623
|
+
}
|
624
|
+
}
|
625
|
+
|
520
626
|
void
|
521
627
|
Init_winevt_subscribe(VALUE rb_cEventLog)
|
522
628
|
{
|
@@ -549,4 +655,24 @@ Init_winevt_subscribe(VALUE rb_cEventLog)
|
|
549
655
|
rb_cSubscribe, "render_as_xml?", rb_winevt_subscribe_render_as_xml_p, 0);
|
550
656
|
rb_define_method(
|
551
657
|
rb_cSubscribe, "render_as_xml=", rb_winevt_subscribe_set_render_as_xml, 1);
|
658
|
+
/*
|
659
|
+
* @since 0.7.3
|
660
|
+
*/
|
661
|
+
rb_define_method(
|
662
|
+
rb_cSubscribe, "preserve_qualifiers?", rb_winevt_subscribe_get_preserve_qualifiers_p, 0);
|
663
|
+
/*
|
664
|
+
* @since 0.7.3
|
665
|
+
*/
|
666
|
+
rb_define_method(
|
667
|
+
rb_cSubscribe, "preserve_qualifiers=", rb_winevt_subscribe_set_preserve_qualifiers, 1);
|
668
|
+
/*
|
669
|
+
* @since 0.8.0
|
670
|
+
*/
|
671
|
+
rb_define_method(
|
672
|
+
rb_cSubscribe, "locale", rb_winevt_subscribe_get_locale, 0);
|
673
|
+
/*
|
674
|
+
* @since 0.8.0
|
675
|
+
*/
|
676
|
+
rb_define_method(
|
677
|
+
rb_cSubscribe, "locale=", rb_winevt_subscribe_set_locale, 1);
|
552
678
|
}
|
data/ext/winevt/winevt_utils.cpp
CHANGED
@@ -76,6 +76,28 @@ render_to_rb_str(EVT_HANDLE handle, DWORD flags)
|
|
76
76
|
return result;
|
77
77
|
}
|
78
78
|
|
79
|
+
EVT_HANDLE
|
80
|
+
connect_to_remote(LPWSTR computerName, LPWSTR domain, LPWSTR username, LPWSTR password,
|
81
|
+
EVT_RPC_LOGIN_FLAGS flags)
|
82
|
+
{
|
83
|
+
EVT_HANDLE hRemote = NULL;
|
84
|
+
EVT_RPC_LOGIN Credentials;
|
85
|
+
|
86
|
+
RtlZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
|
87
|
+
|
88
|
+
Credentials.Server = computerName;
|
89
|
+
Credentials.Domain = domain;
|
90
|
+
Credentials.User = username;
|
91
|
+
Credentials.Password = password;
|
92
|
+
Credentials.Flags = flags;
|
93
|
+
|
94
|
+
hRemote = EvtOpenSession(EvtRpcLogin, &Credentials, 0, 0);
|
95
|
+
|
96
|
+
SecureZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
|
97
|
+
|
98
|
+
return hRemote;
|
99
|
+
}
|
100
|
+
|
79
101
|
static std::wstring
|
80
102
|
guid_to_wstr(const GUID& guid)
|
81
103
|
{
|
@@ -433,7 +455,7 @@ cleanup:
|
|
433
455
|
}
|
434
456
|
|
435
457
|
WCHAR*
|
436
|
-
get_description(EVT_HANDLE handle)
|
458
|
+
get_description(EVT_HANDLE handle, LANGID langID, EVT_HANDLE hRemote)
|
437
459
|
{
|
438
460
|
#define BUFSIZE 4096
|
439
461
|
std::vector<WCHAR> buffer(BUFSIZE);
|
@@ -470,10 +492,10 @@ get_description(EVT_HANDLE handle)
|
|
470
492
|
|
471
493
|
// Open publisher metadata
|
472
494
|
hMetadata = EvtOpenPublisherMetadata(
|
473
|
-
|
495
|
+
hRemote,
|
474
496
|
values[0].StringVal,
|
475
497
|
nullptr,
|
476
|
-
MAKELCID(
|
498
|
+
MAKELCID(langID, SORT_DEFAULT),
|
477
499
|
0);
|
478
500
|
if (hMetadata == nullptr) {
|
479
501
|
// When winevt_c cannot open metadata, then give up to obtain
|
@@ -497,7 +519,7 @@ cleanup:
|
|
497
519
|
}
|
498
520
|
|
499
521
|
VALUE
|
500
|
-
render_system_event(EVT_HANDLE hEvent)
|
522
|
+
render_system_event(EVT_HANDLE hEvent, BOOL preserve_qualifiers)
|
501
523
|
{
|
502
524
|
DWORD status = ERROR_SUCCESS;
|
503
525
|
EVT_HANDLE hContext = NULL;
|
@@ -572,11 +594,23 @@ render_system_event(EVT_HANDLE hEvent)
|
|
572
594
|
}
|
573
595
|
|
574
596
|
EventID = pRenderedValues[EvtSystemEventID].UInt16Val;
|
575
|
-
if (
|
576
|
-
|
577
|
-
|
597
|
+
if (preserve_qualifiers) {
|
598
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemQualifiers].Type) {
|
599
|
+
rb_hash_aset(hash, rb_str_new2("Qualifiers"),
|
600
|
+
INT2NUM(pRenderedValues[EvtSystemQualifiers].UInt16Val));
|
601
|
+
} else {
|
602
|
+
rb_hash_aset(hash, rb_str_new2("Qualifiers"), rb_str_new2(""));
|
603
|
+
}
|
604
|
+
|
605
|
+
rb_hash_aset(hash, rb_str_new2("EventID"), INT2NUM(EventID));
|
606
|
+
} else {
|
607
|
+
if (EvtVarTypeNull != pRenderedValues[EvtSystemQualifiers].Type) {
|
608
|
+
EventID = MAKELONG(pRenderedValues[EvtSystemEventID].UInt16Val,
|
609
|
+
pRenderedValues[EvtSystemQualifiers].UInt16Val);
|
610
|
+
}
|
611
|
+
|
612
|
+
rb_hash_aset(hash, rb_str_new2("EventID"), ULONG2NUM(EventID));
|
578
613
|
}
|
579
|
-
rb_hash_aset(hash, rb_str_new2("EventID"), LONG2NUM(EventID));
|
580
614
|
|
581
615
|
rb_hash_aset(hash,
|
582
616
|
rb_str_new2("Version"),
|
data/lib/winevt.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Winevt
|
2
|
+
class EventLog
|
3
|
+
class Session
|
4
|
+
alias_method :initialize_raw, :initialize
|
5
|
+
|
6
|
+
def initialize(server, domain = nil, username = nil, password = nil)
|
7
|
+
initialize_raw
|
8
|
+
self.server = server
|
9
|
+
self.domain = domain if domain.is_a?(String)
|
10
|
+
self.username = username if username.is_a?(String)
|
11
|
+
self.password = password if password.is_a?(String)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/winevt/subscribe.rb
CHANGED
@@ -3,8 +3,11 @@ module Winevt
|
|
3
3
|
class Subscribe
|
4
4
|
alias_method :subscribe_raw, :subscribe
|
5
5
|
|
6
|
-
def subscribe(path, query, bookmark = nil)
|
7
|
-
if bookmark.is_a?(Winevt::EventLog::Bookmark)
|
6
|
+
def subscribe(path, query, bookmark = nil, session = nil)
|
7
|
+
if bookmark.is_a?(Winevt::EventLog::Bookmark) &&
|
8
|
+
session.is_a?(Winevt::EventLog::Session)
|
9
|
+
subscribe_raw(path, query, bookmark.render, session)
|
10
|
+
elsif bookmark.is_a?(Winevt::EventLog::Bookmark)
|
8
11
|
subscribe_raw(path, query, bookmark.render)
|
9
12
|
else
|
10
13
|
subscribe_raw(path, query)
|
data/lib/winevt/version.rb
CHANGED
data/winevt_c.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_development_dependency "bundler", [">= 1.16", "< 3"]
|
29
29
|
spec.add_development_dependency "rake", "~> 12.0"
|
30
30
|
spec.add_development_dependency "rake-compiler", "~> 1.0"
|
31
|
-
spec.add_development_dependency "rake-compiler-dock", "~> 0.
|
31
|
+
spec.add_development_dependency "rake-compiler-dock", "~> 1.0.0"
|
32
32
|
spec.add_development_dependency "test-unit", "~> 3.2"
|
33
33
|
spec.add_development_dependency "yard", "~> 0.9"
|
34
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: winevt_c
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroshi Hatake
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -64,14 +64,14 @@ dependencies:
|
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: 0.
|
67
|
+
version: 1.0.0
|
68
68
|
type: :development
|
69
69
|
prerelease: false
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
71
71
|
requirements:
|
72
72
|
- - "~>"
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 0.
|
74
|
+
version: 1.0.0
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: test-unit
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- example/bookmark.rb
|
122
122
|
- example/enumerate_channels.rb
|
123
123
|
- example/eventlog.rb
|
124
|
+
- example/locale.rb
|
124
125
|
- example/rate_limit.rb
|
125
126
|
- example/tailing.rb
|
126
127
|
- ext/winevt/extconf.rb
|
@@ -128,12 +129,16 @@ files:
|
|
128
129
|
- ext/winevt/winevt_bookmark.c
|
129
130
|
- ext/winevt/winevt_c.h
|
130
131
|
- ext/winevt/winevt_channel.c
|
132
|
+
- ext/winevt/winevt_locale.c
|
133
|
+
- ext/winevt/winevt_locale_info.c
|
131
134
|
- ext/winevt/winevt_query.c
|
135
|
+
- ext/winevt/winevt_session.c
|
132
136
|
- ext/winevt/winevt_subscribe.c
|
133
137
|
- ext/winevt/winevt_utils.cpp
|
134
138
|
- lib/winevt.rb
|
135
139
|
- lib/winevt/bookmark.rb
|
136
140
|
- lib/winevt/query.rb
|
141
|
+
- lib/winevt/session.rb
|
137
142
|
- lib/winevt/subscribe.rb
|
138
143
|
- lib/winevt/version.rb
|
139
144
|
- winevt_c.gemspec
|