winevt_c 0.7.3 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +55 -0
- data/example/eventlog.rb +5 -1
- data/example/locale.rb +13 -0
- data/example/tailing.rb +7 -1
- data/ext/winevt/winevt.c +7 -0
- data/ext/winevt/winevt_bookmark.c +2 -0
- data/ext/winevt/winevt_c.h +40 -7
- data/ext/winevt/winevt_channel.c +2 -0
- data/ext/winevt/winevt_locale.c +92 -0
- data/ext/winevt/winevt_locale_info.c +68 -0
- data/ext/winevt/winevt_query.c +164 -13
- data/ext/winevt/winevt_session.c +425 -0
- data/ext/winevt/winevt_subscribe.c +173 -15
- data/ext/winevt/winevt_utils.cpp +25 -3
- data/lib/winevt.rb +1 -0
- data/lib/winevt/session.rb +15 -0
- data/lib/winevt/subscribe.rb +5 -2
- data/lib/winevt/version.rb +1 -1
- metadata +7 -2
@@ -0,0 +1,425 @@
|
|
1
|
+
#include <winevt_c.h>
|
2
|
+
|
3
|
+
/* clang-format off */
|
4
|
+
/*
|
5
|
+
* Document-class: Winevt::EventLog::Session
|
6
|
+
*
|
7
|
+
* Manage Session information for Windows EventLog.
|
8
|
+
*
|
9
|
+
* @example
|
10
|
+
* require 'winevt'
|
11
|
+
*
|
12
|
+
* @session = Winevt::EventLog::Session.new("127.0.0.1")
|
13
|
+
*
|
14
|
+
* @session.domain = "<EXAMPLEGROUP>"
|
15
|
+
* @session.username = "<username>"
|
16
|
+
* @session.password = "<password>"
|
17
|
+
* # Then pass @session veriable into Winevt::EventLog::Query or
|
18
|
+
* # Winevt::EventLog::Subscribe#subscribe
|
19
|
+
* @query = Winevt::EventLog::Query.new(
|
20
|
+
* "Application",
|
21
|
+
* "*[System[(Level <= 3) and TimeCreated[timediff(@SystemTime) <= 86400000]]]",
|
22
|
+
* @session
|
23
|
+
* )
|
24
|
+
* # some stuff.
|
25
|
+
*
|
26
|
+
* @subscribe = Winevt::EventLog::Subscribe.new
|
27
|
+
* @subscribe.subscribe(
|
28
|
+
* "Application",
|
29
|
+
* "*[System[(Level <= 4) and TimeCreated[timediff(@SystemTime) <= 86400000]]]",
|
30
|
+
* @session
|
31
|
+
* )
|
32
|
+
* # And some stuff.
|
33
|
+
* @since v0.9.0
|
34
|
+
*/
|
35
|
+
/* clang-format on */
|
36
|
+
|
37
|
+
VALUE rb_cSession;
|
38
|
+
VALUE rb_cRpcLoginFlag;
|
39
|
+
|
40
|
+
static void session_free(void* ptr);
|
41
|
+
|
42
|
+
static const rb_data_type_t rb_winevt_session_type = { "winevt/session",
|
43
|
+
{
|
44
|
+
0,
|
45
|
+
session_free,
|
46
|
+
0,
|
47
|
+
},
|
48
|
+
NULL,
|
49
|
+
NULL,
|
50
|
+
RUBY_TYPED_FREE_IMMEDIATELY };
|
51
|
+
|
52
|
+
static void
|
53
|
+
session_free(void* ptr)
|
54
|
+
{
|
55
|
+
struct WinevtSession* winevtSession = (struct WinevtSession*)ptr;
|
56
|
+
|
57
|
+
if (winevtSession->server)
|
58
|
+
free(winevtSession->server);
|
59
|
+
if (winevtSession->domain)
|
60
|
+
free(winevtSession->domain);
|
61
|
+
if (winevtSession->username)
|
62
|
+
free(winevtSession->username);
|
63
|
+
if (winevtSession->password)
|
64
|
+
free(winevtSession->password);
|
65
|
+
|
66
|
+
xfree(ptr);
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE
|
70
|
+
rb_winevt_session_alloc(VALUE klass)
|
71
|
+
{
|
72
|
+
VALUE obj;
|
73
|
+
struct WinevtSession* winevtSession;
|
74
|
+
obj = TypedData_Make_Struct(
|
75
|
+
klass, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
76
|
+
return obj;
|
77
|
+
}
|
78
|
+
|
79
|
+
/*
|
80
|
+
* Initalize Session class.
|
81
|
+
*
|
82
|
+
* @overload initialize(server, domain=nil, username=nil, password=nil, flags=Winevt::EventLog::Session::RpcLoginFlag::AuthDefault)
|
83
|
+
* @param server [String] Server ip address or fqdn.
|
84
|
+
* @param domain [String] Domain name.
|
85
|
+
* @param username [String] username on remote server.
|
86
|
+
* @param password [String] Remote server user password.
|
87
|
+
* @param flags [Integer] Flags for authentication method choices.
|
88
|
+
* @return [Session]
|
89
|
+
*
|
90
|
+
*/
|
91
|
+
|
92
|
+
static VALUE
|
93
|
+
rb_winevt_session_initialize(VALUE self)
|
94
|
+
{
|
95
|
+
struct WinevtSession* winevtSession;
|
96
|
+
|
97
|
+
TypedData_Get_Struct(
|
98
|
+
self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
99
|
+
|
100
|
+
winevtSession->server = NULL;
|
101
|
+
winevtSession->domain = NULL;
|
102
|
+
winevtSession->username = NULL;
|
103
|
+
winevtSession->password = NULL;
|
104
|
+
winevtSession->flags = EvtRpcLoginAuthDefault;
|
105
|
+
|
106
|
+
return Qnil;
|
107
|
+
}
|
108
|
+
|
109
|
+
/*
|
110
|
+
* This method returns server for remoting access.
|
111
|
+
*
|
112
|
+
* @return [String]
|
113
|
+
*/
|
114
|
+
static VALUE
|
115
|
+
rb_winevt_session_get_server(VALUE self)
|
116
|
+
{
|
117
|
+
struct WinevtSession* winevtSession;
|
118
|
+
|
119
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
120
|
+
|
121
|
+
if (winevtSession->server) {
|
122
|
+
return wstr_to_rb_str(CP_UTF8, winevtSession->server, -1);
|
123
|
+
} else {
|
124
|
+
return rb_str_new2("(NULL)");
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
* This method specifies server for remoting access.
|
130
|
+
*
|
131
|
+
* @param rb_server [String] server
|
132
|
+
*/
|
133
|
+
static VALUE
|
134
|
+
rb_winevt_session_set_server(VALUE self, VALUE rb_server)
|
135
|
+
{
|
136
|
+
struct WinevtSession* winevtSession;
|
137
|
+
DWORD len;
|
138
|
+
VALUE vserverBuf;
|
139
|
+
PWSTR wServer;
|
140
|
+
|
141
|
+
Check_Type(rb_server, T_STRING);
|
142
|
+
|
143
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
144
|
+
|
145
|
+
len =
|
146
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
147
|
+
RSTRING_PTR(rb_server), RSTRING_LEN(rb_server),
|
148
|
+
NULL, 0);
|
149
|
+
wServer = ALLOCV_N(WCHAR, vserverBuf, len + 1);
|
150
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
151
|
+
RSTRING_PTR(rb_server), RSTRING_LEN(rb_server),
|
152
|
+
wServer, len);
|
153
|
+
winevtSession->server = _wcsdup(wServer);
|
154
|
+
wServer[len] = L'\0';
|
155
|
+
|
156
|
+
ALLOCV_END(vserverBuf);
|
157
|
+
|
158
|
+
return Qnil;
|
159
|
+
}
|
160
|
+
|
161
|
+
/*
|
162
|
+
* This method returns domain for remoting access.
|
163
|
+
*
|
164
|
+
* @return [String]
|
165
|
+
*/
|
166
|
+
static VALUE
|
167
|
+
rb_winevt_session_get_domain(VALUE self)
|
168
|
+
{
|
169
|
+
struct WinevtSession* winevtSession;
|
170
|
+
|
171
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
172
|
+
|
173
|
+
if (winevtSession->domain) {
|
174
|
+
return wstr_to_rb_str(CP_UTF8, winevtSession->domain, -1);
|
175
|
+
} else {
|
176
|
+
return rb_str_new2("(NULL)");
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
/*
|
181
|
+
* This method specifies domain for remoting access.
|
182
|
+
*
|
183
|
+
* @param rb_domain [String] domain
|
184
|
+
*/
|
185
|
+
static VALUE
|
186
|
+
rb_winevt_session_set_domain(VALUE self, VALUE rb_domain)
|
187
|
+
{
|
188
|
+
struct WinevtSession* winevtSession;
|
189
|
+
DWORD len;
|
190
|
+
VALUE vdomainBuf;
|
191
|
+
PWSTR wDomain;
|
192
|
+
|
193
|
+
Check_Type(rb_domain, T_STRING);
|
194
|
+
|
195
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
196
|
+
|
197
|
+
len =
|
198
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
199
|
+
RSTRING_PTR(rb_domain), RSTRING_LEN(rb_domain),
|
200
|
+
NULL, 0);
|
201
|
+
wDomain = ALLOCV_N(WCHAR, vdomainBuf, len + 1);
|
202
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
203
|
+
RSTRING_PTR(rb_domain), RSTRING_LEN(rb_domain),
|
204
|
+
wDomain, len);
|
205
|
+
wDomain[len] = L'\0';
|
206
|
+
|
207
|
+
winevtSession->domain = _wcsdup(wDomain);
|
208
|
+
|
209
|
+
ALLOCV_END(vdomainBuf);
|
210
|
+
|
211
|
+
return Qnil;
|
212
|
+
}
|
213
|
+
|
214
|
+
/*
|
215
|
+
* This method returns username for remoting access.
|
216
|
+
*
|
217
|
+
* @return [String]
|
218
|
+
*/
|
219
|
+
static VALUE
|
220
|
+
rb_winevt_session_get_username(VALUE self)
|
221
|
+
{
|
222
|
+
struct WinevtSession* winevtSession;
|
223
|
+
|
224
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
225
|
+
|
226
|
+
if (winevtSession->username) {
|
227
|
+
return wstr_to_rb_str(CP_UTF8, winevtSession->username, -1);
|
228
|
+
} else {
|
229
|
+
return rb_str_new2("(NULL)");
|
230
|
+
}
|
231
|
+
}
|
232
|
+
|
233
|
+
/*
|
234
|
+
* This method specifies username for remoting access.
|
235
|
+
*
|
236
|
+
* @param rb_username [String] username
|
237
|
+
*/
|
238
|
+
static VALUE
|
239
|
+
rb_winevt_session_set_username(VALUE self, VALUE rb_username)
|
240
|
+
{
|
241
|
+
struct WinevtSession* winevtSession;
|
242
|
+
DWORD len;
|
243
|
+
VALUE vusernameBuf;
|
244
|
+
PWSTR wUsername;
|
245
|
+
|
246
|
+
Check_Type(rb_username, T_STRING);
|
247
|
+
|
248
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
249
|
+
|
250
|
+
len =
|
251
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
252
|
+
RSTRING_PTR(rb_username), RSTRING_LEN(rb_username),
|
253
|
+
NULL, 0);
|
254
|
+
wUsername = ALLOCV_N(WCHAR, vusernameBuf, len + 1);
|
255
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
256
|
+
RSTRING_PTR(rb_username), RSTRING_LEN(rb_username),
|
257
|
+
wUsername, len);
|
258
|
+
wUsername[len] = L'\0';
|
259
|
+
|
260
|
+
winevtSession->username = _wcsdup(wUsername);
|
261
|
+
|
262
|
+
ALLOCV_END(vusernameBuf);
|
263
|
+
|
264
|
+
return Qnil;
|
265
|
+
}
|
266
|
+
|
267
|
+
/*
|
268
|
+
* This method returns password for remoting access.
|
269
|
+
*
|
270
|
+
* @return [String]
|
271
|
+
*/
|
272
|
+
static VALUE
|
273
|
+
rb_winevt_session_get_password(VALUE self)
|
274
|
+
{
|
275
|
+
struct WinevtSession* winevtSession;
|
276
|
+
|
277
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
278
|
+
|
279
|
+
if (winevtSession->password) {
|
280
|
+
return wstr_to_rb_str(CP_UTF8, winevtSession->password, -1);
|
281
|
+
} else {
|
282
|
+
return rb_str_new2("(NULL)");
|
283
|
+
}
|
284
|
+
}
|
285
|
+
|
286
|
+
/*
|
287
|
+
* This method specifies password for remoting access.
|
288
|
+
*
|
289
|
+
* @param rb_password [String] password
|
290
|
+
*/
|
291
|
+
static VALUE
|
292
|
+
rb_winevt_session_set_password(VALUE self, VALUE rb_password)
|
293
|
+
{
|
294
|
+
struct WinevtSession* winevtSession;
|
295
|
+
DWORD len;
|
296
|
+
VALUE vpasswordBuf;
|
297
|
+
PWSTR wPassword;
|
298
|
+
|
299
|
+
Check_Type(rb_password, T_STRING);
|
300
|
+
|
301
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
302
|
+
|
303
|
+
len =
|
304
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
305
|
+
RSTRING_PTR(rb_password), RSTRING_LEN(rb_password),
|
306
|
+
NULL, 0);
|
307
|
+
wPassword = ALLOCV_N(WCHAR, vpasswordBuf, len + 1);
|
308
|
+
MultiByteToWideChar(CP_UTF8, 0,
|
309
|
+
RSTRING_PTR(rb_password), RSTRING_LEN(rb_password),
|
310
|
+
wPassword, len);
|
311
|
+
wPassword[len] = L'\0';
|
312
|
+
|
313
|
+
winevtSession->password = _wcsdup(wPassword);
|
314
|
+
|
315
|
+
ALLOCV_END(vpasswordBuf);
|
316
|
+
|
317
|
+
return Qnil;
|
318
|
+
}
|
319
|
+
|
320
|
+
/*
|
321
|
+
* This method returns flags for remoting access.
|
322
|
+
*
|
323
|
+
* @return [Integer]
|
324
|
+
*/
|
325
|
+
static VALUE
|
326
|
+
rb_winevt_session_get_flags(VALUE self)
|
327
|
+
{
|
328
|
+
struct WinevtSession* winevtSession;
|
329
|
+
|
330
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
331
|
+
|
332
|
+
return LONG2NUM(winevtSession->flags);
|
333
|
+
}
|
334
|
+
|
335
|
+
static DWORD
|
336
|
+
get_session_rpc_login_flag_from_cstr(char* flag_str)
|
337
|
+
{
|
338
|
+
if (strcmp(flag_str, "default") == 0)
|
339
|
+
return EvtRpcLoginAuthDefault;
|
340
|
+
else if (strcmp(flag_str, "negociate") == 0)
|
341
|
+
return EvtRpcLoginAuthNegotiate;
|
342
|
+
else if (strcmp(flag_str, "kerberos") == 0)
|
343
|
+
return EvtRpcLoginAuthKerberos;
|
344
|
+
else if (strcmp(flag_str, "ntlm") == 0)
|
345
|
+
return EvtRpcLoginAuthNTLM;
|
346
|
+
else
|
347
|
+
rb_raise(rb_eArgError, "Unknown rpc login flag: %s", flag_str);
|
348
|
+
|
349
|
+
return 0;
|
350
|
+
}
|
351
|
+
|
352
|
+
|
353
|
+
/*
|
354
|
+
* This method specifies flags for remoting access.
|
355
|
+
*
|
356
|
+
* @param rb_flags [Integer] flags
|
357
|
+
*/
|
358
|
+
static VALUE
|
359
|
+
rb_winevt_session_set_flags(VALUE self, VALUE rb_flags)
|
360
|
+
{
|
361
|
+
struct WinevtSession* winevtSession;
|
362
|
+
EVT_RPC_LOGIN_FLAGS flags = EvtRpcLoginAuthDefault;
|
363
|
+
|
364
|
+
TypedData_Get_Struct(self, struct WinevtSession, &rb_winevt_session_type, winevtSession);
|
365
|
+
|
366
|
+
switch(TYPE(rb_flags)) {
|
367
|
+
case T_SYMBOL:
|
368
|
+
flags = get_session_rpc_login_flag_from_cstr(RSTRING_PTR(rb_sym2str(rb_flags)));
|
369
|
+
break;
|
370
|
+
case T_STRING:
|
371
|
+
flags = get_session_rpc_login_flag_from_cstr(StringValuePtr(rb_flags));
|
372
|
+
break;
|
373
|
+
case T_FIXNUM:
|
374
|
+
flags = NUM2LONG(rb_flags);
|
375
|
+
break;
|
376
|
+
default:
|
377
|
+
rb_raise(rb_eArgError, "Expected Symbol, String or Fixnum in flags");
|
378
|
+
}
|
379
|
+
winevtSession->flags = flags;
|
380
|
+
|
381
|
+
return Qnil;
|
382
|
+
}
|
383
|
+
|
384
|
+
void
|
385
|
+
Init_winevt_session(VALUE rb_cEventLog)
|
386
|
+
{
|
387
|
+
rb_cSession = rb_define_class_under(rb_cEventLog, "Session", rb_cObject);
|
388
|
+
|
389
|
+
rb_define_alloc_func(rb_cSession, rb_winevt_session_alloc);
|
390
|
+
|
391
|
+
rb_cRpcLoginFlag = rb_define_module_under(rb_cSession, "RpcLoginFlag");
|
392
|
+
|
393
|
+
rb_define_method(rb_cSession, "initialize", rb_winevt_session_initialize, 0);
|
394
|
+
rb_define_method(rb_cSession, "server", rb_winevt_session_get_server, 0);
|
395
|
+
rb_define_method(rb_cSession, "server=", rb_winevt_session_set_server, 1);
|
396
|
+
rb_define_method(rb_cSession, "domain", rb_winevt_session_get_domain, 0);
|
397
|
+
rb_define_method(rb_cSession, "domain=", rb_winevt_session_set_domain, 1);
|
398
|
+
rb_define_method(rb_cSession, "username", rb_winevt_session_get_username, 0);
|
399
|
+
rb_define_method(rb_cSession, "username=", rb_winevt_session_set_username, 1);
|
400
|
+
rb_define_method(rb_cSession, "password", rb_winevt_session_get_password, 0);
|
401
|
+
rb_define_method(rb_cSession, "password=", rb_winevt_session_set_password, 1);
|
402
|
+
rb_define_method(rb_cSession, "flags", rb_winevt_session_get_flags, 0);
|
403
|
+
rb_define_method(rb_cSession, "flags=", rb_winevt_session_set_flags, 1);
|
404
|
+
|
405
|
+
/*
|
406
|
+
* EVT_RPC_LOGIN_FLAGS enumeration: EvtRpcLoginAuthDefault
|
407
|
+
* @see https://docs.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_rpc_login_flags
|
408
|
+
*/
|
409
|
+
rb_define_const(rb_cRpcLoginFlag, "AuthDefault", LONG2NUM(EvtRpcLoginAuthDefault));
|
410
|
+
/*
|
411
|
+
* EVT_RPC_LOGIN_FLAGS enumeration: EvtRpcLoginAuthNegociate
|
412
|
+
* @see https://docs.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_rpc_login_flags
|
413
|
+
*/
|
414
|
+
rb_define_const(rb_cRpcLoginFlag, "AuthNegociate", LONG2NUM(EvtRpcLoginAuthNegotiate));
|
415
|
+
/*
|
416
|
+
* EVT_RPC_LOGIN_FLAGS enumeration: EvtRpcLoginAuthKerberos
|
417
|
+
* @see https://docs.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_rpc_login_flags
|
418
|
+
*/
|
419
|
+
rb_define_const(rb_cRpcLoginFlag, "AuthKerberos", LONG2NUM(EvtRpcLoginAuthKerberos));
|
420
|
+
/*
|
421
|
+
* EVT_RPC_LOGIN_FLAGS enumeration: EvtRpcLoginAuthNTLM
|
422
|
+
* @see https://docs.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_rpc_login_flags
|
423
|
+
*/
|
424
|
+
rb_define_const(rb_cRpcLoginFlag, "AuthNTLM", LONG2NUM(EvtRpcLoginAuthNTLM));
|
425
|
+
}
|
@@ -39,23 +39,42 @@ static const rb_data_type_t rb_winevt_subscribe_type = { "winevt/subscribe",
|
|
39
39
|
RUBY_TYPED_FREE_IMMEDIATELY };
|
40
40
|
|
41
41
|
static void
|
42
|
-
|
42
|
+
close_handles(struct WinevtSubscribe* winevtSubscribe)
|
43
43
|
{
|
44
|
-
|
45
|
-
if (winevtSubscribe->signalEvent)
|
44
|
+
if (winevtSubscribe->signalEvent) {
|
46
45
|
CloseHandle(winevtSubscribe->signalEvent);
|
46
|
+
winevtSubscribe->signalEvent = NULL;
|
47
|
+
}
|
47
48
|
|
48
|
-
if (winevtSubscribe->subscription)
|
49
|
+
if (winevtSubscribe->subscription) {
|
49
50
|
EvtClose(winevtSubscribe->subscription);
|
51
|
+
winevtSubscribe->subscription = NULL;
|
52
|
+
}
|
50
53
|
|
51
|
-
if (winevtSubscribe->bookmark)
|
54
|
+
if (winevtSubscribe->bookmark) {
|
52
55
|
EvtClose(winevtSubscribe->bookmark);
|
56
|
+
winevtSubscribe->bookmark = NULL;
|
57
|
+
}
|
53
58
|
|
54
59
|
for (int i = 0; i < winevtSubscribe->count; i++) {
|
55
60
|
if (winevtSubscribe->hEvents[i]) {
|
56
61
|
EvtClose(winevtSubscribe->hEvents[i]);
|
62
|
+
winevtSubscribe->hEvents[i] = NULL;
|
57
63
|
}
|
58
64
|
}
|
65
|
+
winevtSubscribe->count = 0;
|
66
|
+
|
67
|
+
if (winevtSubscribe->remoteHandle) {
|
68
|
+
EvtClose(winevtSubscribe->remoteHandle);
|
69
|
+
winevtSubscribe->remoteHandle = NULL;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
static void
|
74
|
+
subscribe_free(void* ptr)
|
75
|
+
{
|
76
|
+
struct WinevtSubscribe* winevtSubscribe = (struct WinevtSubscribe*)ptr;
|
77
|
+
close_handles(winevtSubscribe);
|
59
78
|
|
60
79
|
xfree(ptr);
|
61
80
|
}
|
@@ -90,6 +109,7 @@ rb_winevt_subscribe_initialize(VALUE self)
|
|
90
109
|
winevtSubscribe->renderAsXML = TRUE;
|
91
110
|
winevtSubscribe->readExistingEvents = TRUE;
|
92
111
|
winevtSubscribe->preserveQualifiers = FALSE;
|
112
|
+
winevtSubscribe->localeInfo = &default_locale;
|
93
113
|
|
94
114
|
return Qnil;
|
95
115
|
}
|
@@ -131,23 +151,27 @@ rb_winevt_subscribe_read_existing_events_p(VALUE self)
|
|
131
151
|
/*
|
132
152
|
* Subscribe into a Windows EventLog channel.
|
133
153
|
*
|
134
|
-
* @overload subscribe(path, query,
|
154
|
+
* @overload subscribe(path, query, bookmark=nil, session=nil)
|
135
155
|
* @param path [String] Subscribe Channel
|
136
156
|
* @param query [String] Query string for channel
|
137
|
-
* @
|
157
|
+
* @param bookmark [Bookmark] bookmark Bookmark class instance.
|
158
|
+
* @param session [Session] Session information for remoting access.
|
138
159
|
* @return [Boolean]
|
139
160
|
*
|
140
161
|
*/
|
141
162
|
static VALUE
|
142
163
|
rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
143
164
|
{
|
144
|
-
VALUE rb_path, rb_query, rb_bookmark;
|
165
|
+
VALUE rb_path, rb_query, rb_bookmark, rb_session;
|
145
166
|
EVT_HANDLE hSubscription = NULL, hBookmark = NULL;
|
146
167
|
HANDLE hSignalEvent;
|
168
|
+
EVT_HANDLE hRemoteHandle = NULL;
|
147
169
|
DWORD len, flags = 0L;
|
170
|
+
DWORD err = ERROR_SUCCESS;
|
148
171
|
VALUE wpathBuf, wqueryBuf, wBookmarkBuf;
|
149
172
|
PWSTR path, query, bookmarkXml;
|
150
173
|
DWORD status = ERROR_SUCCESS;
|
174
|
+
struct WinevtSession* winevtSession;
|
151
175
|
struct WinevtSubscribe* winevtSubscribe;
|
152
176
|
|
153
177
|
hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
@@ -155,7 +179,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
155
179
|
TypedData_Get_Struct(
|
156
180
|
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
157
181
|
|
158
|
-
rb_scan_args(argc, argv, "
|
182
|
+
rb_scan_args(argc, argv, "22", &rb_path, &rb_query, &rb_bookmark, &rb_session);
|
159
183
|
Check_Type(rb_path, T_STRING);
|
160
184
|
Check_Type(rb_query, T_STRING);
|
161
185
|
|
@@ -178,6 +202,19 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
178
202
|
raise_system_error(rb_eWinevtQueryError, status);
|
179
203
|
}
|
180
204
|
}
|
205
|
+
if (rb_obj_is_kind_of(rb_session, rb_cSession)) {
|
206
|
+
winevtSession = EventSession(rb_session);
|
207
|
+
hRemoteHandle = connect_to_remote(winevtSession->server,
|
208
|
+
winevtSession->domain,
|
209
|
+
winevtSession->username,
|
210
|
+
winevtSession->password,
|
211
|
+
winevtSession->flags);
|
212
|
+
|
213
|
+
err = GetLastError();
|
214
|
+
if (err != ERROR_SUCCESS) {
|
215
|
+
raise_system_error(rb_eRuntimeError, err);
|
216
|
+
}
|
217
|
+
}
|
181
218
|
|
182
219
|
// path : To wide char
|
183
220
|
len =
|
@@ -203,7 +240,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
203
240
|
}
|
204
241
|
|
205
242
|
hSubscription =
|
206
|
-
EvtSubscribe(
|
243
|
+
EvtSubscribe(hRemoteHandle, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
|
207
244
|
if (!hSubscription) {
|
208
245
|
if (hBookmark != NULL) {
|
209
246
|
EvtClose(hBookmark);
|
@@ -212,7 +249,11 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
212
249
|
CloseHandle(hSignalEvent);
|
213
250
|
}
|
214
251
|
status = GetLastError();
|
215
|
-
|
252
|
+
if (rb_obj_is_kind_of(rb_session, rb_cSession)) {
|
253
|
+
rb_raise(rb_eRemoteHandlerError, "Remoting subscription is not working. errCode: %ld\n", status);
|
254
|
+
} else {
|
255
|
+
raise_system_error(rb_eWinevtQueryError, status);
|
256
|
+
}
|
216
257
|
}
|
217
258
|
|
218
259
|
if (winevtSubscribe->subscription != NULL) {
|
@@ -225,6 +266,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
|
|
225
266
|
|
226
267
|
winevtSubscribe->signalEvent = hSignalEvent;
|
227
268
|
winevtSubscribe->subscription = hSubscription;
|
269
|
+
winevtSubscribe->remoteHandle = hRemoteHandle;
|
228
270
|
if (hBookmark) {
|
229
271
|
winevtSubscribe->bookmark = hBookmark;
|
230
272
|
} else {
|
@@ -302,6 +344,11 @@ rb_winevt_subscribe_next(VALUE self)
|
|
302
344
|
return Qfalse;
|
303
345
|
}
|
304
346
|
|
347
|
+
/* If subscription handle is NULL, it should return false. */
|
348
|
+
if (!winevtSubscribe->subscription) {
|
349
|
+
return Qfalse;
|
350
|
+
}
|
351
|
+
|
305
352
|
if (!EvtNext(winevtSubscribe->subscription,
|
306
353
|
SUBSCRIBE_ARRAY_SIZE,
|
307
354
|
hEvents,
|
@@ -309,6 +356,9 @@ rb_winevt_subscribe_next(VALUE self)
|
|
309
356
|
0,
|
310
357
|
&count)) {
|
311
358
|
status = GetLastError();
|
359
|
+
if (ERROR_CANCELLED == status) {
|
360
|
+
return Qfalse;
|
361
|
+
}
|
312
362
|
if (ERROR_NO_MORE_ITEMS != status) {
|
313
363
|
return Qfalse;
|
314
364
|
}
|
@@ -345,12 +395,12 @@ rb_winevt_subscribe_render(VALUE self, EVT_HANDLE event)
|
|
345
395
|
}
|
346
396
|
|
347
397
|
static VALUE
|
348
|
-
rb_winevt_subscribe_message(EVT_HANDLE event)
|
398
|
+
rb_winevt_subscribe_message(EVT_HANDLE event, LocaleInfo* localeInfo, EVT_HANDLE hRemote)
|
349
399
|
{
|
350
400
|
WCHAR* wResult;
|
351
401
|
VALUE utf8str;
|
352
402
|
|
353
|
-
wResult = get_description(event);
|
403
|
+
wResult = get_description(event, localeInfo->langID, hRemote);
|
354
404
|
utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
|
355
405
|
free(wResult);
|
356
406
|
|
@@ -393,7 +443,8 @@ rb_winevt_subscribe_each_yield(VALUE self)
|
|
393
443
|
for (int i = 0; i < winevtSubscribe->count; i++) {
|
394
444
|
rb_yield_values(3,
|
395
445
|
rb_winevt_subscribe_render(self, winevtSubscribe->hEvents[i]),
|
396
|
-
rb_winevt_subscribe_message(winevtSubscribe->hEvents[i]
|
446
|
+
rb_winevt_subscribe_message(winevtSubscribe->hEvents[i], winevtSubscribe->localeInfo,
|
447
|
+
winevtSubscribe->remoteHandle),
|
397
448
|
rb_winevt_subscribe_string_inserts(winevtSubscribe->hEvents[i]));
|
398
449
|
}
|
399
450
|
|
@@ -522,7 +573,7 @@ rb_winevt_subscribe_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
|
|
522
573
|
* This method specifies whether preserving qualifiers key or not.
|
523
574
|
*
|
524
575
|
* @since 0.7.3
|
525
|
-
* @param
|
576
|
+
* @param rb_preserve_qualifiers [Boolean]
|
526
577
|
*/
|
527
578
|
static VALUE
|
528
579
|
rb_winevt_subscribe_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
|
@@ -554,6 +605,93 @@ rb_winevt_subscribe_get_preserve_qualifiers_p(VALUE self)
|
|
554
605
|
return winevtSubscribe->preserveQualifiers ? Qtrue : Qfalse;
|
555
606
|
}
|
556
607
|
|
608
|
+
/*
|
609
|
+
* This method specifies locale with [String].
|
610
|
+
*
|
611
|
+
* @since 0.8.0
|
612
|
+
* @param rb_locale_str [String]
|
613
|
+
*/
|
614
|
+
static VALUE
|
615
|
+
rb_winevt_subscribe_set_locale(VALUE self, VALUE rb_locale_str)
|
616
|
+
{
|
617
|
+
struct WinevtSubscribe* winevtSubscribe;
|
618
|
+
LocaleInfo* locale_info = &default_locale;
|
619
|
+
|
620
|
+
TypedData_Get_Struct(
|
621
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
622
|
+
|
623
|
+
locale_info = get_locale_info_from_rb_str(rb_locale_str);
|
624
|
+
|
625
|
+
winevtSubscribe->localeInfo = locale_info;
|
626
|
+
|
627
|
+
return Qnil;
|
628
|
+
}
|
629
|
+
|
630
|
+
/*
|
631
|
+
* This method obtains specified locale with [String].
|
632
|
+
*
|
633
|
+
* @since 0.8.0
|
634
|
+
*/
|
635
|
+
static VALUE
|
636
|
+
rb_winevt_subscribe_get_locale(VALUE self)
|
637
|
+
{
|
638
|
+
struct WinevtSubscribe* winevtSubscribe;
|
639
|
+
|
640
|
+
TypedData_Get_Struct(
|
641
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
642
|
+
|
643
|
+
if (winevtSubscribe->localeInfo->langCode) {
|
644
|
+
return rb_str_new2(winevtSubscribe->localeInfo->langCode);
|
645
|
+
} else {
|
646
|
+
return rb_str_new2(default_locale.langCode);
|
647
|
+
}
|
648
|
+
}
|
649
|
+
|
650
|
+
/*
|
651
|
+
* This method cancels channel subscription.
|
652
|
+
*
|
653
|
+
* @return [Boolean]
|
654
|
+
* @since 0.9.1
|
655
|
+
*/
|
656
|
+
static VALUE
|
657
|
+
rb_winevt_subscribe_cancel(VALUE self)
|
658
|
+
{
|
659
|
+
struct WinevtSubscribe* winevtSubscribe;
|
660
|
+
BOOL result = FALSE;
|
661
|
+
|
662
|
+
TypedData_Get_Struct(
|
663
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
664
|
+
|
665
|
+
if (winevtSubscribe->subscription) {
|
666
|
+
result = EvtCancel(winevtSubscribe->subscription);
|
667
|
+
}
|
668
|
+
|
669
|
+
if (result) {
|
670
|
+
return Qtrue;
|
671
|
+
} else {
|
672
|
+
return Qfalse;
|
673
|
+
}
|
674
|
+
}
|
675
|
+
|
676
|
+
/*
|
677
|
+
* This method closes channel handles forcibly.
|
678
|
+
*
|
679
|
+
* @since 0.9.1
|
680
|
+
*/
|
681
|
+
static VALUE
|
682
|
+
rb_winevt_subscribe_close(VALUE self)
|
683
|
+
{
|
684
|
+
struct WinevtSubscribe* winevtSubscribe;
|
685
|
+
|
686
|
+
TypedData_Get_Struct(
|
687
|
+
self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
688
|
+
|
689
|
+
close_handles(winevtSubscribe);
|
690
|
+
|
691
|
+
return Qnil;
|
692
|
+
}
|
693
|
+
|
694
|
+
|
557
695
|
void
|
558
696
|
Init_winevt_subscribe(VALUE rb_cEventLog)
|
559
697
|
{
|
@@ -596,4 +734,24 @@ Init_winevt_subscribe(VALUE rb_cEventLog)
|
|
596
734
|
*/
|
597
735
|
rb_define_method(
|
598
736
|
rb_cSubscribe, "preserve_qualifiers=", rb_winevt_subscribe_set_preserve_qualifiers, 1);
|
737
|
+
/*
|
738
|
+
* @since 0.8.0
|
739
|
+
*/
|
740
|
+
rb_define_method(
|
741
|
+
rb_cSubscribe, "locale", rb_winevt_subscribe_get_locale, 0);
|
742
|
+
/*
|
743
|
+
* @since 0.8.0
|
744
|
+
*/
|
745
|
+
rb_define_method(
|
746
|
+
rb_cSubscribe, "locale=", rb_winevt_subscribe_set_locale, 1);
|
747
|
+
/*
|
748
|
+
* @since 0.9.1
|
749
|
+
*/
|
750
|
+
rb_define_method(
|
751
|
+
rb_cSubscribe, "cancel", rb_winevt_subscribe_cancel, 0);
|
752
|
+
/*
|
753
|
+
* @since 0.9.1
|
754
|
+
*/
|
755
|
+
rb_define_method(
|
756
|
+
rb_cSubscribe, "close", rb_winevt_subscribe_close, 0);
|
599
757
|
}
|