winevt_c 0.8.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29ee7a14f6020b16b7c7dda19d85898f1403721b49074555d71dc43a7a10544f
4
- data.tar.gz: 48be391283aa449cc09d1d997ab2915c48276cd21239a75f8013bca60aaafc03
3
+ metadata.gz: fd29b4664130c80249811fb66df434aaa9219d6d375bcdaa7adfdd3fe72dd25e
4
+ data.tar.gz: 2a1e3ec7cb528269ebb65f4b1df72d6045f882d865956fb85def8bcb925d6944
5
5
  SHA512:
6
- metadata.gz: f321563ec5c53f3305c130b1b13dddaa7136e38a46dbfac5c35e20a0d7525f4cc424546c6247fa226a50fd9932df65f849d5d4c354a56106cd9bcfa15908ec7c
7
- data.tar.gz: 53af124b46df922069f703e624a07bd31f427c1e715f8cb4227a93e3efd5cd94e83eddeb1be649b0db30312fbb594aae143eb27023ee37c230cbfd2ddbf43133
6
+ metadata.gz: 0f80978e4268c233d2e309c0e9556f38386b35300381c04f4d84226ce239a85ccb48b20a2c2a3c59c3d0557347e95ff11e0ca11945eaa128ba2c78c67ebc9250
7
+ data.tar.gz: a8ff4fae4995b41910352186898d54c929a918f86a6a4efe29c0a5c93433d9c95d91be5c9f81fdb52ff5f2307cbb2e2e61790a22fe076b7221ba03c89aed48d5
@@ -1,6 +1,10 @@
1
1
  require 'winevt'
2
2
 
3
- @query = Winevt::EventLog::Query.new("Application", "*[System[(Level <= 3) and TimeCreated[timediff(@SystemTime) <= 86400000]]]")
3
+ @session = Winevt::EventLog::Session.new("127.0.0.1") # Or remote box ip
4
+ # @session.domain = "<EXAMPLEGROUP>"
5
+ # @session.username = "<username>"
6
+ # @session.password = "<password>"
7
+ @query = Winevt::EventLog::Query.new("Application", "*[System[(Level <= 4) and TimeCreated[timediff(@SystemTime) <= 86400000]]]", @session)
4
8
 
5
9
  @query.render_as_xml = true
6
10
  @query.preserve_qualifiers = true
@@ -1,11 +1,17 @@
1
1
  require 'winevt'
2
2
 
3
+ @session = Winevt::EventLog::Session.new("127.0.0.1") # Or remote box ip
4
+ # @session.domain = "<EXAMPLEGROUP>"
5
+ # @session.username = "<username>"
6
+ # @session.password = "<password>"
7
+ @bookmark = Winevt::EventLog::Bookmark.new
3
8
  @subscribe = Winevt::EventLog::Subscribe.new
4
9
  @subscribe.read_existing_events = true
5
10
  @subscribe.preserve_qualifiers = true
6
11
  @subscribe.render_as_xml = true
7
12
  @subscribe.subscribe(
8
- "Security", "*[System[(Level <= 4) and TimeCreated[timediff(@SystemTime) <= 86400000]]]"
13
+ "Security", "*[System[(Level <= 4) and TimeCreated[timediff(@SystemTime) <= 86400000]]]",
14
+ @bookmark, @session
9
15
  )
10
16
  while true do
11
17
  @subscribe.each do |eventlog, message, string_inserts|
@@ -5,6 +5,7 @@ VALUE rb_cQuery;
5
5
  VALUE rb_cEventLog;
6
6
  VALUE rb_cSubscribe;
7
7
  VALUE rb_eWinevtQueryError;
8
+ VALUE rb_eRemoteHandlerError;
8
9
 
9
10
  static ID id_call;
10
11
 
@@ -16,12 +17,14 @@ Init_winevt(void)
16
17
  rb_cQuery = rb_define_class_under(rb_cEventLog, "Query", rb_cObject);
17
18
  rb_cSubscribe = rb_define_class_under(rb_cEventLog, "Subscribe", rb_cObject);
