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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1a95471f55e9dee6e48a8836c27e360dc8f8abc8d8687106805702502586acb2
4
- data.tar.gz: c64666d6e09ce6e5fb4eb04f2cd951eeae8d656b9e20efc70375503ca253c453
3
+ metadata.gz: d691ef9954d626041b79d1d63a4258537ded33c0f9c07c9551fd40b6aa211f12
4
+ data.tar.gz: fbe964ae721b310ca9c9adcf092b0f5ab4f0207e154c41287c17b2a6275932db
5
5
  SHA512:
6
- metadata.gz: ea964c952d8dc9f2d05639309a7a04be8564e13f563b6fce60c6f6fbd70b35d91d28d9f1436e1e1baf88db5cf7d77e66f115d70ad6ea76c99afc5f6cf99044c3
7
- data.tar.gz: c39eeeaa3cfdb4c90a526a5a2a2a7ebc5e217624b89f526b697ab65a07b02118f40b6e1fcd9ef533022d5312d43dee279b9bdca20aba93f5788fddf3fe7cfe8d
6
+ metadata.gz: 90059826d6c9ab0efdce70b7d4c5c4490c69e522fbcaef284e3616aa043b4de63731fe3805c9c4b8837842e44da04f376d8a813b750f926c3ab474c88c332b8c
7
+ data.tar.gz: 4c75263c161461089b754d512c5d7eaaa9aec9d8e7debeff1d9e0c98c73639f4157f332b5c32ad805b6e3df08e8a330e2e5d76fa85902dc70f133c4e4180ea87
data/README.md CHANGED
@@ -31,6 +31,61 @@ Or install it yourself as:
31
31
  ## Usage
32
32
 
33
33
  Usage examples are found in [example directory](example).
34
+
35
+ ### Multilingual description
36
+
37
+ Currently, the following locales should be supported to output description:
38
+
39
+ locale | language
40
+ ---------:|:--------
41
+ bg\_BG | Bulgarian
42
+ zh\_CN | Simplified Chinese
43
+ zh\_TW | Traditional Chinese
44
+ zh\_HK | Chinese (Hong Kong)
45
+ zh\_SG | Chinese (Singapore)
46
+ hr\_HR | Croatian
47
+ cz\_CZ | Czech
48
+ da\_DK | Danish
49
+ nl\_NL | Dutch
50
+ nl\_BG | Dutch (Belgium)
51
+ en\_US | English (United States)
52
+ en\_GB | English (UK)
53
+ en\_AU | English (Australia)
54
+ en\_CA | English (Canada)
55
+ en\_NZ | English (New Zealand)
56
+ en\_IE | English (Ireland)
57
+ fi\_FI | Finnish
58
+ fr\_FR | French
59
+ fr\_BE | French (Belgium)
60
+ fr\_CA | French (Canada)
61
+ fr\_CH | French (Swiss)
62
+ de\_DE | German
63
+ de\_CH | German (Swiss)
64
+ de\_AT | German (Austria)
65
+ el\_GR | Greek (Ελληνικά)
66
+ hu\_HU | Hungarian
67
+ is\_IS | Icelandic
68
+ it\_IT | Italian (Italy)
69
+ it\_CH | Italian (Swiss)
70
+ ja\_JP | Japanese
71
+ ko\_KO | Korean
72
+ no\_NO | Norwegian (Bokmål)
73
+ nb\_NO | Norwegian (Bokmål)
74
+ nn\_NO | Norwegian (Nynorsk)
75
+ pl\_PL | Polish (Poland)
76
+ pt\_PT | Portuguese
77
+ pt\_BR | Portuguese (Brazil)
78
+ ro\_RO | Romanian
79
+ ru\_RU | Russian (русский язык)
80
+ sk\_SK | Slovak
81
+ sl\_SI | Slovenian
82
+ es\_ES | Spanish
83
+ es\_ES\_T | Spanish (Traditional)
84
+ es\_MX | Spanish (Mexico)
85
+ es\_ES\_M | Spanish (Modern)
86
+ sv\_SE | Swedish
87
+ tr\_TR | Turkish
88
+
34
89
  ## Development
35
90
 
