HyperDbg Debugger
Loading...
Searching...
No Matches
Logging.c File Reference

Message logging and tracing implementation. More...

#include "pch.h"

Functions

BOOLEAN LogCheckVmxOperation ()
 Checks whether the message tracing operates on vmx-root mode or not.
 
BOOLEAN LogCheckImmediateSend (UINT32 OperationCode)
 Checks whether the immediate sending is needed or not.
 
BOOLEAN LogSendImmediateMessage (CHAR *OptionalBuffer, UINT32 OptionalBufferLength, UINT32 OperationCode)
 Checks whether the immediate sending is needed or not.
 
BOOLEAN LogInitialize (MESSAGE_TRACING_CALLBACKS *MsgTracingCallbacks)
 Initialize the buffer relating to log message tracing.
 
VOID LogUnInitialize ()
 Uninitialize the buffer relating to log message tracing.
 
BOOLEAN LogCallbackCheckIfBufferIsFull (BOOLEAN Priority)
 Checks whether the priority or regular buffer is full or not.
 
_Use_decl_annotations_ BOOLEAN LogCallbackSendBuffer (UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, BOOLEAN Priority)
 Save buffer to the pool.
 
UINT32 LogMarkAllAsRead (BOOLEAN IsVmxRoot)
 Mark all buffers as read.
 
BOOLEAN LogReadBuffer (BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 *ReturnedLength)
 Attempt to read the buffer.
 
BOOLEAN LogCheckForNewMessage (BOOLEAN IsVmxRoot, BOOLEAN Priority)
 Check if new message is available or not.
 
BOOLEAN LogCallbackPrepareAndSendMessageToQueueWrapper (UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, const char *Fmt, va_list ArgList)
 Prepare a printf-style message mapping and send string messages and tracing for logging and monitoring.
 
BOOLEAN LogCallbackPrepareAndSendMessageToQueue (UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, const char *Fmt,...)
 Prepare a printf-style message mapping and send string messages and tracing for logging and monitoring.
 
BOOLEAN LogCallbackSendMessageToQueue (UINT32 OperationCode, BOOLEAN IsImmediateMessage, CHAR *LogMessage, UINT32 BufferLen, BOOLEAN Priority)
 Send string messages and tracing for logging and monitoring.
 
VOID LogNotifyUsermodeCallback (PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
 Complete the IRP in IRP Pending state and fill the usermode buffers with pool data.
 
BOOLEAN LogRegisterIrpBasedNotification (PVOID TargetIrp, LONG *Status)
 Register a new IRP Pending thread which listens for new buffers.
 
BOOLEAN LogRegisterEventBasedNotification (PVOID TargetIrp)
 Create an event-based usermode notifying mechanism.
 

Detailed Description

Message logging and tracing implementation.

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)
Version
0.1
Date
2020-04-11

Function Documentation

◆ LogCallbackCheckIfBufferIsFull()

BOOLEAN LogCallbackCheckIfBufferIsFull ( BOOLEAN Priority)

Checks whether the priority or regular buffer is full or not.

routines callback for checking if buffer is full

Parameters
PriorityWhether the buffer has priority
Returns
BOOLEAN Returns true if the buffer is full, otherwise, return false
252{
253 UINT32 Index;
254 BOOLEAN IsVmxRoot;
255 UINT32 CurrentIndexToWrite = NULL_ZERO;
256 UINT32 CurrentIndexToWritePriority = NULL_ZERO;
257
258 //
259 // Check that if we're in vmx root-mode
260 //
261 IsVmxRoot = LogCheckVmxOperation();
262
263 if (IsVmxRoot)
264 {
265 //
266 // Set the index
267 //
268 Index = 1;
269 }
270 else
271 {
272 //
273 // Set the index
274 //
275 Index = 0;
276 }
277
278 //
279 // check if the buffer is filled to it's maximum index or not
280 //
281 if (Priority)
282 {
283 CurrentIndexToWritePriority = MessageBufferInformation[Index].CurrentIndexToWritePriority;
284
285 if (MessageBufferInformation[Index].CurrentIndexToWritePriority > MaximumPacketsCapacityPriority - 1)
286 {
287 //
288 // start from the beginning
289 //
290 CurrentIndexToWritePriority = 0;
291 }
292 }
293 else
294 {
295 CurrentIndexToWrite = MessageBufferInformation[Index].CurrentIndexToWrite;
296
297 if (MessageBufferInformation[Index].CurrentIndexToWrite > MaximumPacketsCapacity - 1)
298 {
299 //
300 // start from the beginning
301 //
302 CurrentIndexToWrite = 0;
303 }
304 }
305
306 //
307 // Compute the start of the buffer header
308 //
309 BUFFER_HEADER * Header;
310
311 if (Priority)
312 {
313 Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddressPriority + (CurrentIndexToWritePriority * (PacketChunkSize + sizeof(BUFFER_HEADER))));
314 }
315 else
316 {
317 Header = (BUFFER_HEADER *)((UINT64)MessageBufferInformation[Index].BufferStartAddress + (CurrentIndexToWrite * (PacketChunkSize + sizeof(BUFFER_HEADER))));
318 }
319
320 //
321 // If the next item is valid, then it means the buffer is full and the next
322 // item will replace the previous (not served items)
323 //
324 return Header->Valid;
325}
UCHAR BOOLEAN
Definition BasicTypes.h:39
#define NULL_ZERO
Definition BasicTypes.h:51
unsigned __int64 UINT64
Definition BasicTypes.h:21
unsigned int UINT32
Definition BasicTypes.h:48
#define MaximumPacketsCapacity
Default buffer count of packets for message tracing.
Definition Constants.h:163
#define PacketChunkSize
Size of each packet.
Definition Constants.h:179
#define MaximumPacketsCapacityPriority
Default buffer count of packets for message tracing.
Definition Constants.h:169
BOOLEAN LogCheckVmxOperation()
Checks whether the message tracing operates on vmx-root mode or not.
Definition Logging.c:19
struct _BUFFER_HEADER BUFFER_HEADER
Message buffer structure.
LOG_BUFFER_INFORMATION * MessageBufferInformation
Global Variable for buffer on all cores.
Definition Logging.h:104
Message buffer structure.
Definition Logging.h:58
BOOLEAN Valid
Definition Logging.h:61
UINT64 BufferStartAddress
Definition Logging.h:79
UINT64 BufferStartAddressPriority
Definition Logging.h:88
UINT32 CurrentIndexToWritePriority
Definition Logging.h:92
UINT32 CurrentIndexToWrite
Definition Logging.h:83

◆ LogCallbackPrepareAndSendMessageToQueue()

