winevt_c 0.8.1 → 0.9.0

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 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