18
19
  rb_eWinevtQueryError = rb_define_class_under(rb_cQuery, "Error", rb_eStandardError);
20
+ rb_eRemoteHandlerError = rb_define_class_under(rb_cSubscribe, "RemoteHandlerError", rb_eRuntimeError);
19
21
 
20
22
  Init_winevt_channel(rb_cEventLog);
21
23
  Init_winevt_bookmark(rb_cEventLog);
22
24
  Init_winevt_query(rb_cEventLog);
23
25
  Init_winevt_subscribe(rb_cEventLog);
24
26
  Init_winevt_locale(rb_cEventLog);
27
+ Init_winevt_session(rb_cEventLog);
25
28
 
26
29
  id_call = rb_intern("call");
27
30
  }
@@ -21,6 +21,7 @@
21
21
  #define EventQuery(object) ((struct WinevtQuery*)DATA_PTR(object))
22
22
  #define EventBookMark(object) ((struct WinevtBookmark*)DATA_PTR(object))
23
23
  #define EventChannel(object) ((struct WinevtChannel*)DATA_PTR(object))
24
+ #define EventSession(object) ((struct WinevtSession*)DATA_PTR(object))
24
25
 
25
26
  typedef struct {
26
27
  LANGID langID;
@@ -38,7 +39,10 @@ VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
38
39
  #endif /* __cplusplus */
39
40
  void raise_system_error(VALUE error, DWORD errorCode);
40
41
  VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
41
- WCHAR* get_description(EVT_HANDLE handle, LANGID langID);
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);
42
46
  VALUE get_values(EVT_HANDLE handle);
43
47
  VALUE render_system_event(EVT_HANDLE handle, BOOL preserve_qualifiers);
44
48
  LocaleInfo* get_locale_info_from_rb_str(VALUE rb_locale_str);
@@ -53,7 +57,17 @@ extern VALUE rb_cChannel;
53
57
  extern VALUE rb_cBookmark;
54
58
  extern VALUE rb_cSubscribe;
55
59
  extern VALUE rb_eWinevtQueryError;
60
+ extern VALUE rb_eRemoteHandlerError;
56
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
+ };
57
71
 
58
72
  extern LocaleInfo localeInfoTable[];
59
73
  extern LocaleInfo default_locale;
@@ -84,6 +98,7 @@ struct WinevtQuery
84
98
  BOOL renderAsXML;
85
99
  BOOL preserveQualifiers;
86
100
  LocaleInfo *localeInfo;
101
+ EVT_HANDLE remoteHandle;
87
102
  };
88
103
 
89
104
  #define SUBSCRIBE_ARRAY_SIZE 10
@@ -104,6 +119,7 @@ struct WinevtSubscribe
104
119
  BOOL renderAsXML;
105
120
  BOOL preserveQualifiers;
106
121
  LocaleInfo* localeInfo;
122
+ EVT_HANDLE remoteHandle;
107
123
  };
108
124
 
109
125
  void Init_winevt_query(VALUE rb_cEventLog);
@@ -111,5 +127,6 @@ void Init_winevt_channel(VALUE rb_cEventLog);
111
127
  void Init_winevt_bookmark(VALUE rb_cEventLog);
112
128
  void Init_winevt_subscribe(VALUE rb_cEventLog);
113
129
  void Init_winevt_locale(VALUE rb_cEventLog);
130
+ void Init_winevt_session(VALUE rb_cEventLog);
114
131
 
115
132
  #endif // _WINEVT_C_H
@@ -42,6 +42,10 @@ query_free(void* ptr)
42
42
  if (winevtQuery->hEvents[i])
43
43
  EvtClose(winevtQuery->hEvents[i]);
44
44
  }
45
+
46
+ if (winevtQuery->remoteHandle)
47
+ EvtClose(winevtQuery->remoteHandle);
48
+
45
49
  xfree(ptr);
46
50
  }
47
51
 