BOOLEAN LogCallbackPrepareAndSendMessageToQueue ( UINT32 OperationCode,
BOOLEAN IsImmediateMessage,
BOOLEAN ShowCurrentSystemTime,
BOOLEAN Priority,
const char * Fmt,
... )

Prepare a printf-style message mapping and send string messages and tracing for logging and monitoring.

routines callback for preparing and sending message to queue

Parameters
OperationCodeOptional operation code
IsImmediateMessageShould be sent immediately
ShowCurrentSystemTimeShow system-time
PriorityWhether the message has priority
FmtMessage format-string
...
Returns
BOOLEAN if it was successful then return TRUE, otherwise returns FALSE
1173{
1174 va_list ArgList;
1175 BOOLEAN Result;
1176
1177 va_start(ArgList, Fmt);
1178
1180 IsImmediateMessage,
1181 ShowCurrentSystemTime,
1182 Priority,
1183 Fmt,
1184 ArgList);
1185
1186 va_end(ArgList);
1187
1188 return Result;
1189}
BOOLEAN LogCallbackPrepareAndSendMessageToQueueWrapper(UINT32 OperationCode, BOOLEAN IsImmediateMessage, BOOLEAN ShowCurrentSystemTime, BOOLEAN Priority, const char *Fmt, va_list ArgList)
Prepare a printf-style message mapping and send string messages and tracing for logging and monitorin...
Definition Logging.c:976

◆ LogCallbackPrepareAndSendMessageToQueueWrapper()

BOOLEAN LogCallbackPrepareAndSendMessageToQueueWrapper ( UINT32 OperationCode,
BOOLEAN IsImmediateMessage,
BOOLEAN ShowCurrentSystemTime,
BOOLEAN Priority,
const char * Fmt,
va_list ArgList )

Prepare a printf-style message mapping and send string messages and tracing for logging and monitoring.

Parameters
OperationCodeOptional operation code
IsImmediateMessageShould be sent immediately
ShowCurrentSystemTimeShow system-time
PriorityWhether the message has priority
FmtMessage format-string
...
Returns
BOOLEAN if it was successful then return TRUE, otherwise returns FALSE
982{
983 int SprintfResult;
984 size_t WrittenSize;
985 BOOLEAN IsVmxRootMode;
986 BOOLEAN Result = FALSE; // by default, we assume error happens
987 char * LogMessage = NULL;
988 char * TempMessage = NULL;
989 char TimeBuffer[20] = {0};
990 ULONG CurrentCore = KeGetCurrentProcessorNumberEx(NULL);
991
992 //
993 // Set Vmx State
994 //
995 IsVmxRootMode = LogCheckVmxOperation();
996
997 //
998 // Set the buffer here, we avoid use stack (local variables) because stack might growth
999 // and be problematic
1000 //
1001 if (IsVmxRootMode)
1002 {
1003 LogMessage = &VmxLogMessage[CurrentCore * PacketChunkSize];
1004 TempMessage = &VmxTempMessage[CurrentCore * PacketChunkSize];
1005 }
1006 else
1007 {
1008 //
1009 // To avoid buffer collision and buffer re-writing in VMX non-root, allocate pool
1010 //
1012
1013 if (LogMessage == NULL)
1014 {
1015 //
1016 // Insufficient space
1017 //
1018 return FALSE;
1019 }
1021
1022 if (TempMessage == NULL)
1023 {
1024 //
1025 // Insufficient space
1026 //
1027 PlatformMemFreePool(LogMessage);
1028 return FALSE;
1029 }
1030 }
1031
1032 if (ShowCurrentSystemTime)
1033 {
1034 //
1035 // It's actually not necessary to use -1 but because user-mode code might assume a null-terminated buffer so
1036 // it's better to use - 1
1037 //
1038
1039 //
1040 // We won't use this because we can't use in any IRQL
1041 // Status = RtlStringCchVPrintfA(TempMessage, PacketChunkSize - 1, Fmt, ArgList);
1042 //
1043 SprintfResult = vsprintf_s(TempMessage, PacketChunkSize - 1, Fmt, ArgList);
1044
1045 //
1046 // Check if the buffer passed the limit
1047 //
1048 if (SprintfResult == -1)
1049 {
1050 //
1051 // Probably the buffer is large that we can't store it
1052 //
1053 goto FreeBufferAndReturn;
1054 }
1055
1056 //
1057 // Fill the above with timer
1058 //
1059 TIME_FIELDS TimeFields;
1060 LARGE_INTEGER SystemTime, LocalTime;
1061 KeQuerySystemTime(&SystemTime);
1062 ExSystemTimeToLocalTime(&SystemTime, &LocalTime);
1063 RtlTimeToTimeFields(&LocalTime, &TimeFields);
1064
1065 //
1066 // We won't use this because we can't use in any IRQL
1067 // Status = RtlStringCchPrintfA(TimeBuffer, RTL_NUMBER_OF(TimeBuffer),
1068 // "%02hd:%02hd:%02hd.%03hd", TimeFields.Hour,
1069 // TimeFields.Minute, TimeFields.Second,
1070 // TimeFields.Milliseconds);
1071 //
1072 //
1073 // Append time with previous message
1074 //
1075 // Status = RtlStringCchPrintfA(LogMessage, PacketChunkSize - 1, "(%s)\t %s", TimeBuffer, TempMessage);
1076 //
1077
1078 //
1079 // this function probably run without error, so there is no need to check the return value
1080 //
1081 sprintf_s(TimeBuffer, RTL_NUMBER_OF(TimeBuffer), "%02hd:%02hd:%02hd.%03hd", TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds);
1082
1083 //
1084 // Append time with previous message
1085 //
1086 SprintfResult = sprintf_s(LogMessage, PacketChunkSize - 1, "(%s - core : %d - vmx-root? %s)\t %s", TimeBuffer, CurrentCore, IsVmxRootMode ? "yes" : "no", TempMessage);
1087
1088 //
1089 // Check if the buffer passed the limit
1090 //
1091 if (SprintfResult == -1)
1092 {
1093 //
1094 // Probably the buffer is large that we can't store it
1095 //
1096 goto FreeBufferAndReturn;
1097 }
1098 }
1099 else
1100 {
1101 //
1102 // It's actually not necessary to use -1 but because user-mode code might assume a null-terminated buffer so
1103 // it's better to use - 1
1104 //
1105
1106 //
1107 // We won't use this because we can't use in any IRQL
1108 // Status = RtlStringCchVPrintfA(LogMessage, PacketChunkSize - 1, Fmt, ArgList);
1109 //
1110 SprintfResult = vsprintf_s(LogMessage, PacketChunkSize - 1, Fmt, ArgList);
1111
1112 //
1113 // Check if the buffer passed the limit
1114 //
1115 if (SprintfResult == -1)
1116 {
1117 //
1118 // Probably the buffer is large that we can't store it
1119 //
1120 goto FreeBufferAndReturn;
1121 }
1122 }
1123
1124 //
1125 // Use std function because they can be run in any IRQL
1126 // RtlStringCchLengthA(LogMessage, PacketChunkSize - 1, &WrittenSize);
1127 //
1128 WrittenSize = strnlen_s(LogMessage, PacketChunkSize - 1);
1129
1130 if (LogMessage[0] == '\0')
1131 {
1132 //
1133 // nothing to write
1134 //
1135 goto FreeBufferAndReturn;
1136 }
1137
1138 //
1139 // Send the prepared buffer (with no priority)
1140 //
1141 Result = LogCallbackSendMessageToQueue(OperationCode, IsImmediateMessage, LogMessage, (UINT32)WrittenSize, Priority);
1142
1143FreeBufferAndReturn:
1144
1145 if (!IsVmxRootMode)
1146 {
1147 PlatformMemFreePool(LogMessage);
1148 PlatformMemFreePool(TempMessage);
1149 }
1150
1151 return Result;
1152}
#define FALSE
Definition BasicTypes.h:54
unsigned long ULONG
Definition BasicTypes.h:37
BOOLEAN LogCallbackSendMessageToQueue(UINT32 OperationCode, BOOLEAN IsImmediateMessage, CHAR *LogMessage, UINT32 BufferLen, BOOLEAN Priority)
Send string messages and tracing for logging and monitoring.
Definition Logging.c:1203
char * VmxTempMessage
VMX temporary buffer for logging messages.
Definition Logging.h:29
char * VmxLogMessage
VMX buffer for logging messages.
Definition Logging.h:23
PVOID PlatformMemAllocateNonPagedPool(SIZE_T NumberOfBytes)
Allocate a non-paged buffer.
Definition Mem.c:41
VOID PlatformMemFreePool(PVOID BufferAddress)
Free (dellocate) a non-paged buffer.
Definition Mem.c:86
NULL()
Definition test-case-generator.py:530

