winevt_c 0.7.4 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,92 @@
1
+ #include <winevt_c.h>
2
+
3
+
4
+ /* clang-format off */
5
+ /*
6
+ * Document-class: Winevt::EventLog::Locale
7
+ *
8
+ * handle locales for Windows EventLog's description.
9
+ *
10
+ * @example
11
+ * require 'winevt'
12
+ *
13
+ * @locale = Winevt::EventLog::Locale.new
14
+ * @locale.each {|code, desc|
15
+ * print code, desc
16
+ * }
17
+ * @since v0.8.1
18
+ */
19
+ /* clang-format on */
20
+
21
+ VALUE rb_cLocale;
22
+
23
+ static void locale_free(void* ptr);
24
+
25
+ static const rb_data_type_t rb_winevt_locale_type = { "winevt/locale",
26
+ {
27
+ 0,
28
+ locale_free,
29
+ 0,
30
+ },
31
+ NULL,
32
+ NULL,
33
+ RUBY_TYPED_FREE_IMMEDIATELY };
34
+
35
+ static void
36
+ locale_free(void* ptr)
37
+ {
38
+ xfree(ptr);
39
+ }
40
+
41
+ static VALUE
42
+ rb_winevt_locale_alloc(VALUE klass)
43
+ {
44
+ VALUE obj;
45
+ struct WinevtLocale* winevtLocale;
46
+ obj = TypedData_Make_Struct(
47
+ klass, struct WinevtLocale, &rb_winevt_locale_type, winevtLocale);
48
+ return obj;
49
+ }
50
+
51
+ /*
52
+ * Initalize Locale class.
53
+ *
54
+ * @return [Locale]
55
+ *
56
+ */
57
+ static VALUE
58
+ rb_winevt_locale_initialize(VALUE self)
59
+ {
60
+ return Qnil;
61
+ }
62
+
63
+ /*
64
+ * Enumerate supported locales and its descriptions
65
+ *
66
+ * @yield (String, String)
67
+ *
68
+ */
69
+ static VALUE
70
+ rb_winevt_locale_each(VALUE self)
71
+ {
72
+ RETURN_ENUMERATOR(self, 0, 0);
73
+
74
+ for (int i = 0; localeInfoTable[i].langCode != NULL; i++) {
75
+ rb_yield_values(2,
76
+ rb_utf8_str_new_cstr(localeInfoTable[i].langCode),
77
+ rb_utf8_str_new_cstr(localeInfoTable[i].description));
78
+ }
79
+
80
+ return Qnil;
81
+ }
82
+
83
+ void
84
+ Init_winevt_locale(VALUE rb_cEventLog)
85
+ {
86
+ rb_cLocale = rb_define_class_under(rb_cEventLog, "Locale", rb_cObject);
87
+
88
+ rb_define_alloc_func(rb_cLocale, rb_winevt_locale_alloc);
89
+
90
+ rb_define_method(rb_cLocale, "initialize", rb_winevt_locale_initialize, 0);
91
+ rb_define_method(rb_cLocale, "each", rb_winevt_locale_each, 0);
92
+ }
@@ -0,0 +1,68 @@
1
+ #include <winevt_c.h>
2
+
3
+ LocaleInfo localeInfoTable [] = {
4
+ { MAKELANGID(LANG_BULGARIAN, SUBLANG_DEFAULT), "bg_BG", "Bulgarian"},
5
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), "zh_CN", "Simplified Chinese "},
6
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), "zh_TW", "Traditional Chinese"},
7
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), "zh_HK", "Chinese (Hong Kong)"},
8
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE), "zh_SG", "Chinese (Singapore)"},
9
+ { MAKELANGID(LANG_CROATIAN, SUBLANG_DEFAULT), "hr_HR", "Croatian"},
10
+ { MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT), "cs_CZ", "Czech"},
11
+ { MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT), "da_DK", "Dannish"},
12
+ { MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), "nl_NL", "Dutch"},
13
+ { MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN), "nl_BE", "Dutch (Belgium)"},
14
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), "en_US", "English (United States)"},
15
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), "en_GB", "English (UK)"},
16
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS), "en_AU", "English (Australia)"},
17
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN), "en_CA", "English (Canada)"},
18
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_NZ), "en_NZ", "English (New Zealand)"},
19
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_EIRE), "en_IE", "English (Ireland)"},
20
+ { MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT), "fi_FI", "Finnish"},
21
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), "fr_FR", "French"},
22
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_BELGIAN), "fr_BE", "French (Belgium)"},
23
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CANADIAN), "fr_CA", "French (Canada)"},
24
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_SWISS), "fr_CH", "French (Swiss)"},
25
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), "de_DE", "German"},
26
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS), "de_CH", "German (Swiss)"},
27
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN), "de_AT", "German (Austria))"},
28
+ { MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT), "el_GR", "Greek (Ελληνικά)"},
29
+ { MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT), "hu_HU", "Hungarian"},
30
+ { MAKELANGID(LANG_ICELANDIC, SUBLANG_DEFAULT), "is_IS", "Icelandic"},
31
+ { MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), "it_IT", "Italian (Italy)"},
32
+ { MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN_SWISS), "it_CH", "Italian (Swiss)"},
33
+ { MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), "ja_JP", "Japanases"},
34
+ { MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), "ko_KO", "Korean"},
35
+ { MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL), "no_NO", "Norwegian (Bokmål)"},
36
+ { MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL), "nb_NO", "Norwegian (Bokmål)"},
37
+ { MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK), "nn_NO", "Norwegian (Nynorsk)"},
38
+ { MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), "pl_PL", "Polish"},
39
+ { MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE), "pt_PT", "Portuguese"},
40
+ { MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), "pt_BR", "Portuguese (Brazil)"},
41
+ { MAKELANGID(LANG_ROMANIAN, SUBLANG_DEFAULT), "ro_RO", "Romanian"},
42
+ { MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT), "ru_RU", "Russian (русский язык)"},
43
+ { MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT), "sk_SK", "Slovak"},
44
+ { MAKELANGID(LANG_SLOVENIAN, SUBLANG_DEFAULT), "sl_SI", "Slovenian"},
45
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), "es_ES", "Spanish"},
46
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), "es_ES_T", "Spanish (Traditional)"},
47
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MEXICAN), "es_MX", "Spanish (Mexico)"},
48
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), "es_ES_M", "Spanish (Modern)"},
49
+ { MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT), "sv_SE", "Swedish"},
50
+ { MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT), "tr_TR", "Turkish"},
51
+ { 0, NULL, NULL}
52
+ };
53
+
54
+ LocaleInfo default_locale = {MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "neutral", "Default"};
55
+
56
+ LocaleInfo*
57
+ get_locale_info_from_rb_str(VALUE rb_locale_str)
58
+ {
59
+ CHAR* locale_str = StringValuePtr(rb_locale_str);
60
+
61
+ for (int i = 0; localeInfoTable[i].langCode != NULL; i++) {
62
+ if (stricmp(localeInfoTable[i].langCode, locale_str) == 0) {
63
+ return &localeInfoTable[i];
64
+ }
65
+ }
66
+
67
+ rb_raise(rb_eArgError, "Unknown locale: %s", locale_str);
68
+ }
@@ -1,500 +1,650 @@
1
- #include <winevt_c.h>
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
- VALUE rb_cFlag;
21
-
22
- static void query_free(void* ptr);
23
-
24
- static const rb_data_type_t rb_winevt_query_type = { "winevt/query",
25
- {
26
- 0,
27
- query_free,
28
- 0,
29
- },
30
- NULL,
31
- NULL,
32
- RUBY_TYPED_FREE_IMMEDIATELY };
33
-
34
- static void
35
- query_free(void* ptr)
36
- {
37
- struct WinevtQuery* winevtQuery = (struct WinevtQuery*)ptr;
38
- if (winevtQuery->query)
39
- EvtClose(winevtQuery->query);
40
-
41
- for (int i = 0; i < winevtQuery->count; i++) {
42
- if (winevtQuery->hEvents[i])
43
- EvtClose(winevtQuery->hEvents[i]);
44
- }
45
- xfree(ptr);
46
- }
47
-
48
- static VALUE
49
- rb_winevt_query_alloc(VALUE klass)
50
- {
51
- VALUE obj;
52
- struct WinevtQuery* winevtQuery;
53
- obj =
54
- TypedData_Make_Struct(klass, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
55
- return obj;
56
- }
57
-
58
- /*
59
- * Initalize Query class.
60
- *
61
- * @param channel [String] Querying EventLog channel.
62
- * @param xpath [String] Querying XPath.
63
- * @return [Query]
64
- *
65
- */
66
- static VALUE
67
- rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
68
- {
69
- PWSTR evtChannel, evtXPath;
70
- struct WinevtQuery* winevtQuery;
71
- DWORD len;
72
- VALUE wchannelBuf, wpathBuf;
73
-
74
- Check_Type(channel, T_STRING);
75
- Check_Type(xpath, T_STRING);
76
-
77
- // channel : To wide char
78
- len =
79
- MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), NULL, 0);
80
- evtChannel = ALLOCV_N(WCHAR, wchannelBuf, len + 1);
81
- MultiByteToWideChar(
82
- CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), evtChannel, len);
83
- evtChannel[len] = L'\0';
84
-
85
- // xpath : To wide char
86
- len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(xpath), RSTRING_LEN(xpath), NULL, 0);
87
- evtXPath = ALLOCV_N(WCHAR, wpathBuf, len + 1);
88
- MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(xpath), RSTRING_LEN(xpath), evtXPath, len);
89
- evtXPath[len] = L'\0';
90
-
91
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
92
-
93
- winevtQuery->query = EvtQuery(
94
- NULL, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
95
- winevtQuery->offset = 0L;
96
- winevtQuery->timeout = 0L;
97
- winevtQuery->renderAsXML = TRUE;
98
- winevtQuery->preserveQualifiers = FALSE;
99
-
100
- ALLOCV_END(wchannelBuf);
101
- ALLOCV_END(wpathBuf);
102
-
103
- return Qnil;
104
- }
105
-
106
- /*
107
- * This method returns querying event offset.
108
- *
109
- * @return [Integer]
110
- */
111
- static VALUE
112
- rb_winevt_query_get_offset(VALUE self)
113
- {
114
- struct WinevtQuery* winevtQuery;
115
-
116
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
117
-
118
- return LONG2NUM(winevtQuery->offset);
119
- }
120
-
121
- /*
122
- * This method specifies querying event offset.
123
- *
124
- * @param offset [Integer] offset value
125
- */
126
- static VALUE
127
- rb_winevt_query_set_offset(VALUE self, VALUE offset)
128
- {
129
- struct WinevtQuery* winevtQuery;
130
-
131
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
132
-
133
- winevtQuery->offset = NUM2LONG(offset);
134
-
135
- return Qnil;
136
- }
137
-
138
- /*
139
- * This method returns timeout value.
140
- *
141
- * @return [Integer]
142
- */
143
- static VALUE
144
- rb_winevt_query_get_timeout(VALUE self)
145
- {
146
- struct WinevtQuery* winevtQuery;
147
-
148
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
149
-
150
- return LONG2NUM(winevtQuery->timeout);
151
- }
152
-
153
- /*
154
- * This method specifies timeout value.
155
- *
156
- * @param timeout [Integer] timeout value
157
- */
158
- static VALUE
159
- rb_winevt_query_set_timeout(VALUE self, VALUE timeout)
160
- {
161
- struct WinevtQuery* winevtQuery;
162
-
163
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
164
-
165
- winevtQuery->timeout = NUM2LONG(timeout);
166
-
167
- return Qnil;
168
- }
169
-
170
- /*
171
- * Handle the next values. Since v0.6.0, this method is used for
172
- * testing only. Please use #each instead.
173
- *
174
- * @return [Boolean]
175
- *
176
- * @see each
177
- */
178
- static VALUE
179
- rb_winevt_query_next(VALUE self)
180
- {
181
- EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
182
- ULONG count;
183
- DWORD status = ERROR_SUCCESS;
184
- struct WinevtQuery* winevtQuery;
185
-
186
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
187
-
188
- if (!EvtNext(winevtQuery->query, QUERY_ARRAY_SIZE, hEvents, INFINITE, 0, &count)) {
189
- status = GetLastError();
190
- if (ERROR_NO_MORE_ITEMS != status) {
191
- return Qfalse;
192
- }
193
- }
194
-
195
- if (status == ERROR_SUCCESS) {
196
- winevtQuery->count = count;
197
- for (int i = 0; i < count; i++) {
198
- winevtQuery->hEvents[i] = hEvents[i];
199
- }
200
-
201
- return Qtrue;
202
- }
203
-
204
- return Qfalse;
205
- }
206
-
207
- static VALUE
208
- rb_winevt_query_render(VALUE self, EVT_HANDLE event)
209
- {
210
- struct WinevtQuery* winevtQuery;
211
-
212
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
213
-
214
- if (winevtQuery->renderAsXML) {
215
- return render_to_rb_str(event, EvtRenderEventXml);
216
- } else {
217
- return render_system_event(event, winevtQuery->preserveQualifiers);
218
- }
219
- }
220
-
221
- static VALUE
222
- rb_winevt_query_message(EVT_HANDLE event)
223
- {
224
- WCHAR* wResult;
225
- VALUE utf8str;
226
-
227
- wResult = get_description(event);
228
- utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
229
- free(wResult);
230
-
231
- return utf8str;
232
- }
233
-
234
- static VALUE
235
- rb_winevt_query_string_inserts(EVT_HANDLE event)
236
- {
237
- return get_values(event);
238
- }
239
-
240
- static DWORD
241
- get_evt_seek_flag_from_cstr(char* flag_str)
242
- {
243
- if (strcmp(flag_str, "first") == 0)
244
- return EvtSeekRelativeToFirst;
245
- else if (strcmp(flag_str, "last") == 0)
246
- return EvtSeekRelativeToLast;
247
- else if (strcmp(flag_str, "current") == 0)
248
- return EvtSeekRelativeToCurrent;
249
- else if (strcmp(flag_str, "bookmark") == 0)
250
- return EvtSeekRelativeToBookmark;
251
- else if (strcmp(flag_str, "originmask") == 0)
252
- return EvtSeekOriginMask;
253
- else if (strcmp(flag_str, "strict") == 0)
254
- return EvtSeekStrict;
255
- else
256
- rb_raise(rb_eArgError, "Unknown seek flag: %s", flag_str);
257
-
258
- return 0;
259
- }
260
-
261
- /*
262
- * This method specifies seek strategy.
263
- *
264
- * @param bookmark_or_flag [Bookmark|Query::Flag]
265
- * @return [Boolean]
266
- */
267
- static VALUE
268
- rb_winevt_query_seek(VALUE self, VALUE bookmark_or_flag)
269
- {
270
- struct WinevtQuery* winevtQuery;
271
- struct WinevtBookmark* winevtBookmark = NULL;
272
- DWORD flag = 0;
273
-
274
- switch (TYPE(bookmark_or_flag)) {
275
- case T_SYMBOL:
276
- flag = get_evt_seek_flag_from_cstr(RSTRING_PTR(rb_sym2str(bookmark_or_flag)));
277
- break;
278
- case T_STRING:
279
- flag = get_evt_seek_flag_from_cstr(StringValueCStr(bookmark_or_flag));
280
- break;
281
- case T_FIXNUM:
282
- flag = NUM2LONG(bookmark_or_flag);
283
- break;
284
- default:
285
- if (!rb_obj_is_kind_of(bookmark_or_flag, rb_cBookmark))
286
- rb_raise(rb_eArgError, "Expected a String or a Symbol or a Bookmark instance");
287
-
288
- winevtBookmark = EventBookMark(bookmark_or_flag);
289
- }
290
-
291
- if (winevtBookmark) {
292
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
293
- if (EvtSeek(winevtQuery->query,
294
- winevtQuery->offset,
295
- winevtBookmark->bookmark,
296
- winevtQuery->timeout,
297
- EvtSeekRelativeToBookmark))
298
- return Qtrue;
299
- } else {
300
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
301
- if (EvtSeek(
302
- winevtQuery->query, winevtQuery->offset, NULL, winevtQuery->timeout, flag)) {
303
- return Qtrue;
304
- }
305
- }
306
-
307
- return Qfalse;
308
- }
309
-
310
- static VALUE
311
- rb_winevt_query_close_handle(VALUE self)
312
- {
313
- struct WinevtQuery* winevtQuery;
314
-
315
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
316
-
317
- for (int i = 0; i < winevtQuery->count; i++) {
318
- if (winevtQuery->hEvents[i] != NULL) {
319
- EvtClose(winevtQuery->hEvents[i]);
320
- winevtQuery->hEvents[i] = NULL;
321
- }
322
- }
323
-
324
- return Qnil;
325
- }
326
-
327
- static VALUE
328
- rb_winevt_query_each_yield(VALUE self)
329
- {
330
- RETURN_ENUMERATOR(self, 0, 0);
331
-
332
- struct WinevtQuery* winevtQuery;
333
-
334
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
335
-
336
- for (int i = 0; i < winevtQuery->count; i++) {
337
- rb_yield_values(3,
338
- rb_winevt_query_render(self, winevtQuery->hEvents[i]),
339
- rb_winevt_query_message(winevtQuery->hEvents[i]),
340
- rb_winevt_query_string_inserts(winevtQuery->hEvents[i]));
341
- }
342
- return Qnil;
343
- }
344
-
345
- /*
346
- * Enumerate to obtain Windows EventLog contents.
347
- *
348
- * This method yields the following:
349
- * (Stringified EventLog, Stringified detail message, Stringified
350
- * insert values)
351
- *
352
- * @yield (String,String,String)
353
- *
354
- */
355
- static VALUE
356
- rb_winevt_query_each(VALUE self)
357
- {
358
- RETURN_ENUMERATOR(self, 0, 0);
359
-
360
- while (rb_winevt_query_next(self)) {
361
- rb_ensure(rb_winevt_query_each_yield, self, rb_winevt_query_close_handle, self);
362
- }
363
-
364
- return Qnil;
365
- }
366
-
367
- /*
368
- * This method returns whether render as xml or not.
369
- *
370
- * @return [Boolean]
371
- */
372
- static VALUE
373
- rb_winevt_query_render_as_xml_p(VALUE self)
374
- {
375
- struct WinevtQuery* winevtQuery;
376
-
377
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
378
-
379
- return winevtQuery->renderAsXML ? Qtrue : Qfalse;
380
- }
381
-
382
- /*
383
- * This method specifies whether render as xml or not.
384
- *
385
- * @param rb_render_as_xml [Boolean]
386
- */
387
- static VALUE
388
- rb_winevt_query_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
389
- {
390
- struct WinevtQuery* winevtQuery;
391
-
392
- TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
393
-
394
- winevtQuery->renderAsXML = RTEST(rb_render_as_xml);
395
-
396
- return Qnil;
397
- }
398
-
399
- /*
400
- * This method specifies whether preserving qualifiers key or not.
401
- *
402
- * @since 0.7.3
403
- * @param rb_render_as_xml [Boolean]
404
- */
405
- static VALUE
406
- rb_winevt_query_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
407
- {
408
- struct WinevtQuery* winevtQuery;
409
-
410
- TypedData_Get_Struct(
411
- self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
412
-
413
- winevtQuery->preserveQualifiers = RTEST(rb_preserve_qualifiers);
414
-
415
- return Qnil;
416
- }
417
-
418
- /*
419
- * This method returns whether preserving qualifiers or not.
420
- *
421
- * @since 0.7.3
422
- * @return [Integer]
423
- */
424
- static VALUE
425
- rb_winevt_query_get_preserve_qualifiers_p(VALUE self)
426
- {
427
- struct WinevtQuery* winevtQuery;
428
-
429
- TypedData_Get_Struct(
430
- self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
431
-
432
- return winevtQuery->preserveQualifiers ? Qtrue : Qfalse;
433
- }
434
-
435
- void
436
- Init_winevt_query(VALUE rb_cEventLog)
437
- {
438
- rb_cQuery = rb_define_class_under(rb_cEventLog, "Query", rb_cObject);
439
- rb_define_alloc_func(rb_cQuery, rb_winevt_query_alloc);
440
-
441
- rb_cFlag = rb_define_module_under(rb_cQuery, "Flag");
442
-
443
- /* clang-format off */
444
- /*
445
- * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToFirst
446
- * @since 0.6.0
447
- * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToFirst
448
- */
449
- rb_define_const(rb_cFlag, "RelativeToFirst", LONG2NUM(EvtSeekRelativeToFirst));
450
- /*
451
- * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToLast
452
- * @since 0.6.0
453
- * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToLast
454
- */
455
- rb_define_const(rb_cFlag, "RelativeToLast", LONG2NUM(EvtSeekRelativeToLast));
456
- /*
457
- * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToCurrent
458
- * @since 0.6.0
459
- * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToCurrent
460
- */
461
- rb_define_const(rb_cFlag, "RelativeToCurrent", LONG2NUM(EvtSeekRelativeToCurrent));
462
- /*
463
- * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToBookmark
464
- * @since 0.6.0
465
- * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToBookmark
466
- */
467
- rb_define_const(rb_cFlag, "RelativeToBookmark", LONG2NUM(EvtSeekRelativeToBookmark));
468
- /*
469
- * EVT_SEEK_FLAGS enumeration: EvtSeekOriginMask
470
- * @since 0.6.0
471
- * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekOriginMask
472
- */
473
- rb_define_const(rb_cFlag, "OriginMask", LONG2NUM(EvtSeekOriginMask));
474
- /*
475
- * EVT_SEEK_FLAGS enumeration: EvtSeekStrict
476
- * @since 0.6.0
477
- * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekStrict
478
- */
479
- rb_define_const(rb_cFlag, "Strict", LONG2NUM(EvtSeekStrict));
480
- /* clang-format on */
481
-
482
- rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, 2);
483
- rb_define_method(rb_cQuery, "next", rb_winevt_query_next, 0);
484
- rb_define_method(rb_cQuery, "seek", rb_winevt_query_seek, 1);
485
- rb_define_method(rb_cQuery, "offset", rb_winevt_query_get_offset, 0);
486
- rb_define_method(rb_cQuery, "offset=", rb_winevt_query_set_offset, 1);
487
- rb_define_method(rb_cQuery, "timeout", rb_winevt_query_get_timeout, 0);
488
- rb_define_method(rb_cQuery, "timeout=", rb_winevt_query_set_timeout, 1);
489
- rb_define_method(rb_cQuery, "each", rb_winevt_query_each, 0);
490
- rb_define_method(rb_cQuery, "render_as_xml?", rb_winevt_query_render_as_xml_p, 0);
491
- rb_define_method(rb_cQuery, "render_as_xml=", rb_winevt_query_set_render_as_xml, 1);
492
- /*
493
- * @since 0.7.3
494
- */
495
- rb_define_method(rb_cQuery, "preserve_qualifiers?", rb_winevt_query_get_preserve_qualifiers_p, 0);
496
- /*
497
- * @since 0.7.3
498
- */
499
- rb_define_method(rb_cQuery, "preserve_qualifiers=", rb_winevt_query_set_preserve_qualifiers, 1);
500
- }
1
+ #include <winevt_c.h>
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
+ VALUE rb_cFlag;
21
+
22
+ static void query_free(void* ptr);
23
+
24
+ static const rb_data_type_t rb_winevt_query_type = { "winevt/query",
25
+ {
26
+ 0,
27
+ query_free,
28
+ 0,
29
+ },
30
+ NULL,
31
+ NULL,
32
+ RUBY_TYPED_FREE_IMMEDIATELY };
33
+
34
+ static void
35
+ close_handles(struct WinevtQuery* winevtQuery)
36
+ {
37
+ if (winevtQuery->query) {
38
+ EvtClose(winevtQuery->query);
39
+ winevtQuery->query = NULL;
40
+ }
41
+
42
+ for (int i = 0; i < winevtQuery->count; i++) {
43
+ if (winevtQuery->hEvents[i]) {
44
+ EvtClose(winevtQuery->hEvents[i]);
45
+ winevtQuery->hEvents[i] = NULL;
46
+ }
47
+ }
48
+
49
+ if (winevtQuery->remoteHandle) {
50
+ EvtClose(winevtQuery->remoteHandle);
51
+ winevtQuery->remoteHandle = NULL;
52
+ }
53
+ }
54
+
55
+ static void
56
+ query_free(void* ptr)
57
+ {
58
+ struct WinevtQuery* winevtQuery = (struct WinevtQuery*)ptr;
59
+ close_handles(winevtQuery);
60
+
61
+ xfree(ptr);
62
+ }
63
+
64
+ static VALUE
65
+ rb_winevt_query_alloc(VALUE klass)
66
+ {
67
+ VALUE obj;
68
+ struct WinevtQuery* winevtQuery;
69
+ obj =
70
+ TypedData_Make_Struct(klass, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
71
+ return obj;
72
+ }
73
+
74
+ /*
75
+ * Initalize Query class.
76
+ *
77
+ * @overload initialize(channel, xpath, session=nil)
78
+ * @param channel [String] Querying EventLog channel.
79
+ * @param xpath [String] Querying XPath.
80
+ * @param session [Session] Session information for remoting access.
81
+ * @return [Query]
82
+ *
83
+ */
84
+ static VALUE
85
+ rb_winevt_query_initialize(VALUE argc, VALUE *argv, VALUE self)
86
+ {
87
+ PWSTR evtChannel, evtXPath;
88
+ VALUE channel, xpath, session;
89
+ struct WinevtQuery* winevtQuery;
90
+ struct WinevtSession* winevtSession;
91
+ EVT_HANDLE hRemoteHandle = NULL;
92
+ DWORD len;
93
+ VALUE wchannelBuf, wpathBuf;
94
+ DWORD err;
95
+
96
+ rb_scan_args(argc, argv, "21", &channel, &xpath, &session);
97
+ Check_Type(channel, T_STRING);
98
+ Check_Type(xpath, T_STRING);
99
+
100
+ if (rb_obj_is_kind_of(session, rb_cSession)) {
101
+ winevtSession = EventSession(session);
102
+
103
+ hRemoteHandle = connect_to_remote(winevtSession->server,
104
+ winevtSession->domain,
105
+ winevtSession->username,
106
+ winevtSession->password,
107
+ winevtSession->flags);
108
+
109
+ err = GetLastError();
110
+ if (err != ERROR_SUCCESS) {
111
+ raise_system_error(rb_eRuntimeError, err);
112
+ }
113
+ }
114
+
115
+ // channel : To wide char
116
+ len =
117
+ MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), NULL, 0);
118
+ evtChannel = ALLOCV_N(WCHAR, wchannelBuf, len + 1);
119
+ MultiByteToWideChar(
120
+ CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), evtChannel, len);
121
+ evtChannel[len] = L'\0';
122
+
123
+ // xpath : To wide char
124
+ len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(xpath), RSTRING_LEN(xpath), NULL, 0);
125
+ evtXPath = ALLOCV_N(WCHAR, wpathBuf, len + 1);
126
+ MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(xpath), RSTRING_LEN(xpath), evtXPath, len);
127
+ evtXPath[len] = L'\0';
128
+
129
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
130
+
131
+ winevtQuery->query = EvtQuery(
132
+ hRemoteHandle, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
133
+ err = GetLastError();
134
+ if (err != ERROR_SUCCESS) {
135
+ raise_system_error(rb_eRuntimeError, err);
136
+ }
137
+ winevtQuery->offset = 0L;
138
+ winevtQuery->timeout = 0L;
139
+ winevtQuery->renderAsXML = TRUE;
140
+ winevtQuery->preserveQualifiers = FALSE;
141
+ winevtQuery->localeInfo = &default_locale;
142
+ winevtQuery->remoteHandle = hRemoteHandle;
143
+
144
+ ALLOCV_END(wchannelBuf);
145
+ ALLOCV_END(wpathBuf);
146
+
147
+ return Qnil;
148
+ }
149
+
150
+ /*
151
+ * This method returns querying event offset.
152
+ *
153
+ * @return [Integer]
154
+ */
155
+ static VALUE
156
+ rb_winevt_query_get_offset(VALUE self)
157
+ {
158
+ struct WinevtQuery* winevtQuery;
159
+
160
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
161
+
162
+ return LONG2NUM(winevtQuery->offset);
163
+ }
164
+
165
+ /*
166
+ * This method specifies querying event offset.
167
+ *
168
+ * @param offset [Integer] offset value
169
+ */
170
+ static VALUE
171
+ rb_winevt_query_set_offset(VALUE self, VALUE offset)
172
+ {
173
+ struct WinevtQuery* winevtQuery;
174
+
175
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
176
+
177
+ winevtQuery->offset = NUM2LONG(offset);
178
+
179
+ return Qnil;
180
+ }
181
+
182
+ /*
183
+ * This method returns timeout value.
184
+ *
185
+ * @return [Integer]
186
+ */
187
+ static VALUE
188
+ rb_winevt_query_get_timeout(VALUE self)
189
+ {
190
+ struct WinevtQuery* winevtQuery;
191
+
192
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
193
+
194
+ return LONG2NUM(winevtQuery->timeout);
195
+ }
196
+
197
+ /*
198
+ * This method specifies timeout value.
199
+ *
200
+ * @param timeout [Integer] timeout value
201
+ */
202
+ static VALUE
203
+ rb_winevt_query_set_timeout(VALUE self, VALUE timeout)
204
+ {
205
+ struct WinevtQuery* winevtQuery;
206
+
207
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
208
+
209
+ winevtQuery->timeout = NUM2LONG(timeout);
210
+
211
+ return Qnil;
212
+ }
213
+
214
+ /*
215
+ * Handle the next values. Since v0.6.0, this method is used for
216
+ * testing only. Please use #each instead.
217
+ *
218
+ * @return [Boolean]
219
+ *
220
+ * @see each
221
+ */
222
+ static VALUE
223
+ rb_winevt_query_next(VALUE self)
224
+ {
225
+ EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
226
+ ULONG count;
227
+ DWORD status = ERROR_SUCCESS;
228
+ struct WinevtQuery* winevtQuery;
229
+
230
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
231
+
232
+ if (!EvtNext(winevtQuery->query, QUERY_ARRAY_SIZE, hEvents, INFINITE, 0, &count)) {
233
+ status = GetLastError();
234
+ if (ERROR_CANCELLED == status) {
235
+ return Qfalse;
236
+ }
237
+ if (ERROR_NO_MORE_ITEMS != status) {
238
+ return Qfalse;
239
+ }
240
+ }
241
+
242
+ if (status == ERROR_SUCCESS) {
243
+ winevtQuery->count = count;
244
+ for (int i = 0; i < count; i++) {
245
+ winevtQuery->hEvents[i] = hEvents[i];
246
+ }
247
+
248
+ return Qtrue;
249
+ }
250
+
251
+ return Qfalse;
252
+ }
253
+
254
+ static VALUE
255
+ rb_winevt_query_render(VALUE self, EVT_HANDLE event)
256
+ {
257
+ struct WinevtQuery* winevtQuery;
258
+
259
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
260
+
261
+ if (winevtQuery->renderAsXML) {
262
+ return render_to_rb_str(event, EvtRenderEventXml);
263
+ } else {
264
+ return render_system_event(event, winevtQuery->preserveQualifiers);
265
+ }
266
+ }
267
+
268
+ static VALUE
269
+ rb_winevt_query_message(EVT_HANDLE event, LocaleInfo* localeInfo, EVT_HANDLE hRemote)
270
+ {
271
+ WCHAR* wResult;
272
+ VALUE utf8str;
273
+
274
+ wResult = get_description(event, localeInfo->langID, hRemote);
275
+ utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
276
+ free(wResult);
277
+
278
+ return utf8str;
279
+ }
280
+
281
+ static VALUE
282
+ rb_winevt_query_string_inserts(EVT_HANDLE event)
283
+ {
284
+ return get_values(event);
285
+ }
286
+
287
+ static DWORD
288
+ get_evt_seek_flag_from_cstr(char* flag_str)
289
+ {
290
+ if (strcmp(flag_str, "first") == 0)
291
+ return EvtSeekRelativeToFirst;
292
+ else if (strcmp(flag_str, "last") == 0)
293
+ return EvtSeekRelativeToLast;
294
+ else if (strcmp(flag_str, "current") == 0)
295
+ return EvtSeekRelativeToCurrent;
296
+ else if (strcmp(flag_str, "bookmark") == 0)
297
+ return EvtSeekRelativeToBookmark;
298
+ else if (strcmp(flag_str, "originmask") == 0)
299
+ return EvtSeekOriginMask;
300
+ else if (strcmp(flag_str, "strict") == 0)
301
+ return EvtSeekStrict;
302
+ else
303
+ rb_raise(rb_eArgError, "Unknown seek flag: %s", flag_str);
304
+
305
+ return 0;
306
+ }
307
+
308
+ /*
309
+ * This method specifies seek strategy.
310
+ *
311
+ * @param bookmark_or_flag [Bookmark|Query::Flag]
312
+ * @return [Boolean]
313
+ */
314
+ static VALUE
315
+ rb_winevt_query_seek(VALUE self, VALUE bookmark_or_flag)
316
+ {
317
+ struct WinevtQuery* winevtQuery;
318
+ struct WinevtBookmark* winevtBookmark = NULL;
319
+ DWORD flag = 0;
320
+
321
+ switch (TYPE(bookmark_or_flag)) {
322
+ case T_SYMBOL:
323
+ flag = get_evt_seek_flag_from_cstr(RSTRING_PTR(rb_sym2str(bookmark_or_flag)));
324
+ break;
325
+ case T_STRING:
326
+ flag = get_evt_seek_flag_from_cstr(StringValueCStr(bookmark_or_flag));
327
+ break;
328
+ case T_FIXNUM:
329
+ flag = NUM2LONG(bookmark_or_flag);
330
+ break;
331
+ default:
332
+ if (!rb_obj_is_kind_of(bookmark_or_flag, rb_cBookmark))
333
+ rb_raise(rb_eArgError, "Expected a String or a Symbol or a Bookmark instance");
334
+
335
+ winevtBookmark = EventBookMark(bookmark_or_flag);
336
+ }
337
+
338
+ if (winevtBookmark) {
339
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
340
+ if (EvtSeek(winevtQuery->query,
341
+ winevtQuery->offset,
342
+ winevtBookmark->bookmark,
343
+ winevtQuery->timeout,
344
+ EvtSeekRelativeToBookmark))
345
+ return Qtrue;
346
+ } else {
347
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
348
+ if (EvtSeek(
349
+ winevtQuery->query, winevtQuery->offset, NULL, winevtQuery->timeout, flag)) {
350
+ return Qtrue;
351
+ }
352
+ }
353
+
354
+ return Qfalse;
355
+ }
356
+
357
+ static VALUE
358
+ rb_winevt_query_close_handle(VALUE self)
359
+ {
360
+ struct WinevtQuery* winevtQuery;
361
+
362
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
363
+
364
+ for (int i = 0; i < winevtQuery->count; i++) {
365
+ if (winevtQuery->hEvents[i] != NULL) {
366
+ EvtClose(winevtQuery->hEvents[i]);
367
+ winevtQuery->hEvents[i] = NULL;
368
+ }
369
+ }
370
+
371
+ return Qnil;
372
+ }
373
+
374
+ static VALUE
375
+ rb_winevt_query_each_yield(VALUE self)
376
+ {
377
+ RETURN_ENUMERATOR(self, 0, 0);
378
+
379
+ struct WinevtQuery* winevtQuery;
380
+
381
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
382
+
383
+ for (int i = 0; i < winevtQuery->count; i++) {
384
+ rb_yield_values(3,
385
+ rb_winevt_query_render(self, winevtQuery->hEvents[i]),
386
+ rb_winevt_query_message(winevtQuery->hEvents[i], winevtQuery->localeInfo,
387
+ winevtQuery->remoteHandle),
388
+ rb_winevt_query_string_inserts(winevtQuery->hEvents[i]));
389
+ }
390
+ return Qnil;
391
+ }
392
+
393
+ /*
394
+ * Enumerate to obtain Windows EventLog contents.
395
+ *
396
+ * This method yields the following:
397
+ * (Stringified EventLog, Stringified detail message, Stringified
398
+ * insert values)
399
+ *
400
+ * @yield (String,String,String)
401
+ *
402
+ */
403
+ static VALUE
404
+ rb_winevt_query_each(VALUE self)
405
+ {
406
+ RETURN_ENUMERATOR(self, 0, 0);
407
+
408
+ while (rb_winevt_query_next(self)) {
409
+ rb_ensure(rb_winevt_query_each_yield, self, rb_winevt_query_close_handle, self);
410
+ }
411
+
412
+ return Qnil;
413
+ }
414
+
415
+ /*
416
+ * This method returns whether render as xml or not.
417
+ *
418
+ * @return [Boolean]
419
+ */
420
+ static VALUE
421
+ rb_winevt_query_render_as_xml_p(VALUE self)
422
+ {
423
+ struct WinevtQuery* winevtQuery;
424
+
425
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
426
+
427
+ return winevtQuery->renderAsXML ? Qtrue : Qfalse;
428
+ }
429
+
430
+ /*
431
+ * This method specifies whether render as xml or not.
432
+ *
433
+ * @param rb_render_as_xml [Boolean]
434
+ */
435
+ static VALUE
436
+ rb_winevt_query_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
437
+ {
438
+ struct WinevtQuery* winevtQuery;
439
+
440
+ TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
441
+
442
+ winevtQuery->renderAsXML = RTEST(rb_render_as_xml);
443
+
444
+ return Qnil;
445
+ }
446
+
447
+ /*
448
+ * This method specifies whether preserving qualifiers key or not.
449
+ *
450
+ * @since 0.7.3
451
+ * @param rb_preserve_qualifiers [Boolean]
452
+ */
453
+ static VALUE
454
+ rb_winevt_query_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
455
+ {
456
+ struct WinevtQuery* winevtQuery;
457
+
458
+ TypedData_Get_Struct(
459
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
460
+
461
+ winevtQuery->preserveQualifiers = RTEST(rb_preserve_qualifiers);
462
+
463
+ return Qnil;
464
+ }
465
+
466
+ /*
467
+ * This method returns whether preserving qualifiers or not.
468
+ *
469
+ * @since 0.7.3
470
+ * @return [Integer]
471
+ */
472
+ static VALUE
473
+ rb_winevt_query_get_preserve_qualifiers_p(VALUE self)
474
+ {
475
+ struct WinevtQuery* winevtQuery;
476
+
477
+ TypedData_Get_Struct(
478
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
479
+
480
+ return winevtQuery->preserveQualifiers ? Qtrue : Qfalse;
481
+ }
482
+
483
+ /*
484
+ * This method specifies locale with [String].
485
+ *
486
+ * @since 0.8.0
487
+ * @param rb_locale_str [String]
488
+ */
489
+ static VALUE
490
+ rb_winevt_query_set_locale(VALUE self, VALUE rb_locale_str)
491
+ {
492
+ struct WinevtQuery* winevtQuery;
493
+ LocaleInfo* locale_info = &default_locale;
494
+
495
+ TypedData_Get_Struct(
496
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
497
+
498
+ locale_info = get_locale_info_from_rb_str(rb_locale_str);
499
+
500
+ winevtQuery->localeInfo = locale_info;
501
+
502
+ return Qnil;
503
+ }
504
+
505
+ /*
506
+ * This method obtains specified locale with [String].
507
+ *
508
+ * @since 0.8.0
509
+ */
510
+ static VALUE
511
+ rb_winevt_query_get_locale(VALUE self)
512
+ {
513
+ struct WinevtQuery* winevtQuery;
514
+
515
+ TypedData_Get_Struct(
516
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
517
+
518
+ if (winevtQuery->localeInfo->langCode) {
519
+ return rb_str_new2(winevtQuery->localeInfo->langCode);
520
+ } else {
521
+ return rb_str_new2(default_locale.langCode);
522
+ }
523
+ }
524
+
525
+ /*
526
+ * This method cancels channel query.
527
+ *
528
+ * @return [Boolean]
529
+ * @since 0.9.1
530
+ */
531
+ static VALUE
532
+ rb_winevt_query_cancel(VALUE self)
533
+ {
534
+ struct WinevtQuery* winevtQuery;
535
+ BOOL result = FALSE;
536
+
537
+ TypedData_Get_Struct(
538
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
539
+
540
+ if (winevtQuery->query) {
541
+ result = EvtCancel(winevtQuery->query);
542
+ }
543
+
544
+ if (result) {
545
+ return Qtrue;
546
+ } else {
547
+ return Qfalse;
548
+ }
549
+ }
550
+
551
+ /*
552
+ * This method closes channel handles forcibly.
553
+ *
554
+ * @since 0.9.1
555
+ */
556
+ static VALUE
557
+ rb_winevt_query_close(VALUE self)
558
+ {
559
+ struct WinevtQuery* winevtQuery;
560
+
561
+ TypedData_Get_Struct(
562
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
563
+
564
+ close_handles(winevtQuery);
565
+
566
+ return Qnil;
567
+ }
568
+
569
+ void
570
+ Init_winevt_query(VALUE rb_cEventLog)
571
+ {
572
+ rb_cQuery = rb_define_class_under(rb_cEventLog, "Query", rb_cObject);
573
+ rb_define_alloc_func(rb_cQuery, rb_winevt_query_alloc);
574
+
575
+ rb_cFlag = rb_define_module_under(rb_cQuery, "Flag");
576
+
577
+ /* clang-format off */
578
+ /*
579
+ * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToFirst
580
+ * @since 0.6.0
581
+ * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToFirst
582
+ */
583
+ rb_define_const(rb_cFlag, "RelativeToFirst", LONG2NUM(EvtSeekRelativeToFirst));
584
+ /*
585
+ * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToLast
586
+ * @since 0.6.0
587
+ * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToLast
588
+ */
589
+ rb_define_const(rb_cFlag, "RelativeToLast", LONG2NUM(EvtSeekRelativeToLast));
590
+ /*
591
+ * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToCurrent
592
+ * @since 0.6.0
593
+ * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToCurrent
594
+ */
595
+ rb_define_const(rb_cFlag, "RelativeToCurrent", LONG2NUM(EvtSeekRelativeToCurrent));
596
+ /*
597
+ * EVT_SEEK_FLAGS enumeration: EvtSeekRelativeToBookmark
598
+ * @since 0.6.0
599
+ * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekRelativeToBookmark
600
+ */
601
+ rb_define_const(rb_cFlag, "RelativeToBookmark", LONG2NUM(EvtSeekRelativeToBookmark));
602
+ /*
603
+ * EVT_SEEK_FLAGS enumeration: EvtSeekOriginMask
604
+ * @since 0.6.0
605
+ * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekOriginMask
606
+ */
607
+ rb_define_const(rb_cFlag, "OriginMask", LONG2NUM(EvtSeekOriginMask));
608
+ /*
609
+ * EVT_SEEK_FLAGS enumeration: EvtSeekStrict
610
+ * @since 0.6.0
611
+ * @see https://msdn.microsoft.com/en-us/windows/desktop/aa385575#EvtSeekStrict
612
+ */
613
+ rb_define_const(rb_cFlag, "Strict", LONG2NUM(EvtSeekStrict));
614
+ /* clang-format on */
615
+
616
+ rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, -1);
617
+ rb_define_method(rb_cQuery, "next", rb_winevt_query_next, 0);
618
+ rb_define_method(rb_cQuery, "seek", rb_winevt_query_seek, 1);
619
+ rb_define_method(rb_cQuery, "offset", rb_winevt_query_get_offset, 0);
620
+ rb_define_method(rb_cQuery, "offset=", rb_winevt_query_set_offset, 1);
621
+ rb_define_method(rb_cQuery, "timeout", rb_winevt_query_get_timeout, 0);
622
+ rb_define_method(rb_cQuery, "timeout=", rb_winevt_query_set_timeout, 1);
623
+ rb_define_method(rb_cQuery, "each", rb_winevt_query_each, 0);
624
+ rb_define_method(rb_cQuery, "render_as_xml?", rb_winevt_query_render_as_xml_p, 0);
625
+ rb_define_method(rb_cQuery, "render_as_xml=", rb_winevt_query_set_render_as_xml, 1);
626
+ /*
627
+ * @since 0.7.3
628
+ */
629
+ rb_define_method(rb_cQuery, "preserve_qualifiers?", rb_winevt_query_get_preserve_qualifiers_p, 0);
630
+ /*
631
+ * @since 0.7.3
632
+ */
633
+ rb_define_method(rb_cQuery, "preserve_qualifiers=", rb_winevt_query_set_preserve_qualifiers, 1);
634
+ /*
635
+ * @since 0.8.0
636
+ */
637
+ rb_define_method(rb_cQuery, "locale", rb_winevt_query_get_locale, 0);
638
+ /*
639
+ * @since 0.8.0
640
+ */
641
+ rb_define_method(rb_cQuery, "locale=", rb_winevt_query_set_locale, 1);
642
+ /*
643
+ * @since 0.9.1
644
+ */
645
+ rb_define_method(rb_cQuery, "cancel", rb_winevt_query_cancel, 0);
646
+ /*
647
+ * @since 0.9.1
648
+ */
649
+ rb_define_method(rb_cQuery, "close", rb_winevt_query_close, 0);
650
+ }