winevt_c 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,97 +1,71 @@
1
1
  #include <winevt_c.h>
2
+
2
3
  #include <sddl.h>
3
4
  #include <stdlib.h>
4
5
  #include <string>
5
6
  #include <vector>
6
7
 
7
- char*
8
- wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen)
9
- {
10
- char *ptr;
11
- int len = WideCharToMultiByte(cp, 0, wstr, clen, nullptr, 0, nullptr, nullptr);
12
- if (!(ptr = static_cast<char *>(xmalloc(len)))) return nullptr;
13
- WideCharToMultiByte(cp, 0, wstr, clen, ptr, len, nullptr, nullptr);
14
-
15
- return ptr;
16
- }
17
-
18
- void free_allocated_mbstr(const char* str)
19
- {
20
- if (str)
21
- xfree((char *)str);
22
- }
23
-
24
8
  VALUE
25
- wstr_to_rb_str(UINT cp, const WCHAR *wstr, int clen)
9
+ wstr_to_rb_str(UINT cp, const WCHAR* wstr, int clen)
26
10
  {
27
- VALUE vstr;
28
- CHAR *ptr;
29
- int len = WideCharToMultiByte(cp, 0, wstr, clen, nullptr, 0, nullptr, nullptr);
30
- ptr = ALLOCV_N(CHAR, vstr, len);
31
- WideCharToMultiByte(cp, 0, wstr, clen, ptr, len, nullptr, nullptr);
32
- VALUE str = rb_utf8_str_new_cstr(ptr);
33
- ALLOCV_END(vstr);
34
-
35
- return str;
11
+ VALUE vstr;
12
+ CHAR* ptr;
13
+ int len = WideCharToMultiByte(cp, 0, wstr, clen, nullptr, 0, nullptr, nullptr);
14
+ ptr = ALLOCV_N(CHAR, vstr, len);
15
+ WideCharToMultiByte(cp, 0, wstr, clen, ptr, len, nullptr, nullptr);
16
+ VALUE str = rb_utf8_str_new_cstr(ptr);
17
+ ALLOCV_END(vstr);
18
+
19
+ return str;
36
20
  }
37
21
 
38
- WCHAR* render_event(EVT_HANDLE handle, DWORD flags)
22
+ VALUE
23
+ render_to_rb_str(EVT_HANDLE handle, DWORD flags)
39
24
  {
40
- std::vector<WCHAR> buffer(1);
41
- ULONG bufferSize = 0;
42
- ULONG bufferSizeNeeded = 0;
43
- ULONG status, count;
44
- static WCHAR* result;
45
- LPTSTR msgBuf;
46
-
47
- do {
48
- if (bufferSizeNeeded > bufferSize) {
49
- bufferSize = bufferSizeNeeded;
50
- try {
51
- buffer.resize(bufferSize);
52
- buffer.shrink_to_fit();
53
- } catch (std::bad_alloc e) {
54
- status = ERROR_OUTOFMEMORY;
55
- bufferSize = 0;
56
- rb_raise(rb_eWinevtQueryError, "Out of memory");
57
- break;
58
- }
59
- }
25
+ VALUE vbuffer;
26
+ WCHAR* buffer;
27
+ ULONG bufferSize = 0;
28
+ ULONG bufferSizeUsed = 0;
29
+ ULONG count;
30
+ BOOL succeeded;
31
+ VALUE result;
60
32
 
61
- if (EvtRender(nullptr,
62
- handle,
63
- flags,
64
- buffer.size(),
65
- &buffer.front(),
66
- &bufferSizeNeeded,
67
- &count) != FALSE) {
68
- status = ERROR_SUCCESS;
69
- } else {
70
- status = GetLastError();
71
- }
72
- } while (status == ERROR_INSUFFICIENT_BUFFER);
33
+ if (flags != EvtRenderEventXml && flags != EvtRenderBookmark) {
34
+ return Qnil;
35
+ }
73
36
 
74
- if (status != ERROR_SUCCESS) {
75
- FormatMessage(
76
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
77
- FORMAT_MESSAGE_FROM_SYSTEM |
78
- FORMAT_MESSAGE_IGNORE_INSERTS,
79
- nullptr, status,
80
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
81
- msgBuf, 0, nullptr);
82
-
83
- VALUE errmsg = rb_str_new2(msgBuf);
84
- LocalFree(msgBuf);
85
-
86
- rb_raise(rb_eWinevtQueryError, "ErrorCode: %ld\nError: %s\n", status, RSTRING_PTR(errmsg));
37
+ // Get the size of the buffer
38
+ EvtRender(nullptr, handle, flags, 0, NULL, &bufferSize, &count);
39
+
40
+ // bufferSize is in bytes, not characters
41
+ buffer = (WCHAR*)ALLOCV(vbuffer, bufferSize);
42
+
43
+ succeeded =
44
+ EvtRender(nullptr, handle, flags, bufferSize, buffer, &bufferSizeUsed, &count);
45
+ if (!succeeded) {
46
+ DWORD status = GetLastError();
47
+ CHAR msgBuf[256];
48
+
49
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
50
+ nullptr,
51
+ status,
52
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
53
+ msgBuf,
54
+ _countof(msgBuf),
55
+ nullptr);
56
+ ALLOCV_END(vbuffer);
57
+ rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, msgBuf);
87
58
  }
88
59
 
89
- result = _wcsdup(&buffer.front());
60
+ result = wstr_to_rb_str(CP_UTF8, buffer, -1);
61
+ ALLOCV_END(vbuffer);
90
62
 
91
63
  return result;
92
64
  }
93
65
 