◆ LogCallbackSendBuffer()

_Use_decl_annotations_ BOOLEAN LogCallbackSendBuffer ( UINT32 OperationCode,
PVOID Buffer,
UINT32 BufferLength,
BOOLEAN Priority )

Save buffer to the pool.

Parameters
OperationCodeThe operation code that will be send to user mode
BufferBuffer to be send to user mode
BufferLengthLength of the buffer
PriorityWhether the buffer has priority
Returns
BOOLEAN Returns true if the buffer successfully set to be send to user mode and false if there was an error
340{
341 UINT32 Index;
342 BOOLEAN IsVmxRoot;
343 KIRQL OldIRQL = NULL_ZERO;
344
345 if (BufferLength > PacketChunkSize - 1 || BufferLength == 0)
346 {
347 //
348 // We can't save this huge buffer
349 //
350 return FALSE;
351 }
352
353 //
354 // Check that if we're in vmx root-mode
355 //
356 IsVmxRoot = LogCheckVmxOperation();
357
358 //
359 // Check if we're connected to remote debugger, send it directly to the debugger
360 // and the OPERATION_MANDATORY_DEBUGGEE_BIT should not be set because those operation
361 // codes that their MSB are set should be handled locally
362 //
363 if (LogCheckImmediateSend(OperationCode))
364 {
365 //
366 // if we're in vmx non-root then in order to avoid scheduling we raise the IRQL
367 // to DISPATCH_LEVEL because we will get the lock of sending over serial in the
368 // next function. In vmx-root RFLAGS.IF is cleared so no interrupt happens and
369 // we're safe to get the lock, the same approach is for KeAcquireSpinLock
370 //
371 if (!IsVmxRoot)
372 {
373 //
374 // vmx non-root
375 //
376 OldIRQL = KeRaiseIrqlToDpcLevel();
377 }
378
379 //
380 // Kernel debugger is active, we should send the bytes over serial
381 //
383 Buffer,
384 BufferLength,
385 OperationCode);
386
387 //
388 // Release the vmx non-root lock
389 //
390 if (!IsVmxRoot)
391 {
392 //
393 // vmx non-root
394 //
395 KeLowerIrql(OldIRQL);
396 }
397
398 return TRUE;
399 }
400
401 //
402 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
403 // if not we use the windows spinlock
404 //
405 if (IsVmxRoot)
406 {
407 //
408 // Set the index
409 //
410 Index = 1;
412 }
413 else
414 {
415 //
416 // Set the index
417 //
418 Index = 0;
419
420 //
421 // Acquire the lock
422 //
423 KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL);
424 }
425
426 //
427 // check if the buffer is filled to it's maximum index or not
428 //
429 if (Priority)
430 {
431 if (MessageBufferInformation[Index].CurrentIndexToWritePriority > MaximumPacketsCapacityPriority - 1)
432 {
433 //
434 // start from the beginning
435 //
437 }
438 }
439 else
440 {
441 if (MessageBufferInformation[Index].CurrentIndexToWrite > MaximumPacketsCapacity - 1)
442 {
443 //
444 // start from the beginning
445 //
447 }
448 }
449
450 //
451 // Compute the start of the buffer header
452 //
453 BUFFER_HEADER * Header;
454
455 if (Priority)
456 {
458 }
459 else
460 {
462 }
463
464 //
465 // Set the header
466 //
467 Header->OperationNumber = OperationCode;
468 Header->BufferLength = BufferLength;
469 Header->Valid = TRUE;
470
471 //
472 // ******** Now it's time to fill the buffer ********
473 //
474
475 //
476 // compute the saving index
477 //
478 PVOID SavingBuffer;
479
480 if (Priority)
481 {
483 }
484 else
485 {
487 }
488
489 //
490 // Copy the buffer
491 //
492 RtlCopyBytes(SavingBuffer, Buffer, BufferLength);
493
494 //
495 // Increment the next index to write
496 //
497 if (Priority)
498 {
500 }
501 else
502 {
504 }
505
506 //
507 // check if there is any thread in IRP Pending state, so we can complete their request
508 //
509 if (g_GlobalNotifyRecord != NULL)
510 {
511 //
512 // there is some threads that needs to be completed
513 //
514
515 //
516 // set the target pool
517 //
519
520 //
521 // Insert dpc to queue
522 //
523 KeInsertQueueDpc(&g_GlobalNotifyRecord->Dpc, g_GlobalNotifyRecord, NULL);
524
525 //
526 // set notify routine to null
527 //
529 }
530
531 //
532 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
533 // if not we use the windows spinlock
534 //
535 if (IsVmxRoot)
536 {
538 }
539 else
540 {
541 //
542 // Release the lock
543 //
544 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
545 }
546
547 return TRUE;
548}
#define TRUE
Definition BasicTypes.h:55
BOOLEAN LogSendImmediateMessage(CHAR *OptionalBuffer, UINT32 OptionalBufferLength, UINT32 OperationCode)
Checks whether the immediate sending is needed or not.
Definition Logging.c:70
BOOLEAN LogCheckImmediateSend(UINT32 OperationCode)
Checks whether the immediate sending is needed or not.
Definition Logging.c:43
volatile LONG VmxRootLoggingLock
Vmx-root lock for logging.
Definition Logging.h:110
NOTIFY_RECORD * g_GlobalNotifyRecord
Save the state of the thread that waits for messages to deliver to user-mode.
Definition Logging.h:175
void SpinlockLock(volatile LONG *Lock)
Tries to get the lock and won't return until successfully get the lock.
Definition Spinlock.c:52
void SpinlockUnlock(volatile LONG *Lock)
Release the lock.
Definition Spinlock.c:158
UINT32 BufferLength
Definition Logging.h:60
UINT32 OperationNumber
Definition Logging.h:59
BOOLEAN CheckVmxRootMessagePool
Definition Logging.h:50
KDPC Dpc
Definition Logging.h:49