36
91
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -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
@@ -0,0 +1,13 @@
1
+ require 'winevt'
2
+
3
+ @locale = Winevt::EventLog::Locale.new
4
+
5
+ header = <<EOC
6
+ locale | language
7
+ ---------:|:--------
8
+ EOC
9
+
10
+ print header
11
+ @locale.each do |code, desc|
12
+ print "#{code.gsub("_", "\\_")}#{" "*(8 - code.size)}| #{desc}\n"
13
+ end
@@ -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|
@@ -1,7 +1,11 @@
1
1
  #include <winevt_c.h>
2
2
 
3
3
  VALUE rb_mWinevt;
4
+ VALUE rb_cQuery;
4
5
  VALUE rb_cEventLog;
6
+ VALUE rb_cSubscribe;
7
+ VALUE rb_eWinevtQueryError;
8
+ VALUE rb_eRemoteHandlerError;
5
9
 
6
10
  static ID id_call;
7
11
 
@@ -13,11 +17,14 @@ Init_winevt(void)
13
17
  rb_cQuery = rb_define_class_under(rb_cEventLog, "Query", rb_cObject);
14
18
  rb_cSubscribe = rb_define_class_under(rb_cEventLog, "Subscribe", rb_cObject);
15
19
  rb_eWinevtQueryError = rb_define_class_under(rb_cQuery, "Error", rb_eStandardError);
20
+ rb_eRemoteHandlerError = rb_define_class_under(rb_cSubscribe, "RemoteHandlerError", rb_eRuntimeError);
16
21
 
17
22
  Init_winevt_channel(rb_cEventLog);
18
23
  Init_winevt_bookmark(rb_cEventLog);
19
24
  Init_winevt_query(rb_cEventLog);
20
25
  Init_winevt_subscribe(rb_cEventLog);
26
+ Init_winevt_locale(rb_cEventLog);
27
+ Init_winevt_session(rb_cEventLog);
21
28
 
22
29
  id_call = rb_intern("call");
23
30
  }
@@ -19,6 +19,8 @@
19
19
  */
20
20
  /* clang-format pn */
21
21
 
22
+ VALUE rb_cBookmark;
23
+
22
24
  static void bookmark_free(void* ptr);
23
25
 
24
26
  static const rb_data_type_t rb_winevt_bookmark_type = { "winevt/bookmark",
@@ -21,6 +21,13 @@
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))
25
+
26
+ typedef struct {
27
+ LANGID langID;
28
+ CHAR* langCode;
29
+ CHAR* description;
30
+ } LocaleInfo;
24
31
 
25
32
  #ifdef __cplusplus
26
33
  extern "C" {
@@ -32,20 +39,40 @@ VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
32
39
  #endif /* __cplusplus */
33
40
  void raise_system_error(VALUE error, DWORD errorCode);
34
41
  VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
35
- WCHAR* get_description(EVT_HANDLE handle);
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);
36
46
  VALUE get_values(EVT_HANDLE handle);
37
47
  VALUE render_system_event(EVT_HANDLE handle, BOOL preserve_qualifiers);
48
+ LocaleInfo* get_locale_info_from_rb_str(VALUE rb_locale_str);
38
49
 
39
50
  #ifdef __cplusplus
40
51
  }
41
52
  #endif /* __cplusplus */
42
53
 
43
- VALUE rb_cQuery;
44
- VALUE rb_cFlag;
45
- VALUE rb_cChannel;
46
- VALUE rb_cBookmark;
47
- VALUE rb_cSubscribe;
48
- VALUE rb_eWinevtQueryError;
54
+ extern VALUE rb_cQuery;
55
+ extern VALUE rb_cFlag;
56
+ extern VALUE rb_cChannel;
57
+ extern VALUE rb_cBookmark;
58
+ extern VALUE rb_cSubscribe;
59
+ extern VALUE rb_eWinevtQueryError;
60
+ extern VALUE rb_eRemoteHandlerError;
61
+ extern VALUE rb_cLocale;
62
+ extern VALUE rb_cSession;
63
+
64
+ struct WinevtSession {
65
+ LPWSTR server;
66
+ LPWSTR domain;
67
+ LPWSTR username;
68
+ LPWSTR password;
69
+ EVT_RPC_LOGIN_FLAGS flags;
70
+ };
71
+
72
+ extern LocaleInfo localeInfoTable[];
73
+ extern LocaleInfo default_locale;
74
+
75
+ struct WinevtLocale {};
49
76
 
