Source code of Windows XP (NT5)
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.

286 lines
7.0 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. errorlog.c
  5. Abstract:
  6. This module implements the error logging in the server.
  7. !!! This module must be nonpageable.
  8. Author:
  9. Manny Weiser (mannyw) 11-Feb-92
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // Local procedure forwards
  16. //
  17. VOID
  18. BowserLogIllegalNameWorker(
  19. IN PVOID Ctx
  20. );
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text(PAGE, BowserWriteErrorLogEntry)
  23. #pragma alloc_text(PAGE, BowserLogIllegalNameWorker )
  24. #endif
  25. ULONG
  26. BowserSequenceNumber = 0;
  27. //#pragma optimize("",off)
  28. VOID
  29. _cdecl
  30. BowserWriteErrorLogEntry(
  31. IN ULONG UniqueErrorCode,
  32. IN NTSTATUS NtStatusCode,
  33. IN PVOID ExtraInformationBuffer,
  34. IN USHORT ExtraInformationLength,
  35. IN USHORT NumberOfInsertionStrings,
  36. ...
  37. )
  38. #define LAST_NAMED_ARGUMENT NumberOfInsertionStrings
  39. /*++
  40. Routine Description:
  41. This function allocates an I/O error log record, fills it in and writes it
  42. to the I/O error log.
  43. Arguments:
  44. Return Value:
  45. None.
  46. --*/
  47. {
  48. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  49. int TotalErrorLogEntryLength;
  50. ULONG SizeOfStringData = 0;
  51. va_list ParmPtr; // Pointer to stack parms.
  52. ULONG Length;
  53. PAGED_CODE();
  54. if (NumberOfInsertionStrings != 0) {
  55. ULONG i;
  56. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  57. for (i = 0; i < NumberOfInsertionStrings; i += 1) {
  58. PWSTR String = va_arg(ParmPtr, PWSTR);
  59. Length = wcslen(String);
  60. while ( (Length > 0) && (String[Length-1] == L' ') ) {
  61. Length--;
  62. }
  63. SizeOfStringData += (Length + 1) * sizeof(WCHAR);
  64. }
  65. }
  66. //
  67. // Ideally we want the packet to hold the servername and ExtraInformation.
  68. // Usually the ExtraInformation gets truncated.
  69. //
  70. TotalErrorLogEntryLength =
  71. min( ExtraInformationLength + sizeof(IO_ERROR_LOG_PACKET) + 1 + SizeOfStringData,
  72. ERROR_LOG_MAXIMUM_SIZE );
  73. ErrorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
  74. (PDEVICE_OBJECT)BowserDeviceObject,
  75. (UCHAR)TotalErrorLogEntryLength
  76. );
  77. if (ErrorLogEntry != NULL) {
  78. PCHAR DumpData;
  79. ULONG RemainingSpace = TotalErrorLogEntryLength -
  80. FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData);
  81. ULONG i;
  82. ULONG SizeOfRawData;
  83. if (RemainingSpace > SizeOfStringData) {
  84. SizeOfRawData = RemainingSpace - SizeOfStringData;
  85. } else {
  86. SizeOfStringData = RemainingSpace;
  87. SizeOfRawData = 0;
  88. }
  89. //
  90. // Fill in the error log entry
  91. //
  92. ErrorLogEntry->ErrorCode = UniqueErrorCode;
  93. ErrorLogEntry->MajorFunctionCode = 0;
  94. ErrorLogEntry->RetryCount = 0;
  95. ErrorLogEntry->UniqueErrorValue = 0;
  96. ErrorLogEntry->FinalStatus = NtStatusCode;
  97. ErrorLogEntry->IoControlCode = 0;
  98. ErrorLogEntry->DeviceOffset.LowPart = 0;
  99. ErrorLogEntry->DeviceOffset.HighPart = 0;
  100. ErrorLogEntry->SequenceNumber = (ULONG)BowserSequenceNumber ++;
  101. ErrorLogEntry->StringOffset = (USHORT)(ROUND_UP_COUNT(
  102. FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + SizeOfRawData,
  103. ALIGN_WORD));
  104. DumpData = (PCHAR)ErrorLogEntry->DumpData;
  105. //
  106. // Append the extra information. This information is typically
  107. // an SMB header.
  108. //
  109. if (( ARGUMENT_PRESENT( ExtraInformationBuffer )) &&
  110. ( SizeOfRawData != 0 )) {
  111. ULONG Length;
  112. Length = min(ExtraInformationLength, (USHORT)SizeOfRawData);
  113. RtlCopyMemory(
  114. DumpData,
  115. ExtraInformationBuffer,
  116. Length);
  117. ErrorLogEntry->DumpDataSize = (USHORT)Length;
  118. } else {
  119. ErrorLogEntry->DumpDataSize = 0;
  120. }
  121. ErrorLogEntry->NumberOfStrings = 0;
  122. if (NumberOfInsertionStrings != 0) {
  123. PWSTR StringOffset = (PWSTR)((PCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
  124. PWSTR InsertionString;
  125. //
  126. // Set up ParmPtr to point to first of the caller's parameters.
  127. //
  128. va_start(ParmPtr, LAST_NAMED_ARGUMENT);
  129. for (i = 0 ; i < NumberOfInsertionStrings ; i+= 1) {
  130. InsertionString = va_arg(ParmPtr, PWSTR);
  131. Length = wcslen(InsertionString);
  132. while ( (Length > 0) && (InsertionString[Length-1] == L' ') ) {
  133. Length--;
  134. }
  135. if ( ((Length + 1) * sizeof(WCHAR)) > SizeOfStringData ) {
  136. Length = (SizeOfStringData/sizeof(WCHAR))-1;
  137. }
  138. if ( Length > 0 ) {
  139. RtlCopyMemory(StringOffset, InsertionString, Length*sizeof(WCHAR));
  140. StringOffset += Length;
  141. *StringOffset++ = L'\0';
  142. SizeOfStringData -= (Length + 1) * sizeof(WCHAR);
  143. ErrorLogEntry->NumberOfStrings += 1;
  144. }
  145. }
  146. }
  147. IoWriteErrorLogEntry(ErrorLogEntry);
  148. }
  149. }
  150. typedef struct _ILLEGAL_NAME_CONTEXT {
  151. WORK_QUEUE_ITEM WorkItem;
  152. PTRANSPORT_NAME TransportName;
  153. NTSTATUS EventStatus;
  154. NTSTATUS NtStatusCode;
  155. USHORT BufferSize;
  156. UCHAR Buffer[1];
  157. } ILLEGAL_NAME_CONTEXT, *PILLEGAL_NAME_CONTEXT;
  158. VOID
  159. BowserLogIllegalName(
  160. IN NTSTATUS NtStatusCode,
  161. IN PVOID NameBuffer,
  162. IN USHORT NameBufferSize
  163. )
  164. {
  165. KIRQL OldIrql;
  166. NTSTATUS ErrorStatus = STATUS_SUCCESS;
  167. ACQUIRE_SPIN_LOCK(&BowserTimeSpinLock, &OldIrql);
  168. if (BowserIllegalNameCount > 0) {
  169. BowserIllegalNameCount -= 1;
  170. ErrorStatus = EVENT_BOWSER_NAME_CONVERSION_FAILED;
  171. } else if (!BowserIllegalNameThreshold) {
  172. BowserIllegalNameThreshold = TRUE;
  173. ErrorStatus = EVENT_BOWSER_NAME_CONVERSION_FAILED;
  174. }
  175. RELEASE_SPIN_LOCK(&BowserTimeSpinLock, OldIrql);
  176. if (ErrorStatus != STATUS_SUCCESS) {
  177. PILLEGAL_NAME_CONTEXT Context = NULL;
  178. Context = ALLOCATE_POOL(NonPagedPool, sizeof(ILLEGAL_NAME_CONTEXT)+NameBufferSize, POOL_ILLEGALDGRAM);
  179. if (Context != NULL) {
  180. Context->EventStatus = ErrorStatus;
  181. Context->NtStatusCode = NtStatusCode;
  182. Context->BufferSize = NameBufferSize;
  183. RtlCopyMemory( Context->Buffer, NameBuffer, NameBufferSize );
  184. ExInitializeWorkItem(&Context->WorkItem, BowserLogIllegalNameWorker, Context);
  185. BowserQueueDelayedWorkItem( &Context->WorkItem );
  186. }
  187. }
  188. }
  189. VOID
  190. BowserLogIllegalNameWorker(
  191. IN PVOID Ctx
  192. )
  193. {
  194. PILLEGAL_NAME_CONTEXT Context = Ctx;
  195. NTSTATUS EventContext = Context->EventStatus;
  196. PAGED_CODE();
  197. BowserWriteErrorLogEntry( Context->EventStatus,
  198. Context->NtStatusCode,
  199. Context->Buffer,
  200. Context->BufferSize,
  201. 0 );
  202. FREE_POOL(Context);
  203. }