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.

434 lines
12 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. Arguments:
  40. DeviceObject - device object to log error against
  41. Id - ErrorCode Id (This is different than an ntstatus and must be defined in ntiolog.h
  42. NtStatus - The ntstatus for the failure
  43. RawDataBuffer -
  44. RadDataLength -
  45. Annotations - Strings to add to the record
  46. AnnotationCount - How many strings
  47. --*/
  48. {
  49. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  50. ULONG AnnotationStringLength = 0;
  51. ULONG i;
  52. PWCHAR Buffer;
  53. USHORT PaddedRawDataLength = 0;
  54. ULONG TotalLength = 0;
  55. //
  56. // Calculate length of trailing strings
  57. //
  58. for ( i = 0; i < AnnotationCount ; i++ ) {
  59. AnnotationStringLength += (Annotations[i].Length + sizeof( WCHAR ));
  60. }
  61. //
  62. // pad the raw data buffer so that the insertion string starts
  63. // on an even address.
  64. //
  65. if (ARGUMENT_PRESENT( RawDataBuffer )) {
  66. PaddedRawDataLength = (RawDataLength + 1) & ~1;
  67. }
  68. TotalLength = ( sizeof(IO_ERROR_LOG_PACKET) + PaddedRawDataLength + AnnotationStringLength );
  69. //
  70. // If the value of TotalLength is > than 255 then when we cast it to UCHAR
  71. // below, we get an incorrect smaller number which can cause a buffer over
  72. // run below. MAX_UCHAR == 255.
  73. //
  74. if (TotalLength > 255) {
  75. return;
  76. }
  77. //
  78. // Note: error log entry size is pretty small 256 so truncation is a real possibility
  79. //
  80. ErrorLogEntry = IoAllocateErrorLogEntry( (PDEVICE_OBJECT)DeviceObject,
  81. (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) + PaddedRawDataLength + AnnotationStringLength) );
  82. if (ErrorLogEntry != NULL) {
  83. //
  84. // Fill in the error log entry
  85. //
  86. ErrorLogEntry->ErrorCode = Id;
  87. ErrorLogEntry->MajorFunctionCode = 0;
  88. ErrorLogEntry->RetryCount = 0;
  89. ErrorLogEntry->UniqueErrorValue = 0;
  90. ErrorLogEntry->FinalStatus = NtStatus;
  91. ErrorLogEntry->IoControlCode = 0;
  92. ErrorLogEntry->DeviceOffset.QuadPart = 0;
  93. ErrorLogEntry->DumpDataSize = RawDataLength;
  94. ErrorLogEntry->StringOffset = (USHORT)(FIELD_OFFSET( IO_ERROR_LOG_PACKET, DumpData ) + PaddedRawDataLength);
  95. ErrorLogEntry->NumberOfStrings = (USHORT)AnnotationCount;
  96. ErrorLogEntry->SequenceNumber = 0;
  97. //
  98. // Append the extra information.
  99. //
  100. if (ARGUMENT_PRESENT( RawDataBuffer )) {
  101. RtlCopyMemory( ErrorLogEntry->DumpData, RawDataBuffer, RawDataLength );
  102. }
  103. Buffer = (PWCHAR)Add2Ptr(ErrorLogEntry->DumpData, PaddedRawDataLength );
  104. for ( i = 0; i < AnnotationCount ; i++ ) {
  105. RtlCopyMemory( Buffer, Annotations[i].Buffer, Annotations[i].Length );
  106. Buffer += (Annotations[i].Length / 2);
  107. *Buffer++ = L'\0';
  108. }
  109. //
  110. // Write the entry
  111. //
  112. IoWriteErrorLogEntry( ErrorLogEntry );
  113. }
  114. return;
  115. }
  116. VOID
  117. RxLogEventWithBufferDirect (
  118. IN PRDBSS_DEVICE_OBJECT DeviceObject,
  119. IN PUNICODE_STRING OriginatorId,
  120. IN ULONG EventId,
  121. IN NTSTATUS Status,
  122. IN PVOID DataBuffer,
  123. IN USHORT DataBufferLength,
  124. IN ULONG LineNumber
  125. )
  126. /*++
  127. Routine Description:
  128. Wrapper for RxLogEventWithAnnotation. We encode the line number and status into the raw data buffer
  129. Arguments:
  130. DeviceObject - device object to log error against
  131. OriginatorId - string of caller generating error
  132. EventId - ErrorCode Id (This is different than an ntstatus and must be defined in ntiolog.h
  133. Status - The ntstatus for the failure
  134. DataBuffer -
  135. DataLength -
  136. LineNumber - line number where event was generated
  137. --*/
  138. {
  139. ULONG LocalBuffer[ 20 ];
  140. if (!ARGUMENT_PRESENT( OriginatorId ) || (OriginatorId->Length == 0)) {
  141. OriginatorId = &unknownId;
  142. }
  143. LocalBuffer[0] = Status;
  144. LocalBuffer[1] = LineNumber;
  145. //
  146. // Truncate databuffer if necc.
  147. //
  148. RtlCopyMemory( &LocalBuffer[2], DataBuffer, MIN( DataBufferLength, sizeof( LocalBuffer ) - 2 * sizeof( LocalBuffer[0] ) ) );
  149. RxLogEventWithAnnotation( DeviceObject,
  150. EventId,
  151. Status,
  152. LocalBuffer,
  153. (USHORT)MIN( DataBufferLength + sizeof( LocalBuffer[0] ), sizeof( LocalBuffer ) ),
  154. OriginatorId,
  155. 1 );
  156. }
  157. VOID
  158. RxLogEventDirect (
  159. IN PRDBSS_DEVICE_OBJECT DeviceObject,
  160. IN PUNICODE_STRING OriginatorId,
  161. IN ULONG EventId,
  162. IN NTSTATUS Status,
  163. IN ULONG Line
  164. )
  165. /*++
  166. Routine Description:
  167. This function logs an error. You should use the 'RdrLogFailure'
  168. macro instead of calling this routine directly.
  169. Arguments:
  170. Status is the status code showing the failure
  171. Line is where it happened
  172. Return Value:
  173. None.
  174. --*/
  175. {
  176. ULONG LineAndStatus[2];
  177. LineAndStatus[0] = Line;
  178. LineAndStatus[1] = Status;
  179. if( !ARGUMENT_PRESENT( OriginatorId ) || OriginatorId->Length == 0 ) {
  180. OriginatorId = &unknownId;
  181. }
  182. RxLogEventWithAnnotation(
  183. DeviceObject,
  184. EventId,
  185. Status,
  186. &LineAndStatus,
  187. sizeof(LineAndStatus),
  188. OriginatorId,
  189. 1
  190. );
  191. }
  192. BOOLEAN
  193. RxCcLogError(
  194. IN PDEVICE_OBJECT DeviceObject,
  195. IN PUNICODE_STRING FileName,
  196. IN NTSTATUS Error,
  197. IN NTSTATUS DeviceError,
  198. IN UCHAR IrpMajorCode,
  199. IN PVOID Context
  200. )
  201. /*++
  202. Routine Description:
  203. This routine writes an eventlog entry to the eventlog.
  204. Arguments:
  205. DeviceObject - The device object who owns the file where it occurred.
  206. FileName - The filename to use in logging the error (usually the DOS-side name)
  207. Error - The error to log in the eventlog record
  208. DeviceError - The actual error that occured in the device - will be logged
  209. as user data
  210. Return Value:
  211. True if successful, false if internal memory allocation failed
  212. --*/
  213. {
  214. UCHAR ErrorPacketLength;
  215. UCHAR BasePacketLength;
  216. ULONG StringLength;
  217. PIO_ERROR_LOG_PACKET ErrorLogEntry = NULL;
  218. BOOLEAN Result = FALSE;
  219. PWCHAR String;
  220. PAGED_CODE();
  221. //
  222. // Get our error packet, holding the string and status code. Note we log against the
  223. // true filesystem if this is available.
  224. //
  225. // The sizing of the packet is a bit slimy since the dumpdata is already grown by a
  226. // ULONG onto the end of the packet. Since NTSTATUS is ULONG, well, we just work in
  227. // place.
  228. //
  229. BasePacketLength = sizeof( IO_ERROR_LOG_PACKET );
  230. if ((BasePacketLength + FileName->Length + sizeof( WCHAR )) <= ERROR_LOG_MAXIMUM_SIZE) {
  231. ErrorPacketLength = (UCHAR)(BasePacketLength + FileName->Length + sizeof( WCHAR ));
  232. } else {
  233. ErrorPacketLength = ERROR_LOG_MAXIMUM_SIZE;
  234. }
  235. //
  236. // Generate the lost delayed write popup if necc.
  237. //
  238. if (Error == IO_LOST_DELAYED_WRITE) {
  239. IoRaiseInformationalHardError( STATUS_LOST_WRITEBEHIND_DATA, FileName, NULL );
  240. //
  241. // Increment the CC counter here!
  242. //
  243. InterlockedIncrement( &LDWCount );
  244. KeQuerySystemTime( &LDWLastTime );
  245. LDWLastStatus = DeviceError;
  246. LDWContext = Context;
  247. }
  248. ErrorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceObject,
  249. ErrorPacketLength );
  250. if (ErrorLogEntry) {
  251. //
  252. // Fill in the nonzero members of the packet.
  253. //
  254. ErrorLogEntry->MajorFunctionCode = IrpMajorCode;
  255. ErrorLogEntry->ErrorCode = Error;
  256. ErrorLogEntry->FinalStatus = DeviceError;
  257. ErrorLogEntry->DumpDataSize = sizeof(NTSTATUS);
  258. RtlCopyMemory( &ErrorLogEntry->DumpData, &DeviceError, sizeof( NTSTATUS ) );
  259. //
  260. // The filename string is appended to the end of the error log entry. We may
  261. // have to smash the middle to fit it in the limited space.
  262. //
  263. StringLength = ErrorPacketLength - BasePacketLength - sizeof( WCHAR );
  264. ASSERT(!(StringLength % sizeof( WCHAR )));
  265. String = (PWCHAR)Add2Ptr( ErrorLogEntry, BasePacketLength );
  266. ErrorLogEntry->NumberOfStrings = 1;
  267. ErrorLogEntry->StringOffset = BasePacketLength;
  268. //
  269. // If the name does not fit in the packet, divide the name equally to the
  270. // prefix and suffix, with an ellipsis " .. " (4 wide characters) to indicate
  271. // the loss.
  272. //
  273. if (StringLength < FileName->Length) {
  274. //
  275. // Remember, prefix + " .. " + suffix is the length. Calculate by figuring
  276. // the prefix and then get the suffix by whacking the ellipsis and prefix off
  277. // the total.
  278. //
  279. ULONG NamePrefixSegmentLength = ((StringLength / sizeof( WCHAR ))/2 - 2) * sizeof( WCHAR );
  280. ULONG NameSuffixSegmentLength = StringLength - 4*sizeof( WCHAR ) - NamePrefixSegmentLength;
  281. ASSERT(!(NamePrefixSegmentLength % sizeof( WCHAR )));
  282. ASSERT(!(NameSuffixSegmentLength % sizeof( WCHAR )));
  283. RtlCopyMemory( String, FileName->Buffer, NamePrefixSegmentLength );
  284. String = (PWCHAR)Add2Ptr( String, NamePrefixSegmentLength );
  285. RtlCopyMemory( String,
  286. L" .. ",
  287. 4 * sizeof( WCHAR ) );
  288. String += 4;
  289. RtlCopyMemory( String,
  290. Add2Ptr( FileName->Buffer, FileName->Length - NameSuffixSegmentLength ),
  291. NameSuffixSegmentLength );
  292. String = (PWCHAR)Add2Ptr( String, NameSuffixSegmentLength );
  293. } else {
  294. RtlCopyMemory( String,
  295. FileName->Buffer,
  296. FileName->Length );
  297. String += FileName->Length/sizeof(WCHAR);
  298. }
  299. //
  300. // Null terminate the string and send the packet.
  301. //
  302. *String = L'\0';
  303. IoWriteErrorLogEntry( ErrorLogEntry );
  304. Result = TRUE;
  305. }
  306. return Result;
  307. }