50
77
  struct WinevtChannel
51
78
  {
@@ -70,6 +97,8 @@ struct WinevtQuery
70
97
  LONG timeout;
71
98
  BOOL renderAsXML;
72
99
  BOOL preserveQualifiers;
100
+ LocaleInfo *localeInfo;
101
+ EVT_HANDLE remoteHandle;
73
102
  };
74
103
 
75
104
  #define SUBSCRIBE_ARRAY_SIZE 10
@@ -89,11 +118,15 @@ struct WinevtSubscribe
89
118
  DWORD currentRate;
90
119
  BOOL renderAsXML;
91
120
  BOOL preserveQualifiers;
121
+ LocaleInfo* localeInfo;
122
+ EVT_HANDLE remoteHandle;
92
123
  };
93
124
 
94
125
  void Init_winevt_query(VALUE rb_cEventLog);
95
126
  void Init_winevt_channel(VALUE rb_cEventLog);
96
127
  void Init_winevt_bookmark(VALUE rb_cEventLog);
97
128
  void Init_winevt_subscribe(VALUE rb_cEventLog);
129
+ void Init_winevt_locale(VALUE rb_cEventLog);
130
+ void Init_winevt_session(VALUE rb_cEventLog);
98
131
 
99
132
  #endif // _WINEVT_C_H
@@ -19,6 +19,8 @@
19
19
  * print channels
20
20
  */
21
21
 
22
+ VALUE rb_cChannel;
23
+
22
24
  DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate);
23
25
  DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate);
24
26
  static void channel_free(void* ptr);
