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.

300 lines
8.1 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. InnerIo.c
  5. Abstract:
  6. This module implements the routines that handle the Query and Set File
  7. Information IRPs that are sent to the kernel.
  8. Author:
  9. Rohan Kumar [RohanK] 10-October-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "webdav.h"
  15. #ifdef ALLOC_PRAGMA
  16. #pragma alloc_text(PAGE, DavXxxInformation)
  17. #endif
  18. //
  19. // The IrpCompletionContext structure that is used in the Query and Set File
  20. // Information operations. All we need is an event on which we will wait till
  21. // the underlying file system completes the request. This event gets signalled
  22. // in the Completion routine that we specify.
  23. //
  24. typedef struct _DAV_IRPCOMPLETION_CONTEXT {
  25. //
  26. // The event which is signalled in the Completion routine that is passed
  27. // to IoCallDriver in the Query and Set File Information requests.
  28. //
  29. KEVENT Event;
  30. } DAV_IRPCOMPLETION_CONTEXT, *PDAV_IRPCOMPLETION_CONTEXT;
  31. NTSTATUS
  32. DavIrpCompletionRoutine(
  33. IN PDEVICE_OBJECT DeviceObject,
  34. IN PIRP CalldownIrp,
  35. IN PVOID Context
  36. );
  37. //
  38. // Implementation of functions begins here.
  39. //
  40. NTSTATUS
  41. DavIrpCompletionRoutine(
  42. IN PDEVICE_OBJECT DeviceObject,
  43. IN PIRP CalldownIrp,
  44. IN PVOID Context
  45. )
  46. /*++
  47. Routine Description:
  48. This routine is called when the Query and Set File Information IRP that was
  49. sent to the underlying file system is completed.
  50. Arguments:
  51. DeviceObject - The WebDav Device object.
  52. CalldownIrp - The IRP that was created and sent to the underlying file
  53. system.
  54. Context - The context that was set in the IoSetCompletionRoutine function.
  55. Return Value:
  56. STATUS_MORE_PROCESSING_REQUIRED
  57. --*/
  58. {
  59. PDAV_IRPCOMPLETION_CONTEXT IrpCompletionContext = NULL;
  60. //
  61. // This is not Pageable code.
  62. //
  63. IrpCompletionContext = (PDAV_IRPCOMPLETION_CONTEXT)Context;
  64. //
  65. // If the IoCallDriver routine returned pending then it will be set in the
  66. // IRP's PendingReturned field. In this case we need to set the event on
  67. // which the thread which issued IoCallDriver will be waiting.
  68. //
  69. if (CalldownIrp->PendingReturned){
  70. KeSetEvent( &(IrpCompletionContext->Event), 0, FALSE );
  71. }
  72. return(STATUS_MORE_PROCESSING_REQUIRED);
  73. }
  74. NTSTATUS
  75. DavXxxInformation(
  76. IN const int xMajorFunction,
  77. IN PFILE_OBJECT FileObject,
  78. IN ULONG InformationClass,
  79. IN ULONG Length,
  80. OUT PVOID Information,
  81. OUT PULONG ReturnedLength
  82. )
  83. /*++
  84. Routine Description:
  85. This routine returns the requested information about a specified file
  86. or volume. The information returned is determined by the class that
  87. is specified, and it is placed into the caller's output buffer.
  88. Arguments:
  89. xMajorFunction - The Major Function (Query or Set File Information).
  90. FileObject - Supplies a pointer to the file object about which the
  91. requested information is returned.
  92. InformationClass - Specifies the type of information which should be
  93. returned about the file/volume.
  94. Length - Supplies the length of the buffer in bytes.
  95. Information - Supplies a buffer to receive the requested information
  96. returned about the file. This buffer must not be pageable
  97. and must reside in system space.
  98. ReturnedLength - Supplies a variable that is to receive the length of the
  99. information written to the buffer.
  100. Return Value:
  101. The status returned is the final completion status of the operation.
  102. --*/
  103. {
  104. NTSTATUS NtStatus = STATUS_SUCCESS;
  105. PIRP Irp = NULL, TopIrp = NULL;
  106. PIO_STACK_LOCATION IrpSp = NULL;
  107. PDEVICE_OBJECT DeviceObject = NULL;
  108. DAV_IRPCOMPLETION_CONTEXT IrpCompletionContext;
  109. ULONG DummyReturnedLength = 0;
  110. PAGED_CODE();
  111. if (ReturnedLength == NULL) {
  112. ReturnedLength = &(DummyReturnedLength);
  113. }
  114. DeviceObject = IoGetRelatedDeviceObject(FileObject);
  115. //
  116. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  117. // The allocation is performed with an exception handler in case the
  118. // caller does not have enough quota to allocate the packet.
  119. //
  120. Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
  121. if (Irp == NULL) {
  122. DavDbgTrace(DAV_TRACE_ERROR,
  123. ("%ld: DavXxxInformation/IoAllocateIrp\n",
  124. PsGetCurrentThreadId()));
  125. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  126. goto EXIT_THE_FUNCTION;
  127. }
  128. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  129. Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  130. Irp->RequestorMode = KernelMode;
  131. //
  132. // Get a pointer to the stack location for the first driver. This will be
  133. // used to pass the original function codes and parameters.
  134. //
  135. IrpSp = IoGetNextIrpStackLocation(Irp);
  136. IrpSp->MajorFunction = (UCHAR)xMajorFunction;
  137. IrpSp->FileObject = FileObject;
  138. //
  139. // Set the completion routine to be called everytime.
  140. //
  141. IoSetCompletionRoutine(Irp,
  142. DavIrpCompletionRoutine,
  143. &(IrpCompletionContext),
  144. TRUE,
  145. TRUE,
  146. TRUE);
  147. Irp->AssociatedIrp.SystemBuffer = Information;
  148. IF_DEBUG {
  149. ASSERT( (IrpSp->MajorFunction == IRP_MJ_QUERY_INFORMATION) ||
  150. (IrpSp->MajorFunction == IRP_MJ_SET_INFORMATION) ||
  151. (IrpSp->MajorFunction == IRP_MJ_QUERY_VOLUME_INFORMATION) );
  152. if (IrpSp->MajorFunction == IRP_MJ_SET_INFORMATION) {
  153. ASSERT( (InformationClass == FileAllocationInformation) || (InformationClass == FileEndOfFileInformation) );
  154. }
  155. ASSERT( &(IrpSp->Parameters.QueryFile.Length) == &(IrpSp->Parameters.SetFile.Length) );
  156. ASSERT( &(IrpSp->Parameters.QueryFile.Length) == &(IrpSp->Parameters.QueryVolume.Length) );
  157. ASSERT( &(IrpSp->Parameters.QueryFile.FileInformationClass) == &(IrpSp->Parameters.SetFile.FileInformationClass) );
  158. ASSERT( (PVOID)&(IrpSp->Parameters.QueryFile.FileInformationClass) == (PVOID)&(IrpSp->Parameters.QueryVolume.FsInformationClass) );
  159. }
  160. IrpSp->Parameters.QueryFile.Length = Length;
  161. IrpSp->Parameters.QueryFile.FileInformationClass = InformationClass;
  162. //
  163. // Initialize the event on which we will wait after we call IoCallDriver.
  164. // This event will be signalled in the Completion routine which will be
  165. // called by the underlying file system after it completes the operation.
  166. //
  167. KeInitializeEvent(&(IrpCompletionContext.Event),
  168. NotificationEvent,
  169. FALSE);
  170. //
  171. // Now is the time to call the underlying file system with the Irp that we
  172. // just created.
  173. //
  174. try {
  175. //
  176. // Save the TopLevel Irp.
  177. //
  178. TopIrp = IoGetTopLevelIrp();
  179. //
  180. // Tell the underlying guy he's all clear.
  181. //
  182. IoSetTopLevelIrp(NULL);
  183. //
  184. // Finally, call the underlying file system to process the request.
  185. //
  186. NtStatus = IoCallDriver(DeviceObject, Irp);
  187. } finally {
  188. //
  189. // Restore my context for unwind.
  190. //
  191. IoSetTopLevelIrp(TopIrp);
  192. }
  193. if (NtStatus == STATUS_PENDING) {
  194. //
  195. // If STATUS_PENDING was returned by the underlying file system then we
  196. // wait here till the operation gets completed.
  197. //
  198. KeWaitForSingleObject(&(IrpCompletionContext.Event),
  199. Executive,
  200. KernelMode,
  201. FALSE,
  202. NULL);
  203. NtStatus = Irp->IoStatus.Status;
  204. }
  205. if (NtStatus == STATUS_SUCCESS) {
  206. *ReturnedLength = (ULONG)Irp->IoStatus.Information;
  207. }
  208. EXIT_THE_FUNCTION:
  209. if (Irp != NULL) {
  210. IoFreeIrp(Irp);
  211. }
  212. return(NtStatus);
  213. }