◆ LogCallbackSendMessageToQueue()

BOOLEAN LogCallbackSendMessageToQueue ( UINT32 OperationCode,
BOOLEAN IsImmediateMessage,
CHAR * LogMessage,
UINT32 BufferLen,
BOOLEAN Priority )

Send string messages and tracing for logging and monitoring.

routines callback for sending message to queue

Parameters
OperationCodeOptional operation code
IsImmediateMessageShould be sent immediately
LogMessageLink of message buffer
BufferLenLength of buffer
PriorityWhether the buffer has priority
Returns
BOOLEAN if it was successful then return TRUE, otherwise returns FALSE
1204{
1205 BOOLEAN Result;
1206 UINT32 Index;
1207 BOOLEAN IsVmxRootMode;
1208 KIRQL OldIRQL = NULL_ZERO;
1209
1210 //
1211 // Set Vmx State
1212 //
1213 IsVmxRootMode = LogCheckVmxOperation();
1214
1215#if UseWPPTracing
1216
1217 if (OperationCode == OPERATION_LOG_INFO_MESSAGE)
1218 {
1219 HypervisorTraceLevelMessage(
1220 TRACE_LEVEL_INFORMATION, // ETW Level defined in evntrace.h
1221 HVFS_LOG_INFO,
1222 "%s", // Flag defined in WPP_CONTROL_GUIDS
1223 LogMessage);
1224 }
1225 else if (OperationCode == OPERATION_LOG_WARNING_MESSAGE)
1226 {
1227 HypervisorTraceLevelMessage(
1228 TRACE_LEVEL_WARNING, // ETW Level defined in evntrace.h
1229 HVFS_LOG_WARNING,
1230 "%s", // Flag defined in WPP_CONTROL_GUIDS
1231 LogMessage);
1232 }
1233 else if (OperationCode == OPERATION_LOG_ERROR_MESSAGE)
1234 {
1235 HypervisorTraceLevelMessage(
1236 TRACE_LEVEL_ERROR, // ETW Level defined in evntrace.h
1237 HVFS_LOG_ERROR,
1238 "%s", // Flag defined in WPP_CONTROL_GUIDS
1239 LogMessage);
1240 }
1241 else
1242 {
1243 HypervisorTraceLevelMessage(
1244 TRACE_LEVEL_NONE, // ETW Level defined in evntrace.h
1245 HVFS_LOG,
1246 "%s", // Flag defined in WPP_CONTROL_GUIDS
1247 LogMessage);
1248 }
1249
1250#else
1251 if (IsImmediateMessage)
1252 {
1253 return LogCallbackSendBuffer(OperationCode, LogMessage, BufferLen, Priority);
1254 }
1255 else
1256 {
1257 //
1258 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
1259 // if not we use the windows spinlock
1260 //
1261 if (IsVmxRootMode)
1262 {
1263 //
1264 // Set the index
1265 //
1266 Index = 1;
1268 }
1269 else
1270 {
1271 //
1272 // Set the index
1273 //
1274 Index = 0;
1275
1276 //
1277 // Acquire the lock
1278 //
1279 KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLockForNonImmMessage, &OldIRQL);
1280 }
1281 //
1282 // Set the result to True
1283 //
1284 Result = TRUE;
1285
1286 //
1287 // If log message WrittenSize is above the buffer then we have to send the previous buffer
1288 //
1289 if ((MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer + BufferLen) > PacketChunkSize - 1 && MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer != 0)
1290 {
1291 //
1292 // Send the previous buffer (non-immediate message),
1293 // accumulated messages don't have priority
1294 //
1296 (PVOID)MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage,
1297 MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer,
1298 FALSE);
1299
1300 //
1301 // Free the immediate buffer
1302 //
1304 RtlZeroMemory((void *)MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage, PacketChunkSize);
1305 }
1306
1307 //
1308 // We have to save the message
1309 //
1310 RtlCopyBytes((void *)(MessageBufferInformation[Index].BufferForMultipleNonImmediateMessage +
1311 MessageBufferInformation[Index].CurrentLengthOfNonImmBuffer),
1312 LogMessage,
1313 BufferLen);
1314
1315 //
1316 // add the length
1317 //
1319
1320 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
1321 // if not we use the windows spinlock
1322 //
1323 if (IsVmxRootMode)
1324 {
1326 }
1327 else
1328 {
1329 //
1330 // Release the lock
1331 //
1332 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLockForNonImmMessage, OldIRQL);
1333 }
1334
1335 return Result;
1336 }
1337#endif
1338}
#define OPERATION_LOG_ERROR_MESSAGE
Definition Constants.h:368
#define OPERATION_LOG_WARNING_MESSAGE
Definition Constants.h:367
#define OPERATION_LOG_INFO_MESSAGE
Message logs id that comes from kernel-mode to user-mode.
Definition Constants.h:366
#define OPERATION_LOG_NON_IMMEDIATE_MESSAGE
Definition Constants.h:369
_Use_decl_annotations_ BOOLEAN LogCallbackSendBuffer(UINT32 OperationCode, PVOID Buffer, UINT32 BufferLength, BOOLEAN Priority)
Save buffer to the pool.
Definition Logging.c:339
volatile LONG VmxRootLoggingLockForNonImmBuffers
Vmx-root lock for logging.
Definition Logging.h:116
#define TRACE_LEVEL_WARNING
Definition Trace.h:32
#define TRACE_LEVEL_NONE
Definition Trace.h:29
#define TRACE_LEVEL_ERROR
Definition Trace.h:31
#define TRACE_LEVEL_INFORMATION
Definition Trace.h:33
UINT32 CurrentLengthOfNonImmBuffer
Definition Logging.h:74

