winevt_c 0.8.0 → 0.9.3

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