94
- static std::wstring guid_to_wstr(const GUID& guid) {
66
+ static std::wstring
67
+ guid_to_wstr(const GUID& guid)
68
+ {
95
69
  LPOLESTR p = nullptr;
96
70
  if (FAILED(StringFromCLSID(guid, &p))) {
97
71
  return nullptr;
@@ -101,259 +75,290 @@ static std::wstring guid_to_wstr(const GUID& guid) {
101
75
  return s;
102
76
  }
103
77
 
104
- VALUE get_values(EVT_HANDLE handle)
78
+ static VALUE
79
+ extract_user_evt_variants(PEVT_VARIANT pRenderedValues, DWORD propCount)
105
80
  {
106
- std::vector<WCHAR> buffer;
107
- ULONG bufferSize = 0;
108
- ULONG bufferSizeNeeded = 0;
109
- DWORD status, propCount = 0;
110
- char *result;
111
- LPTSTR msgBuf;
112
- WCHAR* tmpWChar = nullptr;
113
81
  VALUE userValues = rb_ary_new();
114
-
115
- static PCWSTR eventProperties[] = { L"Event/EventData/Data[1]" };
116
- EVT_HANDLE renderContext = EvtCreateRenderContext(0, nullptr, EvtRenderContextUser);
117
- if (renderContext == nullptr) {
118
- rb_raise(rb_eWinevtQueryError, "Failed to create renderContext");
119
- }
120
-
121
- do {
122
- if (bufferSizeNeeded > bufferSize) {
123
- bufferSize = bufferSizeNeeded;
124
- try {
125
- buffer.resize(bufferSize);
126
- buffer.shrink_to_fit();
127
- } catch (std::bad_alloc e) {
128
- status = ERROR_OUTOFMEMORY;
129
- bufferSize = 0;
130
- rb_raise(rb_eWinevtQueryError, "Out of memory");
131
- break;
132
- }
133
- }
134
-
135
- if (EvtRender(renderContext,
136
- handle,
137
- EvtRenderEventValues,
138
- buffer.size(),
139
- &buffer.front(),
140
- &bufferSizeNeeded,
141
- &propCount) != FALSE) {
142
- status = ERROR_SUCCESS;
143
- } else {
144
- status = GetLastError();
145
- }
146
- } while (status == ERROR_INSUFFICIENT_BUFFER);
147
-
148
- if (status != ERROR_SUCCESS) {
149
- FormatMessage(
150
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
151
- FORMAT_MESSAGE_FROM_SYSTEM |
152
- FORMAT_MESSAGE_IGNORE_INSERTS,
153
- nullptr, status,
154
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
155
- msgBuf, 0, nullptr);
156
-
157
- VALUE errmsg = rb_str_new2(msgBuf);
158
- LocalFree(msgBuf);
159
-
160
- rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, RSTRING_PTR(errmsg));
161
- }
162
-
163
- PEVT_VARIANT pRenderedValues = reinterpret_cast<PEVT_VARIANT>(&buffer.front());
164
- LARGE_INTEGER timestamp;
165
- SYSTEMTIME st;
166
- FILETIME ft;
167
- std::vector<CHAR> strTime(128);
168
- std::vector<CHAR> sResult(256);
169
82
  VALUE rbObj;
170
83
 
171
- for (int i = 0; i < propCount; i++) {
84
+ for (DWORD i = 0; i < propCount; i++) {
172
85
  switch (pRenderedValues[i].Type) {
173
- case EvtVarTypeNull:
174
- rb_ary_push(userValues, Qnil);
175
- break;
176
- case EvtVarTypeString:
177
- if (pRenderedValues[i].StringVal == nullptr) {
178
- rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
179
- } else {
180
- std::wstring wStr(pRenderedValues[i].StringVal);
181
- rbObj = wstr_to_rb_str(CP_UTF8, &wStr[0], -1);
86
+ case EvtVarTypeNull:
87
+ rb_ary_push(userValues, Qnil);
88
+ break;
89
+ case EvtVarTypeString:
90
+ if (pRenderedValues[i].StringVal == nullptr) {
91
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
92
+ } else {
93
+ std::wstring wStr(pRenderedValues[i].StringVal);
94
+ rbObj = wstr_to_rb_str(CP_UTF8, &wStr[0], -1);
95
+ rb_ary_push(userValues, rbObj);
96
+ }
97
+ break;
98
+ case EvtVarTypeAnsiString:
99
+ if (pRenderedValues[i].AnsiStringVal == nullptr) {
100
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
101
+ } else {
102
+ rb_ary_push(
103
+ userValues,
104
+ rb_utf8_str_new_cstr(const_cast<char*>(pRenderedValues[i].AnsiStringVal)));
105
+ }
106
+ break;
107
+ case EvtVarTypeSByte:
108
+ rbObj = INT2NUM(static_cast<UINT32>(pRenderedValues[i].SByteVal));
109
+ rb_ary_push(userValues, rbObj);
110
+ break;
111
+ case EvtVarTypeByte:
112
+ rbObj = INT2NUM(static_cast<UINT32>(pRenderedValues[i].ByteVal));
113
+ rb_ary_push(userValues, rbObj);
114
+ break;
115
+ case EvtVarTypeInt16:
116
+ rbObj = INT2NUM(static_cast<INT32>(pRenderedValues[i].Int16Val));
117
+ rb_ary_push(userValues, rbObj);
118
+ break;
119
+ case EvtVarTypeUInt16:
120
+ rbObj = UINT2NUM(static_cast<UINT32>(pRenderedValues[i].UInt16Val));
121
+ rb_ary_push(userValues, rbObj);
122
+ break;
123
+ case EvtVarTypeInt32:
124
+ rbObj = INT2NUM(pRenderedValues[i].Int32Val);
125
+ rb_ary_push(userValues, rbObj);
126
+ break;
127
+ case EvtVarTypeUInt32:
128
+ rbObj = UINT2NUM(pRenderedValues[i].UInt32Val);
129
+ rb_ary_push(userValues, rbObj);
130
+ break;
131
+ case EvtVarTypeInt64:
132
+ rbObj = LONG2NUM(pRenderedValues[i].Int64Val);
133
+ rb_ary_push(userValues, rbObj);
134
+ break;
135
+ case EvtVarTypeUInt64:
136
+ rbObj = ULONG2NUM(pRenderedValues[i].UInt64Val);
182
137
  rb_ary_push(userValues, rbObj);
138
+ break;
139
+ case EvtVarTypeSingle: {
140
+ CHAR sResult[256];
141
+ _snprintf_s(
142
+ sResult, _countof(sResult), _TRUNCATE, "%f", pRenderedValues[i].SingleVal);
143
+ rb_ary_push(userValues, rb_utf8_str_new_cstr(sResult));
144
+ break;
183
145
  }
184
- break;
185
- case EvtVarTypeAnsiString:
186
- if (pRenderedValues[i].AnsiStringVal == nullptr) {
187
- rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
188
- } else {
189
- rb_ary_push(userValues, rb_utf8_str_new_cstr(const_cast<char *>(pRenderedValues[i].AnsiStringVal)));
146
+ case EvtVarTypeDouble: {
147
+ CHAR sResult[256];
148
+ _snprintf_s(
149
+ sResult, _countof(sResult), _TRUNCATE, "%lf", pRenderedValues[i].DoubleVal);
150
+ rb_ary_push(userValues, rb_utf8_str_new_cstr(sResult));
151
+ break;
190
152
  }
191
- break;
192
- case EvtVarTypeSByte:
193
- rbObj = INT2NUM(static_cast<UINT32>(pRenderedValues[i].SByteVal));
194
- rb_ary_push(userValues, rbObj);
195
- break;
196
- case EvtVarTypeByte:
197
- rbObj = INT2NUM(static_cast<UINT32>(pRenderedValues[i].ByteVal));
198
- rb_ary_push(userValues, rbObj);
199
- break;
200
- case EvtVarTypeInt16:
201
- rbObj = INT2NUM(static_cast<INT32>(pRenderedValues[i].Int16Val));
202
- rb_ary_push(userValues, rbObj);
203
- break;
204
- case EvtVarTypeUInt16:
205
- rbObj = UINT2NUM(static_cast<UINT32>(pRenderedValues[i].UInt16Val));
206
- rb_ary_push(userValues, rbObj);
207
- break;
208
- case EvtVarTypeInt32:
209
- rbObj = INT2NUM(pRenderedValues[i].Int32Val);
210
- rb_ary_push(userValues, rbObj);
211
- break;
212
- case EvtVarTypeUInt32:
213
- rbObj = UINT2NUM(pRenderedValues[i].UInt32Val);
214
- rb_ary_push(userValues, rbObj);
215
- break;
216
- case EvtVarTypeInt64:
217
- rbObj = LONG2NUM(pRenderedValues[i].Int64Val);
218
- rb_ary_push(userValues, rbObj);
219
- break;
220
- case EvtVarTypeUInt64:
221
- rbObj = ULONG2NUM(pRenderedValues[i].UInt64Val);
222
- rb_ary_push(userValues, rbObj);
223
- break;
224
- case EvtVarTypeSingle:
225
- _snprintf_s(&sResult.front(), sResult.size(), _TRUNCATE, "%f", pRenderedValues[i].SingleVal);
226
- rb_ary_push(userValues, rb_utf8_str_new_cstr(&sResult.front()));
227
- break;
228
- case EvtVarTypeDouble:
229
- _snprintf_s(&sResult.front(), sResult.size(), _TRUNCATE, "%lf", pRenderedValues[i].DoubleVal);
230
- rb_ary_push(userValues, rb_utf8_str_new_cstr(&sResult.front()));
231
- break;
232
- case EvtVarTypeBoolean:
233
- rbObj = pRenderedValues[i].BooleanVal ? Qtrue : Qfalse;
234
- rb_ary_push(userValues, rbObj);
235
- break;
236
- case EvtVarTypeGuid:
237
- if (pRenderedValues[i].GuidVal != nullptr) {
238
- const GUID guid = *pRenderedValues[i].GuidVal;
239
- std::wstring wstr = guid_to_wstr(guid);
240
- rbObj = wstr_to_rb_str(CP_UTF8, wstr.c_str(), -1);
153
+ case EvtVarTypeBoolean:
154
+ rbObj = pRenderedValues[i].BooleanVal ? Qtrue : Qfalse;
241
155
  rb_ary_push(userValues, rbObj);
242
- } else {
243
- rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
156
+ break;
157
+ case EvtVarTypeGuid:
158
+ if (pRenderedValues[i].GuidVal != nullptr) {
159
+ const GUID guid = *pRenderedValues[i].GuidVal;
160
+ std::wstring wstr = guid_to_wstr(guid);
161
+ rbObj = wstr_to_rb_str(CP_UTF8, wstr.c_str(), -1);
162
+ rb_ary_push(userValues, rbObj);
163
+ } else {
164
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
165
+ }
166
+ break;
167
+ case EvtVarTypeSizeT:
168
+ rbObj = SIZET2NUM(pRenderedValues[i].SizeTVal);
169
+ rb_ary_push(userValues, rbObj);
170
+ break;
171
+ case EvtVarTypeFileTime: {
172
+ LARGE_INTEGER timestamp;
173
+ CHAR strTime[128];
174
+ FILETIME ft;
175
+ SYSTEMTIME st;
176
+ timestamp.QuadPart = pRenderedValues[i].FileTimeVal;
177
+ ft.dwHighDateTime = timestamp.HighPart;
178
+ ft.dwLowDateTime = timestamp.LowPart;
179
+ if (FileTimeToSystemTime(&ft, &st)) {
180
+ _snprintf_s(strTime,
181
+ _countof(strTime),
182
+ _TRUNCATE,
183
+ "%04d-%02d-%02d %02d:%02d:%02d.%dZ",
184
+ st.wYear,
185
+ st.wMonth,
186
+ st.wDay,
187
+ st.wHour,
188
+ st.wMinute,
189
+ st.wSecond,
190
+ st.wMilliseconds);
191
+ rb_ary_push(userValues, rb_utf8_str_new_cstr(strTime));
192
+ } else {
193
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
194
+ }
195
+ break;
244
196
  }
245
- break;
246
- case EvtVarTypeSizeT:
247
- rbObj = SIZET2NUM(pRenderedValues[i].SizeTVal);
248
- rb_ary_push(userValues, rbObj);
249
- break;
250
- case EvtVarTypeFileTime:
251
- timestamp.QuadPart = pRenderedValues[i].FileTimeVal;
252
- ft.dwHighDateTime = timestamp.HighPart;
253
- ft.dwLowDateTime = timestamp.LowPart;
254
- if (FileTimeToSystemTime( &ft, &st )) {
255
- _snprintf_s(&strTime.front(), strTime.size(), _TRUNCATE, "%04d-%02d-%02d %02d:%02d:%02d.%dZ",
256
- st.wYear , st.wMonth , st.wDay ,
257
- st.wHour , st.wMinute , st.wSecond,
258
- st.wMilliseconds);
259
- rb_ary_push(userValues, rb_utf8_str_new_cstr(&strTime.front()));
260
- } else {
261
- rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
197
+ case EvtVarTypeSysTime: {
198
+ CHAR strTime[128];
199
+ SYSTEMTIME st;
200
+ if (pRenderedValues[i].SysTimeVal != nullptr) {
201
+ st = *pRenderedValues[i].SysTimeVal;
202
+ _snprintf_s(strTime,
203
+ _countof(strTime),
204
+ _TRUNCATE,
205
+ "%04d-%02d-%02d %02d:%02d:%02d.%dZ",
206
+ st.wYear,
207
+ st.wMonth,
208
+ st.wDay,
209
+ st.wHour,
210
+ st.wMinute,
211
+ st.wSecond,
212
+ st.wMilliseconds);
213
+ rb_ary_push(userValues, rb_utf8_str_new_cstr(strTime));
214
+ } else {
215
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
216
+ }
217
+ break;
262
218
  }
263
- break;
264
- case EvtVarTypeSysTime:
265
- if (pRenderedValues[i].SysTimeVal != nullptr) {
266
- st = *pRenderedValues[i].SysTimeVal;
267
- _snprintf_s(&strTime.front(), strTime.size(), _TRUNCATE, "%04d-%02d-%02d %02d:%02d:%02d.%dZ",
268
- st.wYear , st.wMonth , st.wDay ,
269
- st.wHour , st.wMinute , st.wSecond,
270
- st.wMilliseconds);
271
- rb_ary_push(userValues, rb_utf8_str_new_cstr(&strTime.front()));
272
- } else {
273
- rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
219
+ case EvtVarTypeSid: {
220
+ WCHAR* tmpWChar = nullptr;
221
+ if (ConvertSidToStringSidW(pRenderedValues[i].SidVal, &tmpWChar)) {
222
+ rbObj = wstr_to_rb_str(CP_UTF8, tmpWChar, -1);
223
+ rb_ary_push(userValues, rbObj);
224
+ LocalFree(tmpWChar);
225
+ } else {
226
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
227
+ }
228
+ break;
274
229
  }
275
- break;
276
- case EvtVarTypeSid:
277
- if (ConvertSidToStringSidW(pRenderedValues[i].SidVal, &tmpWChar)) {
278
- rbObj = wstr_to_rb_str(CP_UTF8, tmpWChar, -1);
230
+ case EvtVarTypeHexInt32:
231
+ rbObj = rb_sprintf("%#x", pRenderedValues[i].UInt32Val);
279
232
  rb_ary_push(userValues, rbObj);
280
- LocalFree(tmpWChar);
281
- } else {
282
- rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
283
- }
284
- break;
285
- case EvtVarTypeHexInt32:
286
- rbObj = ULONG2NUM(pRenderedValues[i].UInt32Val);
287
- rbObj = rb_sprintf("%#x", rbObj);
288
- rb_ary_push(userValues, rbObj);
289
- break;
290
- case EvtVarTypeHexInt64:
291
- rbObj = ULONG2NUM(pRenderedValues[i].UInt64Val);
292
- rbObj = rb_sprintf("%#x", rbObj);
293
- rb_ary_push(userValues, rbObj);
294
- break;
295
- case EvtVarTypeEvtXml:
296
- if (pRenderedValues[i].XmlVal == nullptr) {
297
- rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
298
- } else {
299
- rbObj = wstr_to_rb_str(CP_UTF8, pRenderedValues[i].XmlVal, -1);
233
+ break;
234
+ case EvtVarTypeHexInt64:
235
+ rbObj = rb_sprintf("%#I64x", pRenderedValues[i].UInt64Val);
300
236
  rb_ary_push(userValues, rbObj);
301
- }
302
- break;
303
- default:
304
- rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
305
- break;
237
+ break;
238
+ case EvtVarTypeEvtXml:
239
+ if (pRenderedValues[i].XmlVal == nullptr) {
240
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("(NULL)"));
241
+ } else {
242
+ rbObj = wstr_to_rb_str(CP_UTF8, pRenderedValues[i].XmlVal, -1);
243
+ rb_ary_push(userValues, rbObj);
244
+ }
245
+ break;
246
+ default:
247
+ rb_ary_push(userValues, rb_utf8_str_new_cstr("?"));
248
+ break;
306
249
  }
307
250
  }
308
251
 
309
- if (renderContext)
252
+ return userValues;
253
+ }
254
+
255
+ VALUE
256
+ get_values(EVT_HANDLE handle)
257
+ {
258
+ VALUE vbuffer;
259
+ PEVT_VARIANT pRenderedValues;
260
+ ULONG bufferSize = 0;
261
+ ULONG bufferSizeUsed = 0;
262
+ DWORD propCount = 0;
263
+ BOOL succeeded;
264
+ VALUE userValues = Qnil;
265
+
266
+ EVT_HANDLE renderContext = EvtCreateRenderContext(0, nullptr, EvtRenderContextUser);
267
+ if (renderContext == nullptr) {
268
+ rb_raise(rb_eWinevtQueryError, "Failed to create renderContext");
269
+ }
270
+
271
+ // Get the size of the buffer
272
+ EvtRender(
273
+ renderContext, handle, EvtRenderEventValues, 0, NULL, &bufferSize, &propCount);
274
+
275
+ // bufferSize is in bytes, not array size
276
+ pRenderedValues = (PEVT_VARIANT)ALLOCV(vbuffer, bufferSize);
277
+
278
+ succeeded = EvtRender(renderContext,
279
+ handle,
280
+ EvtRenderEventValues,
281
+ bufferSize,
282
+ pRenderedValues,
283
+ &bufferSizeUsed,
284
+ &propCount);
285
+ if (!succeeded) {
286
+ DWORD status = GetLastError();
287
+ CHAR msgBuf[256];
288
+
289
+ ALLOCV_END(vbuffer);
310
290
  EvtClose(renderContext);
311
291
 
292
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
293
+ nullptr,
294
+ status,
295
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
296
+ msgBuf,
297
+ _countof(msgBuf),
298
+ nullptr);
299
+ rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, msgBuf);
300
+ }
301
+
302
+ userValues = extract_user_evt_variants(pRenderedValues, propCount);
303
+
304
+ ALLOCV_END(vbuffer);
305
+ EvtClose(renderContext);
306
+
312
307
  return userValues;
313
308
  }
314
309
 
315
- static std::vector<WCHAR> get_message(EVT_HANDLE hMetadata, EVT_HANDLE handle)
310
+ static std::vector<WCHAR>
311
+ get_message(EVT_HANDLE hMetadata, EVT_HANDLE handle)
316
312
  {
317
313
  #define BUFSIZE 4096
318
314
  std::vector<WCHAR> result;
319
- ULONG status;
315
+ ULONG status;
320
316
  ULONG bufferSizeNeeded = 0;
321
317
  LPVOID lpMsgBuf;
322
318
  std::vector<WCHAR> message(BUFSIZE);
323
319
 
324
- if (!EvtFormatMessage(hMetadata, handle, 0xffffffff, 0, nullptr, EvtFormatMessageEvent, message.size(), &message[0], &bufferSizeNeeded)) {
320
+ if (!EvtFormatMessage(hMetadata,
321
+ handle,
322
+ 0xffffffff,
323
+ 0,
324
+ nullptr,
325
+ EvtFormatMessageEvent,
326
+ message.size(),
327
+ &message[0],
328
+ &bufferSizeNeeded)) {
325
329
  status = GetLastError();
326
330
 
327
331
  if (status != ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
328
332
  switch (status) {
329
- case ERROR_EVT_MESSAGE_NOT_FOUND:
330
- case ERROR_EVT_MESSAGE_ID_NOT_FOUND:
331
- case ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
332
- case ERROR_RESOURCE_LANG_NOT_FOUND:
333
- case ERROR_MUI_FILE_NOT_FOUND:
334
- case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: {
335
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
336
- FORMAT_MESSAGE_FROM_SYSTEM |
337
- FORMAT_MESSAGE_IGNORE_INSERTS,
333
+ case ERROR_EVT_MESSAGE_NOT_FOUND:
334
+ case ERROR_EVT_MESSAGE_ID_NOT_FOUND:
335
+ case ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
336
+ case ERROR_RESOURCE_LANG_NOT_FOUND:
337
+ case ERROR_MUI_FILE_NOT_FOUND:
338
+ case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT: {
339
+ if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
340
+ FORMAT_MESSAGE_IGNORE_INSERTS,
341
+ nullptr,
342
+ status,
343
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
344
+ reinterpret_cast<WCHAR*>(&lpMsgBuf),
345
+ 0,
346
+ nullptr) == 0)
347
+ FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
348
+ FORMAT_MESSAGE_IGNORE_INSERTS,
338
349
  nullptr,
339
350
  status,
340
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
341
- reinterpret_cast<WCHAR *>(&lpMsgBuf), 0, nullptr) == 0)
342
- FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
343
- FORMAT_MESSAGE_FROM_SYSTEM |
344
- FORMAT_MESSAGE_IGNORE_INSERTS,
345
- nullptr,
346
- status,
347
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
348
- reinterpret_cast<WCHAR *>(&lpMsgBuf), 0, nullptr);
349
-
350
- std::wstring ret(reinterpret_cast<WCHAR *>(lpMsgBuf));
351
- std::copy( ret.begin(), ret.end(), std::back_inserter(result));
352
- LocalFree(lpMsgBuf);
353
-
354
- goto cleanup;
355
- }
351
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
352
+ reinterpret_cast<WCHAR*>(&lpMsgBuf),
353
+ 0,
354
+ nullptr);
355
+
356
+ std::wstring ret(reinterpret_cast<WCHAR*>(lpMsgBuf));
357
+ std::copy(ret.begin(), ret.end(), std::back_inserter(result));
358
+ LocalFree(lpMsgBuf);
356
359
 
360
+ goto cleanup;
361
+ }
357
362
  }
358
363
 
359
364
  if (status != ERROR_INSUFFICIENT_BUFFER)
@@ -364,37 +369,49 @@ static std::vector<WCHAR> get_message(EVT_HANDLE hMetadata, EVT_HANDLE handle)
364
369
  message.resize(bufferSizeNeeded);
365
370
  message.shrink_to_fit();
366
371
 
367
- if(!EvtFormatMessage(hMetadata, handle, 0xffffffff, 0, nullptr, EvtFormatMessageEvent, message.size(), &message.front(), &bufferSizeNeeded)) {
372
+ if (!EvtFormatMessage(hMetadata,
373
+ handle,
374
+ 0xffffffff,
375
+ 0,
376
+ nullptr,
377
+ EvtFormatMessageEvent,
378
+ message.size(),
379
+ &message.front(),
380
+ &bufferSizeNeeded)) {
368
381
  status = GetLastError();
369
382
 
370
383
  if (status != ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
371
384
  switch (status) {
372
- case ERROR_EVT_MESSAGE_NOT_FOUND:
373
- case ERROR_EVT_MESSAGE_ID_NOT_FOUND:
374
- case ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
375
- case ERROR_RESOURCE_LANG_NOT_FOUND:
376
- case ERROR_MUI_FILE_NOT_FOUND:
377
- case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT:
378
- if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
379
- FORMAT_MESSAGE_FROM_SYSTEM |
380
- FORMAT_MESSAGE_IGNORE_INSERTS,
385
+ case ERROR_EVT_MESSAGE_NOT_FOUND:
386
+ case ERROR_EVT_MESSAGE_ID_NOT_FOUND:
387
+ case ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
388
+ case ERROR_RESOURCE_LANG_NOT_FOUND:
389
+ case ERROR_MUI_FILE_NOT_FOUND:
390
+ case ERROR_EVT_UNRESOLVED_PARAMETER_INSERT:
391
+ if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
392
+ FORMAT_MESSAGE_FROM_SYSTEM |
393
+ FORMAT_MESSAGE_IGNORE_INSERTS,
394
+ nullptr,
395
+ status,
396
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
397
+ reinterpret_cast<WCHAR*>(&lpMsgBuf),
398
+ 0,
399
+ nullptr) == 0)
400
+ FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
401
+ FORMAT_MESSAGE_FROM_SYSTEM |
402
+ FORMAT_MESSAGE_IGNORE_INSERTS,
381
403
  nullptr,
382
404
  status,
383
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
384
- reinterpret_cast<WCHAR *>(&lpMsgBuf), 0, nullptr) == 0)
385
- FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
386
- FORMAT_MESSAGE_FROM_SYSTEM |
387
- FORMAT_MESSAGE_IGNORE_INSERTS,
388
- nullptr,
389
- status,
390
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
391
- reinterpret_cast<WCHAR *>(&lpMsgBuf), 0, nullptr);
405
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
406
+ reinterpret_cast<WCHAR*>(&lpMsgBuf),
407
+ 0,
408
+ nullptr);
392
409
 
393
- std::wstring ret(reinterpret_cast<WCHAR *>(lpMsgBuf));
394
- std::copy( ret.begin(), ret.end(), std::back_inserter(result));
395
- LocalFree(lpMsgBuf);
410
+ std::wstring ret(reinterpret_cast<WCHAR*>(lpMsgBuf));
411
+ std::copy(ret.begin(), ret.end(), std::back_inserter(result));
412
+ LocalFree(lpMsgBuf);
396
413
 
397
- goto cleanup;
414
+ goto cleanup;
398
415
  }