@@ -58,22 +62,44 @@ rb_winevt_query_alloc(VALUE klass)
58
62
  /*
59
63
  * Initalize Query class.
60
64
  *
61
- * @param channel [String] Querying EventLog channel.
62
- * @param xpath [String] Querying XPath.
65
+ * @overload initialize(channel, xpath, session=nil)
66
+ * @param channel [String] Querying EventLog channel.
67
+ * @param xpath [String] Querying XPath.
68
+ * @param session [Session] Session information for remoting access.
63
69
  * @return [Query]
64
70
  *
65
71
  */
66
72
  static VALUE
67
- rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
73
+ rb_winevt_query_initialize(VALUE argc, VALUE *argv, VALUE self)
68
74
  {
69
75
  PWSTR evtChannel, evtXPath;
76
+ VALUE channel, xpath, session;
70
77
  struct WinevtQuery* winevtQuery;
78
+ struct WinevtSession* winevtSession;
79
+ EVT_HANDLE hRemoteHandle = NULL;
71
80
  DWORD len;
72
81
  VALUE wchannelBuf, wpathBuf;
82
+ DWORD err;
73
83
 
84
+ rb_scan_args(argc, argv, "21", &channel, &xpath, &session);
74
85
  Check_Type(channel, T_STRING);
75
86
  Check_Type(xpath, T_STRING);
76
87
 
88
+ if (rb_obj_is_kind_of(session, rb_cSession)) {
89
+ winevtSession = EventSession(session);
90
+
91
+ hRemoteHandle = connect_to_remote(winevtSession->server,
92
+ winevtSession->domain,
93
+ winevtSession->username,
94
+ winevtSession->password,
95
+ winevtSession->flags);
96
+
97
+ err = GetLastError();
98
+ if (err != ERROR_SUCCESS) {
99
+ raise_system_error(rb_eRuntimeError, err);
100
+ }
101
+ }
102
+
77
103
  // channel : To wide char
78
104
  len =
79
105
  MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), NULL, 0);
@@ -91,12 +117,17 @@ rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
91
117
  TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
92
118
 
93
119
  winevtQuery->query = EvtQuery(
94
- NULL, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
120
+ hRemoteHandle, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
121
+ err = GetLastError();
122
+ if (err != ERROR_SUCCESS) {
123
+ raise_system_error(rb_eRuntimeError, err);
124
+ }
95
125
  winevtQuery->offset = 0L;
96
126
  winevtQuery->timeout = 0L;
97
127
  winevtQuery->renderAsXML = TRUE;
98
128
  winevtQuery->preserveQualifiers = FALSE;
99
129
  winevtQuery->localeInfo = &default_locale;
130
+ winevtQuery->remoteHandle = hRemoteHandle;
100
131
 
101
132
  ALLOCV_END(wchannelBuf);
102
133
  ALLOCV_END(wpathBuf);
@@ -220,12 +251,12 @@ rb_winevt_query_render(VALUE self, EVT_HANDLE event)
220
251
  }
221
252
 
222
253
  static VALUE
223
- rb_winevt_query_message(EVT_HANDLE event, LocaleInfo* localeInfo)
254
+ rb_winevt_query_message(EVT_HANDLE event, LocaleInfo* localeInfo, EVT_HANDLE hRemote)
224
255
  {
225
256
  WCHAR* wResult;
226
257
  VALUE utf8str;
227
258
 
228
- wResult = get_description(event, localeInfo->langID);
259
+ wResult = get_description(event, localeInfo->langID, hRemote);
229
260
  utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
230
261
  free(wResult);
231
262
 
@@ -337,7 +368,8 @@ rb_winevt_query_each_yield(VALUE self)
337
368
  for (int i = 0; i < winevtQuery->count; i++) {
338
369
  rb_yield_values(3,
339
370
  rb_winevt_query_render(self, winevtQuery->hEvents[i]),
340
- rb_winevt_query_message(winevtQuery->hEvents[i], winevtQuery->localeInfo),
371
+ rb_winevt_query_message(winevtQuery->hEvents[i], winevtQuery->localeInfo,
372
+ winevtQuery->remoteHandle),
341
373
  rb_winevt_query_string_inserts(winevtQuery->hEvents[i]));
342
374
  }
343
375
  return Qnil;
@@ -401,7 +433,7 @@ rb_winevt_query_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
401
433
  * This method specifies whether preserving qualifiers key or not.
402
434
  *
403
435
  * @since 0.7.3
404
- * @param rb_render_as_xml [Boolean]
436
+ * @param rb_preserve_qualifiers [Boolean]
405
437
  */
406
438
  static VALUE
407
439
  rb_winevt_query_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
@@ -522,7 +554,7 @@ Init_winevt_query(VALUE rb_cEventLog)
522
554
  rb_define_const(rb_cFlag, "Strict", LONG2NUM(EvtSeekStrict));
523
555
  /* clang-format on */
524
556
 
525
- rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, 2);
557
+ rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, -1);
526
558
  rb_define_method(rb_cQuery, "next", rb_winevt_query_next, 0);
