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.
@@ -1,18 +1,21 @@
1
1
  #include <winevt_c.h>
2
2
 
3
- static void subscribe_free(void *ptr);
4
-
5
- static const rb_data_type_t rb_winevt_subscribe_type = {
6
- "winevt/subscribe", {
7
- 0, subscribe_free, 0,
8
- }, NULL, NULL,
9
- RUBY_TYPED_FREE_IMMEDIATELY
10
- };
3
+ static void subscribe_free(void* ptr);
4
+
5
+ static const rb_data_type_t rb_winevt_subscribe_type = { "winevt/subscribe",
6
+ {
7
+ 0,
8
+ subscribe_free,
9
+ 0,
10
+ },
11
+ NULL,
12
+ NULL,
13
+ RUBY_TYPED_FREE_IMMEDIATELY };
11
14
 
12
15
  static void
13
- subscribe_free(void *ptr)
16
+ subscribe_free(void* ptr)
14
17
  {
15
- struct WinevtSubscribe *winevtSubscribe = (struct WinevtSubscribe *)ptr;
18
+ struct WinevtSubscribe* winevtSubscribe = (struct WinevtSubscribe*)ptr;
16
19
  if (winevtSubscribe->signalEvent)
17
20
  CloseHandle(winevtSubscribe->signalEvent);
18
21
 
@@ -22,8 +25,11 @@ subscribe_free(void *ptr)
22
25
  if (winevtSubscribe->bookmark)
23
26
  EvtClose(winevtSubscribe->bookmark);
24
27
 
25
- if (winevtSubscribe->event)
26
- EvtClose(winevtSubscribe->event);
28
+ for (int i = 0; i < winevtSubscribe->count; i++) {
29
+ if (winevtSubscribe->hEvents[i]) {
30
+ EvtClose(winevtSubscribe->hEvents[i]);
31
+ }
32
+ }
27
33
 
28
34
  xfree(ptr);
29
35
  }
@@ -32,26 +38,35 @@ static VALUE
32
38
  rb_winevt_subscribe_alloc(VALUE klass)
33
39
  {
34
40
  VALUE obj;
35
- struct WinevtSubscribe *winevtSubscribe;
36
- obj = TypedData_Make_Struct(klass,
37
- struct WinevtSubscribe,
38
- &rb_winevt_subscribe_type,
39
- winevtSubscribe);
41
+ struct WinevtSubscribe* winevtSubscribe;
42
+ obj = TypedData_Make_Struct(
43
+ klass, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
40
44
  return obj;
41
45
  }
42
46
 
43
47
  static VALUE
44
48
  rb_winevt_subscribe_initialize(VALUE self)
45
49
  {
50
+ struct WinevtSubscribe* winevtSubscribe;
51
+
52
+ TypedData_Get_Struct(
53
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
54
+
55
+ winevtSubscribe->rateLimit = SUBSCRIBE_RATE_INFINITE;
56
+ winevtSubscribe->lastTime = 0;
57
+ winevtSubscribe->currentRate = 0;
58
+ winevtSubscribe->renderAsXML = TRUE;
59
+
46
60
  return Qnil;
47
61
  }
48
62
 
49
63
  static VALUE
50
64
  rb_winevt_subscribe_set_tail(VALUE self, VALUE rb_tailing_p)
51
65
  {
52
- struct WinevtSubscribe *winevtSubscribe;
66
+ struct WinevtSubscribe* winevtSubscribe;
53
67
 
54
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
68
+ TypedData_Get_Struct(
69
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
55
70
 
56
71
  winevtSubscribe->tailing = RTEST(rb_tailing_p);
57
72
 
@@ -61,15 +76,16 @@ rb_winevt_subscribe_set_tail(VALUE self, VALUE rb_tailing_p)
61
76
  static VALUE
62
77
  rb_winevt_subscribe_tail_p(VALUE self, VALUE rb_flag)
63
78
  {
64
- struct WinevtSubscribe *winevtSubscribe;
79
+ struct WinevtSubscribe* winevtSubscribe;
65
80
 
66
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
81
+ TypedData_Get_Struct(
82
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
67
83
 
68
84
  return winevtSubscribe->tailing ? Qtrue : Qfalse;
69
85
  }
70
86
 
71
87
  static VALUE
72
- rb_winevt_subscribe_subscribe(int argc, VALUE *argv, VALUE self)
88
+ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
73
89
  {
74
90
  VALUE rb_path, rb_query, rb_bookmark;
75
91
  EVT_HANDLE hSubscription = NULL, hBookmark = NULL;
@@ -78,11 +94,12 @@ rb_winevt_subscribe_subscribe(int argc, VALUE *argv, VALUE self)
78
94
  VALUE wpathBuf, wqueryBuf;
79
95
  PWSTR path, query;
80
96
  DWORD status = ERROR_SUCCESS;
81
- struct WinevtSubscribe *winevtSubscribe;
97
+ struct WinevtSubscribe* winevtSubscribe;
82
98
 
83
99
  hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
84
100
 
85
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
101
+ TypedData_Get_Struct(
102
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
86
103
 
87
104
  rb_scan_args(argc, argv, "21", &rb_path, &rb_query, &rb_bookmark);
88
105
  Check_Type(rb_path, T_STRING);
@@ -93,18 +110,21 @@ rb_winevt_subscribe_subscribe(int argc, VALUE *argv, VALUE self)
93
110
  }
94
111
 
95
112
  // path : To wide char
96
- len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_path), RSTRING_LEN(rb_path), NULL, 0);
97
- path = ALLOCV_N(WCHAR, wpathBuf, len+1);
113
+ len =
114
+ MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_path), RSTRING_LEN(rb_path), NULL, 0);
115
+ path = ALLOCV_N(WCHAR, wpathBuf, len + 1);
98
116
  MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_path), RSTRING_LEN(rb_path), path, len);
