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
@@ -1,18 +1,21 @@
|
|
1
1
|
#include <winevt_c.h>
|
2
2
|
|
3
|
-
static void subscribe_free(void
|
4
|
-
|
5
|
-
static const rb_data_type_t rb_winevt_subscribe_type = {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
16
|
+
subscribe_free(void* ptr)
|
14
17
|
{
|
15
|
-
struct WinevtSubscribe
|
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
|
-
|
26
|
-
|
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
|
36
|
-
obj = TypedData_Make_Struct(
|
37
|
-
|
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
|
66
|
+
struct WinevtSubscribe* winevtSubscribe;
|
53
67
|
|
54
|
-
TypedData_Get_Struct(
|
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
|
79
|
+
struct WinevtSubscribe* winevtSubscribe;
|
65
80
|
|
66
|
-
TypedData_Get_Struct(
|
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
|
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
|
97
|
+
struct WinevtSubscribe* winevtSubscribe;
|
82
98
|
|
83
99
|
hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
84
100
|
|
85
|
-
TypedData_Get_Struct(
|
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 =
|
97
|
-
|
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(
|
103
|
-
|
104
|
-
|
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 =
|
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
|
140
|
-
ULONG
|
141
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
159
|
-
struct WinevtSubscribe *winevtSubscribe;
|
160
|
-
VALUE utf8str;
|
232
|
+
struct WinevtSubscribe* winevtSubscribe;
|
161
233
|
|
162
|
-
TypedData_Get_Struct(
|
163
|
-
|
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 (
|
167
|
-
|
168
|
-
|
169
|
-
|
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(
|
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
|
-
|
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(
|
258
|
+
rb_winevt_subscribe_string_inserts(EVT_HANDLE event)
|
191
259
|
{
|
192
|
-
|
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
|
266
|
+
struct WinevtSubscribe* winevtSubscribe;
|
202
267
|
|
203
|
-
TypedData_Get_Struct(
|
268
|
+
TypedData_Get_Struct(
|
269
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
204
270
|
|
205
|
-
|
206
|
-
|
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(
|
287
|
+
TypedData_Get_Struct(
|
288
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
220
289
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
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(
|
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
|
-
|
249
|
-
struct WinevtSubscribe *winevtSubscribe;
|
250
|
-
VALUE utf8str;
|
316
|
+
struct WinevtSubscribe* winevtSubscribe;
|
251
317
|
|
252
|
-
TypedData_Get_Struct(
|
318
|
+
TypedData_Get_Struct(
|
319
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
253
320
|
|
254
|
-
|
255
|
-
|
321
|
+
return render_to_rb_str(winevtSubscribe->bookmark, EvtRenderBookmark);
|
322
|
+
}
|
256
323
|
|
257
|
-
|
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
|
-
|
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
|
}
|