◆ LogCheckForNewMessage()

BOOLEAN LogCheckForNewMessage ( BOOLEAN IsVmxRoot,
BOOLEAN Priority )

Check if new message is available or not.

Parameters
IsVmxRootCheck vmx root pool for message or check vmx non root pool
PriorityWhether the buffer has priority
Returns
BOOLEAN return of this function shows whether the read was successful or not (e.g FALSE shows there's no new buffer available.)
923{
924 UINT32 Index;
925
926 if (IsVmxRoot)
927 {
928 Index = 1;
929 }
930 else
931 {
932 Index = 0;
933 }
934
935 //
936 // Compute the current buffer to read
937 //
938 BUFFER_HEADER * Header;
939
940 if (Priority)
941 {
943 }
944 else
945 {
947 }
948
949 if (!Header->Valid)
950 {
951 //
952 // there is nothing to send
953 //
954 return FALSE;
955 }
956
957 //
958 // If we reached here, means that there is sth to send
959 //
960 return TRUE;
961}
UINT32 CurrentIndexToSend
Definition Logging.h:82
UINT32 CurrentIndexToSendPriority
Definition Logging.h:91

◆ LogCheckImmediateSend()

BOOLEAN LogCheckImmediateSend ( UINT32 OperationCode)
inline

Checks whether the immediate sending is needed or not.

Returns
BOOLEAN
44{
46
47 if (ImmediateMessageCheck == NULL)
48 {
49 //
50 // As the caller didn't defined a checker we assume there is no
51 // need to send messages immediately
52 //
53 return FALSE;
54 }
55
56 //
57 // The user specified a vmx checker
58 //
59 return ImmediateMessageCheck(OperationCode);
60}
BOOLEAN(* CHECK_IMMEDIATE_MESSAGE_SENDING)(UINT32 OperationCode)
A function that checks whether the immediate message sending is needed or not.
Definition HyperLog.h:30
MESSAGE_TRACING_CALLBACKS g_MsgTracingCallbacks
Global variable that holds callbacks.
Definition Logging.h:181
CHECK_IMMEDIATE_MESSAGE_SENDING CheckImmediateMessageSending
Definition HyperLog.h:51

◆ LogCheckVmxOperation()

BOOLEAN LogCheckVmxOperation ( )
inline

Checks whether the message tracing operates on vmx-root mode or not.

Returns
BOOLEAN
20{
22
23 if (VmxOperationCheck == NULL)
24 {
25 //
26 // As the caller didn't defined a checker for vmx operation, we assume
27 // that it's not operating on vmx-root
28 //
29 return FALSE;
30 }
31
32 //
33 // The user specified a vmx checker
34 //
35 return VmxOperationCheck();
36}
BOOLEAN(* CHECK_VMX_OPERATION)()
A function that checks whether the current operation is on vmx-root mode or not.
Definition HyperLog.h:23
CHECK_VMX_OPERATION VmxOperationCheck
Definition HyperLog.h:50

◆ LogInitialize()

BOOLEAN LogInitialize ( MESSAGE_TRACING_CALLBACKS * MsgTracingCallbacks)

Initialize the buffer relating to log message tracing.

Parameters
MsgTracingCallbacksspecify the callbacks
Returns
BOOLEAN
99{
100 ULONG ProcessorsCount;
101
102 ProcessorsCount = KeQueryActiveProcessorCount(0);
103
104 //
105 // Initialize buffers for trace message and data messages
106 //(we have two buffers one for vmx root and one for vmx non-root)
107 //
109
111 {
112 return FALSE; // STATUS_INSUFFICIENT_RESOURCES
113 }
114
115 //
116 // Allocate VmxTempMessage and VmxLogMessage
117 //
120
121 if (!VmxTempMessage)
122 {
125 return FALSE; // STATUS_INSUFFICIENT_RESOURCES
126 }
127
130
131 if (!VmxLogMessage)
132 {
135
138
139 return FALSE; // STATUS_INSUFFICIENT_RESOURCES
140 }
141
142 //
143 // Initialize the lock for Vmx-root mode (HIGH_IRQL Spinlock)
144 //
146
147 //
148 // Allocate buffer for messages and initialize the core buffer information
149 //
150 for (int i = 0; i < 2; i++)
151 {
152 //
153 // initialize the lock
154 // Actually, only the 0th buffer use this spinlock but let initialize it
155 // for both but the second buffer spinlock is useless
156 // as we use our custom spinlock
157 //
158 KeInitializeSpinLock(&MessageBufferInformation[i].BufferLock);
159 KeInitializeSpinLock(&MessageBufferInformation[i].BufferLockForNonImmMessage);
160
161 //
162 // allocate the buffer for regular buffers
163 //
166
167 if (!MessageBufferInformation[i].BufferStartAddress ||
168 !MessageBufferInformation[i].BufferForMultipleNonImmediateMessage)
169 {
170 return FALSE; // STATUS_INSUFFICIENT_RESOURCES
171 }
172
173 //
174 // allocate the buffer for priority buffers
175 //
177
178 if (!MessageBufferInformation[i].BufferStartAddressPriority)
179 {
180 return FALSE; // STATUS_INSUFFICIENT_RESOURCES
181 }
182
183 //
184 // Zeroing the buffer
185 //
186 RtlZeroMemory((void *)MessageBufferInformation[i].BufferStartAddress, LogBufferSize);
187 RtlZeroMemory((void *)MessageBufferInformation[i].BufferForMultipleNonImmediateMessage, PacketChunkSize);
188 RtlZeroMemory((void *)MessageBufferInformation[i].BufferStartAddressPriority, LogBufferSizePriority);
189
190 //
191 // Set the end address
192 //
195 }
196
197 //
198 // Copy the callbacks into the global callback holder
199 //
200 RtlCopyBytes(&g_MsgTracingCallbacks, MsgTracingCallbacks, sizeof(MESSAGE_TRACING_CALLBACKS));
201
202 return TRUE;
203}
#define LogBufferSize
Final storage size of message tracing.
Definition Constants.h:200
#define LogBufferSizePriority
Final storage size of message tracing.
Definition Constants.h:207
PVOID PlatformMemAllocateZeroedNonPagedPool(SIZE_T NumberOfBytes)
Allocate a non-paged buffer (zeroed)
Definition Mem.c:69
Core-specific buffers.
Definition Logging.h:69
UINT64 BufferEndAddressPriority
Definition Logging.h:89
UINT64 BufferEndAddress
Definition Logging.h:80
UINT64 BufferForMultipleNonImmediateMessage
Definition Logging.h:73
Prototype of each function needed by message tracer.
Definition HyperLog.h:49

◆ LogMarkAllAsRead()

UINT32 LogMarkAllAsRead ( BOOLEAN IsVmxRoot)

Mark all buffers as read.

Priority buffers won't be set as read

Parameters
IsVmxRootDetermine whether you want to read vmx root buffer or vmx non root buffer
Returns
UINT32 return count of messages that set to invalid
559{
560 UINT32 Index;
561 UINT32 ResultsOfBuffersSetToRead = 0;
562 KIRQL OldIRQL = NULL_ZERO;
563
564 //
565 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
566 // if not we use the windows spinlock
567 //
568 if (IsVmxRoot)
569 {
570 //
571 // Set the index
572 //
573 Index = 1;
574
575 //
576 // Acquire the lock
577 //
579 }
580 else
581 {
582 //
583 // Set the index
584 //
585 Index = 0;
586
587 //
588 // Acquire the lock
589 //
590 KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL);
591 }
592
593 //
594 // We have iterate through the all indexes
595 //
596 for (size_t i = 0; i < MaximumPacketsCapacity; i++)
597 {
598 //
599 // Compute the current buffer to read
600 //
603 (PacketChunkSize + sizeof(BUFFER_HEADER))));
604
605 if (!Header->Valid)
606 {
607 //
608 // there is nothing to send
609 //
610
611 //
612 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
613 // if not we use the windows spinlock
614 //
615 if (IsVmxRoot)
616 {
618 }
619 else
620 {
621 //
622 // Release the lock
623 //
624 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
625 }
626
627 return ResultsOfBuffersSetToRead;
628 }
629
630 //
631 // If we reached here, means that there is sth to send
632 //
633 ResultsOfBuffersSetToRead++;
634
635 //
636 // Second, save the buffer contents
637 //
639
640 //
641 // Finally, set the current index to invalid as we sent it
642 //
643 Header->Valid = FALSE;
644
645 //
646 // Last step is to clear the current buffer (we can't do it once when CurrentIndexToSend is zero because
647 // there might be multiple messages on the start of the queue that didn't read yet)
648 // we don't free the header
649 //
650 RtlZeroMemory(SendingBuffer, Header->BufferLength);
651
652 //
653 // Check to see whether we passed the index or not
654 //
655 if (MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2)
656 {
658 }
659 else
660 {
661 //
662 // Increment the next index to read
663 //
665 }
666 }
667
668 //
669 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
670 // if not we use the windows spinlock
671 //
672 if (IsVmxRoot)
673 {
675 }
676 else
677 {
678 //
679 // Release the lock
680 //
681 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
682 }
683
684 return ResultsOfBuffersSetToRead;
685}

