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.

380 lines
9.7 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 rdbss.
  7. Author:
  8. Manny Weiser (mannyw) 11-Feb-92
  9. Revision History:
  10. Joe Linn (joelinn) 23-feb-95 Convert for rdbss
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <align.h>
  15. #include <netevent.h>
  16. //
  17. // The local debug trace level
  18. //
  19. #define MIN(__a,__b) (((__a)<=(__b))?(__a):(__b))
  20. static UNICODE_STRING unknownId = { 6, 6, L"???" };
  21. LONG LDWCount = 0;
  22. NTSTATUS LDWLastStatus;
  23. LARGE_INTEGER LDWLastTime;
  24. PVOID LDWContext;
  25. VOID
  26. RxLogEventWithAnnotation(
  27. IN PRDBSS_DEVICE_OBJECT DeviceObject,
  28. IN ULONG Id,
  29. IN NTSTATUS NtStatus,
  30. IN PVOID RawDataBuffer,
  31. IN USHORT RawDataLength,
  32. IN PUNICODE_STRING Annotations,
  33. IN ULONG AnnotationCount
  34. )
  35. /*++
  36. Routine Description:
  37. This function allocates an I/O error log record, fills it in and writes it
  38. to the I/O error log.
  39. --*/
  40. {
  41. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  42. ULONG AnnotationStringLength = 0;
  43. ULONG i;
  44. PWCHAR Buffer;
  45. USHORT PaddedRawDataLength = 0;
  46. for ( i = 0; i < AnnotationCount ; i++ ) {
  47. AnnotationStringLength += (Annotations[i].Length + sizeof(WCHAR));
  48. }
  49. //
  50. // pad the raw data buffer so that the insertion string starts
  51. // on an even address.
  52. //
  53. if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
  54. PaddedRawDataLength = (RawDataLength + 1) & ~1;
  55. }
  56. ErrorLogEntry = IoAllocateErrorLogEntry(
  57. (PDEVICE_OBJECT)DeviceObject,
  58. (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  59. PaddedRawDataLength + AnnotationStringLength)
  60. );
  61. if (ErrorLogEntry != NULL) {
  62. //
  63. // Fill in the error log entry
  64. //
  65. ErrorLogEntry->ErrorCode = Id;
  66. ErrorLogEntry->MajorFunctionCode = 0;
  67. ErrorLogEntry->RetryCount = 0;
  68. ErrorLogEntry->UniqueErrorValue = 0;
  69. ErrorLogEntry->FinalStatus = NtStatus;
  70. ErrorLogEntry->IoControlCode = 0;
  71. ErrorLogEntry->DeviceOffset.QuadPart = 0;
  72. ErrorLogEntry->DumpDataSize = RawDataLength;
  73. ErrorLogEntry->StringOffset =
  74. (USHORT)(FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + PaddedRawDataLength);
  75. ErrorLogEntry->NumberOfStrings = (USHORT)AnnotationCount;
  76. ErrorLogEntry->SequenceNumber = 0;
  77. //
  78. // Append the extra information.
  79. //
  80. if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
  81. RtlCopyMemory(
  82. ErrorLogEntry->DumpData,
  83. RawDataBuffer,
  84. RawDataLength
  85. );
  86. }
  87. Buffer = (PWCHAR)((PCHAR)ErrorLogEntry->DumpData + PaddedRawDataLength);
  88. for ( i = 0; i < AnnotationCount ; i++ ) {
  89. RtlCopyMemory(
  90. Buffer,
  91. Annotations[i].Buffer,
  92. Annotations[i].Length
  93. );
  94. Buffer += (Annotations[i].Length/2);
  95. *Buffer++ = L'\0';
  96. }
  97. //
  98. // Write the entry
  99. //
  100. IoWriteErrorLogEntry(ErrorLogEntry);
  101. }
  102. }
  103. VOID
  104. RxLogEventWithBufferDirect (
  105. IN PRDBSS_DEVICE_OBJECT DeviceObject,
  106. IN PUNICODE_STRING OriginatorId,
  107. IN ULONG EventId,
  108. IN NTSTATUS Status,
  109. IN PVOID DataBuffer,
  110. IN USHORT DataBufferLength,
  111. IN ULONG LineNumber
  112. )
  113. {
  114. ULONG LocalBuffer[ 20 ];
  115. if( !ARGUMENT_PRESENT( OriginatorId ) || OriginatorId->Length == 0 ) {
  116. OriginatorId = &unknownId;
  117. }
  118. LocalBuffer[0] = Status;
  119. LocalBuffer[1] = LineNumber;
  120. RtlCopyMemory(
  121. &LocalBuffer[2],
  122. DataBuffer,
  123. MIN( DataBufferLength, sizeof( LocalBuffer ) - 2*sizeof( LocalBuffer[0] ) )
  124. );
  125. RxLogEventWithAnnotation(
  126. DeviceObject,
  127. EventId,
  128. Status,
  129. LocalBuffer,
  130. (USHORT)MIN( DataBufferLength + sizeof( LocalBuffer[0] ), sizeof( LocalBuffer ) ),
  131. OriginatorId,
  132. 1
  133. );
  134. }
  135. VOID
  136. RxLogEventDirect (
  137. IN PRDBSS_DEVICE_OBJECT DeviceObject,
  138. IN PUNICODE_STRING OriginatorId,
  139. IN ULONG EventId,
  140. IN NTSTATUS Status,
  141. IN ULONG Line
  142. )
  143. /*++
  144. Routine Description:
  145. This function logs an error. You should use the 'RdrLogFailure'
  146. macro instead of calling this routine directly.
  147. Arguments:
  148. Status is the status code showing the failure
  149. Line is where it happened
  150. Return Value:
  151. None.
  152. --*/
  153. {
  154. ULONG LineAndStatus[2];
  155. LineAndStatus[0] = Line;
  156. LineAndStatus[1] = Status;
  157. if( !ARGUMENT_PRESENT( OriginatorId ) || OriginatorId->Length == 0 ) {
  158. OriginatorId = &unknownId;
  159. }
  160. RxLogEventWithAnnotation(
  161. DeviceObject,
  162. EventId,
  163. Status,
  164. &LineAndStatus,
  165. sizeof(LineAndStatus),
  166. OriginatorId,
  167. 1
  168. );
  169. }
  170. BOOLEAN
  171. RxCcLogError(
  172. IN PDEVICE_OBJECT DeviceObject,
  173. IN PUNICODE_STRING FileName,
  174. IN NTSTATUS Error,
  175. IN NTSTATUS DeviceError,
  176. IN UCHAR IrpMajorCode,
  177. IN PVOID Context
  178. )
  179. /*++
  180. Routine Description:
  181. This routine writes an eventlog entry to the eventlog.
  182. Arguments:
  183. DeviceObject - The device object who owns the file where it occurred.
  184. FileName - The filename to use in logging the error (usually the DOS-side name)
  185. Error - The error to log in the eventlog record
  186. DeviceError - The actual error that occured in the device - will be logged
  187. as user data
  188. Return Value:
  189. True if successful, false if internal memory allocation failed
  190. --*/
  191. {
  192. UCHAR ErrorPacketLength;
  193. UCHAR BasePacketLength;
  194. ULONG StringLength;
  195. PIO_ERROR_LOG_PACKET ErrorLogEntry = NULL;
  196. BOOLEAN Result = FALSE;
  197. PWCHAR String;
  198. PAGED_CODE();
  199. //
  200. // Get our error packet, holding the string and status code. Note we log against the
  201. // true filesystem if this is available.
  202. //
  203. // The sizing of the packet is a bit slimy since the dumpdata is already grown by a
  204. // ULONG onto the end of the packet. Since NTSTATUS is ULONG, well, we just work in
  205. // place.
  206. //
  207. BasePacketLength = sizeof(IO_ERROR_LOG_PACKET);
  208. if ((BasePacketLength + FileName->Length + sizeof(WCHAR)) <= ERROR_LOG_MAXIMUM_SIZE) {
  209. ErrorPacketLength = (UCHAR)(BasePacketLength + FileName->Length + sizeof(WCHAR));
  210. } else {
  211. ErrorPacketLength = ERROR_LOG_MAXIMUM_SIZE;
  212. }
  213. if( Error == IO_LOST_DELAYED_WRITE )
  214. {
  215. IoRaiseInformationalHardError( STATUS_LOST_WRITEBEHIND_DATA, FileName, NULL );
  216. // Increment the CC counter here!
  217. InterlockedIncrement( &LDWCount );
  218. KeQuerySystemTime( &LDWLastTime );
  219. LDWLastStatus = DeviceError;
  220. LDWContext = Context;
  221. }
  222. ErrorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceObject,
  223. ErrorPacketLength );
  224. if (ErrorLogEntry) {
  225. //
  226. // Fill in the nonzero members of the packet.
  227. //
  228. ErrorLogEntry->MajorFunctionCode = IrpMajorCode;
  229. ErrorLogEntry->ErrorCode = Error;
  230. ErrorLogEntry->FinalStatus = DeviceError;
  231. ErrorLogEntry->DumpDataSize = sizeof(NTSTATUS);
  232. RtlCopyMemory( &ErrorLogEntry->DumpData, &DeviceError, sizeof(NTSTATUS) );
  233. //
  234. // The filename string is appended to the end of the error log entry. We may
  235. // have to smash the middle to fit it in the limited space.
  236. //
  237. StringLength = ErrorPacketLength - BasePacketLength - sizeof(WCHAR);
  238. ASSERT(!(StringLength % sizeof(WCHAR)));
  239. String = (PWCHAR) ((PUCHAR)ErrorLogEntry + BasePacketLength);
  240. ErrorLogEntry->NumberOfStrings = 1;
  241. ErrorLogEntry->StringOffset = BasePacketLength;
  242. //
  243. // If the name does not fit in the packet, divide the name equally to the
  244. // prefix and suffix, with an ellipsis " .. " (4 wide characters) to indicate
  245. // the loss.
  246. //
  247. if (StringLength < FileName->Length) {
  248. //
  249. // Remember, prefix + " .. " + suffix is the length. Calculate by figuring
  250. // the prefix and then get the suffix by whacking the ellipsis and prefix off
  251. // the total.
  252. //
  253. ULONG NamePrefixSegmentLength = ((StringLength/sizeof(WCHAR))/2 - 2)*sizeof(WCHAR);
  254. ULONG NameSuffixSegmentLength = StringLength - 4*sizeof(WCHAR) - NamePrefixSegmentLength;
  255. ASSERT(!(NamePrefixSegmentLength % sizeof(WCHAR)));
  256. ASSERT(!(NameSuffixSegmentLength % sizeof(WCHAR)));
  257. RtlCopyMemory( String,
  258. FileName->Buffer,
  259. NamePrefixSegmentLength );
  260. String = (PWCHAR)((PCHAR)String + NamePrefixSegmentLength);
  261. RtlCopyMemory( String,
  262. L" .. ",
  263. 4*sizeof(WCHAR) );
  264. String += 4;
  265. RtlCopyMemory( String,
  266. (PUCHAR)FileName->Buffer +
  267. FileName->Length - NameSuffixSegmentLength,
  268. NameSuffixSegmentLength );
  269. String = (PWCHAR)((PCHAR)String + NameSuffixSegmentLength);
  270. } else {
  271. RtlCopyMemory( String,
  272. FileName->Buffer,
  273. FileName->Length );
  274. String += FileName->Length/sizeof(WCHAR);
  275. }
  276. //
  277. // Null terminate the string and send the packet.
  278. //
  279. *String = L'\0';
  280. IoWriteErrorLogEntry( ErrorLogEntry );
  281. Result = TRUE;
  282. }
  283. return Result;
  284. }