Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
5.9 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. log.c
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Driver - event logging support
  8. Author:
  9. kyrilf
  10. shouse
  11. --*/
  12. #include <ntddk.h>
  13. #include "log.h"
  14. #include "univ.h"
  15. #include "trace.h" // For wmi event tracing
  16. #include "log.tmh"
  17. static ULONG log_module_id = LOG_MODULE_LOG;
  18. BOOLEAN Log_event (NTSTATUS code, PWSTR msg1, PWSTR msg2, PWSTR msg3, ULONG loc, ULONG d1, ULONG d2)
  19. {
  20. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  21. UNICODE_STRING ErrorStr[3];
  22. PWCHAR InsertStr;
  23. ULONG EntrySizeMinimum;
  24. ULONG EntrySize;
  25. ULONG BytesLeft;
  26. ULONG volatile i;
  27. /* Initialize the three log strings. */
  28. RtlInitUnicodeString(&ErrorStr[0], msg1);
  29. RtlInitUnicodeString(&ErrorStr[1], msg2);
  30. RtlInitUnicodeString(&ErrorStr[2], msg3);
  31. /* Remember the insertion string should be NUL terminated. So we allocate the
  32. extra space of WCHAR. The first parameter to IoAllocateErrorLogEntry can
  33. be either the driver object or the device object. If it is given a device
  34. object, the name of the device (used in IoCreateDevice) will show up in the
  35. place of %1 in the message. See the message file (.mc) for more details. */
  36. EntrySize = sizeof(IO_ERROR_LOG_PACKET) + LOG_NUMBER_DUMP_DATA_ENTRIES * sizeof (ULONG) +
  37. ErrorStr[0].Length + ErrorStr[1].Length + ErrorStr[2].Length + 3 * sizeof(WCHAR);
  38. /* This is the minimum that we can get by with - at least enough room for all
  39. of the data dump entries and the 3 NUL terminating characters. */
  40. EntrySizeMinimum = sizeof(IO_ERROR_LOG_PACKET) + LOG_NUMBER_DUMP_DATA_ENTRIES * sizeof (ULONG) + 3 * sizeof(WCHAR);
  41. /* If we can't even allocate the minimum amount of space, then bail out - this
  42. is a critical error that should never happen, as these limits are set at
  43. compile time, not run time, so unless we do something really dumb, like
  44. try to allow 50 strings of 1KB of dump data, this will never happen. */
  45. if (EntrySizeMinimum > ERROR_LOG_MAXIMUM_SIZE) {
  46. UNIV_PRINT_CRIT(("Log_event: Log entry size too large, exiting: min=%u, max=%u", EntrySizeMinimum, ERROR_LOG_MAXIMUM_SIZE));
  47. TRACE_CRIT("%!FUNC! Log entry size too large, exiting: min=%u, max=%u", EntrySizeMinimum, ERROR_LOG_MAXIMUM_SIZE);
  48. return FALSE;
  49. }
  50. /* Truncate the size of the entry if necessary. In this case, we'll put in
  51. whatever we can fit and truncate or eliminate the strings that don't fit. */
  52. if (EntrySize > ERROR_LOG_MAXIMUM_SIZE) {
  53. UNIV_PRINT_CRIT(("Log_event: Log entry size too large, truncating: size=%u, max=%u", EntrySize, ERROR_LOG_MAXIMUM_SIZE));
  54. TRACE_CRIT("%!FUNC! Log entry size too large, truncating: size=%u, max=%u", EntrySize, ERROR_LOG_MAXIMUM_SIZE);
  55. EntrySize = ERROR_LOG_MAXIMUM_SIZE;
  56. }
  57. /* Allocate the log structure. */
  58. ErrorLogEntry = IoAllocateErrorLogEntry(univ_driver_ptr, (UCHAR)(EntrySize));
  59. if (!ErrorLogEntry) {
  60. #if DBG
  61. /* Convert Unicode string to AnsiCode; %ls can only be used in PASSIVE_LEVEL
  62. Since this function is called from pretty much EVERYWHERE, we cannot
  63. assume what IRQ level we're running at, so be cautious. */
  64. CHAR AnsiString[64];
  65. for (i = 0; (i < sizeof(AnsiString) - 1) && (i < ErrorStr[0].Length); i++)
  66. AnsiString[i] = (CHAR)msg1[i];
  67. AnsiString[i] = '\0';
  68. UNIV_PRINT_CRIT(("Log_event: Error allocating log entry %s", AnsiString));
  69. TRACE_CRIT("%!FUNC! Error allocating log entry %s", AnsiString);
  70. #endif
  71. return FALSE;
  72. }
  73. /* Fill in the necessary information into the header. */
  74. ErrorLogEntry->ErrorCode = code;
  75. ErrorLogEntry->SequenceNumber = 0;
  76. ErrorLogEntry->MajorFunctionCode = 0;
  77. ErrorLogEntry->RetryCount = 0;
  78. ErrorLogEntry->UniqueErrorValue = 0;
  79. ErrorLogEntry->FinalStatus = STATUS_SUCCESS;
  80. ErrorLogEntry->DumpDataSize = (LOG_NUMBER_DUMP_DATA_ENTRIES + 1) * sizeof (ULONG);
  81. ErrorLogEntry->StringOffset = sizeof (IO_ERROR_LOG_PACKET) + LOG_NUMBER_DUMP_DATA_ENTRIES * sizeof (ULONG);
  82. ErrorLogEntry->NumberOfStrings = 3;
  83. /* load the NUMBER_DUMP_DATA_ENTRIES plus location id here */
  84. ErrorLogEntry->DumpData [0] = loc;
  85. ErrorLogEntry->DumpData [1] = d1;
  86. ErrorLogEntry->DumpData [2] = d2;
  87. /* Calculate the number of bytes available in the string storage area. */
  88. BytesLeft = EntrySize - ErrorLogEntry->StringOffset;
  89. /* Set a pointer to the beginning of the string storage area. */
  90. InsertStr = (PWCHAR)((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
  91. /* Loop through all strings and put in as much of them as we can - we reserve
  92. at least enough room for all three NUL terminating characters. */
  93. for (i = 0; i < 3; i++) {
  94. ULONG Length;
  95. /* If we're inside the loop there should ALWAYS be at least two bytes left. */
  96. UNIV_ASSERT(BytesLeft);
  97. /* Find out how much of this string we can fit into the buffer - save room for the NUL characters. */
  98. Length = (ErrorStr[i].Length <= (BytesLeft - ((3 - i) * sizeof(WCHAR)))) ? ErrorStr[i].Length : BytesLeft - ((3 - i) * sizeof(WCHAR));
  99. /* Copy the number of characters that will fit. */
  100. RtlMoveMemory(InsertStr, ErrorStr[i].Buffer, Length);
  101. /* Put the NUL character at the end. */
  102. *(PWCHAR)((PCHAR)InsertStr + Length) = L'\0';
  103. /* Move the string pointer past the string. */
  104. InsertStr = (PWCHAR)((PCHAR)InsertStr + Length + sizeof(WCHAR));
  105. /* Calculate the number of bytes left now. */
  106. BytesLeft -= (Length + sizeof(WCHAR));
  107. }
  108. /* Write the log entry. */
  109. IoWriteErrorLogEntry(ErrorLogEntry);
  110. return TRUE;
  111. }