◆ LogNotifyUsermodeCallback()

VOID LogNotifyUsermodeCallback ( PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2 )

Complete the IRP in IRP Pending state and fill the usermode buffers with pool data.

Parameters
Dpc
DeferredContext
SystemArgument1
SystemArgument2
Returns
VOID
1351{
1352 PNOTIFY_RECORD NotifyRecord;
1353 PIRP Irp;
1354 UINT32 Length;
1355
1356 UNREFERENCED_PARAMETER(Dpc);
1357 UNREFERENCED_PARAMETER(SystemArgument1);
1358 UNREFERENCED_PARAMETER(SystemArgument2);
1359
1360 NotifyRecord = DeferredContext;
1361
1362 ASSERT(NotifyRecord != NULL); // can't be NULL
1363 _Analysis_assume_(NotifyRecord != NULL);
1364
1365 switch (NotifyRecord->Type)
1366 {
1367 case IRP_BASED:
1368 Irp = NotifyRecord->Message.PendingIrp;
1369
1370 if (Irp != NULL)
1371 {
1372 PCHAR OutBuff; // pointer to output buffer
1373 ULONG InBuffLength; // Input buffer length
1374 ULONG OutBuffLength; // Output buffer length
1375 PIO_STACK_LOCATION IrpSp;
1376
1377 //
1378 // Make suree that concurrent calls to notify function never occurs
1379 //
1380 if (!(Irp->CurrentLocation <= Irp->StackCount + 1))
1381 {
1382 DbgPrint("Err, probably two or more functions called DPC for an object");
1383 return;
1384 }
1385
1386 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1387 InBuffLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1388 OutBuffLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
1389
1390 if (!InBuffLength || !OutBuffLength)
1391 {
1392 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1393 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1394 break;
1395 }
1396
1397 //
1398 // Check again that SystemBuffer is not null
1399 //
1400 if (!Irp->AssociatedIrp.SystemBuffer)
1401 {
1402 //
1403 // Buffer is invalid
1404 //
1405 return;
1406 }
1407
1408 OutBuff = Irp->AssociatedIrp.SystemBuffer;
1409 Length = 0;
1410
1411 //
1412 // Read Buffer might be empty (nothing to send)
1413 //
1414 if (!LogReadBuffer(NotifyRecord->CheckVmxRootMessagePool, OutBuff, &Length))
1415 {
1416 //
1417 // we have to return here as there is nothing to send here
1418 //
1419 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1420 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1421 break;
1422 }
1423
1424 Irp->IoStatus.Information = Length;
1425
1426 Irp->IoStatus.Status = STATUS_SUCCESS;
1427 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1428 }
1429 break;
1430
1431 case EVENT_BASED:
1432 //
1433 // Signal the Event created in user-mode.
1434 //
1435 KeSetEvent(NotifyRecord->Message.Event, 0, FALSE);
1436
1437 //
1438 // Dereference the object as we are done with it.
1439 //
1440 ObDereferenceObject(NotifyRecord->Message.Event);
1441
1442 break;
1443
1444 default:
1445 ASSERT(FALSE);
1446 break;
1447 }
1448
1449 if (NotifyRecord != NULL)
1450 {
1451 PlatformMemFreePool(NotifyRecord);
1452 }
1453}
@ EVENT_BASED
Definition DataTypes.h:256
@ IRP_BASED
Definition DataTypes.h:255
BOOLEAN LogReadBuffer(BOOLEAN IsVmxRoot, PVOID BufferToSaveMessage, UINT32 *ReturnedLength)
Attempt to read the buffer.
Definition Logging.c:697
The usermode request.
Definition Logging.h:40
PIRP PendingIrp
Definition Logging.h:46
NOTIFY_TYPE Type
Definition Logging.h:41
union _NOTIFY_RECORD::@55 Message
PKEVENT Event
Definition Logging.h:45

◆ LogReadBuffer()

BOOLEAN LogReadBuffer ( BOOLEAN IsVmxRoot,
PVOID BufferToSaveMessage,
UINT32 * ReturnedLength )

Attempt to read the buffer.