99
117
  path[len] = L'\0';
100
118
 
101
119
  // query : To wide char
102
- len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_query), RSTRING_LEN(rb_query), NULL, 0);
103
- query = ALLOCV_N(WCHAR, wqueryBuf, len+1);
104
- MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_query), RSTRING_LEN(rb_query), query, len);
120
+ len = MultiByteToWideChar(
121
+ CP_UTF8, 0, RSTRING_PTR(rb_query), RSTRING_LEN(rb_query), NULL, 0);
122
+ query = ALLOCV_N(WCHAR, wqueryBuf, len + 1);
123
+ MultiByteToWideChar(
124
+ CP_UTF8, 0, RSTRING_PTR(rb_query), RSTRING_LEN(rb_query), query, len);
105
125
  query[len] = L'\0';
106
126
 
107
- if (hBookmark){
127
+ if (hBookmark) {
108
128
  flags |= EvtSubscribeStartAfterBookmark;
109
129
  } else if (winevtSubscribe->tailing) {
110
130
  flags |= EvtSubscribeToFutureEvents;
@@ -112,7 +132,8 @@ rb_winevt_subscribe_subscribe(int argc, VALUE *argv, VALUE self)
112
132
  flags |= EvtSubscribeStartAtOldestRecord;
113
133
  }
114
134
 
115
- hSubscription = EvtSubscribe(NULL, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
135
+ hSubscription =
136
+ EvtSubscribe(NULL, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
116
137
 
117
138
  ALLOCV_END(wpathBuf);
118
139
  ALLOCV_END(wqueryBuf);
@@ -133,18 +154,71 @@ rb_winevt_subscribe_subscribe(int argc, VALUE *argv, VALUE self)
133
154
  return Qfalse;
134
155
  }
135
156
 
157
+ BOOL
158
+ is_rate_limit_exceeded(struct WinevtSubscribe *winevtSubscribe)
159
+ {
160
+ time_t now;
161
+
162
+ if (winevtSubscribe->rateLimit == SUBSCRIBE_RATE_INFINITE)
163
+ return FALSE;
164
+
165
+ time(&now);
166
+
167
+ if (now <= winevtSubscribe->lastTime) {
168
+ if (winevtSubscribe->currentRate >= winevtSubscribe->rateLimit) {
169
+ return TRUE;
170
+ }
171
+ } else {
172
+ winevtSubscribe->currentRate = 0;
173
+ }
174
+
175
+ return FALSE;
176
+ }
177
+
178
+ void
179
+ update_to_reflect_rate_limit_state(struct WinevtSubscribe *winevtSubscribe, ULONG count)
180
+ {
181
+ time_t lastTime = 0;
182
+
183
+ if (winevtSubscribe->rateLimit == SUBSCRIBE_RATE_INFINITE)
184
+ return;
185
+
186
+ time(&lastTime);
187
+ winevtSubscribe->lastTime = lastTime;
188
+ winevtSubscribe->currentRate += count;
189
+ }
190
+
136
191
  static VALUE
137
192
  rb_winevt_subscribe_next(VALUE self)
138
193
  {
139
- EVT_HANDLE event;
140
- ULONG count;
141
- struct WinevtSubscribe *winevtSubscribe;
194
+ EVT_HANDLE hEvents[SUBSCRIBE_ARRAY_SIZE];
195
+ ULONG count = 0;
196
+ DWORD status = ERROR_SUCCESS;
197
+ struct WinevtSubscribe* winevtSubscribe;
198
+
199
+ TypedData_Get_Struct(
200
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
201
+
202
+ if (is_rate_limit_exceeded(winevtSubscribe)) {
203
+ return Qfalse;
204
+ }
142
205
 
143
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
206
+ if (!EvtNext(winevtSubscribe->subscription, SUBSCRIBE_ARRAY_SIZE,
207
+ hEvents, INFINITE, 0, &count)) {
208
+ status = GetLastError();
209
+ if (ERROR_NO_MORE_ITEMS != status) {
210
+ return Qfalse;
211
+ }
212
+ }
213
+
214
+ if (status == ERROR_SUCCESS) {
215
+ winevtSubscribe->count = count;
216
+ for (int i = 0; i < count; i++) {
217
+ winevtSubscribe->hEvents[i] = hEvents[i];
218
+ EvtUpdateBookmark(winevtSubscribe->bookmark, winevtSubscribe->hEvents[i]);
219
+ }
144
220
 
145
- if (EvtNext(winevtSubscribe->subscription, 1, &event, INFINITE, 0, &count) != FALSE) {
146
- winevtSubscribe->event = event;
147
- EvtUpdateBookmark(winevtSubscribe->bookmark, winevtSubscribe->event);
221
+ update_to_reflect_rate_limit_state(winevtSubscribe, count);
148
222
 
149
223
  return Qtrue;
150
224
  }
@@ -153,57 +227,52 @@ rb_winevt_subscribe_next(VALUE self)
153
227
  }
154
228
 
155
229
  static VALUE
156
- rb_winevt_subscribe_render(VALUE self)
230
+ rb_winevt_subscribe_render(VALUE self, EVT_HANDLE event)
157
231
  {
158
- WCHAR* wResult;
159
- struct WinevtSubscribe *winevtSubscribe;
160
- VALUE utf8str;
232
+ struct WinevtSubscribe* winevtSubscribe;
161
233
 
162
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
163
- wResult = render_event(winevtSubscribe->event, EvtRenderEventXml);
164
- utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
234
+ TypedData_Get_Struct(
235
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
165
236
 
166
- if (wResult != NULL)
167
- free(wResult);
168
-
169
- return utf8str;
237
+ if (winevtSubscribe->renderAsXML) {
238
+ return render_to_rb_str(event, EvtRenderEventXml);
239
+ } else {
240
+ return render_system_event(event);
241
+ }
170
242
  }
171
243
 
172
244
  static VALUE
173
- rb_winevt_subscribe_message(VALUE self)
245
+ rb_winevt_subscribe_message(EVT_HANDLE event)
174
246
  {
175
247
  WCHAR* wResult;
176
- struct WinevtSubscribe *winevtSubscribe;
177
248
  VALUE utf8str;
178
249
 
179
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
180
- wResult = get_description(winevtSubscribe->event);
250
+ wResult = get_description(event);
181
251
  utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
182
-
183
- if (wResult != NULL)
184
- free(wResult);
252
+ free(wResult);
185
253
 
186
254
  return utf8str;
187
255
  }
188
256
 
189
257
  static VALUE
190
- rb_winevt_subscribe_string_inserts(VALUE self)
258
+ rb_winevt_subscribe_string_inserts(EVT_HANDLE event)
191
259
  {
192
- struct WinevtSubscribe *winevtSubscribe;
193
-
194
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
195
- return get_values(winevtSubscribe->event);
260
+ return get_values(event);
196
261
  }
197
262
 
198
263
  static VALUE
199
264
  rb_winevt_subscribe_close_handle(VALUE self)
200
265
  {
201
- struct WinevtSubscribe *winevtSubscribe;
266
+ struct WinevtSubscribe* winevtSubscribe;
202
267
 
203
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
268
+ TypedData_Get_Struct(
269
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
204
270
 
205
- if (winevtSubscribe->event != NULL) {
206
- EvtClose(winevtSubscribe->event);
271
+ for (int i = 0; i < winevtSubscribe->count; i++) {
272
+ if (winevtSubscribe->hEvents[i] != NULL) {
273
+ EvtClose(winevtSubscribe->hEvents[i]);
274
+ winevtSubscribe->hEvents[i] = NULL;
275
+ }
207
276
  }
208
277
 
209
278
  return Qnil;
@@ -212,16 +281,18 @@ rb_winevt_subscribe_close_handle(VALUE self)
212
281
  static VALUE
213
282
  rb_winevt_subscribe_each_yield(VALUE self)
214
283
  {
215
- struct WinevtSubscribe *winevtSubscribe;
216
-
217
284
  RETURN_ENUMERATOR(self, 0, 0);
285
+ struct WinevtSubscribe* winevtSubscribe;
218
286
 
219
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
287
+ TypedData_Get_Struct(
288
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
220
289
 
221
- rb_yield_values(3,
222
- rb_winevt_subscribe_render(self),
223
- rb_winevt_subscribe_message(self),
224
- rb_winevt_subscribe_string_inserts(self));
290
+ for (int i = 0; i < winevtSubscribe->count; i++) {
291
+ rb_yield_values(3,
292
+ rb_winevt_subscribe_render(self, winevtSubscribe->hEvents[i]),
293
+ rb_winevt_subscribe_message(winevtSubscribe->hEvents[i]),
294
+ rb_winevt_subscribe_string_inserts(winevtSubscribe->hEvents[i]));
295
+ }
225
296
 
226
297
  return Qnil;
227
298
  }
@@ -229,14 +300,11 @@ rb_winevt_subscribe_each_yield(VALUE self)
229
300
  static VALUE
230
301
  rb_winevt_subscribe_each(VALUE self)
231
302
  {
232
- struct WinevtSubscribe *winevtSubscribe;
233
-
234
303
  RETURN_ENUMERATOR(self, 0, 0);
235
304
 
236
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
237
-
238
305
  while (rb_winevt_subscribe_next(self)) {
239
- rb_ensure(rb_winevt_subscribe_each_yield, self, rb_winevt_subscribe_close_handle, self);
306
+ rb_ensure(
307
+ rb_winevt_subscribe_each_yield, self, rb_winevt_subscribe_close_handle, self);
240
308
  }
241
309
 
242
310
  return Qnil;
@@ -245,32 +313,89 @@ rb_winevt_subscribe_each(VALUE self)
245
313
  static VALUE
246
314
  rb_winevt_subscribe_get_bookmark(VALUE self)
247
315
  {
248
- WCHAR* wResult;
249
- struct WinevtSubscribe *winevtSubscribe;
250
- VALUE utf8str;
316
+ struct WinevtSubscribe* winevtSubscribe;
251
317
 
252
- TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
318
+ TypedData_Get_Struct(
319
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
253
320
 
254
- wResult = render_event(winevtSubscribe->bookmark, EvtRenderBookmark);
255
- utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
321
+ return render_to_rb_str(winevtSubscribe->bookmark, EvtRenderBookmark);
322
+ }
256
323
 
257
- return utf8str;
324
+ static VALUE
325
+ rb_winevt_subscribe_get_rate_limit(VALUE self)
326
+ {
327
+ struct WinevtSubscribe* winevtSubscribe;
328
+
329
+ TypedData_Get_Struct(
330
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
331
+
332
+ return INT2NUM(winevtSubscribe->rateLimit);
258
333
  }
259
334
 
260
- void Init_winevt_subscribe(VALUE rb_cEventLog)
335
+ static VALUE
336
+ rb_winevt_subscribe_set_rate_limit(VALUE self, VALUE rb_rate_limit)
337
+ {
338
+ struct WinevtSubscribe* winevtSubscribe;
339
+ DWORD rateLimit;
340
+
341
+ TypedData_Get_Struct(
342
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
343
+
344
+ rateLimit = NUM2LONG(rb_rate_limit);
345
+
346
+ if ((rateLimit != SUBSCRIBE_RATE_INFINITE) &&
347
+ (rateLimit < 10 || rateLimit % 10)) {
348
+ rb_raise(rb_eArgError,
349
+ "Specify a multiples of 10 or RATE_INFINITE constant");
350
+ } else {
351
+ winevtSubscribe->rateLimit = rateLimit;
352
+ }
353
+
354
+ return Qnil;
355
+ }
356
+
357
+ static VALUE
358
+ rb_winevt_subscribe_render_as_xml_p(VALUE self)
359
+ {
360
+ struct WinevtSubscribe* winevtSubscribe;
361
+
362
+ TypedData_Get_Struct(
363
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
364
+
365
+ return winevtSubscribe->renderAsXML ? Qtrue : Qfalse;
366
+ }
367
+
368
+ static VALUE
369
+ rb_winevt_subscribe_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
370
+ {
371
+ struct WinevtSubscribe* winevtSubscribe;
372
+
373
+ TypedData_Get_Struct(
374
+ self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
375
+
376
+ winevtSubscribe->renderAsXML = RTEST(rb_render_as_xml);
377
+
378
+ return Qnil;
379
+ }
380
+
381
+ void
382
+ Init_winevt_subscribe(VALUE rb_cEventLog)
261
383
  {
262
384
  rb_cSubscribe = rb_define_class_under(rb_cEventLog, "Subscribe", rb_cObject);
263
385
 
264
386
  rb_define_alloc_func(rb_cSubscribe, rb_winevt_subscribe_alloc);
387
+
388
+ rb_define_const(rb_cSubscribe, "RATE_INFINITE", SUBSCRIBE_RATE_INFINITE);
389
+
265
390
  rb_define_method(rb_cSubscribe, "initialize", rb_winevt_subscribe_initialize, 0);
266
391
  rb_define_method(rb_cSubscribe, "subscribe", rb_winevt_subscribe_subscribe, -1);
267
392
  rb_define_method(rb_cSubscribe, "next", rb_winevt_subscribe_next, 0);
268
- rb_define_method(rb_cSubscribe, "render", rb_winevt_subscribe_render, 0);
269
- rb_define_method(rb_cSubscribe, "message", rb_winevt_subscribe_message, 0);
270
- rb_define_method(rb_cSubscribe, "string_inserts", rb_winevt_subscribe_string_inserts, 0);
271
393
  rb_define_method(rb_cSubscribe, "each", rb_winevt_subscribe_each, 0);
272
- rb_define_method(rb_cSubscribe, "close_handle", rb_winevt_subscribe_close_handle, 0);
273
394
  rb_define_method(rb_cSubscribe, "bookmark", rb_winevt_subscribe_get_bookmark, 0);
274
395
  rb_define_method(rb_cSubscribe, "tail?", rb_winevt_subscribe_tail_p, 0);
275
396
  rb_define_method(rb_cSubscribe, "tail=", rb_winevt_subscribe_set_tail, 1);
397
+ rb_define_method(rb_cSubscribe, "rate_limit", rb_winevt_subscribe_get_rate_limit, 0);
398
+ rb_define_method(rb_cSubscribe, "rate_limit=", rb_winevt_subscribe_set_rate_limit, 1);
399
+ rb_define_method(rb_cSubscribe, "render_as_xml?", rb_winevt_subscribe_render_as_xml_p, 0);
400
+ rb_define_method(rb_cSubscribe, "render_as_xml=", rb_winevt_subscribe_set_render_as_xml, 1);
276
401
  }