399
416
 
400
417
  rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu", status);
@@ -412,19 +429,20 @@ cleanup:
412
429
  #undef BUFSIZE
413
430
  }
414
431
 
415
- WCHAR* get_description(EVT_HANDLE handle)
432
+ WCHAR*
433
+ get_description(EVT_HANDLE handle)
416
434
  {
417
435
  #define BUFSIZE 4096
418
436
  std::vector<WCHAR> buffer(BUFSIZE);
419
- ULONG bufferSize = 0;
420
- ULONG bufferSizeNeeded = 0;
421
- ULONG status, count;
437
+ ULONG bufferSizeNeeded = 0;
438
+ ULONG status, count;
422
439
  std::vector<WCHAR> result;
423
- LPTSTR msgBuf;
440
+ CHAR msgBuf[256];
424
441
  EVT_HANDLE hMetadata = nullptr;
425
442
 
426
- static PCWSTR eventProperties[] = {L"Event/System/Provider/@Name"};
427
- EVT_HANDLE renderContext = EvtCreateRenderContext(1, eventProperties, EvtRenderContextValues);
443
+ static PCWSTR eventProperties[] = { L"Event/System/Provider/@Name" };
444
+ EVT_HANDLE renderContext =
445
+ EvtCreateRenderContext(1, eventProperties, EvtRenderContextValues);
428
446
  if (renderContext == nullptr) {
429
447
  rb_raise(rb_eWinevtQueryError, "Failed to create renderContext");
430
448
  }
@@ -442,25 +460,26 @@ WCHAR* get_description(EVT_HANDLE handle)
442
460
  }