527
559
  rb_define_method(rb_cQuery, "seek", rb_winevt_query_seek, 1);
528
560
  rb_define_method(rb_cQuery, "offset", rb_winevt_query_get_offset, 0);
@@ -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
+ }
@@ -57,6 +57,9 @@ subscribe_free(void* ptr)
57
57
  }
58
58
  }
59
59
 
60
+ if (winevtSubscribe->remoteHandle)
61
+ EvtClose(winevtSubscribe->remoteHandle);
62
+
60
63
  xfree(ptr);
61
64
  }
62
65
 
@@ -132,23 +135,27 @@ rb_winevt_subscribe_read_existing_events_p(VALUE self)
132
135
  /*
133
136
  * Subscribe into a Windows EventLog channel.
134
137
  *
135
- * @overload subscribe(path, query, options={})
138
+ * @overload subscribe(path, query, bookmark=nil, session=nil)
136
139
  * @param path [String] Subscribe Channel
137
140
  * @param query [String] Query string for channel
138
- * @option options [Bookmark] bookmark Bookmark class instance.
141
+ * @param bookmark [Bookmark] bookmark Bookmark class instance.
142
+ * @param session [Session] Session information for remoting access.
139
143
  * @return [Boolean]
140
144
  *
141
145
  */
142
146
  static VALUE
143
147
  rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
144
148
  {
145
- VALUE rb_path, rb_query, rb_bookmark;
149
+ VALUE rb_path, rb_query, rb_bookmark, rb_session;
146
150
  EVT_HANDLE hSubscription = NULL, hBookmark = NULL;
147
151
  HANDLE hSignalEvent;
152
+ EVT_HANDLE hRemoteHandle = NULL;
148
153
  DWORD len, flags = 0L;
154
+ DWORD err = ERROR_SUCCESS;
149
155
  VALUE wpathBuf, wqueryBuf, wBookmarkBuf;
150
156
  PWSTR path, query, bookmarkXml;
151
157
  DWORD status = ERROR_SUCCESS;
158
+ struct WinevtSession* winevtSession;
152
159
  struct WinevtSubscribe* winevtSubscribe;
153
160
 
154
161
  hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
@@ -156,7 +163,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
156
163
  TypedData_Get_Struct(
157
164
  self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
158
165
 
159
- rb_scan_args(argc, argv, "21", &rb_path, &rb_query, &rb_bookmark);
166
+ rb_scan_args(argc, argv, "22", &rb_path, &rb_query, &rb_bookmark, &rb_session);
160
167
  Check_Type(rb_path, T_STRING);
161
168
  Check_Type(rb_query, T_STRING);
162
169
 
@@ -179,6 +186,19 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
179
186
  raise_system_error(rb_eWinevtQueryError, status);
180
187
  }
181
188
  }
189
+ if (rb_obj_is_kind_of(rb_session, rb_cSession)) {
190
+ winevtSession = EventSession(rb_session);
191
+ hRemoteHandle = connect_to_remote(winevtSession->server,
192
+ winevtSession->domain,
193
+ winevtSession->username,
194
+ winevtSession->password,
195
+ winevtSession->flags);
196
+
197
+ err = GetLastError();
198
+ if (err != ERROR_SUCCESS) {
199
+ raise_system_error(rb_eRuntimeError, err);
200
+ }
201
+ }
182
202
 