@@ -0,0 +1,92 @@
1
+ #include <winevt_c.h>
2
+
3
+
4
+ /* clang-format off */
5
+ /*
6
+ * Document-class: Winevt::EventLog::Locale
7
+ *
8
+ * handle locales for Windows EventLog's description.
9
+ *
10
+ * @example
11
+ * require 'winevt'
12
+ *
13
+ * @locale = Winevt::EventLog::Locale.new
14
+ * @locale.each {|code, desc|
15
+ * print code, desc
16
+ * }
17
+ * @since v0.8.1
18
+ */
19
+ /* clang-format on */
20
+
21
+ VALUE rb_cLocale;
22
+
23
+ static void locale_free(void* ptr);
24
+
25
+ static const rb_data_type_t rb_winevt_locale_type = { "winevt/locale",
26
+ {
27
+ 0,
28
+ locale_free,
29
+ 0,
30
+ },
31
+ NULL,
32
+ NULL,
33
+ RUBY_TYPED_FREE_IMMEDIATELY };
34
+
35
+ static void
36
+ locale_free(void* ptr)
37
+ {
38
+ xfree(ptr);
39
+ }
40
+
41
+ static VALUE
42
+ rb_winevt_locale_alloc(VALUE klass)
43
+ {
44
+ VALUE obj;
45
+ struct WinevtLocale* winevtLocale;
46
+ obj = TypedData_Make_Struct(
47
+ klass, struct WinevtLocale, &rb_winevt_locale_type, winevtLocale);
48
+ return obj;
49
+ }
50
+
51
+ /*
52
+ * Initalize Locale class.
53
+ *
54
+ * @return [Locale]
55
+ *
56
+ */
57
+ static VALUE
58
+ rb_winevt_locale_initialize(VALUE self)
59
+ {
60
+ return Qnil;
61
+ }
62
+
63
+ /*
64
+ * Enumerate supported locales and its descriptions
65
+ *
66
+ * @yield (String, String)
67
+ *
68
+ */
69
+ static VALUE
70
+ rb_winevt_locale_each(VALUE self)
71
+ {
72
+ RETURN_ENUMERATOR(self, 0, 0);
73
+
74
+ for (int i = 0; localeInfoTable[i].langCode != NULL; i++) {
75
+ rb_yield_values(2,
76
+ rb_utf8_str_new_cstr(localeInfoTable[i].langCode),
77
+ rb_utf8_str_new_cstr(localeInfoTable[i].description));
78
+ }
79
+
80
+ return Qnil;
81
+ }
82
+
83
+ void
84
+ Init_winevt_locale(VALUE rb_cEventLog)
85
+ {
86
+ rb_cLocale = rb_define_class_under(rb_cEventLog, "Locale", rb_cObject);
87
+
88
+ rb_define_alloc_func(rb_cLocale, rb_winevt_locale_alloc);
89
+
90
+ rb_define_method(rb_cLocale, "initialize", rb_winevt_locale_initialize, 0);
91
+ rb_define_method(rb_cLocale, "each", rb_winevt_locale_each, 0);
92
+ }
@@ -0,0 +1,68 @@
1
+ #include <winevt_c.h>
2
+
3
+ LocaleInfo localeInfoTable [] = {
4
+ { MAKELANGID(LANG_BULGARIAN, SUBLANG_DEFAULT), "bg_BG", "Bulgarian"},
5
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), "zh_CN", "Simplified Chinese "},
6
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), "zh_TW", "Traditional Chinese"},
7
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG), "zh_HK", "Chinese (Hong Kong)"},
8
+ { MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE), "zh_SG", "Chinese (Singapore)"},
9
+ { MAKELANGID(LANG_CROATIAN, SUBLANG_DEFAULT), "hr_HR", "Croatian"},
10
+ { MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT), "cs_CZ", "Czech"},
11
+ { MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT), "da_DK", "Dannish"},
12
+ { MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH), "nl_NL", "Dutch"},
13
+ { MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH_BELGIAN), "nl_BE", "Dutch (Belgium)"},
14
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), "en_US", "English (United States)"},
15
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_UK), "en_GB", "English (UK)"},
16
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_AUS), "en_AU", "English (Australia)"},
17
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_CAN), "en_CA", "English (Canada)"},
18
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_NZ), "en_NZ", "English (New Zealand)"},
19
+ { MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_EIRE), "en_IE", "English (Ireland)"},
20
+ { MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT), "fi_FI", "Finnish"},
21
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), "fr_FR", "French"},
22
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_BELGIAN), "fr_BE", "French (Belgium)"},
23
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_CANADIAN), "fr_CA", "French (Canada)"},
24
+ { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH_SWISS), "fr_CH", "French (Swiss)"},
25
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), "de_DE", "German"},
26
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_SWISS), "de_CH", "German (Swiss)"},
27
+ { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN_AUSTRIAN), "de_AT", "German (Austria))"},
28
+ { MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT), "el_GR", "Greek (Ελληνικά)"},
29
+ { MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT), "hu_HU", "Hungarian"},
30
+ { MAKELANGID(LANG_ICELANDIC, SUBLANG_DEFAULT), "is_IS", "Icelandic"},
31
+ { MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN), "it_IT", "Italian (Italy)"},
32
+ { MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN_SWISS), "it_CH", "Italian (Swiss)"},
33
+ { MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT), "ja_JP", "Japanases"},
34
+ { MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT), "ko_KO", "Korean"},
35
+ { MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL), "no_NO", "Norwegian (Bokmål)"},
36
+ { MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL), "nb_NO", "Norwegian (Bokmål)"},
37
+ { MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_NYNORSK), "nn_NO", "Norwegian (Nynorsk)"},
38
+ { MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT), "pl_PL", "Polish"},
39
+ { MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE), "pt_PT", "Portuguese"},
40
+ { MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN), "pt_BR", "Portuguese (Brazil)"},
41
+ { MAKELANGID(LANG_ROMANIAN, SUBLANG_DEFAULT), "ro_RO", "Romanian"},
42
+ { MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT), "ru_RU", "Russian (русский язык)"},
43
+ { MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT), "sk_SK", "Slovak"},
44
+ { MAKELANGID(LANG_SLOVENIAN, SUBLANG_DEFAULT), "sl_SI", "Slovenian"},
45
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), "es_ES", "Spanish"},
46
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), "es_ES_T", "Spanish (Traditional)"},
47
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MEXICAN), "es_MX", "Spanish (Mexico)"},
48
+ { MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), "es_ES_M", "Spanish (Modern)"},
49
+ { MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT), "sv_SE", "Swedish"},
50
+ { MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT), "tr_TR", "Turkish"},
51
+ { 0, NULL, NULL}
52
+ };
53
+
54
+ LocaleInfo default_locale = {MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), "neutral", "Default"};
55
+
56
+ LocaleInfo*
57
+ get_locale_info_from_rb_str(VALUE rb_locale_str)
58
+ {
59
+ CHAR* locale_str = StringValuePtr(rb_locale_str);
60
+
61
+ for (int i = 0; localeInfoTable[i].langCode != NULL; i++) {
62
+ if (stricmp(localeInfoTable[i].langCode, locale_str) == 0) {
63
+ return &localeInfoTable[i];
64
+ }
65
+ }
66
+
67
+ rb_raise(rb_eArgError, "Unknown locale: %s", locale_str);
68
+ }
@@ -17,6 +17,7 @@
17
17
  */