Parameters
IsVmxRootDetermine whether you want to read vmx root buffer or vmx non root buffer
BufferToSaveMessageTarget buffer to save the message
ReturnedLengthThe actual length of the buffer that this function used it
Returns
BOOLEAN return of this function shows whether the read was successful or not (e.g FALSE shows there's no new buffer available.)
698{
699 UINT32 Index;
700 BOOLEAN PriorityMessageIsAvailable = FALSE;
701 KIRQL OldIRQL = NULL_ZERO;
702
703 //
704 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
705 // if not we use the windows spinlock
706 //
707 if (IsVmxRoot)
708 {
709 //
710 // Set the index
711 //
712 Index = 1;
713
714 //
715 // Acquire the lock
716 //
718 }
719 else
720 {
721 //
722 // Set the index
723 //
724 Index = 0;
725
726 //
727 // Acquire the lock
728 //
729 KeAcquireSpinLock(&MessageBufferInformation[Index].BufferLock, &OldIRQL);
730 }
731
732 //
733 // Compute the current buffer to read
734 //
735 BUFFER_HEADER * Header;
736
737 //
738 // Check for priority message
739 //
741
742 if (!Header->Valid)
743 {
744 //
745 // Check for regular message
746 //
748
749 if (!Header->Valid)
750 {
751 //
752 // there is nothing to send
753 //
754
755 //
756 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
757 // if not we use the windows spinlock
758 //
759 if (IsVmxRoot)
760 {
762 }
763 else
764 {
765 //
766 // Release the lock
767 //
768 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
769 }
770
771 return FALSE;
772 }
773 }
774 else
775 {
776 PriorityMessageIsAvailable = TRUE;
777 }
778
779 //
780 // If we reached here, means that there is sth to send
781 //
782
783 //
784 // First copy the header
785 //
786 RtlCopyBytes(BufferToSaveMessage, &Header->OperationNumber, sizeof(UINT32));
787
788 //
789 // Second, save the buffer contents
790 //
791 PVOID SendingBuffer;
792
793 if (PriorityMessageIsAvailable)
794 {
796 }
797 else
798 {
800 }
801
802 //
803 // Because we want to pass the header of usermode header
804 //
805 PVOID SavingAddress = (PVOID)((UINT64)BufferToSaveMessage + sizeof(UINT32));
806
807 RtlCopyBytes(SavingAddress, SendingBuffer, Header->BufferLength);
808
809#if ShowMessagesOnDebugger
810
811 //
812 // Means that show just messages
813 //
815 {
816 //
817 // We're in Dpc level here so it's safe to use DbgPrint
818 // DbgPrint limitation is 512 Byte
819 //
820 if (Header->BufferLength > DbgPrintLimitation)
821 {
822 for (size_t i = 0; i <= Header->BufferLength / DbgPrintLimitation; i++)
823 {
824 if (i != 0)
825 {
826 DbgPrint("%s", (char *)((UINT64)SendingBuffer + (DbgPrintLimitation * i) - 2));
827 }
828 else
829 {
830 DbgPrint("%s", (char *)((UINT64)SendingBuffer + (DbgPrintLimitation * i)));
831 }
832 }
833 }
834 else
835 {
836 DbgPrint("%s", (char *)SendingBuffer);
837 }
838 }
839#endif
840
841 //
842 // Finally, set the current index to invalid as we sent it
843 //
844 Header->Valid = FALSE;
845
846 //
847 // Set the length to show as the ReturnedByted in usermode ioctl function + size of header
848 //
849 *ReturnedLength = Header->BufferLength + sizeof(UINT32);
850
851 //
852 // Last step is to clear the current buffer (we can't do it once when CurrentIndexToSend is zero because
853 // there might be multiple messages on the start of the queue that didn't read yet)
854 // we don't free the header
855 //
856 RtlZeroMemory(SendingBuffer, Header->BufferLength);
857
858 if (PriorityMessageIsAvailable)
859 {
860 //
861 // Check to see whether we passed the index or not
862 //
863 if (MessageBufferInformation[Index].CurrentIndexToSendPriority > MaximumPacketsCapacityPriority - 2)
864 {
866 }
867 else
868 {
869 //
870 // Increment the next index to read
871 //
873 }
874 }
875 else
876 {
877 //
878 // Check to see whether we passed the index or not
879 //
880 if (MessageBufferInformation[Index].CurrentIndexToSend > MaximumPacketsCapacity - 2)
881 {
883 }
884 else
885 {
886 //
887 // Increment the next index to read
888 //
890 }
891 }
892
893 //
894 // Check if we're in Vmx-root, if it is then we use our customized HIGH_IRQL Spinlock,
895 // if not we use the windows spinlock
896 //
897 if (IsVmxRoot)
898 {
900 }
901 else
902 {
903 //
904 // Release the lock
905 //
906 KeReleaseSpinLock(&MessageBufferInformation[Index].BufferLock, OldIRQL);
907 }
908
909 return TRUE;
910}
#define DbgPrintLimitation
limitation of Windows DbgPrint message size
Definition Constants.h:215

◆ LogRegisterEventBasedNotification()

BOOLEAN LogRegisterEventBasedNotification ( PVOID TargetIrp)

Create an event-based usermode notifying mechanism.

Parameters
TargetIrp
Returns
BOOLEAN
1584{
1585 PNOTIFY_RECORD NotifyRecord;
1586 NTSTATUS Status;
1587 PIO_STACK_LOCATION IrpStack;
1588 PREGISTER_NOTIFY_BUFFER RegisterEvent;
1589 PIRP Irp = (PIRP)TargetIrp;
1590
1591 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1592 RegisterEvent = (PREGISTER_NOTIFY_BUFFER)Irp->AssociatedIrp.SystemBuffer;
1593
1594 //
1595 // Allocate a record and save all the event context
1596 //
1598
1599 if (NULL == NotifyRecord)
1600 {
1601 DbgPrint("Err, unable to allocate memory for notify record\n");
1602 return FALSE;
1603 }
1604
1605 NotifyRecord->Type = EVENT_BASED;
1606
1607 KeInitializeDpc(&NotifyRecord->Dpc, // Dpc
1608 LogNotifyUsermodeCallback, // DeferredRoutine
1609 NotifyRecord // DeferredContext
1610 );
1611
1612 //
1613 // Get the object pointer from the handle
1614 // Note we must be in the context of the process that created the handle
1615 //
1616 Status = ObReferenceObjectByHandle(RegisterEvent->hEvent,
1617 SYNCHRONIZE | EVENT_MODIFY_STATE,
1618 *ExEventObjectType,
1619 Irp->RequestorMode,
1620 &NotifyRecord->Message.Event,
1621 NULL);
1622
1623 if (!NT_SUCCESS(Status))
1624 {
1625 DbgPrint("Err, unable to reference user mode event object, status = 0x%x\n", Status);
1626 PlatformMemFreePool(NotifyRecord);
1627 return FALSE;
1628 }
1629
1630 //
1631 // Insert dpc to the queue
1632 //
1633 KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL);
1634
1635 return TRUE;
1636}
struct _REGISTER_NOTIFY_BUFFER * PREGISTER_NOTIFY_BUFFER
VOID LogNotifyUsermodeCallback(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
Complete the IRP in IRP Pending state and fill the usermode buffers with pool data.
Definition Logging.c:1350
PVOID PlatformMemAllocateNonPagedPoolWithQuota(SIZE_T NumberOfBytes)
Allocate a non-paged buffer (use QUOTA)
Definition Mem.c:55
Used to register event for transferring buffer between user-to-kernel.
Definition DataTypes.h:279

◆ LogRegisterIrpBasedNotification()

BOOLEAN LogRegisterIrpBasedNotification ( PVOID TargetIrp,
LONG * Status )

Register a new IRP Pending thread which listens for new buffers.

Parameters
TargetIrp
Status
Returns
BOOLEAN
1465{
1466 PNOTIFY_RECORD NotifyRecord;
1467 PIO_STACK_LOCATION IrpStack;
1468 PREGISTER_NOTIFY_BUFFER RegisterEvent;
1469 PIRP Irp = (PIRP)TargetIrp;
1470
1471 //
1472 // check if current core has another thread with pending IRP,
1473 // if no then put the current thread to pending
1474 // otherwise return and complete thread with STATUS_SUCCESS as
1475 // there is another thread waiting for message
1476 //
1477
1478 if (g_GlobalNotifyRecord == NULL)
1479 {
1480 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1481 RegisterEvent = (PREGISTER_NOTIFY_BUFFER)Irp->AssociatedIrp.SystemBuffer;
1482
1483 //
1484 // Allocate a record and save all the event context
1485 //
1487
1488 if (NULL == NotifyRecord)
1489 {
1490 *Status = (LONG)STATUS_INSUFFICIENT_RESOURCES;
1491 return FALSE;
1492 }
1493
1494 NotifyRecord->Type = IRP_BASED;
1495 NotifyRecord->Message.PendingIrp = Irp;
1496
1497 KeInitializeDpc(&NotifyRecord->Dpc, // Dpc
1498 LogNotifyUsermodeCallback, // DeferredRoutine
1499 NotifyRecord // DeferredContext
1500 );
1501
1502 IoMarkIrpPending(Irp);
1503
1504 //
1505 // check for new message (for both Vmx-root mode or Vmx non root-mode)
1506 // First, we check for priority messages in both buffers then we check
1507 // for regular messages
1508 //
1510 {
1511 //
1512 // check vmx non-root (priority buffers)
1513 //
1514 NotifyRecord->CheckVmxRootMessagePool = FALSE;
1515
1516 //
1517 // Insert dpc to queue
1518 //
1519 KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL);
1520 }
1521 else if (LogCheckForNewMessage(TRUE, TRUE))
1522 {
1523 //
1524 // check vmx root (priority buffers)
1525 //
1526 NotifyRecord->CheckVmxRootMessagePool = TRUE;
1527 //
1528 // Insert dpc to queue
1529 //
1530 KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL);
1531 }
1533 {
1534 //
1535 // check vmx non-root
1536 //
1537 NotifyRecord->CheckVmxRootMessagePool = FALSE;
1538
1539 //
1540 // Insert dpc to queue
1541 //
1542 KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL);
1543 }
1544 else if (LogCheckForNewMessage(TRUE, FALSE))
1545 {
1546 //
1547 // check vmx root
1548 //
1549 NotifyRecord->CheckVmxRootMessagePool = TRUE;
1550 //
1551 // Insert dpc to queue
1552 //
1553 KeInsertQueueDpc(&NotifyRecord->Dpc, NotifyRecord, NULL);
1554 }
1555 else
1556 {
1557 //
1558 // Set the notify routine to the global structure
1559 //
1560 g_GlobalNotifyRecord = NotifyRecord;
1561 }
1562 //
1563 // We will return pending as we have marked the IRP pending
1564 //
1565
1566 *Status = (LONG)STATUS_PENDING;
1567 return TRUE;
1568 }
1569 else
1570 {
1571 *Status = (LONG)STATUS_SUCCESS;
1572 return TRUE;
1573 }
1574}
BOOLEAN LogCheckForNewMessage(BOOLEAN IsVmxRoot, BOOLEAN Priority)
Check if new message is available or not.
Definition Logging.c:922