443
461
 
444
462
  if (status != ERROR_SUCCESS) {
445
- FormatMessage(
446
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
447
- FORMAT_MESSAGE_FROM_SYSTEM |
448
- FORMAT_MESSAGE_IGNORE_INSERTS,
449
- nullptr, status,
450
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
451
- msgBuf, 0, nullptr);
452
-
453
- VALUE errmsg = rb_str_new2(msgBuf);
454
- LocalFree(msgBuf);
455
-
456
- rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, RSTRING_PTR(errmsg));
463
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
464
+ nullptr,
465
+ status,
466
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
467
+ msgBuf,
468
+ sizeof(msgBuf),
469
+ nullptr);
470
+ rb_raise(rb_eWinevtQueryError, "ErrorCode: %lu\nError: %s\n", status, msgBuf);
457
471
  }
458
472
 
459
473
  // Obtain buffer as EVT_VARIANT pointer. To avoid ErrorCide 87 in EvtRender.
460
474
  const PEVT_VARIANT values = reinterpret_cast<PEVT_VARIANT>(&buffer.front());
461
475
 
462
476
  // Open publisher metadata
463
- hMetadata = EvtOpenPublisherMetadata(nullptr, values[0].StringVal, nullptr, MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT), 0);
477
+ hMetadata = EvtOpenPublisherMetadata(
478
+ nullptr,
479
+ values[0].StringVal,
480
+ nullptr,
481
+ MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT),
482
+ 0);
464
483
  if (hMetadata == nullptr) {
465
484
  // When winevt_c cannot open metadata, then give up to obtain
466
485
  // message file and clean up immediately.
@@ -481,3 +500,189 @@ cleanup:
481
500
 
482
501
  return _wcsdup(result.data());
483
502
  }