18
18
  /* clang-format on */
19
19
 
20
+ VALUE rb_cFlag;
20
21
 
21
22
  static void query_free(void* ptr);
22
23
 
@@ -31,16 +32,32 @@ static const rb_data_type_t rb_winevt_query_type = { "winevt/query",
31
32
  RUBY_TYPED_FREE_IMMEDIATELY };
32
33
 
33
34
  static void
34
- query_free(void* ptr)
35
+ close_handles(struct WinevtQuery* winevtQuery)
35
36
  {
36
- struct WinevtQuery* winevtQuery = (struct WinevtQuery*)ptr;
37
- if (winevtQuery->query)
37
+ if (winevtQuery->query) {
38
38
  EvtClose(winevtQuery->query);
39
+ winevtQuery->query = NULL;
40
+ }
39
41
 
40
42
  for (int i = 0; i < winevtQuery->count; i++) {
41
- if (winevtQuery->hEvents[i])
43
+ if (winevtQuery->hEvents[i]) {
42
44
  EvtClose(winevtQuery->hEvents[i]);
45
+ winevtQuery->hEvents[i] = NULL;
46
+ }
47
+ }
48
+
49
+ if (winevtQuery->remoteHandle) {
50
+ EvtClose(winevtQuery->remoteHandle);
51
+ winevtQuery->remoteHandle = NULL;
43
52
  }
53
+ }
54
+
55
+ static void
56
+ query_free(void* ptr)
57
+ {
58
+ struct WinevtQuery* winevtQuery = (struct WinevtQuery*)ptr;
59
+ close_handles(winevtQuery);
60
+
44
61
  xfree(ptr);
45
62
  }
46
63
 
@@ -57,22 +74,44 @@ rb_winevt_query_alloc(VALUE klass)
57
74
  /*
58
75
  * Initalize Query class.
59
76
  *
60
- * @param channel [String] Querying EventLog channel.
61
- * @param xpath [String] Querying XPath.
77
+ * @overload initialize(channel, xpath, session=nil)
78
+ * @param channel [String] Querying EventLog channel.
79
+ * @param xpath [String] Querying XPath.
80
+ * @param session [Session] Session information for remoting access.
62
81
  * @return [Query]
63
82
  *
64
83
  */
65
84
  static VALUE
66
- rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
85
+ rb_winevt_query_initialize(VALUE argc, VALUE *argv, VALUE self)
67
86
  {
68
87
  PWSTR evtChannel, evtXPath;
88
+ VALUE channel, xpath, session;
69
89
  struct WinevtQuery* winevtQuery;
90
+ struct WinevtSession* winevtSession;
91
+ EVT_HANDLE hRemoteHandle = NULL;
70
92
  DWORD len;
71
93
  VALUE wchannelBuf, wpathBuf;
94
+ DWORD err;
72
95
 
96
+ rb_scan_args(argc, argv, "21", &channel, &xpath, &session);
73
97
  Check_Type(channel, T_STRING);
74
98
  Check_Type(xpath, T_STRING);
75
99
 
100
+ if (rb_obj_is_kind_of(session, rb_cSession)) {
101
+ winevtSession = EventSession(session);
102
+
103
+ hRemoteHandle = connect_to_remote(winevtSession->server,
104
+ winevtSession->domain,
105
+ winevtSession->username,
106
+ winevtSession->password,
107
+ winevtSession->flags);
108
+
109
+ err = GetLastError();
110
+ if (err != ERROR_SUCCESS) {
111
+ raise_system_error(rb_eRuntimeError, err);
112
+ }
113
+ }
114
+
76
115
  // channel : To wide char
77
116
  len =
78
117
  MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(channel), RSTRING_LEN(channel), NULL, 0);
