winevt_c 0.5.1 → 0.6.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 +5 -0
- data/README.md +2 -2
- data/example/rate_limit.rb +14 -0
- data/ext/winevt/extconf.rb +2 -2
- data/ext/winevt/winevt_bookmark.c +44 -39
- data/ext/winevt/winevt_c.h +42 -26
- data/ext/winevt/winevt_channel.c +43 -29
- data/ext/winevt/winevt_query.c +140 -92
- data/ext/winevt/winevt_subscribe.c +214 -89
- data/ext/winevt/winevt_utils.cpp +540 -335
- data/lib/winevt/version.rb +1 -1
- data/winevt_c.gemspec +1 -1
- metadata +5 -3
data/ext/winevt/winevt_query.c
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
#include <winevt_c.h>
|
2
2
|
|
3
|
-
static void query_free(void
|
4
|
-
|
5
|
-
static const rb_data_type_t rb_winevt_query_type = {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
}
|
3
|
+
static void query_free(void* ptr);
|
4
|
+
|
5
|
+
static const rb_data_type_t rb_winevt_query_type = { "winevt/query",
|
6
|
+
{
|
7
|
+
0,
|
8
|
+
query_free,
|
9
|
+
0,
|
10
|
+
},
|
11
|
+
NULL,
|
12
|
+
NULL,
|
13
|
+
RUBY_TYPED_FREE_IMMEDIATELY };
|
11
14
|
|
12
15
|
static void
|
13
|
-
query_free(void
|
16
|
+
query_free(void* ptr)
|
14
17
|
{
|
15
|
-
struct WinevtQuery
|
18
|
+
struct WinevtQuery* winevtQuery = (struct WinevtQuery*)ptr;
|
16
19
|
if (winevtQuery->query)
|
17
20
|
EvtClose(winevtQuery->query);
|
18
21
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
for (int i = 0; i < winevtQuery->count; i++) {
|
23
|
+
if (winevtQuery->hEvents[i])
|
24
|
+
EvtClose(winevtQuery->hEvents[i]);
|
25
|
+
}
|
22
26
|
xfree(ptr);
|
23
27
|
}
|
24
28
|
|
@@ -26,11 +30,9 @@ static VALUE
|
|
26
30
|
rb_winevt_query_alloc(VALUE klass)
|
27
31
|
{
|
28
32
|
VALUE obj;
|
29
|
-
struct WinevtQuery
|
30
|
-
obj =
|
31
|
-
|
32
|
-
&rb_winevt_query_type,
|
33
|
-
winevtQuery);
|
33
|
+
struct WinevtQuery* winevtQuery;
|
34
|
+
obj =
|
35
|
+
TypedData_Make_Struct(klass, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
34
36
|
return obj;
|
35
37
|
}
|
36
38
|
|
@@ -38,7 +40,7 @@ static VALUE
|
|
38
40
|
rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
|
39
41
|
{
|
40
42
|
PWSTR evtChannel, evtXPath;
|
41
|
-
struct WinevtQuery
|
43
|
+
struct WinevtQuery* winevtQuery;
|
42
44
|
DWORD len;
|
43
45
|
VALUE wchannelBuf, wpathBuf;
|
44
46
|
|
@@ -46,23 +48,26 @@ rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
|
|
46
48
|
Check_Type(xpath, T_STRING);
|
47
49
|
|
48
50
|
// channel : To wide char
|
49
|
-
len =
|
50
|
-
|
51
|
-
|
51
|
+
len =
|
52
|
+
MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), NULL, 0);
|
53
|
+
evtChannel = ALLOCV_N(WCHAR, wchannelBuf, len + 1);
|
54
|
+
MultiByteToWideChar(
|
55
|
+
CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), evtChannel, len);
|
52
56
|
evtChannel[len] = L'\0';
|
53
57
|
|
54
58
|
// xpath : To wide char
|
55
59
|
len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(xpath), RSTRING_LEN(xpath), NULL, 0);
|
56
|
-
evtXPath = ALLOCV_N(WCHAR, wpathBuf, len+1);
|
60
|
+
evtXPath = ALLOCV_N(WCHAR, wpathBuf, len + 1);
|
57
61
|
MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(xpath), RSTRING_LEN(xpath), evtXPath, len);
|
58
62
|
evtXPath[len] = L'\0';
|
59
63
|
|
60
64
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
61
65
|
|
62
|
-
winevtQuery->query = EvtQuery(
|
63
|
-
|
66
|
+
winevtQuery->query = EvtQuery(
|
67
|
+
NULL, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
|
64
68
|
winevtQuery->offset = 0L;
|
65
69
|
winevtQuery->timeout = 0L;
|
70
|
+
winevtQuery->renderAsXML = TRUE;
|
66
71
|
|
67
72
|
ALLOCV_END(wchannelBuf);
|
68
73
|
ALLOCV_END(wpathBuf);
|
@@ -73,7 +78,7 @@ rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
|
|
73
78
|
static VALUE
|
74
79
|
rb_winevt_query_get_offset(VALUE self, VALUE offset)
|
75
80
|
{
|
76
|
-
struct WinevtQuery
|
81
|
+
struct WinevtQuery* winevtQuery;
|
77
82
|
|
78
83
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
79
84
|
|
@@ -83,7 +88,7 @@ rb_winevt_query_get_offset(VALUE self, VALUE offset)
|
|
83
88
|
static VALUE
|
84
89
|
rb_winevt_query_set_offset(VALUE self, VALUE offset)
|
85
90
|
{
|
86
|
-
struct WinevtQuery
|
91
|
+
struct WinevtQuery* winevtQuery;
|
87
92
|
|
88
93
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
89
94
|
|
@@ -95,7 +100,7 @@ rb_winevt_query_set_offset(VALUE self, VALUE offset)
|
|
95
100
|
static VALUE
|
96
101
|
rb_winevt_query_get_timeout(VALUE self, VALUE timeout)
|
97
102
|
{
|
98
|
-
struct WinevtQuery
|
103
|
+
struct WinevtQuery* winevtQuery;
|
99
104
|
|
100
105
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
101
106
|
|
@@ -105,7 +110,7 @@ rb_winevt_query_get_timeout(VALUE self, VALUE timeout)
|
|
105
110
|
static VALUE
|
106
111
|
rb_winevt_query_set_timeout(VALUE self, VALUE timeout)
|
107
112
|
{
|
108
|
-
struct WinevtQuery
|
113
|
+
struct WinevtQuery* winevtQuery;
|
109
114
|
|
110
115
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
111
116
|
|
@@ -117,15 +122,25 @@ rb_winevt_query_set_timeout(VALUE self, VALUE timeout)
|
|
117
122
|
static VALUE
|
118
123
|
rb_winevt_query_next(VALUE self)
|
119
124
|
{
|
120
|
-
EVT_HANDLE
|
121
|
-
ULONG
|
122
|
-
|
125
|
+
EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
|
126
|
+
ULONG count;
|
127
|
+
DWORD status = ERROR_SUCCESS;
|
128
|
+
struct WinevtQuery* winevtQuery;
|
123
129
|
|
124
130
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
125
131
|
|
126
|
-
if (EvtNext(winevtQuery->query,
|
127
|
-
|
132
|
+
if (!EvtNext(winevtQuery->query, QUERY_ARRAY_SIZE, hEvents, INFINITE, 0, &count)) {
|
133
|
+
status = GetLastError();
|
134
|
+
if (ERROR_NO_MORE_ITEMS != status) {
|
135
|
+
return Qfalse;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
if (status == ERROR_SUCCESS) {
|
128
140
|
winevtQuery->count = count;
|
141
|
+
for (int i = 0; i < count; i++){
|
142
|
+
winevtQuery->hEvents[i] = hEvents[i];
|
143
|
+
}
|
129
144
|
|
130
145
|
return Qtrue;
|
131
146
|
}
|
@@ -133,48 +148,37 @@ rb_winevt_query_next(VALUE self)
|
|
133
148
|
return Qfalse;
|
134
149
|
}
|
135
150
|
|
136
|
-
|
137
151
|
static VALUE
|
138
|
-
rb_winevt_query_render(VALUE self)
|
152
|
+
rb_winevt_query_render(VALUE self, EVT_HANDLE event)
|
139
153
|
{
|
140
|
-
|
141
|
-
struct WinevtQuery *winevtQuery;
|
142
|
-
VALUE utf8str;
|
154
|
+
struct WinevtQuery* winevtQuery;
|
143
155
|
|
144
156
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
145
|
-
wResult = render_event(winevtQuery->event, EvtRenderEventXml);
|
146
|
-
utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
|
147
157
|
|
148
|
-
if (
|
149
|
-
|
150
|
-
|
151
|
-
|
158
|
+
if (winevtQuery->renderAsXML) {
|
159
|
+
return render_to_rb_str(event, EvtRenderEventXml);
|
160
|
+
} else {
|
161
|
+
return render_system_event(event);
|
162
|
+
}
|
152
163
|
}
|
153
164
|
|
154
165
|
static VALUE
|
155
|
-
rb_winevt_query_message(
|
166
|
+
rb_winevt_query_message(EVT_HANDLE event)
|
156
167
|
{
|
157
168
|
WCHAR* wResult;
|
158
|
-
struct WinevtQuery *winevtQuery;
|
159
169
|
VALUE utf8str;
|
160
170
|
|
161
|
-
|
162
|
-
wResult = get_description(winevtQuery->event);
|
171
|
+
wResult = get_description(event);
|
163
172
|
utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
|
164
|
-
|
165
|
-
if (wResult != NULL)
|
166
|
-
free(wResult);
|
173
|
+
free(wResult);
|
167
174
|
|
168
175
|
return utf8str;
|
169
176
|
}
|
170
177
|
|
171
178
|
static VALUE
|
172
|
-
rb_winevt_query_string_inserts(
|
179
|
+
rb_winevt_query_string_inserts(EVT_HANDLE event)
|
173
180
|
{
|
174
|
-
|
175
|
-
|
176
|
-
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
177
|
-
return get_values(winevtQuery->event);
|
181
|
+
return get_values(event);
|
178
182
|
}
|
179
183
|
|
180
184
|
static DWORD
|
@@ -192,37 +196,50 @@ get_evt_seek_flag_from_cstr(char* flag_str)
|
|
192
196
|
return EvtSeekOriginMask;
|
193
197
|
else if (strcmp(flag_str, "strict") == 0)
|
194
198
|
return EvtSeekStrict;
|
199
|
+
else
|
200
|
+
rb_raise(rb_eArgError, "Unknown seek flag: %s", flag_str);
|
201
|
+
|
202
|
+
return 0;
|
195
203
|
}
|
196
204
|
|
197
205
|
static VALUE
|
198
206
|
rb_winevt_query_seek(VALUE self, VALUE bookmark_or_flag)
|
199
207
|
{
|
200
|
-
struct WinevtQuery
|
201
|
-
struct WinevtBookmark
|
202
|
-
DWORD flag;
|
208
|
+
struct WinevtQuery* winevtQuery;
|
209
|
+
struct WinevtBookmark* winevtBookmark = NULL;
|
210
|
+
DWORD flag = 0;
|
203
211
|
|
204
212
|
switch (TYPE(bookmark_or_flag)) {
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
213
|
+
case T_SYMBOL:
|
214
|
+
flag = get_evt_seek_flag_from_cstr(RSTRING_PTR(rb_sym2str(bookmark_or_flag)));
|
215
|
+
break;
|
216
|
+
case T_STRING:
|
217
|
+
flag = get_evt_seek_flag_from_cstr(StringValueCStr(bookmark_or_flag));
|
218
|
+
break;
|
219
|
+
case T_FIXNUM:
|
220
|
+
flag = NUM2LONG(bookmark_or_flag);
|
221
|
+
break;
|
222
|
+
default:
|
223
|
+
if (!rb_obj_is_kind_of(bookmark_or_flag, rb_cBookmark))
|
224
|
+
rb_raise(rb_eArgError, "Expected a String or a Symbol or a Bookmark instance");
|
225
|
+
|
226
|
+
winevtBookmark = EventBookMark(bookmark_or_flag);
|
216
227
|
}
|
217
228
|
|
218
229
|
if (winevtBookmark) {
|
219
230
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
220
|
-
if (EvtSeek(winevtQuery->query,
|
231
|
+
if (EvtSeek(winevtQuery->query,
|
232
|
+
winevtQuery->offset,
|
233
|
+
winevtBookmark->bookmark,
|
234
|
+
winevtQuery->timeout,
|
235
|
+
EvtSeekRelativeToBookmark))
|
221
236
|
return Qtrue;
|
222
237
|
} else {
|
223
238
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
224
|
-
if (EvtSeek(
|
239
|
+
if (EvtSeek(
|
240
|
+
winevtQuery->query, winevtQuery->offset, NULL, winevtQuery->timeout, flag)) {
|
225
241
|
return Qtrue;
|
242
|
+
}
|
226
243
|
}
|
227
244
|
|
228
245
|
return Qfalse;
|
@@ -231,12 +248,15 @@ rb_winevt_query_seek(VALUE self, VALUE bookmark_or_flag)
|
|
231
248
|
static VALUE
|
232
249
|
rb_winevt_query_close_handle(VALUE self)
|
233
250
|
{
|
234
|
-
struct WinevtQuery
|
251
|
+
struct WinevtQuery* winevtQuery;
|
235
252
|
|
236
253
|
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
237
254
|
|
238
|
-
|
239
|
-
|
255
|
+
for (int i = 0; i < winevtQuery->count; i++){
|
256
|
+
if (winevtQuery->hEvents[i] != NULL) {
|
257
|
+
EvtClose(winevtQuery->hEvents[i]);
|
258
|
+
winevtQuery->hEvents[i] = NULL;
|
259
|
+
}
|
240
260
|
}
|
241
261
|
|
242
262
|
return Qnil;
|
@@ -245,28 +265,26 @@ rb_winevt_query_close_handle(VALUE self)
|
|
245
265
|
static VALUE
|
246
266
|
rb_winevt_query_each_yield(VALUE self)
|
247
267
|
{
|
248
|
-
struct WinevtQuery *winevtQuery;
|
249
|
-
|
250
268
|
RETURN_ENUMERATOR(self, 0, 0);
|
251
269
|
|
252
|
-
|
270
|
+
struct WinevtQuery* winevtQuery;
|
253
271
|
|
254
|
-
|
255
|
-
rb_winevt_query_render(self),
|
256
|
-
rb_winevt_query_message(self),
|
257
|
-
rb_winevt_query_string_inserts(self));
|
272
|
+
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
258
273
|
|
274
|
+
for (int i = 0; i < winevtQuery->count; i++) {
|
275
|
+
rb_yield_values(3,
|
276
|
+
rb_winevt_query_render(self, winevtQuery->hEvents[i]),
|
277
|
+
rb_winevt_query_message(winevtQuery->hEvents[i]),
|
278
|
+
rb_winevt_query_string_inserts(winevtQuery->hEvents[i]));
|
279
|
+
}
|
259
280
|
return Qnil;
|
260
281
|
}
|
261
282
|
|
262
283
|
static VALUE
|
263
284
|
rb_winevt_query_each(VALUE self)
|
264
285
|
{
|
265
|
-
struct WinevtQuery *winevtQuery;
|
266
|
-
|
267
286
|
RETURN_ENUMERATOR(self, 0, 0);
|
268
287
|
|
269
|
-
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
270
288
|
while (rb_winevt_query_next(self)) {
|
271
289
|
rb_ensure(rb_winevt_query_each_yield, self, rb_winevt_query_close_handle, self);
|
272
290
|
}
|
@@ -274,21 +292,51 @@ rb_winevt_query_each(VALUE self)
|
|
274
292
|
return Qnil;
|
275
293
|
}
|
276
294
|
|
277
|
-
|
295
|
+
static VALUE
|
296
|
+
rb_winevt_query_render_as_xml_p(VALUE self)
|
278
297
|
{
|
279
|
-
|
298
|
+
struct WinevtQuery* winevtQuery;
|
299
|
+
|
300
|
+
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
301
|
+
|
302
|
+
return winevtQuery->renderAsXML ? Qtrue : Qfalse;
|
303
|
+
}
|
304
|
+
|
305
|
+
static VALUE
|
306
|
+
rb_winevt_query_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
|
307
|
+
{
|
308
|
+
struct WinevtQuery* winevtQuery;
|
280
309
|
|
310
|
+
TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
|
311
|
+
|
312
|
+
winevtQuery->renderAsXML = RTEST(rb_render_as_xml);
|
313
|
+
|
314
|
+
return Qnil;
|
315
|
+
}
|
316
|
+
|
317
|
+
void
|
318
|
+
Init_winevt_query(VALUE rb_cEventLog)
|
319
|
+
{
|
320
|
+
rb_cQuery = rb_define_class_under(rb_cEventLog, "Query", rb_cObject);
|
281
321
|
rb_define_alloc_func(rb_cQuery, rb_winevt_query_alloc);
|
322
|
+
|
323
|
+
rb_cFlag = rb_define_module_under(rb_cQuery, "Flag");
|
324
|
+
|
325
|
+
rb_define_const(rb_cFlag, "RelativeToFirst", LONG2NUM(EvtSeekRelativeToFirst));
|
326
|
+
rb_define_const(rb_cFlag, "RelativeToLast", LONG2NUM(EvtSeekRelativeToLast));
|
327
|
+
rb_define_const(rb_cFlag, "RelativeToCurrent", LONG2NUM(EvtSeekRelativeToCurrent));
|
328
|
+
rb_define_const(rb_cFlag, "RelativeToBookmark", LONG2NUM(EvtSeekRelativeToBookmark));
|
329
|
+
rb_define_const(rb_cFlag, "OriginMask", LONG2NUM(EvtSeekOriginMask));
|
330
|
+
rb_define_const(rb_cFlag, "Strict", LONG2NUM(EvtSeekStrict));
|
331
|
+
|
282
332
|
rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, 2);
|
283
333
|
rb_define_method(rb_cQuery, "next", rb_winevt_query_next, 0);
|
284
|
-
rb_define_method(rb_cQuery, "render", rb_winevt_query_render, 0);
|
285
|
-
rb_define_method(rb_cQuery, "message", rb_winevt_query_message, 0);
|
286
|
-
rb_define_method(rb_cQuery, "string_inserts", rb_winevt_query_string_inserts, 0);
|
287
334
|
rb_define_method(rb_cQuery, "seek", rb_winevt_query_seek, 1);
|
288
335
|
rb_define_method(rb_cQuery, "offset", rb_winevt_query_get_offset, 0);
|
289
336
|
rb_define_method(rb_cQuery, "offset=", rb_winevt_query_set_offset, 1);
|
290
337
|
rb_define_method(rb_cQuery, "timeout", rb_winevt_query_get_timeout, 0);
|
291
338
|
rb_define_method(rb_cQuery, "timeout=", rb_winevt_query_set_timeout, 1);
|
292
|
-
rb_define_method(rb_cQuery, "close_handle", rb_winevt_query_close_handle, 0);
|
293
339
|
rb_define_method(rb_cQuery, "each", rb_winevt_query_each, 0);
|
340
|
+
rb_define_method(rb_cQuery, "render_as_xml?", rb_winevt_query_render_as_xml_p, 0);
|
341
|
+
rb_define_method(rb_cQuery, "render_as_xml=", rb_winevt_query_set_render_as_xml, 1);
|
294
342
|
}
|