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.

359 lines
9.0 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: dfsdata.c
  4. //
  5. // Contents:
  6. // This module declares the global data used by the Dfs file system.
  7. //
  8. // Functions:
  9. //
  10. // History: 12 Nov 1991 AlanW Created from CDFS souce.
  11. //
  12. //-----------------------------------------------------------------------------
  13. #include "dfsprocs.h"
  14. //
  15. // The debug trace level
  16. //
  17. #define Dbg (DEBUG_TRACE_CATCH_EXCEPTIONS)
  18. // DfsBugCheck
  19. // DfsExceptionFilter
  20. // DfsProcessException
  21. #ifdef ALLOC_PRAGMA
  22. #pragma alloc_text ( PAGE, DfsBugCheck )
  23. #pragma alloc_text ( PAGE, DfsExceptionFilter )
  24. #pragma alloc_text ( PAGE, DfsProcessException )
  25. //
  26. // The following rountine cannot be paged because it raises the IRQL to
  27. // complete IRPs.
  28. //
  29. //
  30. // DfsCompleteRequest_Real
  31. //
  32. #endif // ALLOC_PRAGMA
  33. //
  34. // The global FSD data record
  35. //
  36. DFS_DATA DfsData;
  37. //
  38. // The global event logging level
  39. //
  40. ULONG DfsEventLog = 0;
  41. //
  42. // The global Dfs debug level
  43. //
  44. ULONG MupVerbose = 0;
  45. DFS_TIMER_CONTEXT DfsTimerContext;
  46. //
  47. // Some often used strings
  48. //
  49. WCHAR LogicalRootDevPath[ MAX_LOGICAL_ROOT_LEN ] = { DD_DFS_DEVICE_DIRECTORY };
  50. #if DBG
  51. //+---------------------------------------------------------------------------
  52. // Function: DfsDebugTracePrint, public
  53. //
  54. // Synopsis: Produce a DFS debug trace printout
  55. //
  56. // Arguments: [x] -- DbgPrint format string
  57. // [y] -- optional argument to DbgPrint
  58. //
  59. // Returns: None
  60. //
  61. //----------------------------------------------------------------------------
  62. LONG DfsDebugTraceLevel = 0x00000001;
  63. LONG DfsDebugTraceIndent = 0;
  64. VOID
  65. DfsDebugTracePrint(PCHAR x, PVOID y)
  66. {
  67. int i;
  68. DbgPrint("%p:",PsGetCurrentThread());
  69. if (DfsDebugTraceIndent < 0)
  70. DfsDebugTraceIndent = 0;
  71. for (i = 0; i+5 < DfsDebugTraceIndent; i += 5) {
  72. DbgPrint(" ");
  73. }
  74. for ( ; i < DfsDebugTraceIndent; i += 1) {
  75. DbgPrint(" ");
  76. }
  77. DbgPrint(x,y);
  78. }
  79. #endif // DBG
  80. //+---------------------------------------------------------------------------
  81. // Function: DfsBugCheck, public
  82. //
  83. // Synopsis: Call KeBugCheck with DFS' constant
  84. //
  85. // Arguments: [pszmsg] -- message (DBG=1 only)
  86. // [pszfile] -- filename (DBG=1 only)
  87. // [line] -- line number (DBG=1 only)
  88. //
  89. // Returns: None
  90. //
  91. //----------------------------------------------------------------------------
  92. #if DBG
  93. VOID DfsBugCheck(CHAR *pszmsg, CHAR *pszfile, ULONG line)
  94. {
  95. PVOID CallersAddress, CallersCaller;
  96. RtlGetCallersAddress(&CallersAddress, &CallersCaller);
  97. DbgPrint("\nDFS: BugCheck in %s, line %u (%s)\n", pszfile, line, pszmsg);
  98. KeBugCheckEx(DFS_FILE_SYSTEM, (ULONG_PTR)CallersAddress, (ULONG_PTR)pszmsg,
  99. (ULONG_PTR)pszfile, line);
  100. }
  101. #else // DBG
  102. VOID DfsBugCheck(VOID)
  103. {
  104. PVOID CallersAddress, CallersCaller;
  105. RtlGetCallersAddress(&CallersAddress, &CallersCaller);
  106. KeBugCheckEx(DFS_FILE_SYSTEM, (ULONG_PTR)CallersAddress, (ULONG_PTR)CallersCaller,
  107. 0, 0);
  108. }
  109. #endif // DBG
  110. //+----------------------------------------------------------------------------
  111. //
  112. // Function: FillDebugException
  113. //
  114. // Synopsis: Captures the exception record into variables that we can
  115. // look at.
  116. //
  117. // Arguments: [pep] -- Pointer to exception record.
  118. //
  119. // Returns: Nothing
  120. //
  121. //-----------------------------------------------------------------------------
  122. #define CEXCEPTION_STACK 8
  123. PEXCEPTION_RECORD DfsExceptionRecord;
  124. PCONTEXT DfsExceptionContext;
  125. ULONG DfsExceptionStack[CEXCEPTION_STACK];
  126. VOID
  127. FillDebugException(
  128. PEXCEPTION_POINTERS pep)
  129. {
  130. if(pep != NULL) {
  131. DfsExceptionRecord = pep->ExceptionRecord;
  132. DfsExceptionContext = pep->ContextRecord;
  133. }
  134. }
  135. //+-------------------------------------------------------------------
  136. //
  137. // Function: DfsExceptionFilter
  138. //
  139. // Synopsis: Decide if we should or should not handle an exception status
  140. // that is being raised. Insert the status into the IrpContext
  141. // and either indicate that we should handle the exception or
  142. // BugCheck the system.
  143. //
  144. // Arguments: [IrpContext] -- IRP context for the request being processed.
  145. // [ExceptionCode] -- Supplies the exception code to being checked.
  146. //
  147. // Returns: ULONG - returns EXCEPTION_EXECUTE_HANDLER or BugChecks
  148. //
  149. //--------------------------------------------------------------------
  150. LONG
  151. DfsExceptionFilter (
  152. IN PIRP_CONTEXT IrpContext OPTIONAL,
  153. IN NTSTATUS ExceptionCode,
  154. IN PEXCEPTION_POINTERS ExceptionPointers OPTIONAL
  155. ) {
  156. DfsDbgTrace(
  157. 0, DEBUG_TRACE_UNWIND, "DfsExceptionFilter %lx\n", ULongToPtr(ExceptionCode) );
  158. FillDebugException( ExceptionPointers );
  159. ASSERT(ExceptionCode != STATUS_ACCESS_VIOLATION);
  160. ASSERTMSG(
  161. "DfsExceptionFilter entered\n",
  162. !(DfsDebugTraceLevel & DEBUG_TRACE_UNWIND));
  163. //
  164. // If there is not an irp context, we must have had insufficient resources.
  165. //
  166. if (!ARGUMENT_PRESENT( IrpContext )) {
  167. ASSERT( ExceptionCode == STATUS_INSUFFICIENT_RESOURCES );
  168. return EXCEPTION_EXECUTE_HANDLER;
  169. }
  170. IrpContext->Flags |= IRP_CONTEXT_FLAG_WAIT;
  171. if (IrpContext->ExceptionStatus == 0) {
  172. if (FsRtlIsNtstatusExpected( ExceptionCode )) {
  173. IrpContext->ExceptionStatus = ExceptionCode;
  174. } else {
  175. BugCheck( "DfsExceptionFilter: Unexpected exception" );
  176. }
  177. } else {
  178. //
  179. // We raised this code explicitly ourselves, so it had better be
  180. // expected.
  181. //
  182. ASSERT( FsRtlIsNtstatusExpected( ExceptionCode ) );
  183. }
  184. return EXCEPTION_EXECUTE_HANDLER;
  185. }
  186. //+-------------------------------------------------------------------
  187. //
  188. // Function: DfsProcessException, public
  189. //
  190. // Synopsis: This routine processes an exception. It either completes
  191. // the request with the saved exception status or it sends
  192. // the request off to the Fsp.
  193. //
  194. // Arguments: [Irp] -- Supplies the IRP being processed
  195. // [ExceptionCode] -- normalized exception status being handled
  196. //
  197. // Returns: NTSTATUS - Returns the results of either posting the Irp or the
  198. // saved completion status.
  199. //
  200. //--------------------------------------------------------------------
  201. NTSTATUS
  202. DfsProcessException (
  203. IN PIRP_CONTEXT IrpContext,
  204. IN PIRP Irp,
  205. IN NTSTATUS ExceptionCode
  206. )
  207. {
  208. NTSTATUS Status;
  209. DfsDbgTrace(0, Dbg, "DfsProcessException\n", 0);
  210. //
  211. // If there is not an irp context, we must have had insufficient resources.
  212. //
  213. if (!ARGUMENT_PRESENT( IrpContext )) {
  214. ASSERT( ExceptionCode == STATUS_INSUFFICIENT_RESOURCES );
  215. DfsCompleteRequest( IrpContext, Irp, ExceptionCode );
  216. return ExceptionCode;
  217. }
  218. //
  219. // Check if the status is verify required and if so then we
  220. // either send the request off to the fsp or we complete
  221. // the request with verify required.
  222. //
  223. if (ExceptionCode == STATUS_CANT_WAIT) {
  224. Status = DfsFsdPostRequest( IrpContext, Irp );
  225. } else {
  226. //
  227. // We got an error, so zero out the information field before
  228. // completing the request if this was an input operation.
  229. // Otherwise IopCompleteRequest will try to copy to the user's buffer.
  230. //
  231. if ((Irp->Flags & IRP_INPUT_OPERATION) != 0) {
  232. Irp->IoStatus.Information = 0;
  233. }
  234. Status = IrpContext->ExceptionStatus;
  235. DfsCompleteRequest( IrpContext, Irp, Status );
  236. }
  237. return Status;
  238. }
  239. //+-------------------------------------------------------------------
  240. //
  241. // Function: DfsCompleteRequest, public
  242. //
  243. // Synopsis: This routine completes a Irp
  244. //
  245. // Arguments: [IrpContext] - context record to be freed
  246. // [Irp] - Supplies the Irp being processed
  247. // [Status] - Supplies the status to complete the Irp with
  248. //
  249. // Returns: None.
  250. //
  251. //--------------------------------------------------------------------
  252. VOID
  253. DfsCompleteRequest_Real (
  254. IN PIRP_CONTEXT IrpContext OPTIONAL,
  255. IN PIRP Irp OPTIONAL,
  256. IN NTSTATUS Status
  257. ) {
  258. KIRQL PreviousIrql;
  259. //
  260. // If we have an Irp then complete the irp.
  261. //
  262. if (Irp != NULL) {
  263. Irp->IoStatus.Status = Status;
  264. // KeRaiseIrql( DISPATCH_LEVEL, &PreviousIrql );
  265. IoCompleteRequest( Irp, IO_DISK_INCREMENT );
  266. // KeLowerIrql( PreviousIrql );
  267. }
  268. //
  269. // Delete the Irp context.
  270. //
  271. if (IrpContext != NULL) {
  272. DfsDeleteIrpContext( IrpContext );
  273. }
  274. return;
  275. }