◆ LogSendImmediateMessage()

BOOLEAN LogSendImmediateMessage ( CHAR * OptionalBuffer,
UINT32 OptionalBufferLength,
UINT32 OperationCode )
inline

Checks whether the immediate sending is needed or not.

Parameters
OptionalBuffer
OptionalBufferLength
OperationCode
Returns
BOOLEAN
73{
75
76 if (SendImmediateMessage == NULL)
77 {
78 //
79 // As the caller didn't defined a checker we assume there is no
80 // need to send messages immediately
81 //
82 return FALSE;
83 }
84
85 //
86 // The user specified a vmx checker
87 //
88 return SendImmediateMessage(OptionalBuffer, OptionalBufferLength, OperationCode);
89}
BOOLEAN(* SEND_IMMEDIATE_MESSAGE)(CHAR *OptionalBuffer, UINT32 OptionalBufferLength, UINT32 OperationCode)
A function that sends immediate messages.
Definition HyperLog.h:36
SEND_IMMEDIATE_MESSAGE SendImmediateMessage
Definition HyperLog.h:52

◆ LogUnInitialize()

VOID LogUnInitialize ( )

Uninitialize the buffer relating to log message tracing.

Returns
VOID
212{
213 //
214 // de-allocate buffer for messages and initialize the core buffer information (for vmx-root core)
215 //
216 for (int i = 0; i < 2; i++)
217 {
218 //
219 // Free each buffers
220 //
221 if (MessageBufferInformation[i].BufferStartAddress != NULL64_ZERO)
222 {
223 PlatformMemFreePool((PVOID)MessageBufferInformation[i].BufferStartAddress);
224 }
225
226 if (MessageBufferInformation[i].BufferStartAddressPriority != NULL64_ZERO)
227 {
228 PlatformMemFreePool((PVOID)MessageBufferInformation[i].BufferStartAddressPriority);
229 }
230
231 if (MessageBufferInformation[i].BufferForMultipleNonImmediateMessage != NULL64_ZERO)
232 {
233 PlatformMemFreePool((PVOID)MessageBufferInformation[i].BufferForMultipleNonImmediateMessage);
234 }
235 }
236
237 //
238 // de-allocate buffers for trace message and data messages
239 //
242}
#define NULL64_ZERO
Definition BasicTypes.h:52