503
+
504
+ VALUE
505
+ render_system_event(EVT_HANDLE hEvent)
506
+ {
507
+ DWORD status = ERROR_SUCCESS;
508
+ EVT_HANDLE hContext = NULL;
509
+ DWORD dwBufferSize = 0;
510
+ DWORD dwBufferUsed = 0;
511
+ DWORD dwPropertyCount = 0;
512
+ VALUE vRenderedValues;
513
+ PEVT_VARIANT pRenderedValues = NULL;
514
+ WCHAR wsGuid[50];
515
+ LPSTR pwsSid = NULL;
516
+ ULONGLONG ullTimeStamp = 0;
517
+ ULONGLONG ullNanoseconds = 0;
518
+ SYSTEMTIME st;
519
+ FILETIME ft;
520
+ CHAR buffer[32];
521
+ VALUE rbstr;
522
+ DWORD EventID;
523
+ VALUE hash = rb_hash_new();
524
+
525
+ hContext = EvtCreateRenderContext(0, NULL, EvtRenderContextSystem);
526
+ if (NULL == hContext) {
527
+ rb_raise(rb_eWinevtQueryError,
528
+ "Failed to create renderContext with %lu\n", GetLastError());
529
+ }
530
+
531
+ if (!EvtRender(hContext,
532
+ hEvent,
533
+ EvtRenderEventValues,
534
+ dwBufferSize,
535
+ pRenderedValues,
536
+ &dwBufferUsed,
537
+ &dwPropertyCount)) {
538
+ status = GetLastError();
539
+ if (ERROR_INSUFFICIENT_BUFFER == status) {
540
+ dwBufferSize = dwBufferUsed;
541
+ pRenderedValues = (PEVT_VARIANT)ALLOCV(vRenderedValues, dwBufferSize);
542
+ if (pRenderedValues) {
543
+ EvtRender(hContext,
544
+ hEvent,
545
+ EvtRenderEventValues,
546
+ dwBufferSize,
547
+ pRenderedValues,
548
+ &dwBufferUsed,
549
+ &dwPropertyCount);
550
+ } else {
551
+ EvtClose(hContext);
552
+ rb_raise(rb_eRuntimeError,
553
+ "Failed to malloc memory with %lu\n", status);
554
+ }
555
+ }
556
+
557
+ status = GetLastError();
558
+ if (ERROR_SUCCESS != status) {
559
+ EvtClose(hContext);
560
+ ALLOCV_END(vRenderedValues);
561
+
562
+ rb_raise(rb_eWinevtQueryError,
563
+ "EvtRender failed with %lu\n", status);
564
+ }
565
+ }
566
+
567
+ // EVT_VARIANT value with EvtRenderContextSystem will be decomposed
568
+ // as the following enum definition:
569
+ // https://docs.microsoft.com/en-us/windows/win32/api/winevt/ne-winevt-evt_system_property_id
570
+ rbstr = wstr_to_rb_str(CP_UTF8, pRenderedValues[EvtSystemProviderName].StringVal, -1);
571
+ rb_hash_aset(hash, rb_str_new2("ProviderName"), rbstr);
572
+ if (NULL != pRenderedValues[EvtSystemProviderGuid].GuidVal) {
573
+ const GUID* Guid = pRenderedValues[EvtSystemProviderGuid].GuidVal;
574
+ StringFromGUID2(*Guid, wsGuid, _countof(wsGuid));
575
+ rbstr = wstr_to_rb_str(CP_UTF8, wsGuid, -1);
576
+ rb_hash_aset(hash, rb_str_new2("ProviderGuid"), rbstr);
577
+ } else {
578
+ rb_hash_aset(hash, rb_str_new2("ProviderGuid"), Qnil);
579
+ }
580
+
581
+ EventID = pRenderedValues[EvtSystemEventID].UInt16Val;
582
+ if (EvtVarTypeNull != pRenderedValues[EvtSystemQualifiers].Type) {
583
+ EventID = MAKELONG(pRenderedValues[EvtSystemEventID].UInt16Val,
584
+ pRenderedValues[EvtSystemQualifiers].UInt16Val);
585
+ }
586
+ rb_hash_aset(hash, rb_str_new2("EventID"), LONG2NUM(EventID));
587
+
588
+ rb_hash_aset(hash,
589
+ rb_str_new2("Version"),
590
+ (EvtVarTypeNull == pRenderedValues[EvtSystemVersion].Type)
591
+ ? INT2NUM(0)
592
+ : INT2NUM(pRenderedValues[EvtSystemVersion].ByteVal));
593
+ rb_hash_aset(hash,
594
+ rb_str_new2("Level"),
595
+ (EvtVarTypeNull == pRenderedValues[EvtSystemLevel].Type)
596
+ ? INT2NUM(0)
597
+ : INT2NUM(pRenderedValues[EvtSystemLevel].ByteVal));
598
+ rb_hash_aset(hash,
599
+ rb_str_new2("Task"),
600
+ (EvtVarTypeNull == pRenderedValues[EvtSystemTask].Type)
601
+ ? INT2NUM(0)
602
+ : INT2NUM(pRenderedValues[EvtSystemTask].UInt16Val));
603
+ rb_hash_aset(hash,
604
+ rb_str_new2("Opcode"),
605
+ (EvtVarTypeNull == pRenderedValues[EvtSystemOpcode].Type)
606
+ ? INT2NUM(0)
607
+ : INT2NUM(pRenderedValues[EvtSystemOpcode].ByteVal));
608
+ _snprintf_s(buffer, _countof(buffer), _TRUNCATE,
609
+ "0x%llx", pRenderedValues[EvtSystemKeywords].UInt64Val);
610
+ rb_hash_aset(hash,
611
+ rb_str_new2("Keywords"),
612
+ (EvtVarTypeNull == pRenderedValues[EvtSystemKeywords].Type)
613
+ ? Qnil
614
+ : rb_str_new2(buffer));
615
+
616
+ ullTimeStamp = pRenderedValues[EvtSystemTimeCreated].FileTimeVal;
617
+ ft.dwHighDateTime = (DWORD)((ullTimeStamp >> 32) & 0xFFFFFFFF);
618
+ ft.dwLowDateTime = (DWORD)(ullTimeStamp & 0xFFFFFFFF);
619
+
620
+ FileTimeToSystemTime(&ft, &st);
621
+ ullNanoseconds =
622
+ (ullTimeStamp % 10000000) *
623
+ 100; // Display nanoseconds instead of milliseconds for higher resolution
624
+ _snprintf_s(buffer,
625
+ _countof(buffer),
626
+ _TRUNCATE,
627
+ "%02d/%02d/%02d %02d:%02d:%02d.%llu",
628
+ st.wYear,
629
+ st.wMonth,
630
+ st.wDay,
631
+ st.wHour,
632
+ st.wMinute,
633
+ st.wSecond,
634
+ ullNanoseconds);
635
+ rb_hash_aset(hash,
636
+ rb_str_new2("TimeCreated"),
637
+ (EvtVarTypeNull == pRenderedValues[EvtSystemKeywords].Type)
638
+ ? Qnil
639
+ : rb_str_new2(buffer));
640
+ _snprintf_s(buffer,
641
+ _countof(buffer),
642
+ _TRUNCATE,
643
+ "%llu",
644
+ pRenderedValues[EvtSystemEventRecordId].UInt64Val);
645
+ rb_hash_aset(hash,
646
+ rb_str_new2("EventRecordID"),
647
+ (EvtVarTypeNull == pRenderedValues[EvtSystemEventRecordId].UInt64Val)
648
+ ? Qnil
649
+ : rb_str_new2(buffer));
650
+
651
+ if (EvtVarTypeNull != pRenderedValues[EvtSystemActivityID].Type) {
652
+ const GUID* Guid = pRenderedValues[EvtSystemActivityID].GuidVal;
653
+ StringFromGUID2(*Guid, wsGuid, _countof(wsGuid));
654
+ rbstr = wstr_to_rb_str(CP_UTF8, wsGuid, -1);
655
+ rb_hash_aset(hash, rb_str_new2("ActivityID"), rbstr);
656
+ }
657
+
658
+ if (EvtVarTypeNull != pRenderedValues[EvtSystemRelatedActivityID].Type) {
659
+ const GUID* Guid = pRenderedValues[EvtSystemRelatedActivityID].GuidVal;
660
+ StringFromGUID2(*Guid, wsGuid, _countof(wsGuid));
661
+ rbstr = wstr_to_rb_str(CP_UTF8, wsGuid, -1);
662
+ rb_hash_aset(hash, rb_str_new2("RelatedActivityID"), rbstr);
663
+ }
664
+
665
+ rb_hash_aset(hash,
666
+ rb_str_new2("ProcessID"),
667
+ UINT2NUM(pRenderedValues[EvtSystemProcessID].UInt32Val));
668
+ rb_hash_aset(hash,
669
+ rb_str_new2("ThreadID"),
670
+ UINT2NUM(pRenderedValues[EvtSystemThreadID].UInt32Val));
671
+ rbstr = wstr_to_rb_str(CP_UTF8, pRenderedValues[EvtSystemChannel].StringVal, -1);
672
+ rb_hash_aset(hash, rb_str_new2("Channel"), rbstr);
673
+ rbstr = wstr_to_rb_str(CP_UTF8, pRenderedValues[EvtSystemComputer].StringVal, -1);
674
+ rb_hash_aset(hash, rb_str_new2("Computer"), rbstr);
675
+
676
+ if (EvtVarTypeNull != pRenderedValues[EvtSystemUserID].Type) {
677
+ if (ConvertSidToStringSid(pRenderedValues[EvtSystemUserID].SidVal, &pwsSid)) {
678
+ rbstr = rb_utf8_str_new_cstr(pwsSid);
679
+ rb_hash_aset(hash, rb_str_new2("UserID"), rbstr);
680
+ LocalFree(pwsSid);
681
+ }
682
+ }
683
+
684
+ EvtClose(hContext);
685
+ ALLOCV_END(vRenderedValues);
686
+
687
+ return hash;
688
+ }