winevt_c 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/eventlog.rb +11 -2
- data/example/tailing.rb +13 -2
- data/ext/winevt/winevt.c +6 -737
- data/ext/winevt/winevt_bookmark.c +100 -0
- data/ext/winevt/winevt_c.h +65 -0
- data/ext/winevt/winevt_channel.c +103 -0
- data/ext/winevt/winevt_query.c +245 -0
- data/ext/winevt/winevt_subscribe.c +220 -0
- data/ext/winevt/winevt_utils.c +236 -0
- data/lib/winevt/version.rb +3 -3
- metadata +8 -2
@@ -0,0 +1,220 @@
|
|
1
|
+
#include <winevt_c.h>
|
2
|
+
|
3
|
+
static void subscribe_free(void *ptr);
|
4
|
+
|
5
|
+
static const rb_data_type_t rb_winevt_subscribe_type = {
|
6
|
+
"winevt/subscribe", {
|
7
|
+
0, subscribe_free, 0,
|
8
|
+
}, NULL, NULL,
|
9
|
+
RUBY_TYPED_FREE_IMMEDIATELY
|
10
|
+
};
|
11
|
+
|
12
|
+
static void
|
13
|
+
subscribe_free(void *ptr)
|
14
|
+
{
|
15
|
+
struct WinevtSubscribe *winevtSubscribe = (struct WinevtSubscribe *)ptr;
|
16
|
+
if (winevtSubscribe->signalEvent)
|
17
|
+
CloseHandle(winevtSubscribe->signalEvent);
|
18
|
+
|
19
|
+
if (winevtSubscribe->subscription)
|
20
|
+
EvtClose(winevtSubscribe->subscription);
|
21
|
+
|
22
|
+
if (winevtSubscribe->bookmark)
|
23
|
+
EvtClose(winevtSubscribe->bookmark);
|
24
|
+
|
25
|
+
if (winevtSubscribe->event)
|
26
|
+
EvtClose(winevtSubscribe->event);
|
27
|
+
|
28
|
+
xfree(ptr);
|
29
|
+
}
|
30
|
+
|
31
|
+
static VALUE
|
32
|
+
rb_winevt_subscribe_alloc(VALUE klass)
|
33
|
+
{
|
34
|
+
VALUE obj;
|
35
|
+
struct WinevtSubscribe *winevtSubscribe;
|
36
|
+
obj = TypedData_Make_Struct(klass,
|
37
|
+
struct WinevtSubscribe,
|
38
|
+
&rb_winevt_subscribe_type,
|
39
|
+
winevtSubscribe);
|
40
|
+
return obj;
|
41
|
+
}
|
42
|
+
|
43
|
+
static VALUE
|
44
|
+
rb_winevt_subscribe_initialize(VALUE self)
|
45
|
+
{
|
46
|
+
return Qnil;
|
47
|
+
}
|
48
|
+
|
49
|
+
static VALUE
|
50
|
+
rb_winevt_subscribe_set_tail(VALUE self, VALUE rb_tailing_p)
|
51
|
+
{
|
52
|
+
struct WinevtSubscribe *winevtSubscribe;
|
53
|
+
|
54
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
55
|
+
|
56
|
+
winevtSubscribe->tailing = RTEST(rb_tailing_p);
|
57
|
+
|
58
|
+
return Qnil;
|
59
|
+
}
|
60
|
+
|
61
|
+
static VALUE
|
62
|
+
rb_winevt_subscribe_tail_p(VALUE self, VALUE rb_flag)
|
63
|
+
{
|
64
|
+
struct WinevtSubscribe *winevtSubscribe;
|
65
|
+
|
66
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
67
|
+
|
68
|
+
return winevtSubscribe->tailing ? Qtrue : Qfalse;
|
69
|
+
}
|
70
|
+
|
71
|
+
static VALUE
|
72
|
+
rb_winevt_subscribe_subscribe(int argc, VALUE argv, VALUE self)
|
73
|
+
{
|
74
|
+
VALUE rb_path, rb_query, rb_bookmark;
|
75
|
+
EVT_HANDLE hSubscription = NULL, hBookmark = NULL;
|
76
|
+
HANDLE hSignalEvent;
|
77
|
+
DWORD len, flags;
|
78
|
+
VALUE wpathBuf, wqueryBuf;
|
79
|
+
PWSTR path, query;
|
80
|
+
DWORD status = ERROR_SUCCESS;
|
81
|
+
struct WinevtBookmark *winevtBookmark;
|
82
|
+
struct WinevtSubscribe *winevtSubscribe;
|
83
|
+
|
84
|
+
hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
85
|
+
|
86
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
87
|
+
|
88
|
+
rb_scan_args(argc, argv, "21", &rb_path, &rb_query, &rb_bookmark);
|
89
|
+
Check_Type(rb_path, T_STRING);
|
90
|
+
Check_Type(rb_query, T_STRING);
|
91
|
+
|
92
|
+
if (rb_obj_is_kind_of(rb_bookmark, rb_cBookmark)) {
|
93
|
+
hBookmark = EventBookMark(rb_bookmark)->bookmark;
|
94
|
+
}
|
95
|
+
|
96
|
+
// path : To wide char
|
97
|
+
len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_path), RSTRING_LEN(rb_path), NULL, 0);
|
98
|
+
path = ALLOCV_N(WCHAR, wpathBuf, len+1);
|
99
|
+
MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_path), RSTRING_LEN(rb_path), path, len);
|
100
|
+
path[len] = L'\0';
|
101
|
+
|
102
|
+
// query : To wide char
|
103
|
+
len = MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_query), RSTRING_LEN(rb_query), NULL, 0);
|
104
|
+
query = ALLOCV_N(WCHAR, wqueryBuf, len+1);
|
105
|
+
MultiByteToWideChar(CP_UTF8, 0, RSTRING_PTR(rb_query), RSTRING_LEN(rb_query), query, len);
|
106
|
+
query[len] = L'\0';
|
107
|
+
|
108
|
+
if (hBookmark){
|
109
|
+
flags |= EvtSubscribeStartAfterBookmark;
|
110
|
+
} else if (winevtSubscribe->tailing) {
|
111
|
+
flags |= EvtSubscribeToFutureEvents;
|
112
|
+
} else {
|
113
|
+
flags |= EvtSubscribeStartAtOldestRecord;
|
114
|
+
}
|
115
|
+
|
116
|
+
hSubscription = EvtSubscribe(NULL, hSignalEvent, path, query, hBookmark, NULL, NULL, flags);
|
117
|
+
|
118
|
+
winevtSubscribe->signalEvent = hSignalEvent;
|
119
|
+
winevtSubscribe->subscription = hSubscription;
|
120
|
+
if (hBookmark) {
|
121
|
+
winevtSubscribe->bookmark = hBookmark;
|
122
|
+
} else {
|
123
|
+
winevtSubscribe->bookmark = EvtCreateBookmark(NULL);
|
124
|
+
}
|
125
|
+
|
126
|
+
status = GetLastError();
|
127
|
+
|
128
|
+
if (status == ERROR_SUCCESS)
|
129
|
+
return Qtrue;
|
130
|
+
|
131
|
+
return Qfalse;
|
132
|
+
}
|
133
|
+
|
134
|
+
static VALUE
|
135
|
+
rb_winevt_subscribe_next(VALUE self)
|
136
|
+
{
|
137
|
+
EVT_HANDLE event;
|
138
|
+
ULONG count;
|
139
|
+
struct WinevtSubscribe *winevtSubscribe;
|
140
|
+
|
141
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
142
|
+
|
143
|
+
if (EvtNext(winevtSubscribe->subscription, 1, &event, INFINITE, 0, &count) != FALSE) {
|
144
|
+
winevtSubscribe->event = event;
|
145
|
+
EvtUpdateBookmark(winevtSubscribe->bookmark, winevtSubscribe->event);
|
146
|
+
|
147
|
+
return Qtrue;
|
148
|
+
}
|
149
|
+
|
150
|
+
return Qfalse;
|
151
|
+
}
|
152
|
+
|
153
|
+
static VALUE
|
154
|
+
rb_winevt_subscribe_render(VALUE self)
|
155
|
+
{
|
156
|
+
char* result;
|
157
|
+
struct WinevtSubscribe *winevtSubscribe;
|
158
|
+
|
159
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
160
|
+
result = render_event(winevtSubscribe->event, EvtRenderEventXml);
|
161
|
+
|
162
|
+
return rb_str_new2(result);
|
163
|
+
}
|
164
|
+
|
165
|
+
static VALUE
|
166
|
+
rb_winevt_subscribe_message(VALUE self)
|
167
|
+
{
|
168
|
+
char* result;
|
169
|
+
struct WinevtSubscribe *winevtSubscribe;
|
170
|
+
|
171
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
172
|
+
result = get_description(winevtSubscribe->event);
|
173
|
+
|
174
|
+
return rb_str_new2(result);
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE
|
178
|
+
rb_winevt_subscribe_each(VALUE self)
|
179
|
+
{
|
180
|
+
struct WinevtSubscribe *winevtSubscribe;
|
181
|
+
|
182
|
+
RETURN_ENUMERATOR(self, 0, 0);
|
183
|
+
|
184
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
185
|
+
|
186
|
+
while (rb_winevt_subscribe_next(self)) {
|
187
|
+
rb_yield_values(2, rb_winevt_subscribe_render(self), rb_winevt_subscribe_message(self));
|
188
|
+
}
|
189
|
+
|
190
|
+
return Qnil;
|
191
|
+
}
|
192
|
+
|
193
|
+
static VALUE
|
194
|
+
rb_winevt_subscribe_get_bookmark(VALUE self)
|
195
|
+
{
|
196
|
+
char* result;
|
197
|
+
struct WinevtSubscribe *winevtSubscribe;
|
198
|
+
|
199
|
+
TypedData_Get_Struct(self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe);
|
200
|
+
|
201
|
+
result = render_event(winevtSubscribe->bookmark, EvtRenderBookmark);
|
202
|
+
|
203
|
+
return rb_str_new2(result);
|
204
|
+
}
|
205
|
+
|
206
|
+
void Init_winevt_subscribe(VALUE rb_cEventLog)
|
207
|
+
{
|
208
|
+
rb_cSubscribe = rb_define_class_under(rb_cEventLog, "Subscribe", rb_cObject);
|
209
|
+
|
210
|
+
rb_define_alloc_func(rb_cSubscribe, rb_winevt_subscribe_alloc);
|
211
|
+
rb_define_method(rb_cSubscribe, "initialize", rb_winevt_subscribe_initialize, 0);
|
212
|
+
rb_define_method(rb_cSubscribe, "subscribe", rb_winevt_subscribe_subscribe, -1);
|
213
|
+
rb_define_method(rb_cSubscribe, "next", rb_winevt_subscribe_next, 0);
|
214
|
+
rb_define_method(rb_cSubscribe, "render", rb_winevt_subscribe_render, 0);
|
215
|
+
rb_define_method(rb_cSubscribe, "message", rb_winevt_subscribe_message, 0);
|
216
|
+
rb_define_method(rb_cSubscribe, "each", rb_winevt_subscribe_each, 0);
|
217
|
+
rb_define_method(rb_cSubscribe, "bookmark", rb_winevt_subscribe_get_bookmark, 0);
|
218
|
+
rb_define_method(rb_cSubscribe, "tail?", rb_winevt_subscribe_tail_p, 0);
|
219
|
+
rb_define_method(rb_cSubscribe, "tail=", rb_winevt_subscribe_set_tail, 1);
|
220
|
+
}
|
@@ -0,0 +1,236 @@
|
|
1
|
+
#include <winevt_c.h>
|
2
|
+
|
3
|
+
char*
|
4
|
+
wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen)
|
5
|
+
{
|
6
|
+
char *ptr;
|
7
|
+
int len = WideCharToMultiByte(cp, 0, wstr, clen, NULL, 0, NULL, NULL);
|
8
|
+
if (!(ptr = malloc(len))) return 0;
|
9
|
+
WideCharToMultiByte(cp, 0, wstr, clen, ptr, len, NULL, NULL);
|
10
|
+
|
11
|
+
return ptr;
|
12
|
+
}
|
13
|
+
|
14
|
+
char* render_event(EVT_HANDLE handle, DWORD flags)
|
15
|
+
{
|
16
|
+
PWSTR buffer = NULL;
|
17
|
+
ULONG bufferSize = 0;
|
18
|
+
ULONG bufferSizeNeeded = 0;
|
19
|
+
EVT_HANDLE event;
|
20
|
+
ULONG status, count;
|
21
|
+
char* errBuf;
|
22
|
+
char* result;
|
23
|
+
LPTSTR msgBuf;
|
24
|
+
|
25
|
+
do {
|
26
|
+
if (bufferSizeNeeded > bufferSize) {
|
27
|
+
free(buffer);
|
28
|
+
bufferSize = bufferSizeNeeded;
|
29
|
+
buffer = malloc(bufferSize);
|
30
|
+
if (buffer == NULL) {
|
31
|
+
status = ERROR_OUTOFMEMORY;
|
32
|
+
bufferSize = 0;
|
33
|
+
rb_raise(rb_eWinevtQueryError, "Out of memory");
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
if (EvtRender(NULL,
|
39
|
+
handle,
|
40
|
+
flags,
|
41
|
+
bufferSize,
|
42
|
+
buffer,
|
43
|
+
&bufferSizeNeeded,
|
44
|
+
&count) != FALSE) {
|
45
|
+
status = ERROR_SUCCESS;
|
46
|
+
} else {
|
47
|
+
status = GetLastError();
|
48
|
+
}
|
49
|
+
} while (status == ERROR_INSUFFICIENT_BUFFER);
|
50
|
+
|
51
|
+
if (status != ERROR_SUCCESS) {
|
52
|
+
FormatMessage(
|
53
|
+
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
54
|
+
FORMAT_MESSAGE_FROM_SYSTEM |
|
55
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
56
|
+
NULL, status,
|
57
|
+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
58
|
+
&msgBuf, 0, NULL);
|
59
|
+
result = wstr_to_mbstr(CP_ACP, msgBuf, -1);
|
60
|
+
|
61
|
+
rb_raise(rb_eWinevtQueryError, "ErrorCode: %d\nError: %s\n", status, result);
|
62
|
+
}
|
63
|
+
|
64
|
+
result = wstr_to_mbstr(CP_UTF8, buffer, -1);
|
65
|
+
|
66
|
+
if (buffer)
|
67
|
+
free(buffer);
|
68
|
+
|
69
|
+
return result;
|
70
|
+
}
|
71
|
+
|
72
|
+
char* get_description(EVT_HANDLE handle)
|
73
|
+
{
|
74
|
+
#define MAX_BUFFER 65535
|
75
|
+
WCHAR buffer[4096], file[4096];
|
76
|
+
WCHAR descriptionBuffer[MAX_BUFFER];
|
77
|
+
ULONG bufferSize = 0;
|
78
|
+
ULONG bufferSizeNeeded = 0;
|
79
|
+
EVT_HANDLE event;
|
80
|
+
ULONG status, count;
|
81
|
+
char* errBuf;
|
82
|
+
char* result = "";
|
83
|
+
LPTSTR msgBuf;
|
84
|
+
TCHAR publisherName[MAX_PATH];
|
85
|
+
TCHAR fileName[MAX_PATH];
|
86
|
+
EVT_HANDLE hMetadata = NULL;
|
87
|
+
PEVT_VARIANT values = NULL;
|
88
|
+
PEVT_VARIANT pProperty = NULL;
|
89
|
+
PEVT_VARIANT pTemp = NULL;
|
90
|
+
TCHAR paramEXE[MAX_PATH], messageEXE[MAX_PATH];
|
91
|
+
HMODULE hModule = NULL;
|
92
|
+
|
93
|
+
static PCWSTR eventProperties[] = {L"Event/System/Provider/@Name", L"Event/System/EventID"};
|
94
|
+
EVT_HANDLE renderContext = EvtCreateRenderContext(2, eventProperties, EvtRenderContextValues);
|
95
|
+
if (renderContext == NULL) {
|
96
|
+
rb_raise(rb_eWinevtQueryError, "Failed to create renderContext");
|
97
|
+
}
|
98
|
+
|
99
|
+
if (EvtRender(renderContext,
|
100
|
+
handle,
|
101
|
+
EvtRenderEventValues,
|
102
|
+
_countof(buffer),
|
103
|
+
buffer,
|
104
|
+
&bufferSizeNeeded,
|
105
|
+
&count) != FALSE) {
|
106
|
+
status = ERROR_SUCCESS;
|
107
|
+
} else {
|
108
|
+
status = GetLastError();
|
109
|
+
}
|
110
|
+
|
111
|
+
if (status != ERROR_SUCCESS) {
|
112
|
+
FormatMessage(
|
113
|
+
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
114
|
+
FORMAT_MESSAGE_FROM_SYSTEM |
|
115
|
+
FORMAT_MESSAGE_IGNORE_INSERTS,
|
116
|
+
NULL, status,
|
117
|
+
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
118
|
+
&msgBuf, 0, NULL);
|
119
|
+
result = wstr_to_mbstr(CP_ACP, msgBuf, -1);
|
120
|
+
|
121
|
+
rb_raise(rb_eWinevtQueryError, "ErrorCode: %d\nError: %s\n", status, result);
|
122
|
+
}
|
123
|
+
|
124
|
+
// Obtain buffer as EVT_VARIANT pointer. To avoid ErrorCide 87 in EvtRender.
|
125
|
+
values = (PEVT_VARIANT)buffer;
|
126
|
+
if ((values[0].Type == EvtVarTypeString) && (values[0].StringVal != NULL)) {
|
127
|
+
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, values[0].StringVal, -1, publisherName, MAX_PATH, NULL, NULL);
|
128
|
+
}
|
129
|
+
|
130
|
+
DWORD eventId = 0;
|
131
|
+
if (values[1].Type == EvtVarTypeUInt16) {
|
132
|
+
eventId = values[1].UInt16Val;
|
133
|
+
}
|
134
|
+
|
135
|
+
// Open publisher metadata
|
136
|
+
hMetadata = EvtOpenPublisherMetadata(NULL, values[0].StringVal, NULL, MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT), 0);
|
137
|
+
if (hMetadata == NULL) {
|
138
|
+
// When winevt_c cannot open metadata, then give up to obtain
|
139
|
+
// message file and clean up immediately.
|
140
|
+
goto cleanup;
|
141
|
+
}
|
142
|
+
|
143
|
+
/* TODO: Should we implement parameter file reading in C?
|
144
|
+
// Get the metadata property. If the buffer is not big enough, reallocate the buffer.
|
145
|
+
// Get parameter file first.
|
146
|
+
if (!EvtGetPublisherMetadataProperty(hMetadata, EvtPublisherMetadataParameterFilePath, 0, bufferSize, pProperty, &count)) {
|
147
|
+
status = GetLastError();
|
148
|
+
if (ERROR_INSUFFICIENT_BUFFER == status) {
|
149
|
+
bufferSize = count;
|
150
|
+
pTemp = (PEVT_VARIANT)realloc(pProperty, bufferSize);
|
151
|
+
if (pTemp) {
|
152
|
+
pProperty = pTemp;
|
153
|
+
pTemp = NULL;
|
154
|
+
EvtGetPublisherMetadataProperty(hMetadata, EvtPublisherMetadataParameterFilePath, 0, bufferSize, pProperty, &count);
|
155
|
+
} else {
|
156
|
+
rb_raise(rb_eWinevtQueryError, "realloc failed");
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
if (ERROR_SUCCESS != (status = GetLastError())) {
|
161
|
+
rb_raise(rb_eWinevtQueryError, "EvtGetPublisherMetadataProperty for parameter file failed with %d\n", GetLastError());
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
if ((pProperty->Type == EvtVarTypeString) && (pProperty->StringVal != NULL)) {
|
166
|
+
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, pProperty->StringVal, -1, fileName, MAX_PATH, NULL, NULL);
|
167
|
+
}
|
168
|
+
if (paramEXE) {
|
169
|
+
ExpandEnvironmentStrings(fileName, paramEXE, _countof(paramEXE));
|
170
|
+
}
|
171
|
+
*/
|
172
|
+
|
173
|
+
// Get the metadata property. If the buffer is not big enough, reallocate the buffer.
|
174
|
+
// Get message file contents.
|
175
|
+
if (!EvtGetPublisherMetadataProperty(hMetadata, EvtPublisherMetadataMessageFilePath, 0, bufferSize, pProperty, &count)) {
|
176
|
+
status = GetLastError();
|
177
|
+
if (ERROR_INSUFFICIENT_BUFFER == status) {
|
178
|
+
bufferSize = count;
|
179
|
+
pTemp = (PEVT_VARIANT)realloc(pProperty, bufferSize);
|
180
|
+
if (pTemp) {
|
181
|
+
pProperty = pTemp;
|
182
|
+
pTemp = NULL;
|
183
|
+
EvtGetPublisherMetadataProperty(hMetadata, EvtPublisherMetadataMessageFilePath, 0, bufferSize, pProperty, &count);
|
184
|
+
} else {
|
185
|
+
rb_raise(rb_eWinevtQueryError, "realloc failed");
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
if (ERROR_SUCCESS != (status = GetLastError())) {
|
190
|
+
rb_raise(rb_eWinevtQueryError, "EvtGetPublisherMetadataProperty for message file failed with %d\n", GetLastError());
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
if ((pProperty->Type == EvtVarTypeString) && (pProperty->StringVal != NULL)) {
|
195
|
+
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, pProperty->StringVal, -1, fileName, MAX_PATH, NULL, NULL);
|
196
|
+
}
|
197
|
+
if (messageEXE) {
|
198
|
+
ExpandEnvironmentStrings(fileName, messageEXE, _countof(messageEXE));
|
199
|
+
}
|
200
|
+
|
201
|
+
if (messageEXE != NULL) {
|
202
|
+
hModule = LoadLibraryEx(messageEXE, NULL,
|
203
|
+
DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
|
204
|
+
|
205
|
+
if (FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
|
206
|
+
hModule,
|
207
|
+
eventId,
|
208
|
+
0, // Use current code page. Users must specify character encoding in Ruby side.
|
209
|
+
descriptionBuffer,
|
210
|
+
MAX_BUFFER,
|
211
|
+
NULL)) {
|
212
|
+
} else if (!FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS,
|
213
|
+
hModule,
|
214
|
+
0xB0000000 | eventId,
|
215
|
+
0, // Use current code page. Users must specify character encoding in Ruby side.
|
216
|
+
descriptionBuffer,
|
217
|
+
MAX_BUFFER,
|
218
|
+
NULL)){
|
219
|
+
goto cleanup;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
|
223
|
+
result = wstr_to_mbstr(CP_ACP, descriptionBuffer, -1);
|
224
|
+
|
225
|
+
#undef MAX_BUFFER
|
226
|
+
|
227
|
+
cleanup:
|
228
|
+
|
229
|
+
if (hMetadata)
|
230
|
+
EvtClose(hMetadata);
|
231
|
+
|
232
|
+
if (hModule)
|
233
|
+
FreeLibrary(hModule);
|
234
|
+
|
235
|
+
return result;
|
236
|
+
}
|
data/lib/winevt/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Winevt
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
1
|
+
module Winevt
|
2
|
+
VERSION = "0.2.0"
|
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.
|
4
|
+
version: 0.2.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: 2019-06-
|
11
|
+
date: 2019-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -107,6 +107,12 @@ files:
|
|
107
107
|
- example/tailing.rb
|
108
108
|
- ext/winevt/extconf.rb
|
109
109
|
- ext/winevt/winevt.c
|
110
|
+
- ext/winevt/winevt_bookmark.c
|
111
|
+
- ext/winevt/winevt_c.h
|
112
|
+
- ext/winevt/winevt_channel.c
|
113
|
+
- ext/winevt/winevt_query.c
|
114
|
+
- ext/winevt/winevt_subscribe.c
|
115
|
+
- ext/winevt/winevt_utils.c
|
110
116
|
- lib/winevt.rb
|
111
117
|
- lib/winevt/query.rb
|
112
118
|
- lib/winevt/version.rb
|