183
203
  // path : To wide char
184
204
  len =
@@ -204,7 +224,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
204
224
  }
205
225
 
206
226
  hSubscription =
207
- EvtSubscribe(NULL, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
227
+ EvtSubscribe(hRemoteHandle, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
208
228
  if (!hSubscription) {
209
229
  if (hBookmark != NULL) {
210
230
  EvtClose(hBookmark);
@@ -213,7 +233,11 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
213
233
  CloseHandle(hSignalEvent);
214
234
  }
215
235
  status = GetLastError();
216
- raise_system_error(rb_eWinevtQueryError, status);
236
+ if (rb_obj_is_kind_of(rb_session, rb_cSession)) {
237
+ rb_raise(rb_eRemoteHandlerError, "Remoting subscription is not working. errCode: %ld\n", status);
238
+ } else {
239
+ raise_system_error(rb_eWinevtQueryError, status);
240
+ }
217
241
  }
218
242
 
219
243
  if (winevtSubscribe->subscription != NULL) {
@@ -226,6 +250,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self)
226
250
 
227
251
  winevtSubscribe->signalEvent = hSignalEvent;
228
252
  winevtSubscribe->subscription = hSubscription;
253
+ winevtSubscribe->remoteHandle = hRemoteHandle;
229
254
  if (hBookmark) {
230
255
  winevtSubscribe->bookmark = hBookmark;
231
256
  } else {
@@ -346,12 +371,12 @@ rb_winevt_subscribe_render(VALUE self, EVT_HANDLE event)
346
371
  }
347
372
 
348
373
  static VALUE
349
- rb_winevt_subscribe_message(EVT_HANDLE event, LocaleInfo* localeInfo)
374
+ rb_winevt_subscribe_message(EVT_HANDLE event, LocaleInfo* localeInfo, EVT_HANDLE hRemote)
350
375
  {
351
376
  WCHAR* wResult;
352
377
  VALUE utf8str;
353
378
 
354
- wResult = get_description(event, localeInfo->langID);
379
+ wResult = get_description(event, localeInfo->langID, hRemote);
355
380
  utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
356
381
  free(wResult);
357
382
 
@@ -394,7 +419,8 @@ rb_winevt_subscribe_each_yield(VALUE self)
394
419
  for (int i = 0; i < winevtSubscribe->count; i++) {
395
420
  rb_yield_values(3,
396
421
  rb_winevt_subscribe_render(self, winevtSubscribe->hEvents[i]),
397
- rb_winevt_subscribe_message(winevtSubscribe->hEvents[i], winevtSubscribe->localeInfo),
422
+ rb_winevt_subscribe_message(winevtSubscribe->hEvents[i], winevtSubscribe->localeInfo,
423
+ winevtSubscribe->remoteHandle),
398
424
  rb_winevt_subscribe_string_inserts(winevtSubscribe->hEvents[i]));
399
425
  }
400
426
 
@@ -523,7 +549,7 @@ rb_winevt_subscribe_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
523
549
  * This method specifies whether preserving qualifiers key or not.
524
550
  *
525
551
  * @since 0.7.3
526
- * @param rb_render_as_xml [Boolean]
552
+ * @param rb_preserve_qualifiers [Boolean]
527
553
  */
528
554
  static VALUE
529
555
  rb_winevt_subscribe_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
@@ -76,6 +76,28 @@ render_to_rb_str(EVT_HANDLE handle, DWORD flags)
76
76
  return result;
77
77
  }
78
78
 
79
+ EVT_HANDLE
80
+ connect_to_remote(LPWSTR computerName, LPWSTR domain, LPWSTR username, LPWSTR password,
81
+ EVT_RPC_LOGIN_FLAGS flags)
82
+ {
83
+ EVT_HANDLE hRemote = NULL;
84
+ EVT_RPC_LOGIN Credentials;
85
+
86
+ RtlZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
87
+
88
+ Credentials.Server = computerName;
89
+ Credentials.Domain = domain;
90
+ Credentials.User = username;
91
+ Credentials.Password = password;
92
+ Credentials.Flags = flags;
93
+
94
+ hRemote = EvtOpenSession(EvtRpcLogin, &Credentials, 0, 0);
95
+
96
+ SecureZeroMemory(&Credentials, sizeof(EVT_RPC_LOGIN));
97
+
98
+ return hRemote;
99
+ }
100
+
79
101
  static std::wstring
80
102
  guid_to_wstr(const GUID& guid)
81
103
  {
@@ -433,7 +455,7 @@ cleanup:
433
455
  }
434
456
 
435
457
  WCHAR*
436
- get_description(EVT_HANDLE handle, LANGID langID)
458
+ get_description(EVT_HANDLE handle, LANGID langID, EVT_HANDLE hRemote)
437
459
  {
438
460
  #define BUFSIZE 4096
439
461
  std::vector<WCHAR> buffer(BUFSIZE);
@@ -470,7 +492,7 @@ get_description(EVT_HANDLE handle, LANGID langID)
470
492
 
471
493
  // Open publisher metadata
472
494
  hMetadata = EvtOpenPublisherMetadata(
473
- nullptr,
495
+ hRemote,
474
496
  values[0].StringVal,
475
497
  nullptr,
476
498
  MAKELCID(langID, SORT_DEFAULT),
@@ -7,6 +7,7 @@ require "winevt/bookmark"
7
7
  require "winevt/query"
8
8
  require "winevt/subscribe"
9
9
  require "winevt/version"
10
+ require "winevt/session"
10
11
 
11
12
  module Winevt
12
13
  # Your code goes here...
@@ -0,0 +1,15 @@
1
+ module Winevt
2
+ class EventLog
3
+ class Session
4
+ alias_method :initialize_raw, :initialize
5
+
6
+ def initialize(server, domain = nil, username = nil, password = nil)
7
+ initialize_raw
8
+ self.server = server
9
+ self.domain = domain if domain.is_a?(String)
10
+ self.username = username if username.is_a?(String)
11
+ self.password = password if password.is_a?(String)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -3,8 +3,11 @@ module Winevt
3
3
  class Subscribe
4
4
  alias_method :subscribe_raw, :subscribe
5
5
 
6
- def subscribe(path, query, bookmark = nil)
7
- if bookmark.is_a?(Winevt::EventLog::Bookmark)
6
+ def subscribe(path, query, bookmark = nil, session = nil)
7
+ if bookmark.is_a?(Winevt::EventLog::Bookmark) &&
8
+ session.is_a?(Winevt::EventLog::Session)
9
+ subscribe_raw(path, query, bookmark.render, session)
10
+ elsif bookmark.is_a?(Winevt::EventLog::Bookmark)
8
11
  subscribe_raw(path, query, bookmark.render)
9
12
  else
10
13
  subscribe_raw(path, query)
@@ -1,3 +1,3 @@
1
1
  module Winevt
2
- VERSION = "0.8.1"
2
+ VERSION = "0.9.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: winevt_c
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroshi Hatake
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-22 00:00:00.000000000 Z
11
+ date: 2020-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -132,11 +132,13 @@ files:
132
132
  - ext/winevt/winevt_locale.c
133
133
  - ext/winevt/winevt_locale_info.c
134
134
  - ext/winevt/winevt_query.c
135
+ - ext/winevt/winevt_session.c
135
136
  - ext/winevt/winevt_subscribe.c
136
137
  - ext/winevt/winevt_utils.cpp
137
138
  - lib/winevt.rb
138
139
  - lib/winevt/bookmark.rb
139
140
  - lib/winevt/query.rb
141
+ - lib/winevt/session.rb
140
142
  - lib/winevt/subscribe.rb
141
143
  - lib/winevt/version.rb
142
144
  - winevt_c.gemspec