@@ -90,11 +129,17 @@ rb_winevt_query_initialize(VALUE self, VALUE channel, VALUE xpath)
90
129
  TypedData_Get_Struct(self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
91
130
 
92
131
  winevtQuery->query = EvtQuery(
93
- NULL, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
132
+ hRemoteHandle, evtChannel, evtXPath, EvtQueryChannelPath | EvtQueryTolerateQueryErrors);
133
+ err = GetLastError();
134
+ if (err != ERROR_SUCCESS) {
135
+ raise_system_error(rb_eRuntimeError, err);
136
+ }
94
137
  winevtQuery->offset = 0L;
95
138
  winevtQuery->timeout = 0L;
96
139
  winevtQuery->renderAsXML = TRUE;
97
140
  winevtQuery->preserveQualifiers = FALSE;
141
+ winevtQuery->localeInfo = &default_locale;
142
+ winevtQuery->remoteHandle = hRemoteHandle;
98
143
 
99
144
  ALLOCV_END(wchannelBuf);
100
145
  ALLOCV_END(wpathBuf);
@@ -186,6 +231,9 @@ rb_winevt_query_next(VALUE self)
186
231
 
187
232
  if (!EvtNext(winevtQuery->query, QUERY_ARRAY_SIZE, hEvents, INFINITE, 0, &count)) {
188
233
  status = GetLastError();
234
+ if (ERROR_CANCELLED == status) {
235
+ return Qfalse;
236
+ }
189
237
  if (ERROR_NO_MORE_ITEMS != status) {
190
238
  return Qfalse;
191
239
  }
@@ -218,12 +266,12 @@ rb_winevt_query_render(VALUE self, EVT_HANDLE event)
218
266
  }
219
267
 
220
268
  static VALUE
221
- rb_winevt_query_message(EVT_HANDLE event)
269
+ rb_winevt_query_message(EVT_HANDLE event, LocaleInfo* localeInfo, EVT_HANDLE hRemote)
222
270
  {
223
271
  WCHAR* wResult;
224
272
  VALUE utf8str;
225
273
 
226
- wResult = get_description(event);
274
+ wResult = get_description(event, localeInfo->langID, hRemote);
227
275
  utf8str = wstr_to_rb_str(CP_UTF8, wResult, -1);
228
276
  free(wResult);
229
277
 
@@ -335,7 +383,8 @@ rb_winevt_query_each_yield(VALUE self)
335
383
  for (int i = 0; i < winevtQuery->count; i++) {
336
384
  rb_yield_values(3,
337
385
  rb_winevt_query_render(self, winevtQuery->hEvents[i]),
338
- rb_winevt_query_message(winevtQuery->hEvents[i]),
386
+ rb_winevt_query_message(winevtQuery->hEvents[i], winevtQuery->localeInfo,
387
+ winevtQuery->remoteHandle),
339
388
  rb_winevt_query_string_inserts(winevtQuery->hEvents[i]));
340
389
  }
341
390
  return Qnil;
@@ -399,7 +448,7 @@ rb_winevt_query_set_render_as_xml(VALUE self, VALUE rb_render_as_xml)
399
448
  * This method specifies whether preserving qualifiers key or not.
400
449
  *
401
450
  * @since 0.7.3
402
- * @param rb_render_as_xml [Boolean]
451
+ * @param rb_preserve_qualifiers [Boolean]
403
452
  */
404
453
  static VALUE
405
454
  rb_winevt_query_set_preserve_qualifiers(VALUE self, VALUE rb_preserve_qualifiers)
@@ -431,6 +480,92 @@ rb_winevt_query_get_preserve_qualifiers_p(VALUE self)
431
480
  return winevtQuery->preserveQualifiers ? Qtrue : Qfalse;
432
481
  }
433
482
 
483
+ /*
484
+ * This method specifies locale with [String].
485
+ *
486
+ * @since 0.8.0
487
+ * @param rb_locale_str [String]
488
+ */
489
+ static VALUE
490
+ rb_winevt_query_set_locale(VALUE self, VALUE rb_locale_str)
491
+ {
492
+ struct WinevtQuery* winevtQuery;
493
+ LocaleInfo* locale_info = &default_locale;
494
+
495
+ TypedData_Get_Struct(
496
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
497
+
498
+ locale_info = get_locale_info_from_rb_str(rb_locale_str);
499
+
500
+ winevtQuery->localeInfo = locale_info;
501
+
502
+ return Qnil;
503
+ }
504
+
505
+ /*
506
+ * This method obtains specified locale with [String].
507
+ *
508
+ * @since 0.8.0
509
+ */
510
+ static VALUE
511
+ rb_winevt_query_get_locale(VALUE self)
512
+ {
513
+ struct WinevtQuery* winevtQuery;
514
+
515
+ TypedData_Get_Struct(
516
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
517
+
518
+ if (winevtQuery->localeInfo->langCode) {
519
+ return rb_str_new2(winevtQuery->localeInfo->langCode);
520
+ } else {
521
+ return rb_str_new2(default_locale.langCode);
522
+ }
523
+ }
524
+
525
+ /*
526
+ * This method cancels channel query.
527
+ *
528
+ * @return [Boolean]
529
+ * @since 0.9.1
530
+ */
531
+ static VALUE
532
+ rb_winevt_query_cancel(VALUE self)
533
+ {
534
+ struct WinevtQuery* winevtQuery;
535
+ BOOL result = FALSE;
536
+
537
+ TypedData_Get_Struct(
538
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
539
+
540
+ if (winevtQuery->query) {
541
+ result = EvtCancel(winevtQuery->query);
542
+ }
543
+
544
+ if (result) {
545
+ return Qtrue;
546
+ } else {
547
+ return Qfalse;
548
+ }
549
+ }
550
+
551
+ /*
552
+ * This method closes channel handles forcibly.
553
+ *
554
+ * @since 0.9.1
555
+ */
556
+ static VALUE
557
+ rb_winevt_query_close(VALUE self)
558
+ {
559
+ struct WinevtQuery* winevtQuery;
560
+
561
+ TypedData_Get_Struct(
562
+ self, struct WinevtQuery, &rb_winevt_query_type, winevtQuery);
563
+
564
+ close_handles(winevtQuery);
565
+
566
+ return Qnil;
567
+ }
568
+
434
569
  void
435
570
  Init_winevt_query(VALUE rb_cEventLog)
436
571
  {
@@ -478,7 +613,7 @@ Init_winevt_query(VALUE rb_cEventLog)
478
613
  rb_define_const(rb_cFlag, "Strict", LONG2NUM(EvtSeekStrict));
479
614
  /* clang-format on */
480
615
 
481
- rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, 2);
616
+ rb_define_method(rb_cQuery, "initialize", rb_winevt_query_initialize, -1);
482
617
  rb_define_method(rb_cQuery, "next", rb_winevt_query_next, 0);
483
618
  rb_define_method(rb_cQuery, "seek", rb_winevt_query_seek, 1);
484
619
  rb_define_method(rb_cQuery, "offset", rb_winevt_query_get_offset, 0);
@@ -496,4 +631,20 @@ Init_winevt_query(VALUE rb_cEventLog)
496
631
  * @since 0.7.3
497
632
  */
498
633
  rb_define_method(rb_cQuery, "preserve_qualifiers=", rb_winevt_query_set_preserve_qualifiers, 1);
634
+ /*
635
+ * @since 0.8.0
636
+ */
637
+ rb_define_method(rb_cQuery, "locale", rb_winevt_query_get_locale, 0);
638
+ /*
639
+ * @since 0.8.0
640
+ */
641
+ rb_define_method(rb_cQuery, "locale=", rb_winevt_query_set_locale, 1);
642
+ /*
643
+ * @since 0.9.1
644
+ */
645
+ rb_define_method(rb_cQuery, "cancel", rb_winevt_query_cancel, 0);
646
+ /*
647
+ * @since 0.9.1
648
+ */
649
+ rb_define_method(rb_cQuery, "close", rb_winevt_query_close, 0);
499
650
  }