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.

414 lines
9.6 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. fscontrl.c
  5. Abstract:
  6. This module implements the file system control routines for the MUP
  7. called by the dispatch driver.
  8. Author:
  9. Manny Weiser (mannyw) 26-Dec-1991
  10. Revision History:
  11. --*/
  12. #include "mup.h"
  13. //
  14. // The debug trace level
  15. //
  16. #define Dbg (DEBUG_TRACE_FSCONTROL)
  17. //
  18. // local procedure prototypes
  19. //
  20. NTSTATUS
  21. RegisterUncProvider (
  22. IN PMUP_DEVICE_OBJECT MupDeviceObject,
  23. IN PIRP Irp
  24. );
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text( PAGE, MupFsControl )
  27. #pragma alloc_text( PAGE, RegisterUncProvider )
  28. #endif
  29. NTSTATUS
  30. MupFsControl (
  31. IN PMUP_DEVICE_OBJECT MupDeviceObject,
  32. IN PIRP Irp
  33. )
  34. /*++
  35. Routine Description:
  36. This routine implements the the File System Control IRP.
  37. Arguments:
  38. MupDeviceObject - Supplies the device object to use.
  39. Irp - Supplies the Irp being processed
  40. Return Value:
  41. NTSTATUS - The status for the Irp
  42. --*/
  43. {
  44. NTSTATUS status;
  45. PIO_STACK_LOCATION irpSp;
  46. PFILE_OBJECT FileObject;
  47. PAGED_CODE();
  48. irpSp = IoGetCurrentIrpStackLocation( Irp );
  49. FileObject = irpSp->FileObject;
  50. DebugTrace(+1, Dbg, "MupFsControl\n", 0);
  51. MUP_TRACE_HIGH(TRACE_IRP, MupFsControl_Entry,
  52. LOGPTR(MupDeviceObject)
  53. LOGPTR(Irp)
  54. LOGPTR(FileObject));
  55. //
  56. // Reference our input parameters to make things easier
  57. //
  58. DebugTrace(+1, Dbg, "MupFileSystemControl\n", 0);
  59. DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp);
  60. DebugTrace( 0, Dbg, "OutputBufferLength = %08lx\n", irpSp->Parameters.FileSystemControl.OutputBufferLength);
  61. DebugTrace( 0, Dbg, "InputBufferLength = %08lx\n", irpSp->Parameters.FileSystemControl.InputBufferLength);
  62. DebugTrace( 0, Dbg, "FsControlCode = %08lx\n", irpSp->Parameters.FileSystemControl.FsControlCode);
  63. try {
  64. //
  65. // Decide how to handle this IRP. Call the appropriate worker function.
  66. //
  67. switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
  68. case FSCTL_MUP_REGISTER_UNC_PROVIDER:
  69. if( Irp->RequestorMode != KernelMode ) {
  70. status = STATUS_ACCESS_DENIED;
  71. MupCompleteRequest(Irp, STATUS_ACCESS_DENIED);
  72. return STATUS_ACCESS_DENIED;
  73. }
  74. status = RegisterUncProvider( MupDeviceObject, Irp );
  75. break;
  76. default:
  77. if (MupEnableDfs) {
  78. status = DfsFsdFileSystemControl(
  79. (PDEVICE_OBJECT) MupDeviceObject,
  80. Irp);
  81. } else {
  82. status = STATUS_INVALID_PARAMETER;
  83. MupCompleteRequest(Irp, STATUS_INVALID_PARAMETER);
  84. }
  85. }
  86. } except ( EXCEPTION_EXECUTE_HANDLER ) {
  87. NOTHING;
  88. }
  89. //
  90. // Return to the caller.
  91. //
  92. MUP_TRACE_HIGH(TRACE_IRP, MupFsControl_Exit,
  93. LOGSTATUS(status)
  94. LOGPTR(MupDeviceObject)
  95. LOGPTR(FileObject)
  96. LOGPTR(Irp));
  97. DebugTrace(-1, Dbg, "MupFsControl -> %08lx\n", status);
  98. return status;
  99. }
  100. NTSTATUS
  101. RegisterUncProvider (
  102. IN PMUP_DEVICE_OBJECT MupDeviceObject,
  103. IN PIRP Irp
  104. )
  105. /*++
  106. Routine Description:
  107. This function handles registration of a UNC provider. The provider
  108. is added to the list of available providers.
  109. Arguments:
  110. MupDeviceObject - A pointer to the file system device object.
  111. Irp - Supplies the Irp to process
  112. Return Value:
  113. NTSTATUS - the return status for the operation
  114. --*/
  115. {
  116. NTSTATUS status;
  117. PVCB vcb;
  118. PVOID fsContext2;
  119. PIO_STACK_LOCATION irpSp;
  120. PREDIRECTOR_REGISTRATION paramBuffer;
  121. ULONG paramLength;
  122. BLOCK_TYPE blockType;
  123. PUNC_PROVIDER uncProvider = NULL;
  124. PUNC_PROVIDER provider;
  125. PLIST_ENTRY listEntry;
  126. PVOID dataBuffer;
  127. OBJECT_ATTRIBUTES objectAttributes;
  128. IO_STATUS_BLOCK ioStatusBlock;
  129. OBJECT_HANDLE_INFORMATION handleInformation;
  130. BOOLEAN InsertInProviderList = FALSE;
  131. MupDeviceObject;
  132. PAGED_CODE();
  133. irpSp = IoGetCurrentIrpStackLocation( Irp );
  134. DebugTrace(+1, Dbg, "RegisterUncProvider\n", 0);
  135. //
  136. // Get MUP ordering information, if we haven't already.
  137. //
  138. MupAcquireGlobalLock();
  139. if ( !MupOrderInitialized ) {
  140. MupOrderInitialized = TRUE;
  141. MupReleaseGlobalLock();
  142. MupGetProviderInformation();
  143. } else {
  144. MupReleaseGlobalLock();
  145. }
  146. //
  147. // Make local copies of the input parameters to make things easier.
  148. //
  149. paramLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  150. paramBuffer = Irp->AssociatedIrp.SystemBuffer;
  151. //
  152. // Decode the file object. If it is the file system VCB, it will be
  153. // referenced.
  154. //
  155. blockType = MupDecodeFileObject(
  156. irpSp->FileObject,
  157. (PVOID *)&vcb,
  158. &fsContext2
  159. );
  160. if ( blockType != BlockTypeVcb ) {
  161. DebugTrace(0, Dbg, "File is disconnected from us\n", 0);
  162. MupCompleteRequest( Irp, STATUS_INVALID_HANDLE );
  163. status = STATUS_INVALID_HANDLE;
  164. DebugTrace(-1, Dbg, "RegisterUncProvider -> %08lx\n", status );
  165. return status;
  166. }
  167. try {
  168. UNICODE_STRING deviceName;
  169. deviceName.Length = (USHORT)paramBuffer->DeviceNameLength;
  170. deviceName.MaximumLength = (USHORT)paramBuffer->DeviceNameLength;
  171. deviceName.Buffer = (PWCH)((PCHAR)paramBuffer + paramBuffer->DeviceNameOffset);
  172. //
  173. // Do the work
  174. //
  175. uncProvider = MupCheckForUnregisteredProvider( &deviceName );
  176. if ( uncProvider == NULL) {
  177. InsertInProviderList = TRUE;
  178. uncProvider = MupAllocateUncProvider(
  179. paramBuffer->DeviceNameLength);
  180. if (uncProvider != NULL) {
  181. //
  182. // Copy the data from the IRP.
  183. //
  184. dataBuffer = uncProvider + 1;
  185. uncProvider->DeviceName = deviceName;
  186. uncProvider->DeviceName.Buffer = dataBuffer;
  187. uncProvider->Priority = 0x7FFFFFFF;
  188. RtlMoveMemory(
  189. uncProvider->DeviceName.Buffer,
  190. (PCHAR)paramBuffer + paramBuffer->DeviceNameOffset,
  191. paramBuffer->DeviceNameLength);
  192. } else {
  193. status = STATUS_INVALID_USER_BUFFER;
  194. try_return( NOTHING );
  195. }
  196. }
  197. dataBuffer = (PCHAR)dataBuffer + uncProvider->DeviceName.MaximumLength;
  198. uncProvider->MailslotsSupported = paramBuffer->MailslotsSupported;
  199. //
  200. // Reference the unc provider
  201. //
  202. MupReferenceBlock( uncProvider );
  203. //
  204. // Get a handle to the provider.
  205. //
  206. InitializeObjectAttributes(
  207. &objectAttributes,
  208. &uncProvider->DeviceName,
  209. OBJ_CASE_INSENSITIVE, // Attributes
  210. 0, // Root Directory
  211. NULL // Security
  212. );
  213. status = NtOpenFile(
  214. &uncProvider->Handle,
  215. FILE_TRAVERSE,
  216. &objectAttributes,
  217. &ioStatusBlock,
  218. FILE_SHARE_READ | FILE_SHARE_WRITE,
  219. FILE_DIRECTORY_FILE
  220. );
  221. if ( NT_SUCCESS( status ) ) {
  222. status = ioStatusBlock.Status;
  223. }
  224. if ( NT_SUCCESS( status ) ) {
  225. //
  226. // Use the file object, to keep a pointer to the uncProvider
  227. //
  228. irpSp->FileObject->FsContext2 = uncProvider;
  229. //
  230. // 426184, need to check return code for errors.
  231. //
  232. status = ObReferenceObjectByHandle(
  233. uncProvider->Handle,
  234. 0,
  235. NULL,
  236. KernelMode,
  237. (PVOID *)&uncProvider->FileObject,
  238. &handleInformation
  239. );
  240. if (!NT_SUCCESS( status)) {
  241. NtClose(uncProvider->Handle);
  242. }
  243. }
  244. if ( !NT_SUCCESS( status ) ) {
  245. MupDereferenceUncProvider(uncProvider);
  246. }
  247. else {
  248. uncProvider->DeviceObject = IoGetRelatedDeviceObject(
  249. uncProvider->FileObject
  250. );
  251. MupAcquireGlobalLock();
  252. MupProviderCount++;
  253. if(InsertInProviderList) {
  254. //
  255. // We need to make sure we put the providers in the list in order of priority.
  256. //
  257. listEntry = MupProviderList.Flink;
  258. while ( listEntry != &MupProviderList ) {
  259. provider = CONTAINING_RECORD(
  260. listEntry,
  261. UNC_PROVIDER,
  262. ListEntry
  263. );
  264. if( uncProvider->Priority < provider->Priority ) {
  265. break;
  266. }
  267. listEntry = listEntry->Flink;
  268. }
  269. InsertTailList(listEntry, &uncProvider->ListEntry);
  270. }
  271. uncProvider->Registered = TRUE;
  272. MupReleaseGlobalLock();
  273. //
  274. // !!! What do we do with the handle? It is useless.
  275. //
  276. //
  277. // Finish up the fs control IRP.
  278. //
  279. status = STATUS_SUCCESS;
  280. }
  281. try_exit: NOTHING;
  282. } finally {
  283. if ( AbnormalTermination() ) {
  284. status = STATUS_INVALID_USER_BUFFER;
  285. }
  286. //
  287. // Release the reference to the VCB.
  288. //
  289. MupDereferenceVcb( vcb );
  290. DebugTrace(-1, Dbg, "MupRegisterUncProvider -> %08lx\n", status);
  291. }
  292. MupCompleteRequest( Irp, status );
  293. return status;
  294. }