winevt_c 0.6.0 → 0.6.1
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/README.md +4 -0
- data/Rakefile +1 -1
- data/ext/winevt/winevt_bookmark.c +38 -0
- data/ext/winevt/winevt_c.h +1 -0
- data/ext/winevt/winevt_channel.c +27 -0
- data/ext/winevt/winevt_query.c +116 -4
- data/ext/winevt/winevt_subscribe.c +148 -21
- data/ext/winevt/winevt_utils.cpp +34 -38
- data/lib/winevt.rb +1 -0
- data/lib/winevt/bookmark.rb +6 -0
- data/lib/winevt/subscribe.rb +9 -0
- data/lib/winevt/version.rb +1 -1
- data/winevt_c.gemspec +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b390dc340de45facd91c7de698c1d72f7f706e961f6beb776a748499886fa4c2
|
4
|
+
data.tar.gz: cb6bb22241cb81551cbb84363e7c9bddb205f38fb6aa138da2c6c4489667044c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8e2666c0d51dcf9bfc114c1bd73b1f075a1702999d44e8dd318878d837b762a568aceffffadfc89f0ce33010629fb677f0edd040a312d32a5f35a20c6f3f0cc
|
7
|
+
data.tar.gz: 6adec333c1e0998a712b149f470091ed24f441806b5454a05e80d937bca63de7346b806ddd1904835428344158e81108b12a1cc2aa628a595299ed243ce83abc
|
data/README.md
CHANGED
@@ -24,6 +24,10 @@ Or install it yourself as:
|
|
24
24
|
|
25
25
|
$ ridk exec gem install winevt_c
|
26
26
|
|
27
|
+
## Fat gems building
|
28
|
+
|
29
|
+
* Docker is needed to build fat gem due to rake-compiler-dock uses docker container.
|
30
|
+
|
27
31
|
## Usage
|
28
32
|
|
29
33
|
Usage examples are found in [example directory](example).
|
data/Rakefile
CHANGED
@@ -27,7 +27,7 @@ desc 'Build gems for Windows per rake-compiler-dock'
|
|
27
27
|
task 'gem:native' do
|
28
28
|
# See RUBY_CC_VERSION in https://github.com/rake-compiler/rake-compiler-dock/blob/master/Dockerfile.mri
|
29
29
|
RakeCompilerDock.sh <<-EOS
|
30
|
-
bundle --local
|
30
|
+
gem install bundler --no-doc && bundle --local
|
31
31
|
bundle exec rake cross native gem RUBY_CC_VERSION=2.4.0:2.5.0:2.6.0
|
32
32
|
EOS
|
33
33
|
end
|
@@ -1,5 +1,24 @@
|
|
1
1
|
#include <winevt_c.h>
|
2
2
|
|
3
|
+
/* clang-format off */
|
4
|
+
/*
|
5
|
+
* Document-class: Winevt::EventLog::Bookmark
|
6
|
+
*
|
7
|
+
* Bookmark for querying/subscribing Windows EventLog progress.
|
8
|
+
*
|
9
|
+
* @example
|
10
|
+
* require 'winevt'
|
11
|
+
*
|
12
|
+
* @query = Winevt::EventLog::Query.new("Application", "*[System[(Level <= 3) and TimeCreated[timediff(@SystemTime) <= 86400000]]]")
|
13
|
+
* @bookmark = Winevt::EventLog::Bookmark.new
|
14
|
+
* @query.each do |xml|
|
15
|
+
* @bookmark.update(@query)
|
16
|
+
* end
|
17
|
+
*
|
18
|
+
* puts @bookmark.render
|
19
|
+
*/
|
20
|
+
/* clang-format pn */
|
21
|
+
|
3
22
|
static void bookmark_free(void* ptr);
|
4
23
|
|
5
24
|
static const rb_data_type_t rb_winevt_bookmark_type = { "winevt/bookmark",
|
@@ -32,6 +51,14 @@ rb_winevt_bookmark_alloc(VALUE klass)
|
|
32
51
|
return obj;
|
33
52
|
}
|
34
53
|
|
54
|
+
/*
|
55
|
+
* Initalize Bookmark class. Receive XML string or nil.
|
56
|
+
*
|
57
|
+
* @overload initailize(options={})
|
58
|
+
* @option options [String] XML rendered Bookmark string.
|
59
|
+
* @return [Bookmark]
|
60
|
+
*
|
61
|
+
*/
|
35
62
|
static VALUE
|
36
63
|
rb_winevt_bookmark_initialize(int argc, VALUE* argv, VALUE self)
|
37
64
|
{
|
@@ -68,6 +95,12 @@ rb_winevt_bookmark_initialize(int argc, VALUE* argv, VALUE self)
|
|
68
95
|
return Qnil;
|
69
96
|
}
|
70
97
|
|
98
|
+
/*
|
99
|
+
* This method updates bookmark and returns Bookmark instance.
|
100
|
+
*
|
101
|
+
* @param event [Query]
|
102
|
+
* @return [Bookmark]
|
103
|
+
*/
|
71
104
|
static VALUE
|
72
105
|
rb_winevt_bookmark_update(VALUE self, VALUE event)
|
73
106
|
{
|
@@ -86,6 +119,11 @@ rb_winevt_bookmark_update(VALUE self, VALUE event)
|
|
86
119
|
return Qtrue;
|
87
120
|
}
|
88
121
|
|
122
|
+
/*
|
123
|
+
* This method renders bookmark class content.
|
124
|
+
*
|
125
|
+
* @return [String]
|
126
|
+
*/
|
89
127
|
static VALUE
|
90
128
|
rb_winevt_bookmark_render(VALUE self)
|
91
129
|
{
|
data/ext/winevt/winevt_c.h
CHANGED
@@ -27,6 +27,7 @@ extern "C" {
|
|
27
27
|
#endif /* __cplusplus */
|
28
28
|
|
29
29
|
VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
|
30
|
+
void raise_system_error(VALUE error, DWORD errorCode);
|
30
31
|
VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
|
31
32
|
WCHAR* get_description(EVT_HANDLE handle);
|
32
33
|
VALUE get_values(EVT_HANDLE handle);
|
data/ext/winevt/winevt_channel.c
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
#include <winevt_c.h>
|
2
2
|
|
3
|
+
/*
|
4
|
+
* Document-class: Winevt::EventLog::Channel
|
5
|
+
*
|
6
|
+
* Retrieve Windows EventLog channel name.
|
7
|
+
*
|
8
|
+
* @example
|
9
|
+
* require 'winevt'
|
10
|
+
* channels = []
|
11
|
+
* @channel = Winevt::EventLog::Channel.new
|
12
|
+
* @channel.each do |channel|
|
13
|
+
* channels << channel
|
14
|
+
* end
|
15
|
+
* print channels
|
16
|
+
*/
|
17
|
+
|
3
18
|
static void channel_free(void* ptr);
|
4
19
|
|
5
20
|
static const rb_data_type_t rb_winevt_channel_type = { "winevt/channel",
|
@@ -32,12 +47,24 @@ rb_winevt_channel_alloc(VALUE klass)
|
|
32
47
|
return obj;
|
33
48
|
}
|
34
49
|
|
50
|
+
/*
|
51
|
+
* Initalize Channel class.
|
52
|
+
*
|
53
|
+
* @return [Channel]
|
54
|
+
*
|
55
|
+
*/
|
35
56
|
static VALUE
|
36
57
|
rb_winevt_channel_initialize(VALUE klass)
|
37
58
|
{
|
38
59
|
return Qnil;
|
39
60
|
}
|
40
61
|
|
62
|
+
/*
|
63
|
+
* Enumerate Windows EventLog channels
|
64
|
+
*
|
65
|
+
* @yield (String)
|
66
|
+
*
|
67
|
+
*/
|
41
68
|
static VALUE
|
42
69
|
rb_winevt_channel_each(VALUE self)
|
43
70
|
{
|
data/ext/winevt/winevt_query.c
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
#include <winevt_c.h>
|
2
2
|
|
3
|
+
/* clang-format off */
|
4
|
+
/*
|
5
|
+
* Document-class: Winevt::EventLog::Query
|
6
|
+
*
|
7
|
+
* Query Windows EventLog channel.
|
8
|
+
*
|
9
|
+
* @example
|
10
|
+
* require 'winevt'
|
11
|
+
*
|
12
|
+
* @query = Winevt::EventLog::Query.new("Application", "*[System[(Level <= 3) and TimeCreated[timediff(@SystemTime) <= 86400000]]]")
|
13
|
+
*
|
14
|
+
* @query.each do |eventlog, message, string_inserts|
|
15
|
+
* puts ({eventlog: eventlog, data: message})
|
16
|
+
* end
|
17
|
+
*/
|
18
|
+
/* clang-format on */
|
19
|
+
|
20
|
+
|
3
21
|
static void query_free(void* ptr);
|
4
22
|
|
5
23
|
static const rb_data_type_t rb_winevt_query_type = { "winevt/query",
|
@@ -36,6 +54,14 @@ rb_winevt_query_alloc(VALUE klass)
|
|
36
54
|
return obj;
|
37
55
|
}
|
38
56
|
|
57
|
+
/*
|
58
|
+
* Initalize Query class.
|
59
|
+
*
|
60
|
+
* @param channel [String] Querying EventLog channel.
|
61
|
+
* @param xpath [String] Querying XPath.
|
62
|
+
* @return [Query]
|
63
|
+
*
|
64
|
+
*/
|
39
65
|
static VALUE
|
40
66
|
rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
|
41
67
|
{
|
@@ -75,8 +101,13 @@ rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
|
|
75
101
|
return Qnil;
|
76
102
|
}
|
77
103
|
|
104
|
+
/*
|
105
|
+
* This method returns querying event offset.
|
106
|
+
*
|
107
|
+
* @return [Integer]
|
108
|
+
*/
|
78
109
|
static VALUE
|
79
|
-
rb_winevt_query_get_offset(VALUE self
|
110
|
+
rb_winevt_query_get_offset(VALUE self)
|
80
111
|
{
|
81
112
|
struct WinevtQuery* winevtQuery;
|
82
113
|
|
@@ -85,6 +116,11 @@ rb_winevt_query_get_offset(VALUE self, VALUE offset)
|
|
85
116
|
return LONG2NUM(winevtQuery->offset);
|
86
117
|
}
|
87
118
|
|
119
|
+
/*
|
120
|
+
* This method specifies querying event offset.
|
121
|
+
*
|
122
|
+
* @param offset [Integer] offset value
|
123
|
+
*/
|
88
124
|
static VALUE
|
89
125
|
rb_winevt_query_set_offset(VALUE self, VALUE offset)
|
90
126
|
{
|
@@ -97,8 +133,13 @@ rb_winevt_query_set_offset(VALUE self, VALUE offset)
|
|
97
133
|
return Qnil;
|
98
134
|
}
|
99
135
|
|
136
|
+
/*
|
137
|
+
* This method returns timeout value.
|
138
|
+
*
|
139
|
+
* @return [Integer]
|
140
|
+
*/
|
100
141
|
static VALUE
|
101
|
-
rb_winevt_query_get_timeout(VALUE self
|
142
|
+
rb_winevt_query_get_timeout(VALUE self)
|
102
143
|
{
|
103
144
|
struct WinevtQuery* winevtQuery;
|
104
145
|
|
@@ -107,6 +148,11 @@ rb_winevt_query_get_timeout(VALUE self, VALUE timeout)
|
|
107
148
|
return LONG2NUM(winevtQuery->timeout);
|
108
149
|
}
|
109
150
|
|
151
|
+
/*
|
152
|
+
* This method specifies timeout value.
|
153
|
+
*
|
154
|
+
* @param timeout [Integer] timeout value
|
155
|
+
*/
|
110
156
|
static VALUE
|
111
157
|
rb_winevt_query_set_timeout(VALUE self, VALUE timeout)
|
112
158
|
{
|
@@ -119,6 +165,14 @@ rb_winevt_query_set_timeout(VALUE self, VALUE timeout)
|
|
119
165
|
return Qnil;
|
120
166
|
}
|
121
167
|
|
168
|
+
/*
|
169
|
+
* Handle the next values. Since v0.6.0, this method is used for
|
170
|
+
* testing only. Please use #each instead.
|
171
|
+
*
|
172
|
+
* @return [Boolean]
|
173
|
+
*
|
174
|
+
* @see each
|
175
|
+
*/
|
122
176
|
static VALUE
|
123
177
|
rb_winevt_query_next(VALUE self)
|
124
178
|
{
|
@@ -138,7 +192,7 @@ rb_winevt_query_next(VALUE self)
|
|
138
192
|
|
139
193
|
if (status == ERROR_SUCCESS) {
|
140
194
|
winevtQuery->count = count;
|
141
|
-
for (int i = 0; i < count; i++){
|
195
|
+
for (int i = 0; i < count; i++) {
|
142
196
|
winevtQuery->hEvents[i] = hEvents[i];
|
143
197
|
}
|
144
198
|
|
@@ -202,6 +256,12 @@ get_evt_seek_flag_from_cstr(char* flag_str)
|
|
202
256
|
return 0;
|
203
257
|
}
|
204
258
|
|
259
|
+
/*
|
260
|
+
* This method specifies seek strategy.
|
261
|
+
*
|
262
|
+
* @param bookmark_or_flag [Bookmark|Query::Flag]
|
263
|
+
* @return [Boolean]
|
264
|
+
*/
|
205
265
|
static VALUE
|
206
266
|
rb_winevt_query_seek(VALUE self, VALUE bookmark_or_flag)
|
207
267
|
{
|
@@ -252,7 +312,7 @@ rb_winevt_query_close_handle(VALUE self)
|
|
252
312
|
|
253
313
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
254
314
|
|
255
|
-
for (int i = 0; i < winevtQuery->count; i++){
|
315
|
+
for (int i = 0; i < winevtQuery->count; i++) {
|
256
316
|
if (winevtQuery->hEvents[i] != NULL) {
|
257
317
|
EvtClose(winevtQuery->hEvents[i]);
|
258
318
|
winevtQuery->hEvents[i] = NULL;
|
@@ -280,6 +340,16 @@ rb_winevt_query_each_yield(VALUE self)
|
|
280
340
|
return Qnil;
|
281
341
|
}
|
282
342
|
|
343
|
+
/*
|
344
|
+
* Enumerate to obtain Windows EventLog contents.
|
345
|
+
*
|
346
|
+
* This method yields the following:
|
347
|
+
* (Stringified EventLog, Stringified detail message, Stringified
|
348
|
+
* insert values)
|
349
|
+
*
|
350
|
+
* @yield (String,String,String)
|
351
|
+
*
|
352
|
+
*/
|
283
353
|
static VALUE
|
284
354
|
rb_winevt_query_each(VALUE self)
|
285
355
|
{
|
@@ -292,6 +362,11 @@ rb_winevt_query_each(VALUE self)
|
|
292
362
|
return Qnil;
|
293
363
|
}
|
294
364
|
|
365
|
+
/*
|
366
|
+
* This method returns whether render as xml or not.
|
367
|
+
*
|
368
|
+
* @return [Boolean]
|
369
|
+
*/
|
295
370
|
static VALUE
|
296
371
|
rb_winevt_query_render_as_xml_p(VALUE self)
|
297
372
|
{
|
@@ -302,6 +377,11 @@ rb_winevt_query_render_as_xml_p(VALUE self)
|
|
302
377
|
return winevtQuery->renderAsXML ? Qtrue : Qfalse;
|
303
378
|
}
|
304
379
|
|
380
|
+
/*
|
381
|
+
* This method specifies whether render as xml or not.
|
382
|
+
*
|
383
|
+
* @param rb_render_as_xml [Boolean]
|
384
|
+
*/
|
305
385
|
static VALUE
|
306
386
|
rb_winevt_query_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
|
307
387
|
{
|
@@ -322,12 +402,44 @@ Init_winevt_query(VALUE rb_cEventLog)
|
|
322
402
|
|
323
403
|
rb_cFlag = rb_define_module_under(rb_cQuery, "Flag");
|
324
404
|
|
405
|
+
/* clang-format off */
|
406
|
+
/*
|
407
|
+
* EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToFirst
|
408
|
+
* @since 0.6.0
|
409
|
+
* @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToFirst
|
410
|
+
*/
|
325
411
|
rb_define_const(rb_cFlag, "RelativeToFirst", LONG2NUM(EvtSeekRelativeToFirst));
|
412
|
+
/*
|
413
|
+
* EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToLast
|
414
|
+
* @since 0.6.0
|
415
|
+
* @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToLast
|
416
|
+
*/
|
326
417
|
rb_define_const(rb_cFlag, "RelativeToLast", LONG2NUM(EvtSeekRelativeToLast));
|
418
|
+
/*
|
419
|
+
* EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToCurrent
|
420
|
+
* @since 0.6.0
|
421
|
+
* @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToCurrent
|
422
|
+
*/
|
327
423
|
rb_define_const(rb_cFlag, "RelativeToCurrent", LONG2NUM(EvtSeekRelativeToCurrent));
|
424
|
+
/*
|
425
|
+
* EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToBookmark
|
426
|
+
* @since 0.6.0
|
427
|
+
* @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToBookmark
|
428
|
+
*/
|
328
429
|
rb_define_const(rb_cFlag, "RelativeToBookmark", LONG2NUM(EvtSeekRelativeToBookmark));
|
430
|
+
/*
|
431
|
+
* EVT_SEEK_FLAGS enumeration: EvtSeekOriginMask
|
432
|
+
* @since 0.6.0
|
433
|
+
* @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekOriginMask
|
434
|
+
*/
|
329
435
|
rb_define_const(rb_cFlag, "OriginMask", LONG2NUM(EvtSeekOriginMask));
|
436
|
+
/*
|
437
|
+
* EVT_SEEK_FLAGS enumeration: EvtSeekStrict
|
438
|
+
* @since 0.6.0
|
439
|
+
* @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekStrict
|
440
|
+
*/
|
330
441
|
rb_define_const(rb_cFlag, "Strict", LONG2NUM(EvtSeekStrict));
|
442
|
+
/* clang-format on */
|
331
443
|
|
332
444
|
rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, 2);
|
333
445
|
rb_define_method(rb_cQuery, "next", rb_winevt_query_next, 0);
|
@@ -1,5 +1,31 @@
|
|
1
1
|
#include <winevt_c.h>
|
2
2
|
|
3
|
+
/* clang-format off */
|
4
|
+
/*
|
5
|
+
* Document-class: Winevt::EventLog::Subscribe
|
6
|
+
*
|
7
|
+
* Subscribe Windows EventLog channel.
|
8
|
+
*
|
9
|
+
* @example
|
10
|
+
* require 'winevt'
|
11
|
+
*
|
12
|
+
* @subscribe = Winevt::EventLog::Subscribe.new
|
13
|
+
* @subscribe.tail = true
|
14
|
+
* @subscribe.rate_limit = 80
|
15
|
+
* @subscribe.subscribe(
|
16
|
+
* "Application", "*[System[(Level <= 4) and TimeCreated[timediff(@SystemTime) <= 86400000]]]"
|
17
|
+
* )
|
18
|
+
* while true do
|
19
|
+
* @subscribe.each do |eventlog, message, string_inserts|
|
20
|
+
* puts ({eventlog: eventlog, data: message})
|
21
|
+
* end
|
22
|
+
* sleep(0.1)
|
23
|
+
* end
|
24
|
+
*
|
25
|
+
* @see https://docs.microsoft.com/en-us/windows/win32/api/winevt/nf-winevt-evtsubscribe
|
26
|
+
*/
|
27
|
+
/* clang-format on */
|
28
|
+
|
3
29
|
static void subscribe_free(void* ptr);
|
4
30
|
|
5
31
|
static const rb_data_type_t rb_winevt_subscribe_type = { "winevt/subscribe",
|
@@ -44,6 +70,12 @@ rb_winevt_subscribe_alloc(VALUE klass)
|
|
44
70
|
return obj;
|
45
71
|
}
|
46
72
|
|
73
|
+
/*
|
74
|
+
* Initalize Subscribe class.
|
75
|
+
*
|
76
|
+
* @return [Subscribe]
|
77
|
+
*
|
78
|
+
*/
|
47
79
|
static VALUE
|
48
80
|
rb_winevt_subscribe_initialize(VALUE self)
|
49
81
|
{
|
@@ -60,6 +92,11 @@ rb_winevt_subscribe_initialize(VALUE self)
|
|
60
92
|
return Qnil;
|
61
93
|
}
|
62
94
|
|
95
|
+
/*
|
96
|
+
* This method specifies whether tailing or not.
|
97
|
+
*
|
98
|
+
* @param rb_tailing_p [Boolean]
|
99
|
+
*/
|
63
100
|
static VALUE
|
64
101
|
rb_winevt_subscribe_set_tail(VALUE self, VALUE rb_tailing_p)
|
65
102
|
{
|
@@ -73,8 +110,13 @@ rb_winevt_subscribe_set_tail(VALUE self, VALUE rb_tailing_p)
|
|
73
110
|
return Qnil;
|
74
111
|
}
|
75
112
|
|
113
|
+
/*
|
114
|
+
* This method returns whether tailing or not.
|
115
|
+
*
|
116
|
+
* @return [Boolean]
|
117
|
+
*/
|
76
118
|
static VALUE
|
77
|
-
rb_winevt_subscribe_tail_p(VALUE self
|
119
|
+
rb_winevt_subscribe_tail_p(VALUE self)
|
78
120
|
{
|
79
121
|
struct WinevtSubscribe* winevtSubscribe;
|
80
122
|
|
@@ -84,6 +126,16 @@ rb_winevt_subscribe_tail_p(VALUE self, VALUE rb_flag)
|
|
84
126
|
return winevtSubscribe->tailing ? Qtrue : Qfalse;
|
85
127
|
}
|
86
128
|
|
129
|
+
/*
|
130
|
+
* Subscribe into a Windows EventLog channel.
|
131
|
+
*
|
132
|
+
* @overload subscribe(path, query, options={})
|
133
|
+
* @param path [String] Subscribe Channel
|
134
|
+
* @param query [String] Query string for channel
|
135
|
+
* @option options [Bookmark] bookmark Bookmark class instance.
|
136
|
+
* @return [Boolean]
|
137
|
+
*
|
138
|
+
*/
|
87
139
|
static VALUE
|
88
140
|
rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
89
141
|
{
|
@@ -91,8 +143,8 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
91
143
|
EVT_HANDLE hSubscription = NULL, hBookmark = NULL;
|
92
144
|
HANDLE hSignalEvent;
|
93
145
|
DWORD len, flags = 0L;
|
94
|
-
VALUE wpathBuf, wqueryBuf;
|
95
|
-
PWSTR path, query;
|
146
|
+
VALUE wpathBuf, wqueryBuf, wBookmarkBuf;
|
147
|
+
PWSTR path, query, bookmarkXml;
|
96
148
|
DWORD status = ERROR_SUCCESS;
|
97
149
|
struct WinevtSubscribe* winevtSubscribe;
|
98
150
|
|
@@ -105,8 +157,24 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
105
157
|
Check_Type(rb_path, T_STRING);
|
106
158
|
Check_Type(rb_query, T_STRING);
|
107
159
|
|
108
|
-
if (rb_obj_is_kind_of(rb_bookmark,
|
109
|
-
|
160
|
+
if (rb_obj_is_kind_of(rb_bookmark, rb_cString)) {
|
161
|
+
// bookmarkXml : To wide char
|
162
|
+
len = MultiByteToWideChar(
|
163
|
+
CP_UTF8, 0, RSTRING_PTR(rb_bookmark), RSTRING_LEN(rb_bookmark), NULL, 0);
|
164
|
+
bookmarkXml = ALLOCV_N(WCHAR, wBookmarkBuf, len + 1);
|
165
|
+
MultiByteToWideChar(CP_UTF8,
|
166
|
+
0,
|
167
|
+
RSTRING_PTR(rb_bookmark),
|
168
|
+
RSTRING_LEN(rb_bookmark),
|
169
|
+
bookmarkXml,
|
170
|
+
len);
|
171
|
+
bookmarkXml[len] = L'\0';
|
172
|
+
hBookmark = EvtCreateBookmark(bookmarkXml);
|
173
|
+
ALLOCV_END(wBookmarkBuf);
|
174
|
+
if (hBookmark == NULL) {
|
175
|
+
status = GetLastError();
|
176
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
177
|
+
}
|
110
178
|
}
|
111
179
|
|
112
180
|
// path : To wide char
|
@@ -134,6 +202,10 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
134
202
|
|
135
203
|
hSubscription =
|
136
204
|
EvtSubscribe(NULL, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
|
205
|
+
if (!hSubscription) {
|
206
|
+
status = GetLastError();
|
207
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
208
|
+
}
|
137
209
|
|
138
210
|
ALLOCV_END(wpathBuf);
|
139
211
|
ALLOCV_END(wqueryBuf);
|
@@ -144,18 +216,17 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
144
216
|
winevtSubscribe->bookmark = hBookmark;
|
145
217
|
} else {
|
146
218
|
winevtSubscribe->bookmark = EvtCreateBookmark(NULL);
|
219
|
+
if (winevtSubscribe->bookmark == NULL) {
|
220
|
+
status = GetLastError();
|
221
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
222
|
+
}
|
147
223
|
}
|
148
224
|
|
149
|
-
|
150
|
-
|
151
|
-
if (status == ERROR_SUCCESS)
|
152
|
-
return Qtrue;
|
153
|
-
|
154
|
-
return Qfalse;
|
225
|
+
return Qtrue;
|
155
226
|
}
|
156
227
|
|
157
228
|
BOOL
|
158
|
-
is_rate_limit_exceeded(struct WinevtSubscribe
|
229
|
+
is_rate_limit_exceeded(struct WinevtSubscribe* winevtSubscribe)
|
159
230
|
{
|
160
231
|
time_t now;
|
161
232
|
|
@@ -176,7 +247,7 @@ is_rate_limit_exceeded(struct WinevtSubscribe *winevtSubscribe)
|
|
176
247
|
}
|
177
248
|
|
178
249
|
void
|
179
|
-
update_to_reflect_rate_limit_state(struct WinevtSubscribe
|
250
|
+
update_to_reflect_rate_limit_state(struct WinevtSubscribe* winevtSubscribe, ULONG count)
|
180
251
|
{
|
181
252
|
time_t lastTime = 0;
|
182
253
|
|
@@ -188,6 +259,15 @@ update_to_reflect_rate_limit_state(struct WinevtSubscribe *winevtSubscribe, ULON
|
|
188
259
|
winevtSubscribe->currentRate += count;
|
189
260
|
}
|
190
261
|
|
262
|
+
/*
|
263
|
+
* Handle the next values. Since v0.6.0, this method is used for
|
264
|
+
* testing only. Please use #each instead.
|
265
|
+
*
|
266
|
+
* @return [Boolean]
|
267
|
+
*
|
268
|
+
* @see each
|
269
|
+
*/
|
270
|
+
|
191
271
|
static VALUE
|
192
272
|
rb_winevt_subscribe_next(VALUE self)
|
193
273
|
{
|
@@ -203,8 +283,12 @@ rb_winevt_subscribe_next(VALUE self)
|
|
203
283
|
return Qfalse;
|
204
284
|
}
|
205
285
|
|
206
|
-
if (!EvtNext(winevtSubscribe->subscription,
|
207
|
-
|
286
|
+
if (!EvtNext(winevtSubscribe->subscription,
|
287
|
+
SUBSCRIBE_ARRAY_SIZE,
|
288
|
+
hEvents,
|
289
|
+
INFINITE,
|
290
|
+
0,
|
291
|
+
&count)) {
|
208
292
|
status = GetLastError();
|
209
293
|
if (ERROR_NO_MORE_ITEMS != status) {
|
210
294
|
return Qfalse;
|
@@ -297,6 +381,16 @@ rb_winevt_subscribe_each_yield(VALUE self)
|
|
297
381
|
return Qnil;
|
298
382
|
}
|
299
383
|
|
384
|
+
/*
|
385
|
+
* Enumerate to obtain Windows EventLog contents.
|
386
|
+
*
|
387
|
+
* This method yields the following:
|
388
|
+
* (Stringified EventLog, Stringified detail message, Stringified
|
389
|
+
* insert values)
|
390
|
+
*
|
391
|
+
* @yield (String,String,String)
|
392
|
+
*
|
393
|
+
*/
|
300
394
|
static VALUE
|
301
395
|
rb_winevt_subscribe_each(VALUE self)
|
302
396
|
{
|
@@ -310,6 +404,11 @@ rb_winevt_subscribe_each(VALUE self)
|
|
310
404
|
return Qnil;
|
311
405
|
}
|
312
406
|
|
407
|
+
/*
|
408
|
+
* This method renders bookmark content which is related to Subscribe class instance.
|
409
|
+
*
|
410
|
+
* @return [String]
|
411
|
+
*/
|
313
412
|
static VALUE
|
314
413
|
rb_winevt_subscribe_get_bookmark(VALUE self)
|
315
414
|
{
|
@@ -321,6 +420,12 @@ rb_winevt_subscribe_get_bookmark(VALUE self)
|
|
321
420
|
return render_to_rb_str(winevtSubscribe->bookmark, EvtRenderBookmark);
|
322
421
|
}
|
323
422
|
|
423
|
+
/*
|
424
|
+
* This method returns rate limit value.
|
425
|
+
*
|
426
|
+
* @since 0.6.0
|
427
|
+
* @return [Integer]
|
428
|
+
*/
|
324
429
|
static VALUE
|
325
430
|
rb_winevt_subscribe_get_rate_limit(VALUE self)
|
326
431
|
{
|
@@ -332,6 +437,12 @@ rb_winevt_subscribe_get_rate_limit(VALUE self)
|
|
332
437
|
return INT2NUM(winevtSubscribe->rateLimit);
|
333
438
|
}
|
334
439
|
|
440
|
+
/*
|
441
|
+
* This method specifies rate limit value.
|
442
|
+
*
|
443
|
+
* @since 0.6.0
|
444
|
+
* @param rb_rate_limit [Integer] rate_limit value
|
445
|
+
*/
|
335
446
|
static VALUE
|
336
447
|
rb_winevt_subscribe_set_rate_limit(VALUE self, VALUE rb_rate_limit)
|
337
448
|
{
|
@@ -343,10 +454,8 @@ rb_winevt_subscribe_set_rate_limit(VALUE self, VALUE rb_rate_limit)
|
|
343
454
|
|
344
455
|
rateLimit = NUM2LONG(rb_rate_limit);
|
345
456
|
|
346
|
-
if ((rateLimit != SUBSCRIBE_RATE_INFINITE) &&
|
347
|
-
|
348
|
-
rb_raise(rb_eArgError,
|
349
|
-
"Specify a multiples of 10 or RATE_INFINITE constant");
|
457
|
+
if ((rateLimit != SUBSCRIBE_RATE_INFINITE) && (rateLimit < 10 || rateLimit % 10)) {
|
458
|
+
rb_raise(rb_eArgError, "Specify a multiples of 10 or RATE_INFINITE constant");
|
350
459
|
} else {
|
351
460
|
winevtSubscribe->rateLimit = rateLimit;
|
352
461
|
}
|
@@ -354,6 +463,12 @@ rb_winevt_subscribe_set_rate_limit(VALUE self, VALUE rb_rate_limit)
|
|
354
463
|
return Qnil;
|
355
464
|
}
|
356
465
|
|
466
|
+
/*
|
467
|
+
* This method returns whether render as xml or not.
|
468
|
+
*
|
469
|
+
* @since 0.6.0
|
470
|
+
* @return [Boolean]
|
471
|
+
*/
|
357
472
|
static VALUE
|
358
473
|
rb_winevt_subscribe_render_as_xml_p(VALUE self)
|
359
474
|
{
|
@@ -365,6 +480,12 @@ rb_winevt_subscribe_render_as_xml_p(VALUE self)
|
|
365
480
|
return winevtSubscribe->renderAsXML ? Qtrue : Qfalse;
|
366
481
|
}
|
367
482
|
|
483
|
+
/*
|
484
|
+
* This method specifies whether render as xml or not.
|
485
|
+
*
|
486
|
+
* @since 0.6.0
|
487
|
+
* @param rb_render_as_xml [Boolean]
|
488
|
+
*/
|
368
489
|
static VALUE
|
369
490
|
rb_winevt_subscribe_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
|
370
491
|
{
|
@@ -385,6 +506,10 @@ Init_winevt_subscribe(VALUE rb_cEventLog)
|
|
385
506
|
|
386
507
|
rb_define_alloc_func(rb_cSubscribe, rb_winevt_subscribe_alloc);
|
387
508
|
|
509
|
+
/*
|
510
|
+
* For Subscribe#rate_limit=. It represents unspecified rate limit.
|
511
|
+
* @since 0.6.0
|
512
|
+
*/
|
388
513
|
rb_define_const(rb_cSubscribe, "RATE_INFINITE", SUBSCRIBE_RATE_INFINITE);
|
389
514
|
|
390
515
|
rb_define_method(rb_cSubscribe, "initialize", rb_winevt_subscribe_initialize, 0);
|
@@ -396,6 +521,8 @@ Init_winevt_subscribe(VALUE rb_cEventLog)
|
|
396
521
|
rb_define_method(rb_cSubscribe, "tail=", rb_winevt_subscribe_set_tail, 1);
|
397
522
|
rb_define_method(rb_cSubscribe, "rate_limit", rb_winevt_subscribe_get_rate_limit, 0);
|
398
523
|
rb_define_method(rb_cSubscribe, "rate_limit=", rb_winevt_subscribe_set_rate_limit, 1);
|
399
|
-
rb_define_method(
|
400
|
-
|
524
|
+
rb_define_method(
|
525
|
+
rb_cSubscribe, "render_as_xml?", rb_winevt_subscribe_render_as_xml_p, 0);
|
526
|
+
rb_define_method(
|
527
|
+
rb_cSubscribe, "render_as_xml=", rb_winevt_subscribe_set_render_as_xml, 1);
|
401
528
|
}
|
data/ext/winevt/winevt_utils.cpp
CHANGED
@@ -19,6 +19,28 @@ wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen)
|
|
19
19
|
return str;
|
20
20
|
}
|
21
21
|
|
22
|
+
void
|
23
|
+
raise_system_error(VALUE error, DWORD errorCode)
|
24
|
+
{
|
25
|
+
WCHAR msgBuf[256] = { 0 };
|
26
|
+
VALUE errorMessage;
|
27
|
+
|
28
|
+
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
29
|
+
NULL,
|
30
|
+
errorCode,
|
31
|
+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
32
|
+
msgBuf,
|
33
|
+
_countof(msgBuf),
|
34
|
+
NULL);
|
35
|
+
errorMessage = wstr_to_rb_str(CP_UTF8, msgBuf, -1);
|
36
|
+
|
37
|
+
#pragma GCC diagnostic push
|
38
|
+
#pragma GCC diagnostic ignored "-Wformat="
|
39
|
+
#pragma GCC diagnostic ignored "-Wformat-extra-args"
|
40
|
+
rb_raise(error, "ErrorCode: %lu\nError: %" PRIsVALUE "\n", errorCode, errorMessage);
|
41
|
+
#pragma GCC diagnostic pop
|
42
|
+
}
|
43
|
+
|
22
44
|
VALUE
|
23
45
|
render_to_rb_str(EVT_HANDLE handle, DWORD flags)
|
24
46
|
{
|
@@ -44,17 +66,8 @@ render_to_rb_str(EVT_HANDLE handle, DWORD flags)
|
|
44
66
|
EvtRender(nullptr, handle, flags, bufferSize, buffer, &bufferSizeUsed, &count);
|
45
67
|
if (!succeeded) {
|
46
68
|
DWORD status = GetLastError();
|
47
|
-
CHAR msgBuf[256];
|
48
|
-
|
49
|
-
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
50
|
-
nullptr,
|
51
|
-
status,
|
52
|
-
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
53
|
-
msgBuf,
|
54
|
-
_countof(msgBuf),
|
55
|
-
nullptr);
|
56
69
|
ALLOCV_END(vbuffer);
|
57
|
-
|
70
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
58
71
|
}
|
59
72
|
|
60
73
|
result = wstr_to_rb_str(CP_UTF8, buffer, -1);
|
@@ -284,19 +297,9 @@ get_values(EVT_HANDLE handle)
|
|
284
297
|
&propCount);
|
285
298
|
if (!succeeded) {
|
286
299
|
DWORD status = GetLastError();
|
287
|
-
CHAR msgBuf[256];
|
288
|
-
|
289
300
|
ALLOCV_END(vbuffer);
|
290
301
|
EvtClose(renderContext);
|
291
|
-
|
292
|
-
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
293
|
-
nullptr,
|
294
|
-
status,
|
295
|
-
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
296
|
-
msgBuf,
|
297
|
-
_countof(msgBuf),
|
298
|
-
nullptr);
|
299
|
-
rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, msgBuf);
|
302
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
300
303
|
}
|
301
304
|
|
302
305
|
userValues = extract_user_evt_variants(pRenderedValues, propCount);
|
@@ -437,7 +440,6 @@ get_description(EVT_HANDLE handle)
|
|
437
440
|
ULONG bufferSizeNeeded = 0;
|
438
441
|
ULONG status, count;
|
439
442
|
std::vector<WCHAR> result;
|
440
|
-
CHAR msgBuf[256];
|
441
443
|
EVT_HANDLE hMetadata = nullptr;
|
442
444
|
|
443
445
|
static PCWSTR eventProperties[] = { L"Event/System/Provider/@Name" };
|
@@ -460,14 +462,7 @@ get_description(EVT_HANDLE handle)
|
|
460
462
|
}
|
461
463
|
|
462
464
|
if (status != ERROR_SUCCESS) {
|
463
|
-
|
464
|
-
nullptr,
|
465
|
-
status,
|
466
|
-
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
467
|
-
msgBuf,
|
468
|
-
sizeof(msgBuf),
|
469
|
-
nullptr);
|
470
|
-
rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, msgBuf);
|
465
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
471
466
|
}
|
472
467
|
|
473
468
|
// Obtain buffer as EVT_VARIANT pointer. To avoid ErrorCide 87 in EvtRender.
|
@@ -524,8 +519,8 @@ render_system_event(EVT_HANDLE hEvent)
|
|
524
519
|
|
525
520
|
hContext = EvtCreateRenderContext(0, NULL, EvtRenderContextSystem);
|
526
521
|
if (NULL == hContext) {
|
527
|
-
rb_raise(
|
528
|
-
|
522
|
+
rb_raise(
|
523
|
+
rb_eWinevtQueryError, "Failed to create renderContext with %lu\n", GetLastError());
|
529
524
|
}
|
530
525
|
|
531
526
|
if (!EvtRender(hContext,
|
@@ -549,8 +544,7 @@ render_system_event(EVT_HANDLE hEvent)
|
|
549
544
|
&dwPropertyCount);
|
550
545
|
} else {
|
551
546
|
EvtClose(hContext);
|
552
|
-
rb_raise(rb_eRuntimeError,
|
553
|
-
"Failed to malloc memory with %lu\n", status);
|
547
|
+
rb_raise(rb_eRuntimeError, "Failed to malloc memory with %lu\n", status);
|
554
548
|
}
|
555
549
|
}
|
556
550
|
|
@@ -559,8 +553,7 @@ render_system_event(EVT_HANDLE hEvent)
|
|
559
553
|
EvtClose(hContext);
|
560
554
|
ALLOCV_END(vRenderedValues);
|
561
555
|
|
562
|
-
rb_raise(rb_eWinevtQueryError,
|
563
|
-
"EvtRender failed with %lu\n", status);
|
556
|
+
rb_raise(rb_eWinevtQueryError, "EvtRender failed with %lu\n", status);
|
564
557
|
}
|
565
558
|
}
|
566
559
|
|
@@ -605,8 +598,11 @@ render_system_event(EVT_HANDLE hEvent)
|
|
605
598
|
(EvtVarTypeNull == pRenderedValues[EvtSystemOpcode].Type)
|
606
599
|
? INT2NUM(0)
|
607
600
|
: INT2NUM(pRenderedValues[EvtSystemOpcode].ByteVal));
|
608
|
-
_snprintf_s(buffer,
|
609
|
-
|
601
|
+
_snprintf_s(buffer,
|
602
|
+
_countof(buffer),
|
603
|
+
_TRUNCATE,
|
604
|
+
"0x%llx",
|
605
|
+
pRenderedValues[EvtSystemKeywords].UInt64Val);
|
610
606
|
rb_hash_aset(hash,
|
611
607
|
rb_str_new2("Keywords"),
|
612
608
|
(EvtVarTypeNull == pRenderedValues[EvtSystemKeywords].Type)
|
data/lib/winevt.rb
CHANGED
data/lib/winevt/subscribe.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
module Winevt
|
2
2
|
class EventLog
|
3
3
|
class Subscribe
|
4
|
+
alias_method :subscribe_raw, :subscribe
|
5
|
+
|
6
|
+
def subscribe(path, query, bookmark = nil)
|
7
|
+
if bookmark.is_a?(Winevt::EventLog::Bookmark)
|
8
|
+
subscribe_raw(path, query, bookmark.render)
|
9
|
+
else
|
10
|
+
subscribe_raw(path, query)
|
11
|
+
end
|
12
|
+
end
|
4
13
|
end
|
5
14
|
end
|
6
15
|
end
|
data/lib/winevt/version.rb
CHANGED
data/winevt_c.gemspec
CHANGED
@@ -30,4 +30,5 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency "rake-compiler", "~> 1.0"
|
31
31
|
spec.add_development_dependency "rake-compiler-dock", "~> 0.7.2"
|
32
32
|
spec.add_development_dependency "test-unit", "~> 3.2"
|
33
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
33
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.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroshi Hatake
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -86,6 +86,20 @@ dependencies:
|
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '3.2'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: yard
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.9'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0.9'
|
89
103
|
description: Windows Event Log API bindings from winevt.h.
|
90
104
|
email:
|
91
105
|
- cosmo0920.wp@gmail.com
|
@@ -116,6 +130,7 @@ files:
|
|
116
130
|
- ext/winevt/winevt_subscribe.c
|
117
131
|
- ext/winevt/winevt_utils.cpp
|
118
132
|
- lib/winevt.rb
|
133
|
+
- lib/winevt/bookmark.rb
|
119
134
|
- lib/winevt/query.rb
|
120
135
|
- lib/winevt/subscribe.rb
|
121
136
|
- lib/winevt/version.rb
|