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.

357 lines
7.4 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. Author:
  8. Manny Weiser (mannyw) 11-Feb-92
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "errorlog.tmh"
  13. #pragma hdrstop
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text( PAGE, SrvLogInvalidSmbDirect )
  16. #pragma alloc_text( PAGE, SrvLogServiceFailureDirect )
  17. #if DBG
  18. #pragma alloc_text( PAGE, SrvLogTableFullError )
  19. #endif
  20. #endif
  21. #if 0
  22. NOT PAGEABLE -- SrvLogError
  23. NOT PAGEABLE -- SrvCheckSendCompletionStatus
  24. NOT PAGEABLE -- SrvIsLoggableError
  25. #endif
  26. VOID
  27. SrvLogInvalidSmbDirect (
  28. IN PWORK_CONTEXT WorkContext,
  29. IN ULONG LineNumber
  30. )
  31. {
  32. UNICODE_STRING unknownClient;
  33. PUNICODE_STRING clientName;
  34. ULONG LocalBuffer[ 13 ];
  35. PAGED_CODE( );
  36. //
  37. // Let this client log at most one SMB error
  38. //
  39. if( ARGUMENT_PRESENT( WorkContext ) ) {
  40. if( WorkContext->Connection->PagedConnection->LoggedInvalidSmb ) {
  41. return;
  42. }
  43. WorkContext->Connection->PagedConnection->LoggedInvalidSmb = TRUE;
  44. }
  45. if ( ARGUMENT_PRESENT(WorkContext) &&
  46. (WorkContext->Connection->PagedConnection->ClientMachineNameString.Length != 0) ) {
  47. clientName = &WorkContext->Connection->PagedConnection->ClientMachineNameString;
  48. } else {
  49. RtlInitUnicodeString( &unknownClient, StrUnknownClient );
  50. clientName = &unknownClient;
  51. }
  52. if ( ARGUMENT_PRESENT(WorkContext) ) {
  53. LocalBuffer[0] = LineNumber;
  54. RtlCopyMemory(
  55. &LocalBuffer[1],
  56. WorkContext->RequestHeader,
  57. MIN( WorkContext->RequestBuffer->DataLength, sizeof( LocalBuffer ) - sizeof( LocalBuffer[0] ) )
  58. );
  59. SrvLogError(
  60. SrvDeviceObject,
  61. EVENT_SRV_INVALID_REQUEST,
  62. STATUS_INVALID_SMB,
  63. LocalBuffer,
  64. (USHORT)MIN( WorkContext->RequestBuffer->DataLength + sizeof( LocalBuffer[0] ), sizeof( LocalBuffer ) ),
  65. clientName,
  66. 1
  67. );
  68. } else {
  69. SrvLogError(
  70. SrvDeviceObject,
  71. EVENT_SRV_INVALID_REQUEST,
  72. STATUS_INVALID_SMB,
  73. &LineNumber,
  74. (USHORT)sizeof( LineNumber ),
  75. clientName,
  76. 1
  77. );
  78. }
  79. return;
  80. } // SrvLogInvalidSmb
  81. BOOLEAN
  82. SrvIsLoggableError( IN NTSTATUS Status )
  83. {
  84. NTSTATUS *pstatus;
  85. BOOLEAN ret = TRUE;
  86. for( pstatus = SrvErrorLogIgnore; *pstatus; pstatus++ ) {
  87. if( *pstatus == Status ) {
  88. ret = FALSE;
  89. break;
  90. }
  91. }
  92. return ret;
  93. }
  94. VOID
  95. SrvLogServiceFailureDirect (
  96. IN ULONG LineAndService,
  97. IN NTSTATUS Status
  98. )
  99. /*++
  100. Routine Description:
  101. This function logs a srv svc error. You should use the 'SrvLogServiceFailure'
  102. macro instead of calling this routine directly.
  103. Arguments:
  104. LineAndService consists of the line number of the original call in the highword, and
  105. the service code in the lowword
  106. Status is the status code of the called routine
  107. Return Value:
  108. None.
  109. --*/
  110. {
  111. PAGED_CODE( );
  112. //
  113. // Don't log certain errors that are expected to happen occasionally.
  114. //
  115. if( (LineAndService & 01) || SrvIsLoggableError( Status ) ) {
  116. SrvLogError(
  117. SrvDeviceObject,
  118. EVENT_SRV_SERVICE_FAILED,
  119. Status,
  120. &LineAndService,
  121. sizeof(LineAndService),
  122. NULL,
  123. 0
  124. );
  125. }
  126. return;
  127. } // SrvLogServiceFailure
  128. //
  129. // I have disabled this for retail builds because it is not a good idea to
  130. // allow an evil client to so easily fill the server's system log
  131. //
  132. VOID
  133. SrvLogTableFullError (
  134. IN ULONG Type
  135. )
  136. {
  137. #if DBG
  138. PAGED_CODE( );
  139. SrvLogError(
  140. SrvDeviceObject,
  141. EVENT_SRV_CANT_GROW_TABLE,
  142. STATUS_INSUFFICIENT_RESOURCES,
  143. &Type,
  144. sizeof(ULONG),
  145. NULL,
  146. 0
  147. );
  148. return;
  149. #endif
  150. } // SrvLogTableFullError
  151. VOID
  152. SrvLogError(
  153. IN PVOID DeviceOrDriverObject,
  154. IN ULONG UniqueErrorCode,
  155. IN NTSTATUS NtStatusCode,
  156. IN PVOID RawDataBuffer,
  157. IN USHORT RawDataLength,
  158. IN PUNICODE_STRING InsertionString OPTIONAL,
  159. IN ULONG InsertionStringCount
  160. )
  161. /*++
  162. Routine Description:
  163. This function allocates an I/O error log record, fills it in and writes it
  164. to the I/O error log.
  165. Arguments:
  166. Return Value:
  167. None.
  168. --*/
  169. {
  170. PIO_ERROR_LOG_PACKET errorLogEntry;
  171. ULONG insertionStringLength = 0;
  172. ULONG i;
  173. PWCHAR buffer;
  174. USHORT paddedRawDataLength = 0;
  175. //
  176. // Update the server error counts
  177. //
  178. if ( UniqueErrorCode == EVENT_SRV_NETWORK_ERROR ) {
  179. SrvUpdateErrorCount( &SrvNetworkErrorRecord, TRUE );
  180. } else {
  181. SrvUpdateErrorCount( &SrvErrorRecord, TRUE );
  182. }
  183. for ( i = 0; i < InsertionStringCount ; i++ ) {
  184. insertionStringLength += (InsertionString[i].Length + sizeof(WCHAR));
  185. }
  186. //
  187. // pad the raw data buffer so that the insertion string starts
  188. // on an even address.
  189. //
  190. if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
  191. paddedRawDataLength = (RawDataLength + 1) & ~1;
  192. }
  193. errorLogEntry = IoAllocateErrorLogEntry(
  194. DeviceOrDriverObject,
  195. (UCHAR)(sizeof(IO_ERROR_LOG_PACKET) +
  196. paddedRawDataLength + insertionStringLength)
  197. );
  198. if (errorLogEntry != NULL) {
  199. //
  200. // Fill in the error log entry
  201. //
  202. errorLogEntry->ErrorCode = UniqueErrorCode;
  203. errorLogEntry->MajorFunctionCode = 0;
  204. errorLogEntry->RetryCount = 0;
  205. errorLogEntry->UniqueErrorValue = 0;
  206. errorLogEntry->FinalStatus = NtStatusCode;
  207. errorLogEntry->IoControlCode = 0;
  208. errorLogEntry->DeviceOffset.QuadPart = 0;
  209. errorLogEntry->DumpDataSize = RawDataLength;
  210. errorLogEntry->StringOffset =
  211. (USHORT)(FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + paddedRawDataLength);
  212. errorLogEntry->NumberOfStrings = (USHORT)InsertionStringCount;
  213. errorLogEntry->SequenceNumber = 0;
  214. //
  215. // Append the extra information. This information is typically
  216. // an SMB header.
  217. //
  218. if ( ARGUMENT_PRESENT( RawDataBuffer ) ) {
  219. RtlCopyMemory(
  220. errorLogEntry->DumpData,
  221. RawDataBuffer,
  222. RawDataLength
  223. );
  224. }
  225. buffer = (PWCHAR)((PCHAR)errorLogEntry->DumpData + paddedRawDataLength);
  226. for ( i = 0; i < InsertionStringCount ; i++ ) {
  227. RtlCopyMemory(
  228. buffer,
  229. InsertionString[i].Buffer,
  230. InsertionString[i].Length
  231. );
  232. buffer += (InsertionString[i].Length/2);
  233. *buffer++ = L'\0';
  234. }
  235. //
  236. // Write the entry
  237. //
  238. IoWriteErrorLogEntry(errorLogEntry);
  239. }
  240. } // SrvLogError
  241. VOID
  242. SrvCheckSendCompletionStatus(
  243. IN NTSTATUS Status,
  244. IN ULONG LineNumber
  245. )
  246. /*++
  247. Routine Description:
  248. Routine to log send completion errors.
  249. Arguments:
  250. Return Value:
  251. None.
  252. --*/
  253. {
  254. if( SrvIsLoggableError( Status ) ) {
  255. SrvLogError( SrvDeviceObject,
  256. EVENT_SRV_NETWORK_ERROR,
  257. Status,
  258. &LineNumber, sizeof(LineNumber),
  259. NULL, 0 );
  260. }
  261. } // SrvCheckSendCompletionStatus