winevt_c 0.8.0 → 0.9.3

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