winevt_c 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.clang-format +4 -4
- data/.github/workflows/linux.yml +26 -0
- data/Gemfile +6 -6
- data/LICENSE.txt +202 -202
- data/README.md +97 -97
- data/Rakefile +37 -37
- data/appveyor.yml +32 -26
- data/example/bookmark.rb +9 -9
- data/example/enumerate_channels.rb +13 -13
- data/example/eventlog.rb +13 -13
- data/example/locale.rb +13 -13
- data/example/rate_limit.rb +14 -14
- data/example/tailing.rb +21 -21
- data/ext/winevt/extconf.rb +24 -24
- data/ext/winevt/winevt.c +30 -30
- data/ext/winevt/winevt_bookmark.c +149 -149
- data/ext/winevt/winevt_c.h +132 -132
- data/ext/winevt/winevt_channel.c +327 -327
- data/ext/winevt/winevt_locale.c +92 -92
- data/ext/winevt/winevt_locale_info.c +68 -68
- data/ext/winevt/winevt_query.c +650 -650
- data/ext/winevt/winevt_session.c +425 -425
- data/ext/winevt/winevt_subscribe.c +757 -757
- data/ext/winevt/winevt_utils.cpp +723 -718
- data/lib/winevt.rb +14 -14
- data/lib/winevt/bookmark.rb +6 -6
- data/lib/winevt/query.rb +6 -6
- data/lib/winevt/session.rb +15 -15
- data/lib/winevt/subscribe.rb +18 -18
- data/lib/winevt/version.rb +3 -3
- data/winevt_c.gemspec +34 -34
- metadata +8 -9
- data/.travis.yml +0 -15
data/ext/winevt/winevt_c.h
CHANGED
@@ -1,132 +1,132 @@
|
|
1
|
-
#ifndef _WINEVT_C_H_
|
2
|
-
#define _WINEVT_C_H_
|
3
|
-
|
4
|
-
#include <ruby.h>
|
5
|
-
#include <ruby/encoding.h>
|
6
|
-
|
7
|
-
#ifdef __GNUC__
|
8
|
-
#include <w32api.h>
|
9
|
-
#define MINIMUM_WINDOWS_VERSION WindowsVista
|
10
|
-
#else /* __GNUC__ */
|
11
|
-
#define MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */
|
12
|
-
#endif /* __GNUC__ */
|
13
|
-
|
14
|
-
#ifdef _WIN32_WINNT
|
15
|
-
#undef _WIN32_WINNT
|
16
|
-
#endif /* WIN32_WINNT */
|
17
|
-
#define _WIN32_WINNT MINIMUM_WINDOWS_VERSION
|
18
|
-
|
19
|
-
#include <time.h>
|
20
|
-
#include <winevt.h>
|
21
|
-
#define EventQuery(object) ((struct WinevtQuery*)DATA_PTR(object))
|
22
|
-
#define EventBookMark(object) ((struct WinevtBookmark*)DATA_PTR(object))
|
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;
|
31
|
-
|
32
|
-
#ifdef __cplusplus
|
33
|
-
extern "C" {
|
34
|
-
#endif /* __cplusplus */
|
35
|
-
|
36
|
-
VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
|
37
|
-
#if defined(__cplusplus)
|
38
|
-
[[ noreturn ]]
|
39
|
-
#endif /* __cplusplus */
|
40
|
-
void raise_system_error(VALUE error, DWORD errorCode);
|
41
|
-
VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
|
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);
|
46
|
-
VALUE get_values(EVT_HANDLE handle);
|
47
|
-
VALUE render_system_event(EVT_HANDLE handle, BOOL preserve_qualifiers);
|
48
|
-
LocaleInfo* get_locale_info_from_rb_str(VALUE rb_locale_str);
|
49
|
-
|
50
|
-
#ifdef __cplusplus
|
51
|
-
}
|
52
|
-
#endif /* __cplusplus */
|
53
|
-
|
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 {};
|
76
|
-
|
77
|
-
struct WinevtChannel
|
78
|
-
{
|
79
|
-
EVT_HANDLE channels;
|
80
|
-
BOOL force_enumerate;
|
81
|
-
};
|
82
|
-
|
83
|
-
struct WinevtBookmark
|
84
|
-
{
|
85
|
-
EVT_HANDLE bookmark;
|
86
|
-
ULONG count;
|
87
|
-
};
|
88
|
-
|
89
|
-
#define QUERY_ARRAY_SIZE 10
|
90
|
-
|
91
|
-
struct WinevtQuery
|
92
|
-
{
|
93
|
-
EVT_HANDLE query;
|
94
|
-
EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
|
95
|
-
ULONG count;
|
96
|
-
LONG offset;
|
97
|
-
LONG timeout;
|
98
|
-
BOOL renderAsXML;
|
99
|
-
BOOL preserveQualifiers;
|
100
|
-
LocaleInfo *localeInfo;
|
101
|
-
EVT_HANDLE remoteHandle;
|
102
|
-
};
|
103
|
-
|
104
|
-
#define SUBSCRIBE_ARRAY_SIZE 10
|
105
|
-
#define SUBSCRIBE_RATE_INFINITE -1
|
106
|
-
|
107
|
-
struct WinevtSubscribe
|
108
|
-
{
|
109
|
-
HANDLE signalEvent;
|
110
|
-
EVT_HANDLE subscription;
|
111
|
-
EVT_HANDLE bookmark;
|
112
|
-
EVT_HANDLE hEvents[SUBSCRIBE_ARRAY_SIZE];
|
113
|
-
DWORD count;
|
114
|
-
DWORD flags;
|
115
|
-
BOOL readExistingEvents;
|
116
|
-
DWORD rateLimit;
|
117
|
-
time_t lastTime;
|
118
|
-
DWORD currentRate;
|
119
|
-
BOOL renderAsXML;
|
120
|
-
BOOL preserveQualifiers;
|
121
|
-
LocaleInfo* localeInfo;
|
122
|
-
EVT_HANDLE remoteHandle;
|
123
|
-
};
|
124
|
-
|
125
|
-
void Init_winevt_query(VALUE rb_cEventLog);
|
126
|
-
void Init_winevt_channel(VALUE rb_cEventLog);
|
127
|
-
void Init_winevt_bookmark(VALUE rb_cEventLog);
|
128
|
-
void Init_winevt_subscribe(VALUE rb_cEventLog);
|
129
|
-
void Init_winevt_locale(VALUE rb_cEventLog);
|
130
|
-
void Init_winevt_session(VALUE rb_cEventLog);
|
131
|
-
|
132
|
-
#endif // _WINEVT_C_H
|
1
|
+
#ifndef _WINEVT_C_H_
|
2
|
+
#define _WINEVT_C_H_
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <ruby/encoding.h>
|
6
|
+
|
7
|
+
#ifdef __GNUC__
|
8
|
+
#include <w32api.h>
|
9
|
+
#define MINIMUM_WINDOWS_VERSION WindowsVista
|
10
|
+
#else /* __GNUC__ */
|
11
|
+
#define MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */
|
12
|
+
#endif /* __GNUC__ */
|
13
|
+
|
14
|
+
#ifdef _WIN32_WINNT
|
15
|
+
#undef _WIN32_WINNT
|
16
|
+
#endif /* WIN32_WINNT */
|
17
|
+
#define _WIN32_WINNT MINIMUM_WINDOWS_VERSION
|
18
|
+
|
19
|
+
#include <time.h>
|
20
|
+
#include <winevt.h>
|
21
|
+
#define EventQuery(object) ((struct WinevtQuery*)DATA_PTR(object))
|
22
|
+
#define EventBookMark(object) ((struct WinevtBookmark*)DATA_PTR(object))
|
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;
|
31
|
+
|
32
|
+
#ifdef __cplusplus
|
33
|
+
extern "C" {
|
34
|
+
#endif /* __cplusplus */
|
35
|
+
|
36
|
+
VALUE wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen);
|
37
|
+
#if defined(__cplusplus)
|
38
|
+
[[ noreturn ]]
|
39
|
+
#endif /* __cplusplus */
|
40
|
+
void raise_system_error(VALUE error, DWORD errorCode);
|
41
|
+
VALUE render_to_rb_str(EVT_HANDLE handle, DWORD flags);
|
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);
|
46
|
+
VALUE get_values(EVT_HANDLE handle);
|
47
|
+
VALUE render_system_event(EVT_HANDLE handle, BOOL preserve_qualifiers);
|
48
|
+
LocaleInfo* get_locale_info_from_rb_str(VALUE rb_locale_str);
|
49
|
+
|
50
|
+
#ifdef __cplusplus
|
51
|
+
}
|
52
|
+
#endif /* __cplusplus */
|
53
|
+
|
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 {};
|
76
|
+
|
77
|
+
struct WinevtChannel
|
78
|
+
{
|
79
|
+
EVT_HANDLE channels;
|
80
|
+
BOOL force_enumerate;
|
81
|
+
};
|
82
|
+
|
83
|
+
struct WinevtBookmark
|
84
|
+
{
|
85
|
+
EVT_HANDLE bookmark;
|
86
|
+
ULONG count;
|
87
|
+
};
|
88
|
+
|
89
|
+
#define QUERY_ARRAY_SIZE 10
|
90
|
+
|
91
|
+
struct WinevtQuery
|
92
|
+
{
|
93
|
+
EVT_HANDLE query;
|
94
|
+
EVT_HANDLE hEvents[QUERY_ARRAY_SIZE];
|
95
|
+
ULONG count;
|
96
|
+
LONG offset;
|
97
|
+
LONG timeout;
|
98
|
+
BOOL renderAsXML;
|
99
|
+
BOOL preserveQualifiers;
|
100
|
+
LocaleInfo *localeInfo;
|
101
|
+
EVT_HANDLE remoteHandle;
|
102
|
+
};
|
103
|
+
|
104
|
+
#define SUBSCRIBE_ARRAY_SIZE 10
|
105
|
+
#define SUBSCRIBE_RATE_INFINITE -1
|
106
|
+
|
107
|
+
struct WinevtSubscribe
|
108
|
+
{
|
109
|
+
HANDLE signalEvent;
|
110
|
+
EVT_HANDLE subscription;
|
111
|
+
EVT_HANDLE bookmark;
|
112
|
+
EVT_HANDLE hEvents[SUBSCRIBE_ARRAY_SIZE];
|
113
|
+
DWORD count;
|
114
|
+
DWORD flags;
|
115
|
+
BOOL readExistingEvents;
|
116
|
+
DWORD rateLimit;
|
117
|
+
time_t lastTime;
|
118
|
+
DWORD currentRate;
|
119
|
+
BOOL renderAsXML;
|
120
|
+
BOOL preserveQualifiers;
|
121
|
+
LocaleInfo* localeInfo;
|
122
|
+
EVT_HANDLE remoteHandle;
|
123
|
+
};
|
124
|
+
|
125
|
+
void Init_winevt_query(VALUE rb_cEventLog);
|
126
|
+
void Init_winevt_channel(VALUE rb_cEventLog);
|
127
|
+
void Init_winevt_bookmark(VALUE rb_cEventLog);
|
128
|
+
void Init_winevt_subscribe(VALUE rb_cEventLog);
|
129
|
+
void Init_winevt_locale(VALUE rb_cEventLog);
|
130
|
+
void Init_winevt_session(VALUE rb_cEventLog);
|
131
|
+
|
132
|
+
#endif // _WINEVT_C_H
|
data/ext/winevt/winevt_channel.c
CHANGED
@@ -1,327 +1,327 @@
|
|
1
|
-
#include <winevt_c.h>
|
2
|
-
|
3
|
-
/*
|
4
|
-
* Document-class: Winevt::EventLog::Channel
|
5
|
-
*
|
6
|
-
* Retrieve Windows EventLog channel name.
|
7
|
-
*
|
8
|
-
* @example
|
9
|
-
* require 'winevt'
|
10
|
-
* channels = []
|
11
|
-
* @channel = Winevt::EventLog::Channel.new
|
12
|
-
* # If users want to retrieve all channel names that
|
13
|
-
* # including type of Debug and Analytical,
|
14
|
-
* # it should be set as true.
|
15
|
-
* @channel.force_enumerate = false
|
16
|
-
* @channel.each do |channel|
|
17
|
-
* channels << channel
|
18
|
-
* end
|
19
|
-
* print channels
|
20
|
-
*/
|
21
|
-
|
22
|
-
VALUE rb_cChannel;
|
23
|
-
|
24
|
-
DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate);
|
25
|
-
DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate);
|
26
|
-
static void channel_free(void* ptr);
|
27
|
-
|
28
|
-
static const rb_data_type_t rb_winevt_channel_type = { "winevt/channel",
|
29
|
-
{
|
30
|
-
0,
|
31
|
-
channel_free,
|
32
|
-
0,
|
33
|
-
},
|
34
|
-
NULL,
|
35
|
-
NULL,
|
36
|
-
RUBY_TYPED_FREE_IMMEDIATELY };
|
37
|
-
|
38
|
-
static void
|
39
|
-
channel_free(void* ptr)
|
40
|
-
{
|
41
|
-
struct WinevtChannel* winevtChannel = (struct WinevtChannel*)ptr;
|
42
|
-
if (winevtChannel->channels)
|
43
|
-
EvtClose(winevtChannel->channels);
|
44
|
-
|
45
|
-
xfree(ptr);
|
46
|
-
}
|
47
|
-
|
48
|
-
static VALUE
|
49
|
-
rb_winevt_channel_alloc(VALUE klass)
|
50
|
-
{
|
51
|
-
VALUE obj;
|
52
|
-
struct WinevtChannel* winevtChannel;
|
53
|
-
obj = TypedData_Make_Struct(
|
54
|
-
klass, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
55
|
-
return obj;
|
56
|
-
}
|
57
|
-
|
58
|
-
/*
|
59
|
-
* Initalize Channel class.
|
60
|
-
*
|
61
|
-
* @return [Channel]
|
62
|
-
*
|
63
|
-
*/
|
64
|
-
static VALUE
|
65
|
-
rb_winevt_channel_initialize(VALUE self)
|
66
|
-
{
|
67
|
-
struct WinevtChannel* winevtChannel;
|
68
|
-
|
69
|
-
TypedData_Get_Struct(
|
70
|
-
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
71
|
-
|
72
|
-
winevtChannel->force_enumerate = FALSE;
|
73
|
-
|
74
|
-
return Qnil;
|
75
|
-
}
|
76
|
-
|
77
|
-
/*
|
78
|
-
* This method specifies whether forcing to enumerate channel which
|
79
|
-
* type is Debug and Analytical or not.
|
80
|
-
*
|
81
|
-
* @param rb_force_enumerate_p [Boolean]
|
82
|
-
* @since 0.7.1
|
83
|
-
*/
|
84
|
-
static VALUE
|
85
|
-
rb_winevt_channel_set_force_enumerate(VALUE self, VALUE rb_force_enumerate_p)
|
86
|
-
{
|
87
|
-
struct WinevtChannel* winevtChannel;
|
88
|
-
|
89
|
-
TypedData_Get_Struct(
|
90
|
-
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
91
|
-
|
92
|
-
winevtChannel->force_enumerate = RTEST(rb_force_enumerate_p);
|
93
|
-
|
94
|
-
return Qnil;
|
95
|
-
}
|
96
|
-
|
97
|
-
/*
|
98
|
-
* This method returns whether forcing to enumerate channel which type
|
99
|
-
* is Debug and Analytical or not.
|
100
|
-
*
|
101
|
-
* @return [Boolean]
|
102
|
-
* @since 0.7.1
|
103
|
-
*/
|
104
|
-
static VALUE
|
105
|
-
rb_winevt_channel_get_force_enumerate(VALUE self)
|
106
|
-
{
|
107
|
-
struct WinevtChannel* winevtChannel;
|
108
|
-
|
109
|
-
TypedData_Get_Struct(
|
110
|
-
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
111
|
-
|
112
|
-
return winevtChannel->force_enumerate ? Qtrue : Qfalse;
|
113
|
-
}
|
114
|
-
|
115
|
-
DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate)
|
116
|
-
{
|
117
|
-
PEVT_VARIANT pProperty = NULL;
|
118
|
-
PEVT_VARIANT pTemp = NULL;
|
119
|
-
DWORD dwBufferSize = 0;
|
120
|
-
DWORD dwBufferUsed = 0;
|
121
|
-
DWORD status = ERROR_SUCCESS;
|
122
|
-
|
123
|
-
for (int Id = 0; Id < EvtChannelConfigPropertyIdEND; Id++) {
|
124
|
-
if (!EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed)) {
|
125
|
-
status = GetLastError();
|
126
|
-
if (ERROR_INSUFFICIENT_BUFFER == status) {
|
127
|
-
dwBufferSize = dwBufferUsed;
|
128
|
-
pTemp = (PEVT_VARIANT)realloc(pProperty, dwBufferSize);
|
129
|
-
if (pTemp) {
|
130
|
-
pProperty = pTemp;
|
131
|
-
pTemp = NULL;
|
132
|
-
EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed);
|
133
|
-
status = GetLastError();
|
134
|
-
} else {
|
135
|
-
free(pProperty);
|
136
|
-
|
137
|
-
status = ERROR_OUTOFMEMORY;
|
138
|
-
|
139
|
-
goto cleanup;
|
140
|
-
}
|
141
|
-
}
|
142
|
-
|
143
|
-
if (ERROR_SUCCESS != status) {
|
144
|
-
free(pProperty);
|
145
|
-
|
146
|
-
goto cleanup;
|
147
|
-
}
|
148
|
-
}
|
149
|
-
|
150
|
-
status = check_subscribable_with_channel_config_type(Id, pProperty, force_enumerate);
|
151
|
-
if (status != ERROR_SUCCESS)
|
152
|
-
break;
|
153
|
-
}
|
154
|
-
|
155
|
-
cleanup:
|
156
|
-
|
157
|
-
free(pProperty);
|
158
|
-
|
159
|
-
return status;
|
160
|
-
}
|
161
|
-
|
162
|
-
#define EVENT_DEBUG_TYPE 2
|
163
|
-
#define EVENT_ANALYTICAL_TYPE 3
|
164
|
-
|
165
|
-
DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate)
|
166
|
-
{
|
167
|
-
DWORD status = ERROR_SUCCESS;
|
168
|
-
switch(Id) {
|
169
|
-
case EvtChannelConfigType:
|
170
|
-
if (!force_enumerate &&
|
171
|
-
(pProperty->UInt32Val == EVENT_DEBUG_TYPE ||
|
172
|
-
pProperty->UInt32Val == EVENT_ANALYTICAL_TYPE)) {
|
173
|
-
return ERROR_INVALID_DATA;
|
174
|
-
}
|
175
|
-
break;
|
176
|
-
}
|
177
|
-
|
178
|
-
return status;
|
179
|
-
}
|
180
|
-
|
181
|
-
#undef EVENT_DEBUG_TYPE
|
182
|
-
#undef EVENT_ANALYTICAL_TYPE
|
183
|
-
|
184
|
-
/*
|
185
|
-
* Enumerate Windows EventLog channels
|
186
|
-
*
|
187
|
-
* @yield (String)
|
188
|
-
*
|
189
|
-
*/
|
190
|
-
static VALUE
|
191
|
-
rb_winevt_channel_each(VALUE self)
|
192
|
-
{
|
193
|
-
EVT_HANDLE hChannels;
|
194
|
-
EVT_HANDLE hChannelConfig = NULL;
|
195
|
-
struct WinevtChannel* winevtChannel;
|
196
|
-
char errBuf[256];
|
197
|
-
LPWSTR buffer = NULL;
|
198
|
-
DWORD bufferSize = 0;
|
199
|
-
DWORD bufferUsed = 0;
|
200
|
-
DWORD status = ERROR_SUCCESS;
|
201
|
-
VALUE utf8str;
|
202
|
-
|
203
|
-
RETURN_ENUMERATOR(self, 0, 0);
|
204
|
-
|
205
|
-
TypedData_Get_Struct(
|
206
|
-
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
207
|
-
|
208
|
-
hChannels = EvtOpenChannelEnum(NULL, 0);
|
209
|
-
|
210
|
-
if (hChannels) {
|
211
|
-
winevtChannel->channels = hChannels;
|
212
|
-
} else {
|
213
|
-
_snprintf_s(errBuf,
|
214
|
-
_countof(errBuf),
|
215
|
-
_TRUNCATE,
|
216
|
-
"Failed to enumerate channels with %lu\n",
|
217
|
-
GetLastError());
|
218
|
-
rb_raise(rb_eRuntimeError, errBuf);
|
219
|
-
}
|
220
|
-
|
221
|
-
while (1) {
|
222
|
-
if (!EvtNextChannelPath(winevtChannel->channels, bufferSize, buffer, &bufferUsed)) {
|
223
|
-
status = GetLastError();
|
224
|
-
|
225
|
-
if (ERROR_NO_MORE_ITEMS == status) {
|
226
|
-
break;
|
227
|
-
} else if (ERROR_INSUFFICIENT_BUFFER == status) {
|
228
|
-
bufferSize = bufferUsed;
|
229
|
-
buffer = (LPWSTR)malloc(bufferSize * sizeof(WCHAR));
|
230
|
-
if (buffer) {
|
231
|
-
continue;
|
232
|
-
} else {
|
233
|
-
free(buffer);
|
234
|
-
EvtClose(winevtChannel->channels);
|
235
|
-
winevtChannel->channels = NULL;
|
236
|
-
rb_raise(rb_eRuntimeError, "realloc failed");
|
237
|
-
}
|
238
|
-
} else {
|
239
|
-
free(buffer);
|
240
|
-
EvtClose(winevtChannel->channels);
|
241
|
-
winevtChannel->channels = NULL;
|
242
|
-
_snprintf_s(errBuf,
|
243
|
-
_countof(errBuf),
|
244
|
-
_TRUNCATE,
|
245
|
-
"EvtNextChannelPath failed with %lu.\n",
|
246
|
-
status);
|
247
|
-
rb_raise(rb_eRuntimeError, errBuf);
|
248
|
-
}
|
249
|
-
}
|
250
|
-
hChannelConfig = EvtOpenChannelConfig(NULL, buffer, 0);
|
251
|
-
if (NULL == hChannelConfig) {
|
252
|
-
_snprintf_s(errBuf,
|
253
|
-
_countof(errBuf),
|
254
|
-
_TRUNCATE,
|
255
|
-
"EvtOpenChannelConfig failed with %lu.\n",
|
256
|
-
GetLastError());
|
257
|
-
|
258
|
-
EvtClose(winevtChannel->channels);
|
259
|
-
winevtChannel->channels = NULL;
|
260
|
-
|
261
|
-
free(buffer);
|
262
|
-
buffer = NULL;
|
263
|
-
bufferSize = 0;
|
264
|
-
|
265
|
-
rb_raise(rb_eRuntimeError, errBuf);
|
266
|
-
}
|
267
|
-
|
268
|
-
status = is_subscribable_channel_p(hChannelConfig, winevtChannel->force_enumerate);
|
269
|
-
EvtClose(hChannelConfig);
|
270
|
-
|
271
|
-
if (status == ERROR_INVALID_DATA) {
|
272
|
-
free(buffer);
|
273
|
-
buffer = NULL;
|
274
|
-
bufferSize = 0;
|
275
|
-
|
276
|
-
continue;
|
277
|
-
}
|
278
|
-
|
279
|
-
if (status == ERROR_OUTOFMEMORY) {
|
280
|
-
EvtClose(winevtChannel->channels);
|
281
|
-
winevtChannel->channels = NULL;
|
282
|
-
|
283
|
-
free(buffer);
|
284
|
-
buffer = NULL;
|
285
|
-
bufferSize = 0;
|
286
|
-
|
287
|
-
rb_raise(rb_eRuntimeError, "realloc failed\n");
|
288
|
-
} else if (status != ERROR_SUCCESS) {
|
289
|
-
EvtClose(winevtChannel->channels);
|
290
|
-
winevtChannel->channels = NULL;
|
291
|
-
|
292
|
-
free(buffer);
|
293
|
-
buffer = NULL;
|
294
|
-
bufferSize = 0;
|
295
|
-
|
296
|
-
rb_raise(rb_eRuntimeError, "is_subscribe_channel_p is failed with %ld\n", status);
|
297
|
-
}
|
298
|
-
|
299
|
-
utf8str = wstr_to_rb_str(CP_UTF8, buffer, -1);
|
300
|
-
|
301
|
-
free(buffer);
|
302
|
-
buffer = NULL;
|
303
|
-
bufferSize = 0;
|
304
|
-
|
305
|
-
rb_yield(utf8str);
|
306
|
-
}
|
307
|
-
|
308
|
-
if (winevtChannel->channels) {
|
309
|
-
EvtClose(winevtChannel->channels);
|
310
|
-
winevtChannel->channels = NULL;
|
311
|
-
}
|
312
|
-
|
313
|
-
free(buffer);
|
314
|
-
|
315
|
-
return Qnil;
|
316
|
-
}
|
317
|
-
|
318
|
-
void
|
319
|
-
Init_winevt_channel(VALUE rb_cEventLog)
|
320
|
-
{
|
321
|
-
rb_cChannel = rb_define_class_under(rb_cEventLog, "Channel", rb_cObject);
|
322
|
-
rb_define_alloc_func(rb_cChannel, rb_winevt_channel_alloc);
|
323
|
-
rb_define_method(rb_cChannel, "initialize", rb_winevt_channel_initialize, 0);
|
324
|
-
rb_define_method(rb_cChannel, "each", rb_winevt_channel_each, 0);
|
325
|
-
rb_define_method(rb_cChannel, "force_enumerate", rb_winevt_channel_get_force_enumerate, 0);
|
326
|
-
rb_define_method(rb_cChannel, "force_enumerate=", rb_winevt_channel_set_force_enumerate, 1);
|
327
|
-
}
|
1
|
+
#include <winevt_c.h>
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Document-class: Winevt::EventLog::Channel
|
5
|
+
*
|
6
|
+
* Retrieve Windows EventLog channel name.
|
7
|
+
*
|
8
|
+
* @example
|
9
|
+
* require 'winevt'
|
10
|
+
* channels = []
|
11
|
+
* @channel = Winevt::EventLog::Channel.new
|
12
|
+
* # If users want to retrieve all channel names that
|
13
|
+
* # including type of Debug and Analytical,
|
14
|
+
* # it should be set as true.
|
15
|
+
* @channel.force_enumerate = false
|
16
|
+
* @channel.each do |channel|
|
17
|
+
* channels << channel
|
18
|
+
* end
|
19
|
+
* print channels
|
20
|
+
*/
|
21
|
+
|
22
|
+
VALUE rb_cChannel;
|
23
|
+
|
24
|
+
DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate);
|
25
|
+
DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate);
|
26
|
+
static void channel_free(void* ptr);
|
27
|
+
|
28
|
+
static const rb_data_type_t rb_winevt_channel_type = { "winevt/channel",
|
29
|
+
{
|
30
|
+
0,
|
31
|
+
channel_free,
|
32
|
+
0,
|
33
|
+
},
|
34
|
+
NULL,
|
35
|
+
NULL,
|
36
|
+
RUBY_TYPED_FREE_IMMEDIATELY };
|
37
|
+
|
38
|
+
static void
|
39
|
+
channel_free(void* ptr)
|
40
|
+
{
|
41
|
+
struct WinevtChannel* winevtChannel = (struct WinevtChannel*)ptr;
|
42
|
+
if (winevtChannel->channels)
|
43
|
+
EvtClose(winevtChannel->channels);
|
44
|
+
|
45
|
+
xfree(ptr);
|
46
|
+
}
|
47
|
+
|
48
|
+
static VALUE
|
49
|
+
rb_winevt_channel_alloc(VALUE klass)
|
50
|
+
{
|
51
|
+
VALUE obj;
|
52
|
+
struct WinevtChannel* winevtChannel;
|
53
|
+
obj = TypedData_Make_Struct(
|
54
|
+
klass, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
55
|
+
return obj;
|
56
|
+
}
|
57
|
+
|
58
|
+
/*
|
59
|
+
* Initalize Channel class.
|
60
|
+
*
|
61
|
+
* @return [Channel]
|
62
|
+
*
|
63
|
+
*/
|
64
|
+
static VALUE
|
65
|
+
rb_winevt_channel_initialize(VALUE self)
|
66
|
+
{
|
67
|
+
struct WinevtChannel* winevtChannel;
|
68
|
+
|
69
|
+
TypedData_Get_Struct(
|
70
|
+
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
71
|
+
|
72
|
+
winevtChannel->force_enumerate = FALSE;
|
73
|
+
|
74
|
+
return Qnil;
|
75
|
+
}
|
76
|
+
|
77
|
+
/*
|
78
|
+
* This method specifies whether forcing to enumerate channel which
|
79
|
+
* type is Debug and Analytical or not.
|
80
|
+
*
|
81
|
+
* @param rb_force_enumerate_p [Boolean]
|
82
|
+
* @since 0.7.1
|
83
|
+
*/
|
84
|
+
static VALUE
|
85
|
+
rb_winevt_channel_set_force_enumerate(VALUE self, VALUE rb_force_enumerate_p)
|
86
|
+
{
|
87
|
+
struct WinevtChannel* winevtChannel;
|
88
|
+
|
89
|
+
TypedData_Get_Struct(
|
90
|
+
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
91
|
+
|
92
|
+
winevtChannel->force_enumerate = RTEST(rb_force_enumerate_p);
|
93
|
+
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
/*
|
98
|
+
* This method returns whether forcing to enumerate channel which type
|
99
|
+
* is Debug and Analytical or not.
|
100
|
+
*
|
101
|
+
* @return [Boolean]
|
102
|
+
* @since 0.7.1
|
103
|
+
*/
|
104
|
+
static VALUE
|
105
|
+
rb_winevt_channel_get_force_enumerate(VALUE self)
|
106
|
+
{
|
107
|
+
struct WinevtChannel* winevtChannel;
|
108
|
+
|
109
|
+
TypedData_Get_Struct(
|
110
|
+
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
111
|
+
|
112
|
+
return winevtChannel->force_enumerate ? Qtrue : Qfalse;
|
113
|
+
}
|
114
|
+
|
115
|
+
DWORD is_subscribable_channel_p(EVT_HANDLE hChannel, BOOL force_enumerate)
|
116
|
+
{
|
117
|
+
PEVT_VARIANT pProperty = NULL;
|
118
|
+
PEVT_VARIANT pTemp = NULL;
|
119
|
+
DWORD dwBufferSize = 0;
|
120
|
+
DWORD dwBufferUsed = 0;
|
121
|
+
DWORD status = ERROR_SUCCESS;
|
122
|
+
|
123
|
+
for (int Id = 0; Id < EvtChannelConfigPropertyIdEND; Id++) {
|
124
|
+
if (!EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed)) {
|
125
|
+
status = GetLastError();
|
126
|
+
if (ERROR_INSUFFICIENT_BUFFER == status) {
|
127
|
+
dwBufferSize = dwBufferUsed;
|
128
|
+
pTemp = (PEVT_VARIANT)realloc(pProperty, dwBufferSize);
|
129
|
+
if (pTemp) {
|
130
|
+
pProperty = pTemp;
|
131
|
+
pTemp = NULL;
|
132
|
+
EvtGetChannelConfigProperty(hChannel, (EVT_CHANNEL_CONFIG_PROPERTY_ID)Id, 0, dwBufferSize, pProperty, &dwBufferUsed);
|
133
|
+
status = GetLastError();
|
134
|
+
} else {
|
135
|
+
free(pProperty);
|
136
|
+
|
137
|
+
status = ERROR_OUTOFMEMORY;
|
138
|
+
|
139
|
+
goto cleanup;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
if (ERROR_SUCCESS != status) {
|
144
|
+
free(pProperty);
|
145
|
+
|
146
|
+
goto cleanup;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
status = check_subscribable_with_channel_config_type(Id, pProperty, force_enumerate);
|
151
|
+
if (status != ERROR_SUCCESS)
|
152
|
+
break;
|
153
|
+
}
|
154
|
+
|
155
|
+
cleanup:
|
156
|
+
|
157
|
+
free(pProperty);
|
158
|
+
|
159
|
+
return status;
|
160
|
+
}
|
161
|
+
|
162
|
+
#define EVENT_DEBUG_TYPE 2
|
163
|
+
#define EVENT_ANALYTICAL_TYPE 3
|
164
|
+
|
165
|
+
DWORD check_subscribable_with_channel_config_type(int Id, PEVT_VARIANT pProperty, BOOL force_enumerate)
|
166
|
+
{
|
167
|
+
DWORD status = ERROR_SUCCESS;
|
168
|
+
switch(Id) {
|
169
|
+
case EvtChannelConfigType:
|
170
|
+
if (!force_enumerate &&
|
171
|
+
(pProperty->UInt32Val == EVENT_DEBUG_TYPE ||
|
172
|
+
pProperty->UInt32Val == EVENT_ANALYTICAL_TYPE)) {
|
173
|
+
return ERROR_INVALID_DATA;
|
174
|
+
}
|
175
|
+
break;
|
176
|
+
}
|
177
|
+
|
178
|
+
return status;
|
179
|
+
}
|
180
|
+
|
181
|
+
#undef EVENT_DEBUG_TYPE
|
182
|
+
#undef EVENT_ANALYTICAL_TYPE
|
183
|
+
|
184
|
+
/*
|
185
|
+
* Enumerate Windows EventLog channels
|
186
|
+
*
|
187
|
+
* @yield (String)
|
188
|
+
*
|
189
|
+
*/
|
190
|
+
static VALUE
|
191
|
+
rb_winevt_channel_each(VALUE self)
|
192
|
+
{
|
193
|
+
EVT_HANDLE hChannels;
|
194
|
+
EVT_HANDLE hChannelConfig = NULL;
|
195
|
+
struct WinevtChannel* winevtChannel;
|
196
|
+
char errBuf[256];
|
197
|
+
LPWSTR buffer = NULL;
|
198
|
+
DWORD bufferSize = 0;
|
199
|
+
DWORD bufferUsed = 0;
|
200
|
+
DWORD status = ERROR_SUCCESS;
|
201
|
+
VALUE utf8str;
|
202
|
+
|
203
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
204
|
+
|
205
|
+
TypedData_Get_Struct(
|
206
|
+
self, struct WinevtChannel, &rb_winevt_channel_type, winevtChannel);
|
207
|
+
|
208
|
+
hChannels = EvtOpenChannelEnum(NULL, 0);
|
209
|
+
|
210
|
+
if (hChannels) {
|
211
|
+
winevtChannel->channels = hChannels;
|
212
|
+
} else {
|
213
|
+
_snprintf_s(errBuf,
|
214
|
+
_countof(errBuf),
|
215
|
+
_TRUNCATE,
|
216
|
+
"Failed to enumerate channels with %lu\n",
|
217
|
+
GetLastError());
|
218
|
+
rb_raise(rb_eRuntimeError, errBuf);
|
219
|
+
}
|
220
|
+
|
221
|
+
while (1) {
|
222
|
+
if (!EvtNextChannelPath(winevtChannel->channels, bufferSize, buffer, &bufferUsed)) {
|
223
|
+
status = GetLastError();
|
224
|
+
|
225
|
+
if (ERROR_NO_MORE_ITEMS == status) {
|
226
|
+
break;
|
227
|
+
} else if (ERROR_INSUFFICIENT_BUFFER == status) {
|
228
|
+
bufferSize = bufferUsed;
|
229
|
+
buffer = (LPWSTR)malloc(bufferSize * sizeof(WCHAR));
|
230
|
+
if (buffer) {
|
231
|
+
continue;
|
232
|
+
} else {
|
233
|
+
free(buffer);
|
234
|
+
EvtClose(winevtChannel->channels);
|
235
|
+
winevtChannel->channels = NULL;
|
236
|
+
rb_raise(rb_eRuntimeError, "realloc failed");
|
237
|
+
}
|
238
|
+
} else {
|
239
|
+
free(buffer);
|
240
|
+
EvtClose(winevtChannel->channels);
|
241
|
+
winevtChannel->channels = NULL;
|
242
|
+
_snprintf_s(errBuf,
|
243
|
+
_countof(errBuf),
|
244
|
+
_TRUNCATE,
|
245
|
+
"EvtNextChannelPath failed with %lu.\n",
|
246
|
+
status);
|
247
|
+
rb_raise(rb_eRuntimeError, errBuf);
|
248
|
+
}
|
249
|
+
}
|
250
|
+
hChannelConfig = EvtOpenChannelConfig(NULL, buffer, 0);
|
251
|
+
if (NULL == hChannelConfig) {
|
252
|
+
_snprintf_s(errBuf,
|
253
|
+
_countof(errBuf),
|
254
|
+
_TRUNCATE,
|
255
|
+
"EvtOpenChannelConfig failed with %lu.\n",
|
256
|
+
GetLastError());
|
257
|
+
|
258
|
+
EvtClose(winevtChannel->channels);
|
259
|
+
winevtChannel->channels = NULL;
|
260
|
+
|
261
|
+
free(buffer);
|
262
|
+
buffer = NULL;
|
263
|
+
bufferSize = 0;
|
264
|
+
|
265
|
+
rb_raise(rb_eRuntimeError, errBuf);
|
266
|
+
}
|
267
|
+
|
268
|
+
status = is_subscribable_channel_p(hChannelConfig, winevtChannel->force_enumerate);
|
269
|
+
EvtClose(hChannelConfig);
|
270
|
+
|
271
|
+
if (status == ERROR_INVALID_DATA) {
|
272
|
+
free(buffer);
|
273
|
+
buffer = NULL;
|
274
|
+
bufferSize = 0;
|
275
|
+
|
276
|
+
continue;
|
277
|
+
}
|
278
|
+
|
279
|
+
if (status == ERROR_OUTOFMEMORY) {
|
280
|
+
EvtClose(winevtChannel->channels);
|
281
|
+
winevtChannel->channels = NULL;
|
282
|
+
|
283
|
+
free(buffer);
|
284
|
+
buffer = NULL;
|
285
|
+
bufferSize = 0;
|
286
|
+
|
287
|
+
rb_raise(rb_eRuntimeError, "realloc failed\n");
|
288
|
+
} else if (status != ERROR_SUCCESS) {
|
289
|
+
EvtClose(winevtChannel->channels);
|
290
|
+
winevtChannel->channels = NULL;
|
291
|
+
|
292
|
+
free(buffer);
|
293
|
+
buffer = NULL;
|
294
|
+
bufferSize = 0;
|
295
|
+
|
296
|
+
rb_raise(rb_eRuntimeError, "is_subscribe_channel_p is failed with %ld\n", status);
|
297
|
+
}
|
298
|
+
|
299
|
+
utf8str = wstr_to_rb_str(CP_UTF8, buffer, -1);
|
300
|
+
|
301
|
+
free(buffer);
|
302
|
+
buffer = NULL;
|
303
|
+
bufferSize = 0;
|
304
|
+
|
305
|
+
rb_yield(utf8str);
|
306
|
+
}
|
307
|
+
|
308
|
+
if (winevtChannel->channels) {
|
309
|
+
EvtClose(winevtChannel->channels);
|
310
|
+
winevtChannel->channels = NULL;
|
311
|
+
}
|
312
|
+
|
313
|
+
free(buffer);
|
314
|
+
|
315
|
+
return Qnil;
|
316
|
+
}
|
317
|
+
|
318
|
+
void
|
319
|
+
Init_winevt_channel(VALUE rb_cEventLog)
|
320
|
+
{
|
321
|
+
rb_cChannel = rb_define_class_under(rb_cEventLog, "Channel", rb_cObject);
|
322
|
+
rb_define_alloc_func(rb_cChannel, rb_winevt_channel_alloc);
|
323
|
+
rb_define_method(rb_cChannel, "initialize", rb_winevt_channel_initialize, 0);
|
324
|
+
rb_define_method(rb_cChannel, "each", rb_winevt_channel_each, 0);
|
325
|
+
rb_define_method(rb_cChannel, "force_enumerate", rb_winevt_channel_get_force_enumerate, 0);
|
326
|
+
rb_define_method(rb_cChannel, "force_enumerate=", rb_winevt_channel_set_force_enumerate, 1);
|
327
|
+
}
|