winevt_c 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  }