winevt_c 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,132 +1,132 @@
1
- #ifndef _WINEVT_C_H_
2
- #define _WINEVT_C_H_
3
-
4
- #include <ruby.h>
5
- #include <ruby/encoding.h>
6
-
7
- #ifdef __GNUC__
8
- #include <w32api.h>
9
- #define MINIMUM_WINDOWS_VERSION WindowsVista
10
- #else /* __GNUC__ */
11
- #define MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */
12
- #endif /* __GNUC__ */
13
-
14
- #ifdef _WIN32_WINNT
15
- #undef _WIN32_WINNT
16
- #endif /* WIN32_WINNT */
17
- #define _WIN32_WINNT MINIMUM_WINDOWS_VERSION
18
-
19
- #include <time.h>
20
- #include <winevt.h>
21
- #define EventQuery(object) ((struct WinevtQuery*)DATA_PTR(object))
22
- #define EventBookMark(object) ((struct WinevtBookmark*)DATA_PTR(object))
23
- #define EventChannel(object) ((struct WinevtChannel*)DATA_PTR(object))
24
- #define EventSession(object) ((struct WinevtSession*)DATA_PTR(object))
25
-
26
- typedef struct {
27
- LANGID langID;
28
- CHAR* langCode;
29
- CHAR* description;
30
- } LocaleInfo;
31
-
32
- #ifdef __cplusplus
33
- extern "C" {
34
- #endif /* __cplusplus */
35
-
36
- VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
37
- #if defined(__cplusplus)
38
- [[ noreturn ]]
39
- #endif /* __cplusplus */
40
- void raise_system_error(VALUE error, DWORD errorCode);
41
- VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
42
- EVT_HANDLE connect_to_remote(LPWSTR computerName, LPWSTR domain,
43
- LPWSTR username, LPWSTR password,
44
- EVT_RPC_LOGIN_FLAGS flags);
45
- WCHAR* get_description(EVT_HANDLE handle, LANGID langID, EVT_HANDLE hRemote);
46
- VALUE get_values(EVT_HANDLE handle);
47
- VALUE render_system_event(EVT_HANDLE handle, BOOL preserve_qualifiers);
48
- LocaleInfo* get_locale_info_from_rb_str(VALUE rb_locale_str);
49
-
50
- #ifdef __cplusplus
51
- }
52
- #endif /* __cplusplus */
53
-
54
- extern VALUE rb_cQuery;
55
- extern VALUE rb_cFlag;
56
- extern VALUE rb_cChannel;
57
- extern VALUE rb_cBookmark;
58
- extern VALUE rb_cSubscribe;
59
- extern VALUE rb_eWinevtQueryError;
60
- extern VALUE rb_eRemoteHandlerError;
61
- extern VALUE rb_cLocale;
62
- extern VALUE rb_cSession;
63
-
64
- struct WinevtSession {
65
- LPWSTR server;
66
- LPWSTR domain;
67
- LPWSTR username;
68
- LPWSTR password;
69
- EVT_RPC_LOGIN_FLAGS flags;
70
- };
71
-
72
- extern LocaleInfo localeInfoTable[];
73
- extern LocaleInfo default_locale;
74
-
75
- struct WinevtLocale {};
76
-
77
- struct WinevtChannel
78
- {
79
- EVT_HANDLE channels;
80
- BOOL force_enumerate;
81
- };
82
-
83
- struct WinevtBookmark
84
- {
85
- EVT_HANDLE bookmark;
86
- ULONG count;
87
- };
88
-
89
- #define QUERY_ARRAY_SIZE 10
90
-
91
- struct WinevtQuery
92
- {
93
- EVT_HANDLE query;
94
- EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
95
- ULONG count;
96
- LONG offset;
97
- LONG timeout;
98
- BOOL renderAsXML;
99
- BOOL preserveQualifiers;
100
- LocaleInfo *localeInfo;
101
- EVT_HANDLE remoteHandle;
102
- };
103
-
104
- #define SUBSCRIBE_ARRAY_SIZE 10
105
- #define SUBSCRIBE_RATE_INFINITE -1
106
-
107
- struct WinevtSubscribe
108
- {
109
- HANDLE signalEvent;
110
- EVT_HANDLE subscription;
111
- EVT_HANDLE bookmark;
112
- EVT_HANDLE hEvents[SUBSCRIBE_ARRAY_SIZE];
113
- DWORD count;
114
- DWORD flags;
115
- BOOL readExistingEvents;
116
- DWORD rateLimit;
117
- time_t lastTime;
118
- DWORD currentRate;
119
- BOOL renderAsXML;
120
- BOOL preserveQualifiers;
121
- LocaleInfo* localeInfo;
122
- EVT_HANDLE remoteHandle;
123
- };
124
-
125
- void Init_winevt_query(VALUE rb_cEventLog);
126
- void Init_winevt_channel(VALUE rb_cEventLog);
127
- void Init_winevt_bookmark(VALUE rb_cEventLog);
128
- void Init_winevt_subscribe(VALUE rb_cEventLog);
129
- void Init_winevt_locale(VALUE rb_cEventLog);
130
- void Init_winevt_session(VALUE rb_cEventLog);
131
-
132
- #endif // _WINEVT_C_H
1
+ #ifndef _WINEVT_C_H_
2
+ #define _WINEVT_C_H_
3
+
4
+ #include <ruby.h>
5
+ #include <ruby/encoding.h>
6
+
7
+ #ifdef __GNUC__
8
+ #include <w32api.h>
9
+ #define MINIMUM_WINDOWS_VERSION WindowsVista
10
+ #else /* __GNUC__ */
11
+ #define MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */
12
+ #endif /* __GNUC__ */
13
+
14
+ #ifdef _WIN32_WINNT
15
+ #undef _WIN32_WINNT
16
+ #endif /* WIN32_WINNT */
17
+ #define _WIN32_WINNT MINIMUM_WINDOWS_VERSION
18
+
19
+ #include <time.h>
20
+ #include <winevt.h>
21
+ #define EventQuery(object) ((struct WinevtQuery*)DATA_PTR(object))
22
+ #define EventBookMark(object) ((struct WinevtBookmark*)DATA_PTR(object))
23
+ #define EventChannel(object) ((struct WinevtChannel*)DATA_PTR(object))
24
+ #define EventSession(object) ((struct WinevtSession*)DATA_PTR(object))
25
+
26
+ typedef struct {
27
+ LANGID langID;
28
+ CHAR* langCode;
29
+ CHAR* description;
30
+ } LocaleInfo;
31
+
32
+ #ifdef __cplusplus
33
+ extern "C" {
34
+ #endif /* __cplusplus */
35
+
36
+ VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
37
+ #if defined(__cplusplus)
38
+ [[ noreturn ]]
39
+ #endif /* __cplusplus */
40
+ void raise_system_error(VALUE error, DWORD errorCode);
41
+ VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
42
+ EVT_HANDLE connect_to_remote(LPWSTR computerName, LPWSTR domain,
43
+ LPWSTR username, LPWSTR password,
44
+ EVT_RPC_LOGIN_FLAGS flags);
45
+ WCHAR* get_description(EVT_HANDLE handle, LANGID langID, EVT_HANDLE hRemote);
46
+ VALUE get_values(EVT_HANDLE handle);
47
+ VALUE render_system_event(EVT_HANDLE handle, BOOL preserve_qualifiers);
48
+ LocaleInfo* get_locale_info_from_rb_str(VALUE rb_locale_str);
49
+
50
+ #ifdef __cplusplus
51
+ }
52
+ #endif /* __cplusplus */
53
+
54
+ extern VALUE rb_cQuery;
55
+ extern VALUE rb_cFlag;
56
+ extern VALUE rb_cChannel;
57
+ extern VALUE rb_cBookmark;
58
+ extern VALUE rb_cSubscribe;
59
+ extern VALUE rb_eWinevtQueryError;
60
+ extern VALUE rb_eRemoteHandlerError;
61
+ extern VALUE rb_cLocale;
62
+ extern VALUE rb_cSession;
63
+
64
+ struct WinevtSession {
65
+ LPWSTR server;
66
+ LPWSTR domain;
67
+ LPWSTR username;
68
+ LPWSTR password;
69
+ EVT_RPC_LOGIN_FLAGS flags;
70
+ };
71
+
72
+ extern LocaleInfo localeInfoTable[];
73
+ extern LocaleInfo default_locale;
74
+
75
+ struct WinevtLocale {};
76
+
77
+ struct WinevtChannel
78
+ {
79
+ EVT_HANDLE channels;
80
+ BOOL force_enumerate;
81
+ };
82
+
83
+ struct WinevtBookmark
84
+ {
85
+ EVT_HANDLE bookmark;
86
+ ULONG count;
87
+ };
88
+
89
+ #define QUERY_ARRAY_SIZE 10
90
+
91
+ struct WinevtQuery
92
+ {
93
+ EVT_HANDLE query;
94
+ EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
95
+ ULONG count;
96
+ LONG offset;
97
+ LONG timeout;
98
+ BOOL renderAsXML;
99
+ BOOL preserveQualifiers;
100
+ LocaleInfo *localeInfo;
101
+ EVT_HANDLE remoteHandle;
102
+ };
103
+
104
+ #define SUBSCRIBE_ARRAY_SIZE 10
105
+ #define SUBSCRIBE_RATE_INFINITE -1
106
+
107
+ struct WinevtSubscribe
108
+ {
109
+ HANDLE signalEvent;
110
+ EVT_HANDLE subscription;
111
+ EVT_HANDLE bookmark;
112
+ EVT_HANDLE hEvents[SUBSCRIBE_ARRAY_SIZE];
113
+ DWORD count;
114
+ DWORD flags;
115
+ BOOL readExistingEvents;
116
+ DWORD rateLimit;
117
+ time_t lastTime;
118
+ DWORD currentRate;
119
+ BOOL renderAsXML;
120
+ BOOL preserveQualifiers;
121
+ LocaleInfo* localeInfo;
122
+ EVT_HANDLE remoteHandle;
123
+ };
124
+
125
+ void Init_winevt_query(VALUE rb_cEventLog);
126
+ void Init_winevt_channel(VALUE rb_cEventLog);
127
+ void Init_winevt_bookmark(VALUE rb_cEventLog);
128
+ void Init_winevt_subscribe(VALUE rb_cEventLog);
129
+ void Init_winevt_locale(VALUE rb_cEventLog);
130
+ void Init_winevt_session(VALUE rb_cEventLog);
131
+
132
+ #endif // _WINEVT_C_H
@@ -1,327 +1,327 @@
1
- #include <winevt_c.h>
2
-
3
- /*
4
- * Document-class: Winevt::EventLog::Channel
5
- *
6
- * Retrieve Windows EventLog channel name.
7
- *
8
- * @example
9
- * require 'winevt'
10
- * channels = []
11
- * @channel = Winevt::EventLog::Channel.new
12
- * # If users want to retrieve all channel names that
13
- * # including type of Debug and Analytical,
14
- * # it should be set as true.
15
- * @channel.force_enumerate = false
16
- * @channel.each do |channel|
17
- * channels << channel
18
- * end
19
- * print channels
20
- */
21
-
22
- VALUE rb_cChannel;
23
-
24
- DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate);
25
- DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate);
26
- static void channel_free(void* ptr);
27
-
28
- static const rb_data_type_t rb_winevt_channel_type = { "winevt/channel",
29
- {
30
- 0,
31
- channel_free,
32
- 0,
33
- },
34
- NULL,
35
- NULL,
36
- RUBY_TYPED_FREE_IMMEDIATELY };
37
-
38
- static void
39
- channel_free(void* ptr)
40
- {
41
- struct WinevtChannel* winevtChannel = (struct WinevtChannel*)ptr;
42
- if (winevtChannel->channels)
43
- EvtClose(winevtChannel->channels);
44
-
45
- xfree(ptr);
46
- }
47
-
48
- static VALUE
49
- rb_winevt_channel_alloc(VALUE klass)
50
- {
51
- VALUE obj;
52
- struct WinevtChannel* winevtChannel;
53
- obj = TypedData_Make_Struct(
54
- klass, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
55
- return obj;
56
- }
57
-
58
- /*
59
- * Initalize Channel class.
60
- *
61
- * @return [Channel]
62
- *
63
- */
64
- static VALUE
65
- rb_winevt_channel_initialize(VALUE self)
66
- {
67
- struct WinevtChannel* winevtChannel;
68
-
69
- TypedData_Get_Struct(
70
- self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
71
-
72
- winevtChannel->force_enumerate = FALSE;
73
-
74
- return Qnil;
75
- }
76
-
77
- /*
78
- * This method specifies whether forcing to enumerate channel which
79
- * type is Debug and Analytical or not.
80
- *
81
- * @param rb_force_enumerate_p [Boolean]
82
- * @since 0.7.1
83
- */
84
- static VALUE
85
- rb_winevt_channel_set_force_enumerate(VALUE self, VALUE rb_force_enumerate_p)
86
- {
87
- struct WinevtChannel* winevtChannel;
88
-
89
- TypedData_Get_Struct(
90
- self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
91
-
92
- winevtChannel->force_enumerate = RTEST(rb_force_enumerate_p);
93
-
94
- return Qnil;
95
- }
96
-
97
- /*
98
- * This method returns whether forcing to enumerate channel which type
99
- * is Debug and Analytical or not.
100
- *
101
- * @return [Boolean]
102
- * @since 0.7.1
103
- */
104
- static VALUE
105
- rb_winevt_channel_get_force_enumerate(VALUE self)
106
- {
107
- struct WinevtChannel* winevtChannel;
108
-
109
- TypedData_Get_Struct(
110
- self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
111
-
112
- return winevtChannel->force_enumerate ? Qtrue : Qfalse;
113
- }
114
-
115
- DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate)
116
- {
117
- PEVT_VARIANT pProperty = NULL;
118
- PEVT_VARIANT pTemp = NULL;
119
- DWORD dwBufferSize = 0;
120
- DWORD dwBufferUsed = 0;
121
- DWORD status = ERROR_SUCCESS;
122
-
123
- for (int Id = 0; Id < EvtChannelConfigPropertyIdEND; Id++) {
124
- if (!EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed)) {
125
- status = GetLastError();
126
- if (ERROR_INSUFFICIENT_BUFFER == status) {
127
- dwBufferSize = dwBufferUsed;
128
- pTemp = (PEVT_VARIANT)realloc(pProperty, dwBufferSize);
129
- if (pTemp) {
130
- pProperty = pTemp;
131
- pTemp = NULL;
132
- EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed);
133
- status = GetLastError();
134
- } else {
135
- free(pProperty);
136
-
137
- status = ERROR_OUTOFMEMORY;
138
-
139
- goto cleanup;
140
- }
141
- }
142
-
143
- if (ERROR_SUCCESS != status) {
144
- free(pProperty);
145
-
146
- goto cleanup;
147
- }
148
- }
149
-
150
- status = check_subscribable_with_channel_config_type(Id, pProperty, force_enumerate);
151
- if (status != ERROR_SUCCESS)
152
- break;
153
- }
154
-
155
- cleanup:
156
-
157
- free(pProperty);
158
-
159
- return status;
160
- }
161
-
162
- #define EVENT_DEBUG_TYPE 2
163
- #define EVENT_ANALYTICAL_TYPE 3
164
-
165
- DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate)
166
- {
167
- DWORD status = ERROR_SUCCESS;
168
- switch(Id) {
169
- case EvtChannelConfigType:
170
- if (!force_enumerate &&
171
- (pProperty->UInt32Val == EVENT_DEBUG_TYPE ||
172
- pProperty->UInt32Val == EVENT_ANALYTICAL_TYPE)) {
173
- return ERROR_INVALID_DATA;
174
- }
175
- break;
176
- }
177
-
178
- return status;
179
- }
180
-
181
- #undef EVENT_DEBUG_TYPE
182
- #undef EVENT_ANALYTICAL_TYPE
183
-
184
- /*
185
- * Enumerate Windows EventLog channels
186
- *
187
- * @yield (String)
188
- *
189
- */
190
- static VALUE
191
- rb_winevt_channel_each(VALUE self)
192
- {
193
- EVT_HANDLE hChannels;
194
- EVT_HANDLE hChannelConfig = NULL;
195
- struct WinevtChannel* winevtChannel;
196
- char errBuf[256];
197
- LPWSTR buffer = NULL;
198
- DWORD bufferSize = 0;
199
- DWORD bufferUsed = 0;
200
- DWORD status = ERROR_SUCCESS;
201
- VALUE utf8str;
202
-
203
- RETURN_ENUMERATOR(self, 0, 0);
204
-
205
- TypedData_Get_Struct(
206
- self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
207
-
208
- hChannels = EvtOpenChannelEnum(NULL, 0);
209
-
210
- if (hChannels) {
211
- winevtChannel->channels = hChannels;
212
- } else {
213
- _snprintf_s(errBuf,
214
- _countof(errBuf),
215
- _TRUNCATE,
216
- "Failed to enumerate channels with %lu\n",
217
- GetLastError());
218
- rb_raise(rb_eRuntimeError, errBuf);
219
- }
220
-
221
- while (1) {
222
- if (!EvtNextChannelPath(winevtChannel->channels, bufferSize, buffer, &bufferUsed)) {
223
- status = GetLastError();
224
-
225
- if (ERROR_NO_MORE_ITEMS == status) {
226
- break;
227
- } else if (ERROR_INSUFFICIENT_BUFFER == status) {
228
- bufferSize = bufferUsed;
229
- buffer = (LPWSTR)malloc(bufferSize * sizeof(WCHAR));
230
- if (buffer) {
231
- continue;
232
- } else {
233
- free(buffer);
234
- EvtClose(winevtChannel->channels);
235
- winevtChannel->channels = NULL;
236
- rb_raise(rb_eRuntimeError, "realloc failed");
237
- }
238
- } else {
239
- free(buffer);
240
- EvtClose(winevtChannel->channels);
241
- winevtChannel->channels = NULL;
242
- _snprintf_s(errBuf,
243
- _countof(errBuf),
244
- _TRUNCATE,
245
- "EvtNextChannelPath failed with %lu.\n",
246
- status);
247
- rb_raise(rb_eRuntimeError, errBuf);
248
- }
249
- }
250
- hChannelConfig = EvtOpenChannelConfig(NULL, buffer, 0);
251
- if (NULL == hChannelConfig) {
252
- _snprintf_s(errBuf,
253
- _countof(errBuf),
254
- _TRUNCATE,
255
- "EvtOpenChannelConfig failed with %lu.\n",
256
- GetLastError());
257
-
258
- EvtClose(winevtChannel->channels);
259
- winevtChannel->channels = NULL;
260
-
261
- free(buffer);
262
- buffer = NULL;
263
- bufferSize = 0;
264
-
265
- rb_raise(rb_eRuntimeError, errBuf);
266
- }
267
-
268
- status = is_subscribable_channel_p(hChannelConfig, winevtChannel->force_enumerate);
269
- EvtClose(hChannelConfig);
270
-
271
- if (status == ERROR_INVALID_DATA) {
272
- free(buffer);
273
- buffer = NULL;
274
- bufferSize = 0;
275
-
276
- continue;
277
- }
278
-
279
- if (status == ERROR_OUTOFMEMORY) {
280
- EvtClose(winevtChannel->channels);
281
- winevtChannel->channels = NULL;
282
-
283
- free(buffer);
284
- buffer = NULL;
285
- bufferSize = 0;
286
-
287
- rb_raise(rb_eRuntimeError, "realloc failed\n");
288
- } else if (status != ERROR_SUCCESS) {
289
- EvtClose(winevtChannel->channels);
290
- winevtChannel->channels = NULL;
291
-
292
- free(buffer);
293
- buffer = NULL;
294
- bufferSize = 0;
295
-
296
- rb_raise(rb_eRuntimeError, "is_subscribe_channel_p is failed with %ld\n", status);
297
- }
298
-
299
- utf8str = wstr_to_rb_str(CP_UTF8, buffer, -1);
300
-
301
- free(buffer);
302
- buffer = NULL;
303
- bufferSize = 0;
304
-
305
- rb_yield(utf8str);
306
- }
307
-
308
- if (winevtChannel->channels) {
309
- EvtClose(winevtChannel->channels);
310
- winevtChannel->channels = NULL;
311
- }
312
-
313
- free(buffer);
314
-
315
- return Qnil;
316
- }
317
-
318
- void
319
- Init_winevt_channel(VALUE rb_cEventLog)
320
- {
321
- rb_cChannel = rb_define_class_under(rb_cEventLog, "Channel", rb_cObject);
322
- rb_define_alloc_func(rb_cChannel, rb_winevt_channel_alloc);
323
- rb_define_method(rb_cChannel, "initialize", rb_winevt_channel_initialize, 0);
324
- rb_define_method(rb_cChannel, "each", rb_winevt_channel_each, 0);
325
- rb_define_method(rb_cChannel, "force_enumerate", rb_winevt_channel_get_force_enumerate, 0);
326
- rb_define_method(rb_cChannel, "force_enumerate=", rb_winevt_channel_set_force_enumerate, 1);
327
- }
1
+ #include <winevt_c.h>
2
+
3
+ /*
4
+ * Document-class: Winevt::EventLog::Channel
5
+ *
6
+ * Retrieve Windows EventLog channel name.
7
+ *
8
+ * @example
9
+ * require 'winevt'
10
+ * channels = []
11
+ * @channel = Winevt::EventLog::Channel.new
12
+ * # If users want to retrieve all channel names that
13
+ * # including type of Debug and Analytical,
14
+ * # it should be set as true.
15
+ * @channel.force_enumerate = false
16
+ * @channel.each do |channel|
17
+ * channels << channel
18
+ * end
19
+ * print channels
20
+ */
21
+
22
+ VALUE rb_cChannel;
23
+
24
+ DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate);
25
+ DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate);
26
+ static void channel_free(void* ptr);
27
+
28
+ static const rb_data_type_t rb_winevt_channel_type = { "winevt/channel",
29
+ {
30
+ 0,
31
+ channel_free,
32
+ 0,
33
+ },
34
+ NULL,
35
+ NULL,
36
+ RUBY_TYPED_FREE_IMMEDIATELY };
37
+
38
+ static void
39
+ channel_free(void* ptr)
40
+ {
41
+ struct WinevtChannel* winevtChannel = (struct WinevtChannel*)ptr;
42
+ if (winevtChannel->channels)
43
+ EvtClose(winevtChannel->channels);
44
+
45
+ xfree(ptr);
46
+ }
47
+
48
+ static VALUE
49
+ rb_winevt_channel_alloc(VALUE klass)
50
+ {
51
+ VALUE obj;
52
+ struct WinevtChannel* winevtChannel;
53
+ obj = TypedData_Make_Struct(
54
+ klass, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
55
+ return obj;
56
+ }
57
+
58
+ /*
59
+ * Initalize Channel class.
60
+ *
61
+ * @return [Channel]
62
+ *
63
+ */
64
+ static VALUE
65
+ rb_winevt_channel_initialize(VALUE self)
66
+ {
67
+ struct WinevtChannel* winevtChannel;
68
+
69
+ TypedData_Get_Struct(
70
+ self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
71
+
72
+ winevtChannel->force_enumerate = FALSE;
73
+
74
+ return Qnil;
75
+ }
76
+
77
+ /*
78
+ * This method specifies whether forcing to enumerate channel which
79
+ * type is Debug and Analytical or not.
80
+ *
81
+ * @param rb_force_enumerate_p [Boolean]
82
+ * @since 0.7.1
83
+ */
84
+ static VALUE
85
+ rb_winevt_channel_set_force_enumerate(VALUE self, VALUE rb_force_enumerate_p)
86
+ {
87
+ struct WinevtChannel* winevtChannel;
88
+
89
+ TypedData_Get_Struct(
90
+ self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
91
+
92
+ winevtChannel->force_enumerate = RTEST(rb_force_enumerate_p);
93
+
94
+ return Qnil;
95
+ }
96
+
97
+ /*
98
+ * This method returns whether forcing to enumerate channel which type
99
+ * is Debug and Analytical or not.
100
+ *
101
+ * @return [Boolean]
102
+ * @since 0.7.1
103
+ */
104
+ static VALUE
105
+ rb_winevt_channel_get_force_enumerate(VALUE self)
106
+ {
107
+ struct WinevtChannel* winevtChannel;
108
+
109
+ TypedData_Get_Struct(
110
+ self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
111
+
112
+ return winevtChannel->force_enumerate ? Qtrue : Qfalse;
113
+ }
114
+
115
+ DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate)
116
+ {
117
+ PEVT_VARIANT pProperty = NULL;
118
+ PEVT_VARIANT pTemp = NULL;
119
+ DWORD dwBufferSize = 0;
120
+ DWORD dwBufferUsed = 0;
121
+ DWORD status = ERROR_SUCCESS;
122
+
123
+ for (int Id = 0; Id < EvtChannelConfigPropertyIdEND; Id++) {
124
+ if (!EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed)) {
125
+ status = GetLastError();
126
+ if (ERROR_INSUFFICIENT_BUFFER == status) {
127
+ dwBufferSize = dwBufferUsed;
128
+ pTemp = (PEVT_VARIANT)realloc(pProperty, dwBufferSize);
129
+ if (pTemp) {
130
+ pProperty = pTemp;
131
+ pTemp = NULL;
132
+ EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed);
133
+ status = GetLastError();
134
+ } else {
135
+ free(pProperty);
136
+
137
+ status = ERROR_OUTOFMEMORY;
138
+
139
+ goto cleanup;
140
+ }
141
+ }
142
+
143
+ if (ERROR_SUCCESS != status) {
144
+ free(pProperty);
145
+
146
+ goto cleanup;
147
+ }
148
+ }
149
+
150
+ status = check_subscribable_with_channel_config_type(Id, pProperty, force_enumerate);
151
+ if (status != ERROR_SUCCESS)
152
+ break;
153
+ }
154
+
155
+ cleanup:
156
+
157
+ free(pProperty);
158
+
159
+ return status;
160
+ }
161
+
162
+ #define EVENT_DEBUG_TYPE 2
163
+ #define EVENT_ANALYTICAL_TYPE 3
164
+
165
+ DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate)
166
+ {
167
+ DWORD status = ERROR_SUCCESS;
168
+ switch(Id) {
169
+ case EvtChannelConfigType:
170
+ if (!force_enumerate &&
171
+ (pProperty->UInt32Val == EVENT_DEBUG_TYPE ||
172
+ pProperty->UInt32Val == EVENT_ANALYTICAL_TYPE)) {
173
+ return ERROR_INVALID_DATA;
174
+ }
175
+ break;
176
+ }
177
+
178
+ return status;
179
+ }
180
+
181
+ #undef EVENT_DEBUG_TYPE
182
+ #undef EVENT_ANALYTICAL_TYPE
183
+
184
+ /*
185
+ * Enumerate Windows EventLog channels
186
+ *
187
+ * @yield (String)
188
+ *
189
+ */
190
+ static VALUE
191
+ rb_winevt_channel_each(VALUE self)
192
+ {
193
+ EVT_HANDLE hChannels;
194
+ EVT_HANDLE hChannelConfig = NULL;
195
+ struct WinevtChannel* winevtChannel;
196
+ char errBuf[256];
197
+ LPWSTR buffer = NULL;
198
+ DWORD bufferSize = 0;
199
+ DWORD bufferUsed = 0;
200
+ DWORD status = ERROR_SUCCESS;
201
+ VALUE utf8str;
202
+
203
+ RETURN_ENUMERATOR(self, 0, 0);
204
+
205
+ TypedData_Get_Struct(
206
+ self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
207
+
208
+ hChannels = EvtOpenChannelEnum(NULL, 0);
209
+
210
+ if (hChannels) {
211
+ winevtChannel->channels = hChannels;
212
+ } else {
213
+ _snprintf_s(errBuf,
214
+ _countof(errBuf),
215
+ _TRUNCATE,
216
+ "Failed to enumerate channels with %lu\n",
217
+ GetLastError());
218
+ rb_raise(rb_eRuntimeError, errBuf);
219
+ }
220
+
221
+ while (1) {
222
+ if (!EvtNextChannelPath(winevtChannel->channels, bufferSize, buffer, &bufferUsed)) {
223
+ status = GetLastError();
224
+
225
+ if (ERROR_NO_MORE_ITEMS == status) {
226
+ break;
227
+ } else if (ERROR_INSUFFICIENT_BUFFER == status) {
228
+ bufferSize = bufferUsed;
229
+ buffer = (LPWSTR)malloc(bufferSize * sizeof(WCHAR));
230
+ if (buffer) {
231
+ continue;
232
+ } else {
233
+ free(buffer);
234
+ EvtClose(winevtChannel->channels);
235
+ winevtChannel->channels = NULL;
236
+ rb_raise(rb_eRuntimeError, "realloc failed");
237
+ }
238
+ } else {
239
+ free(buffer);
240
+ EvtClose(winevtChannel->channels);
241
+ winevtChannel->channels = NULL;
242
+ _snprintf_s(errBuf,
243
+ _countof(errBuf),
244
+ _TRUNCATE,
245
+ "EvtNextChannelPath failed with %lu.\n",
246
+ status);
247
+ rb_raise(rb_eRuntimeError, errBuf);
248
+ }
249
+ }
250
+ hChannelConfig = EvtOpenChannelConfig(NULL, buffer, 0);
251
+ if (NULL == hChannelConfig) {
252
+ _snprintf_s(errBuf,
253
+ _countof(errBuf),
254
+ _TRUNCATE,
255
+ "EvtOpenChannelConfig failed with %lu.\n",
256
+ GetLastError());
257
+
258
+ EvtClose(winevtChannel->channels);
259
+ winevtChannel->channels = NULL;
260
+
261
+ free(buffer);
262
+ buffer = NULL;
263
+ bufferSize = 0;
264
+
265
+ rb_raise(rb_eRuntimeError, errBuf);
266
+ }
267
+
268
+ status = is_subscribable_channel_p(hChannelConfig, winevtChannel->force_enumerate);
269
+ EvtClose(hChannelConfig);
270
+
271
+ if (status == ERROR_INVALID_DATA) {
272
+ free(buffer);
273
+ buffer = NULL;
274
+ bufferSize = 0;
275
+
276
+ continue;
277
+ }
278
+
279
+ if (status == ERROR_OUTOFMEMORY) {
280
+ EvtClose(winevtChannel->channels);
281
+ winevtChannel->channels = NULL;
282
+
283
+ free(buffer);
284
+ buffer = NULL;
285
+ bufferSize = 0;
286
+
287
+ rb_raise(rb_eRuntimeError, "realloc failed\n");
288
+ } else if (status != ERROR_SUCCESS) {
289
+ EvtClose(winevtChannel->channels);
290
+ winevtChannel->channels = NULL;
291
+
292
+ free(buffer);
293
+ buffer = NULL;
294
+ bufferSize = 0;
295
+
296
+ rb_raise(rb_eRuntimeError, "is_subscribe_channel_p is failed with %ld\n", status);
297
+ }
298
+
299
+ utf8str = wstr_to_rb_str(CP_UTF8, buffer, -1);
300
+
301
+ free(buffer);
302
+ buffer = NULL;
303
+ bufferSize = 0;
304
+
305
+ rb_yield(utf8str);
306
+ }
307
+
308
+ if (winevtChannel->channels) {
309
+ EvtClose(winevtChannel->channels);
310
+ winevtChannel->channels = NULL;
311
+ }
312
+
313
+ free(buffer);
314
+
315
+ return Qnil;
316
+ }
317
+
318
+ void
319
+ Init_winevt_channel(VALUE rb_cEventLog)
320
+ {
321
+ rb_cChannel = rb_define_class_under(rb_cEventLog, "Channel", rb_cObject);
322
+ rb_define_alloc_func(rb_cChannel, rb_winevt_channel_alloc);
323
+ rb_define_method(rb_cChannel, "initialize", rb_winevt_channel_initialize, 0);
324
+ rb_define_method(rb_cChannel, "each", rb_winevt_channel_each, 0);
325
+ rb_define_method(rb_cChannel, "force_enumerate", rb_winevt_channel_get_force_enumerate, 0);
326
+ rb_define_method(rb_cChannel, "force_enumerate=", rb_winevt_channel_set_force_enumerate, 1);
327
+ }