winevt_c 0.7.3 → 0.9.1

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