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.

1159 lines
34 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1992, Microsoft Corporation.
  4. //
  5. // File: attach.c
  6. //
  7. // Contents: This module contains routines for managing attached file
  8. // systems.
  9. //
  10. // Functions:
  11. //
  12. //-----------------------------------------------------------------------------
  13. #include "dfsprocs.h"
  14. #include "attach.h"
  15. #include "dfswml.h"
  16. #define Dbg (DEBUG_TRACE_ATTACH)
  17. NTSTATUS
  18. DfsReferenceVdoByFileName(
  19. IN PUNICODE_STRING TargetName,
  20. OUT PDEVICE_OBJECT *DeviceObject,
  21. OUT PDEVICE_OBJECT *RealDeviceObject,
  22. OUT PULONG DevObjNameLen OPTIONAL
  23. );
  24. VOID
  25. DfsAttachToFileSystem(
  26. IN PDEVICE_OBJECT FileSystemObject);
  27. VOID
  28. DfsDetachFromFileSystem(
  29. IN PDEVICE_OBJECT FileSystemObject);
  30. PDEVICE_OBJECT
  31. DfsGetDfsFilterDeviceObject(
  32. IN PFILE_OBJECT targetFile);
  33. #ifdef ALLOC_PRAGMA
  34. #pragma alloc_text( PAGE, DfsReferenceVdoByFileName )
  35. #pragma alloc_text( PAGE, DfsGetAttachName )
  36. #pragma alloc_text( PAGE, DfsSetupVdo)
  37. #pragma alloc_text( PAGE, DfsAttachVolume )
  38. #pragma alloc_text( PAGE, DfsDetachVolume )
  39. #pragma alloc_text( PAGE, DfsGetDfsFilterDeviceObject)
  40. //
  41. // The following are not pageable since they can be called at DPC level
  42. //
  43. // DfsVolumePassThrough
  44. //
  45. #endif // ALLOC_PRAGMA
  46. //
  47. // Generator value for local provider IDs.
  48. //
  49. static USHORT LocalProviderID = 0xF000;
  50. //+-------------------------------------------------------------------------
  51. //
  52. // Function: DfsReferenceVdoByFileName, private
  53. //
  54. // Synopsis: Given a file path name, this function will return a pointer
  55. // to its corresponding volume device object.
  56. //
  57. // Arguments: [TargetName] -- File path name of the root directory of the
  58. // local volume.
  59. // [DeviceObject] -- Upon successful return, contains a
  60. // referenced pointer to the first attached device
  61. // object for the file.
  62. // [RealDeviceObject] -- Upon successful return, contains a
  63. // non-referenced pointer to the real device object
  64. // for the file.
  65. // [DevObjNameLen] -- An optional argument, which if present,
  66. // gives the length (in bytes) of the path to the
  67. // returned device object.
  68. //
  69. // Returns: NTSTATUS -- STATUS_SUCCESS if successful. Otherwise, the
  70. // status returned by the file open attempt.
  71. //
  72. // Notes: This could return a pointer to a DFS volume object if one
  73. // has already been attached.
  74. //
  75. // ObDereferenceObject must be called on the returned
  76. // DeviceObject
  77. //
  78. //--------------------------------------------------------------------------
  79. NTSTATUS
  80. DfsReferenceVdoByFileName(
  81. IN PUNICODE_STRING TargetName,
  82. OUT PDEVICE_OBJECT *DeviceObject,
  83. OUT PDEVICE_OBJECT *RealDeviceObject,
  84. OUT PULONG DevObjNameLen OPTIONAL
  85. )
  86. {
  87. NTSTATUS Status;
  88. UNICODE_STRING fileName;
  89. OBJECT_ATTRIBUTES objectAttributes;
  90. IO_STATUS_BLOCK ioStatusBlock;
  91. HANDLE targetFileHandle = NULL;
  92. OBJECT_HANDLE_INFORMATION handleInformation;
  93. PFILE_OBJECT targetFileObject;
  94. DebugTrace(+1, Dbg, "DfsReferenceVdoByFileName: Entered\n", 0);
  95. //
  96. // Make sure what we have is indeed a file name, and not a device name!
  97. //
  98. if (TargetName->Buffer[ TargetName->Length/sizeof(WCHAR) - 1 ] ==
  99. UNICODE_DRIVE_SEP) {
  100. fileName.Length = 0;
  101. fileName.MaximumLength = TargetName->Length + 2 * sizeof(WCHAR);
  102. fileName.Buffer = ExAllocatePoolWithTag(PagedPool, fileName.MaximumLength, ' sfD');
  103. if (fileName.Buffer == NULL) {
  104. DebugTrace(0, Dbg,
  105. "Unable to allocate %d bytes\n", fileName.MaximumLength);
  106. Status = STATUS_INSUFFICIENT_RESOURCES;
  107. } else {
  108. RtlCopyUnicodeString(&fileName, TargetName);
  109. RtlAppendUnicodeToString(
  110. &fileName,
  111. (LPWSTR) UNICODE_PATH_SEP_STR);
  112. Status = STATUS_SUCCESS;
  113. }
  114. } else {
  115. fileName = *TargetName;
  116. Status = STATUS_SUCCESS;
  117. }
  118. if (NT_SUCCESS(Status)) {
  119. //
  120. // create the object attribtues argument
  121. //
  122. InitializeObjectAttributes(
  123. &objectAttributes,
  124. &fileName,
  125. OBJ_CASE_INSENSITIVE,
  126. NULL,
  127. NULL);
  128. DebugTrace(0,Dbg, "DfsReferenceVdoByFileName: Attempting to open file [%wZ]\n", &fileName );
  129. //
  130. // Open the root of the volume
  131. //
  132. Status = ZwOpenFile(&targetFileHandle,
  133. FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY,
  134. &objectAttributes,
  135. &ioStatusBlock,
  136. FILE_SHARE_READ,
  137. FILE_DIRECTORY_FILE);
  138. }
  139. //
  140. // if we have successfully opened the file then we begin the
  141. // task of getting a reference to the file object itself.
  142. //
  143. if (NT_SUCCESS(Status)) {
  144. DebugTrace(0,Dbg,
  145. "DfsReferenceVdoByFileName: Attempting get file object \n", 0);
  146. Status = ObReferenceObjectByHandle(
  147. targetFileHandle,
  148. 0,
  149. NULL,
  150. KernelMode,
  151. (PVOID *)&targetFileObject,
  152. &handleInformation);
  153. //
  154. // if we have successfully obtained a reference to the file object
  155. // we can now begin the task of getting the related device object.
  156. //
  157. if (NT_SUCCESS(Status)) {
  158. *DeviceObject = DfsGetDfsFilterDeviceObject(targetFileObject);
  159. if (*DeviceObject == NULL) {
  160. *DeviceObject = IoGetRelatedDeviceObject(targetFileObject);
  161. }
  162. *RealDeviceObject = targetFileObject->Vpb->RealDevice;
  163. Status = ObReferenceObjectByPointer(
  164. *DeviceObject,
  165. 0,
  166. NULL,
  167. KernelMode);
  168. if (NT_SUCCESS(Status) && ARGUMENT_PRESENT(DevObjNameLen)) {
  169. ASSERT(
  170. fileName.Length > targetFileObject->FileName.Length);
  171. *DevObjNameLen = fileName.Length -
  172. targetFileObject->FileName.Length;
  173. }
  174. ObDereferenceObject(targetFileObject);
  175. DebugTrace( 0, Dbg, "Referenced Vdo [%08lx]\n", *DeviceObject);
  176. DebugTrace( 0, Dbg, "Real Device Object [%08lx]\n",
  177. *RealDeviceObject);
  178. }
  179. ZwClose(targetFileHandle);
  180. }
  181. if (fileName.Buffer != NULL && fileName.Buffer != TargetName->Buffer) {
  182. ExFreePool( fileName.Buffer );
  183. }
  184. DebugTrace(-1,Dbg, "DfsReferenceVdoByFileName: Exit -> %08lx\n", ULongToPtr( Status ) );
  185. return Status;
  186. }
  187. //+-------------------------------------------------------------------------
  188. //
  189. // Function: DfsGetAttachName, public
  190. //
  191. // Synopsis: A DFS local volume storage ID is parsed into the portion
  192. // which refers to a volume device object, and the portion
  193. // which refers to the volume-relative path to the root of
  194. // the local volume storageID.
  195. //
  196. // Arguments: [LocalVolumeStorageId] -- file path name of the root of
  197. // the local DFS volume.
  198. // [LocalVolumeRelativeName] -- the name of LocalVolumeStorageId
  199. // relative to the volume object name. This
  200. // includes a leading \.
  201. //
  202. // Returns: Status from DfsReferenceVdoByFileName()
  203. //
  204. // Notes: The returned string is a pointer into the input string.
  205. // The string storage should be duplicated as needed.
  206. //
  207. //--------------------------------------------------------------------------
  208. NTSTATUS
  209. DfsGetAttachName(
  210. IN PUNICODE_STRING LocalVolumeStorageId,
  211. OUT PUNICODE_STRING LocalVolumeRelativeName
  212. )
  213. {
  214. NTSTATUS Status;
  215. PDEVICE_OBJECT targetVdo, realDevice;
  216. ULONG volNameLen;
  217. DebugTrace(+1, Dbg, "DfsGetAttachName: Entered\n", 0);
  218. //
  219. // Get our hands on the volume object
  220. //
  221. DebugTrace(0, Dbg,
  222. "DfsGetAttachName: Attempting to reference volume\n", 0);
  223. Status = DfsReferenceVdoByFileName(
  224. LocalVolumeStorageId,
  225. &targetVdo,
  226. &realDevice,
  227. &volNameLen);
  228. if (NT_SUCCESS(Status)) {
  229. *LocalVolumeRelativeName = *LocalVolumeStorageId;
  230. if (LocalVolumeRelativeName->Length -= (USHORT)volNameLen) {
  231. LocalVolumeRelativeName->Buffer =
  232. (PWCHAR)((PCHAR)LocalVolumeRelativeName->Buffer + volNameLen);
  233. ASSERT (LocalVolumeRelativeName->Buffer[0] == UNICODE_PATH_SEP);
  234. LocalVolumeRelativeName->MaximumLength -=
  235. LocalVolumeStorageId->Length - LocalVolumeRelativeName->Length;
  236. } else {
  237. LocalVolumeRelativeName->Buffer = NULL;
  238. LocalVolumeRelativeName->MaximumLength = 0;
  239. }
  240. ObDereferenceObject(targetVdo);
  241. }
  242. DebugTrace(-1,Dbg, "DfsGetAttachName: Exit -> %08lx\n", ULongToPtr( Status ) );
  243. return Status;
  244. }
  245. //+-------------------------------------------------------------------------
  246. //
  247. // Function: DfsAttachVolume, public
  248. //
  249. // Synopsis: A DFS volume device object is attached to the volume
  250. // device object for some local file system, and a provider
  251. // definition is built for the local volume.
  252. //
  253. // Arguments: [RootName] -- file path name of the root of the local
  254. // volume.
  255. // [ppProvider] -- On successful return, contains a pointer
  256. // to a PROVIDER_DEF record that descibes the
  257. // attached device.
  258. //
  259. // Returns: [STATUS_INSUFFICIENT_RESOURCES] -- If unable to allocate
  260. // pool for provider name.
  261. //
  262. // Status from DfsSetupVdo()
  263. //
  264. //--------------------------------------------------------------------------
  265. NTSTATUS
  266. DfsAttachVolume(
  267. IN PUNICODE_STRING RootName,
  268. OUT PPROVIDER_DEF *ppProvider
  269. )
  270. {
  271. NTSTATUS Status;
  272. PDEVICE_OBJECT targetVdo, realDevice;
  273. PDFS_VOLUME_OBJECT dfsVdo = NULL;
  274. ULONG volNameLen;
  275. BOOLEAN fReferenced = FALSE;
  276. DebugTrace(+1, Dbg, "DfsAttachVolume: Entered\n", 0);
  277. Status = DfsReferenceVdoByFileName(
  278. RootName,
  279. &targetVdo,
  280. &realDevice,
  281. &volNameLen);
  282. if (NT_SUCCESS(Status)) {
  283. fReferenced = TRUE;
  284. if (targetVdo->DeviceType != FILE_DEVICE_DFS_VOLUME) {
  285. Status = DfsSetupVdo(RootName, targetVdo, realDevice, volNameLen, &dfsVdo);
  286. if (NT_SUCCESS(Status)) {
  287. InsertTailList(&DfsData.AVdoQueue, &dfsVdo->VdoLinks);
  288. dfsVdo->DfsEnable = TRUE;
  289. dfsVdo->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
  290. }
  291. } else {
  292. //
  293. // Upon dereferencing the volume device object, we found one
  294. // of our own Vdos. Just bump the reference count on it.
  295. //
  296. DebugTrace(0, Dbg,
  297. "DfsAttachVolume: Attaching multiple times to device %x\n",
  298. targetVdo);
  299. dfsVdo = (PDFS_VOLUME_OBJECT) targetVdo;
  300. dfsVdo->DfsEnable = TRUE;
  301. dfsVdo->AttachCount++;
  302. }
  303. }
  304. if (NT_SUCCESS(Status)) {
  305. *ppProvider = &dfsVdo->Provider;
  306. }
  307. if (fReferenced) {
  308. ObDereferenceObject(targetVdo);
  309. }
  310. DfspGetMaxReferrals();
  311. DebugTrace(-1,Dbg, "DfsAttachVolume: Exit -> %08lx\n", ULongToPtr( Status ) );
  312. return Status;
  313. }
  314. //+-------------------------------------------------------------------------
  315. //
  316. // Function: DfsDetachVolume, public
  317. //
  318. // Synopsis: The DFS volume device object referred to by the file
  319. // RootName is dereferenced. If it is the last reference,
  320. // the Vdo is detached from the device chain.
  321. //
  322. // Arguments: [RootName] -- file path name of the root of the local
  323. // volume.
  324. //
  325. // Returns: Status from DfsReferenceVdoByFileName
  326. //
  327. //--------------------------------------------------------------------------
  328. NTSTATUS
  329. DfsDetachVolume(
  330. IN PUNICODE_STRING RootName
  331. )
  332. {
  333. NTSTATUS Status;
  334. PDFS_VOLUME_OBJECT dfsVdo;
  335. PDEVICE_OBJECT realDevice;
  336. DebugTrace(+1, Dbg, "DfsDetachVolume: Entered\n", 0);
  337. //
  338. // Get our hands on the volume object
  339. //
  340. DebugTrace(0, Dbg, "DfsDetachVolume: Attempting to reference volume\n", 0);
  341. Status = DfsReferenceVdoByFileName(
  342. RootName,
  343. (PDEVICE_OBJECT *)&dfsVdo,
  344. &realDevice,
  345. NULL);
  346. if (NT_SUCCESS(Status)) {
  347. //
  348. // We should have our hands on one of our device objects
  349. //
  350. if ((dfsVdo->DeviceObject.DeviceType == FILE_DEVICE_DFS_VOLUME) &&
  351. (--dfsVdo->AttachCount == 0)) {
  352. //
  353. // Go ahead and detach the device
  354. //
  355. dfsVdo->DfsEnable = FALSE;
  356. }
  357. ObDereferenceObject(dfsVdo);
  358. }
  359. DebugTrace(-1,Dbg, "DfsDetachVolume: Exit -> %08lx\n", ULongToPtr( Status ) );
  360. return Status;
  361. }
  362. //+----------------------------------------------------------------------------
  363. //
  364. // Function: DfsDetachVolumeForDelete, public
  365. //
  366. // Synopsis: This routine does the work of detaching from a target
  367. // device object so that the target device object may be
  368. // deleted.
  369. //
  370. //
  371. // Arguments: [DfsVdo] -- The dfs attached device object.
  372. //
  373. // Returns:
  374. //
  375. //-----------------------------------------------------------------------------
  376. NTSTATUS
  377. DfsDetachVolumeForDelete(
  378. IN PDEVICE_OBJECT DeviceObject)
  379. {
  380. //
  381. // Acquire the Pkt exclusively so no one will access this Vdo while we
  382. // are detaching it.
  383. //
  384. if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {
  385. DfsDetachFromFileSystem( ((PDFS_ATTACH_FILE_SYSTEM_OBJECT) DeviceObject)->TargetDevice );
  386. } else {
  387. PDFS_PKT pkt;
  388. PDFS_VOLUME_OBJECT DfsVdo = (PDFS_VOLUME_OBJECT) DeviceObject;
  389. pkt = _GetPkt();
  390. PktAcquireExclusive( pkt, TRUE );
  391. //
  392. // Detach from the underlying FS...
  393. //
  394. IoDetachDevice(DfsVdo->Provider.DeviceObject);
  395. //
  396. // Flag our provider to be unavailable...
  397. //
  398. DfsVdo->Provider.fProvCapability |= PROV_UNAVAILABLE;
  399. PktRelease( pkt );
  400. }
  401. return( STATUS_SUCCESS );
  402. }
  403. //+----------------------------------------------------------------------------
  404. //
  405. // Function: DfsReattachToMountedVolume, public
  406. //
  407. // Synopsis: If one runs chkdsk, format etc on a volume that has been
  408. // attached to, the underlying file system will need to
  409. // unmount the volume. This will be handled by the
  410. // DfsDetachVolumeForDelete routine above. Ater the operation is
  411. // done, the volume will need to be remounted again. This
  412. // routine will reattach on the remount.
  413. //
  414. // Arguments: [TargetDevice] -- The Volume Device Object for the volume
  415. // that was just mounted.
  416. //
  417. // [Vpb] -- The Volume Parameter Block of the volume that was
  418. // just mounted.
  419. //
  420. // Returns:
  421. //
  422. //-----------------------------------------------------------------------------
  423. VOID
  424. DfsReattachToMountedVolume(
  425. IN PDEVICE_OBJECT TargetDevice,
  426. IN PVPB Vpb)
  427. {
  428. NTSTATUS Status;
  429. PDFS_PKT pkt;
  430. PUNICODE_PREFIX_TABLE_ENTRY lvPrefix;
  431. PDFS_LOCAL_VOL_ENTRY localVol;
  432. //
  433. // If the local volumes are being initialized as we speak, we won't
  434. // check to see if there are any unmounted volumes that need to be
  435. // reattached. This is because we need to acquire the pkt to do the
  436. // check. However, the local volume init itself might be causing this
  437. // volume to be mounted, in which case they already have the Pkt locked.
  438. //
  439. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  440. if (DfsData.LvState == LV_INITINPROGRESS ||
  441. DfsData.LvState == LV_UNINITIALIZED) {
  442. DebugTrace(0, Dbg, "Local volumes being initialized - no action taken\n", 0);
  443. ExReleaseResourceLite( &DfsData.Resource );
  444. return;
  445. }
  446. ExReleaseResourceLite( &DfsData.Resource );
  447. //
  448. // We will go through all our local volumes to see if any of them have
  449. // a provider that has been detached (marked as PROV_UNAVAILABLE). If
  450. // we find any, we will see if the volume being mounted is one which
  451. // was dismounted before. If so, we reattach.
  452. //
  453. pkt = _GetPkt();
  454. PktAcquireExclusive( pkt, TRUE );
  455. lvPrefix = DfsNextUnicodePrefix(&pkt->LocalVolTable, TRUE);
  456. DebugTrace(0, Dbg, "Looking for Real Device %08lx\n", Vpb->RealDevice);
  457. while (lvPrefix != NULL) {
  458. PPROVIDER_DEF provider;
  459. PDFS_VOLUME_OBJECT candidateObject;
  460. localVol = (PDFS_LOCAL_VOL_ENTRY) CONTAINING_RECORD(
  461. lvPrefix,
  462. DFS_LOCAL_VOL_ENTRY,
  463. PrefixTableEntry);
  464. ASSERT(localVol->PktEntry->LocalService != NULL);
  465. provider = localVol->PktEntry->LocalService->pProvider;
  466. if (provider != NULL) {
  467. candidateObject = CONTAINING_RECORD(
  468. provider,
  469. DFS_VOLUME_OBJECT,
  470. Provider);
  471. if (provider->fProvCapability & PROV_UNAVAILABLE) {
  472. DebugTrace(0, Dbg, "Examining dismounted volume [%wZ]\n",
  473. &localVol->PktEntry->Id.Prefix);
  474. if (Vpb->RealDevice == candidateObject->RealDevice) {
  475. DebugTrace(0, Dbg, "Found detached device %08lx\n",
  476. candidateObject);
  477. provider->DeviceObject = TargetDevice;
  478. Status = IoAttachDeviceByPointer(
  479. &candidateObject->DeviceObject,
  480. TargetDevice);
  481. if (NT_SUCCESS(Status)) {
  482. provider->fProvCapability &= ~PROV_UNAVAILABLE;
  483. }
  484. } else {
  485. DebugTrace(0, Dbg, "Real Device %08lx did not match\n",
  486. candidateObject->RealDevice);
  487. }
  488. }
  489. }
  490. lvPrefix = DfsNextUnicodePrefix( &pkt->LocalVolTable, FALSE );
  491. localVol = (PDFS_LOCAL_VOL_ENTRY) CONTAINING_RECORD(
  492. lvPrefix,
  493. DFS_LOCAL_VOL_ENTRY,
  494. PrefixTableEntry);
  495. }
  496. PktRelease( pkt );
  497. }
  498. //+-------------------------------------------------------------------
  499. //
  500. // Function: DfsVolumePassThrough, public
  501. //
  502. // Synopsis: This is the main FSD routine that passes a request
  503. // on to an attached-to device, or to a redirected
  504. // file.
  505. //
  506. // Arguments: [DeviceObject] -- Supplies a pointer to the Dfs device
  507. // object this request was aimed at.
  508. // [Irp] -- Supplies a pointer to the I/O request packet.
  509. //
  510. // Returns: [STATUS_INVALID_DEVICE_REQUEST] -- If the DeviceObject
  511. // argument is of unknown type, or the type of file
  512. // is invalid for the request being performed.
  513. //
  514. // NT Status from calling the underlying file system that
  515. // opened the file.
  516. //
  517. //--------------------------------------------------------------------
  518. NTSTATUS
  519. DfsVolumePassThrough(
  520. IN PDEVICE_OBJECT DeviceObject,
  521. IN PIRP Irp
  522. )
  523. {
  524. NTSTATUS Status = STATUS_SUCCESS;
  525. PIO_STACK_LOCATION IrpSp;
  526. PIO_STACK_LOCATION NextIrpSp;
  527. PFILE_OBJECT FileObject;
  528. DebugTrace(+1, Dbg, "DfsVolumePassThrough: Entered\n", 0);
  529. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  530. FileObject = IrpSp->FileObject;
  531. DebugTrace(0, Dbg, "DeviceObject = %x\n", DeviceObject);
  532. DebugTrace(0, Dbg, "Irp = %x\n", Irp );
  533. DebugTrace(0, Dbg, " MajorFunction = %x\n", IrpSp->MajorFunction );
  534. DebugTrace(0, Dbg, " MinorFunction = %x\n", IrpSp->MinorFunction );
  535. if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  536. PDEVICE_OBJECT Vdo;
  537. //
  538. // Copy the stack from one to the next...
  539. //
  540. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  541. (*NextIrpSp) = (*IrpSp);
  542. IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);
  543. //
  544. // Find out what device to call...and call it
  545. //
  546. Vdo = ((PDFS_VOLUME_OBJECT) DeviceObject)->Provider.DeviceObject;
  547. Status = IoCallDriver( Vdo, Irp );
  548. DFS_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsVolumePassThrough_Error_Vol_IoCallDriver,
  549. LOGSTATUS(Status)
  550. LOGPTR(Irp)
  551. LOGPTR(FileObject));
  552. } else if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {
  553. PDEVICE_OBJECT Fso;
  554. //
  555. // Copy the stack from one to the next...
  556. //
  557. NextIrpSp = IoGetNextIrpStackLocation(Irp);
  558. (*NextIrpSp) = (*IrpSp);
  559. IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);
  560. //
  561. // Find out what device to call...and call it
  562. //
  563. Fso = ((PDFS_ATTACH_FILE_SYSTEM_OBJECT) DeviceObject)->TargetDevice;
  564. Status = IoCallDriver( Fso, Irp );
  565. DFS_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsVolumePassThrough_Error_FS_IoCallDriver,
  566. LOGPTR(Irp)
  567. LOGSTATUS(Status)
  568. LOGPTR(FileObject));
  569. } else {
  570. DebugTrace(0, Dbg, "DfsVolumePassThrough: Unexpected Dev = %x\n",
  571. DeviceObject);
  572. Status = STATUS_INVALID_DEVICE_REQUEST;
  573. DFS_TRACE_HIGH(ERROR, DfsVolumePassThrough_Error1,
  574. LOGSTATUS(Status)
  575. LOGPTR(FileObject)
  576. LOGPTR(Irp));
  577. Irp->IoStatus.Status = Status;
  578. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  579. }
  580. DebugTrace(-1, Dbg, "DfsVolumePassThrough: Exit -> %08lx\n", ULongToPtr( Status ) );
  581. return Status;
  582. }
  583. //+----------------------------------------------------------------------------
  584. //
  585. // Function: DfsFsNotification, public
  586. //
  587. // Synopsis: Routine to be registered as a callback with the IO subsystem.
  588. // It gets called every time a file system is loaded or
  589. // unloaded. Here, we attach to the file system so that we can
  590. // trap MOUNT fsctrls. We need to trap MOUNT fsctrls so that
  591. // we can attach to the Volume Device Objects of volumes that
  592. // are mounted in the Dfs namespace.
  593. //
  594. // Arguments: [FileSystemObject] -- The File System Device Object of the
  595. // File System that is being loaded/unloaded.
  596. //
  597. // [fLoading] -- TRUE if the File System is being loaded. FALSE
  598. // if it is being unloaded.
  599. //
  600. // Returns: Nothing.
  601. //
  602. //-----------------------------------------------------------------------------
  603. VOID
  604. DfsFsNotification(
  605. IN PDEVICE_OBJECT FileSystemObject,
  606. IN BOOLEAN fLoading)
  607. {
  608. ASSERT( FileSystemObject->DriverObject != NULL );
  609. DebugTrace(+1, Dbg, "DfsFsNotification - Entered\n", 0);
  610. DebugTrace(0, Dbg, "File System [%wZ]\n", &FileSystemObject->DriverObject->DriverName);
  611. DebugTrace(0, Dbg, "%s\n", fLoading ? "Loading" : "Unloading" );
  612. //
  613. // Check if this is a DISK based file system. If not, we don't care about
  614. // it.
  615. //
  616. if (FileSystemObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM) {
  617. DebugTrace(-1, Dbg, "DfsFsNotification - Not Disk File System\n",0);
  618. return;
  619. }
  620. //
  621. // A disk file system is being loaded or unloaded. If it is being loaded,
  622. // we want to attach to the File System Device Object being passed in. If
  623. // it is being unloaded, we try to find our attached device and detach
  624. // ourselves.
  625. //
  626. if (fLoading) {
  627. DfsAttachToFileSystem( FileSystemObject );
  628. } else {
  629. DfsDetachFromFileSystem( FileSystemObject );
  630. }
  631. DebugTrace(-1, Dbg, "DfsFsNotification - Exited\n", 0);
  632. }
  633. //+----------------------------------------------------------------------------
  634. //
  635. // Function: DfsAttachToFileSystem
  636. //
  637. // Synopsis: Attaches to a File System Device Object so we can trap
  638. // MOUNT calls.
  639. //
  640. // Arguments: [FileSystemObject] -- The File System Object to attach to.
  641. //
  642. // Returns: Nothing
  643. //
  644. //-----------------------------------------------------------------------------
  645. VOID
  646. DfsAttachToFileSystem(
  647. IN PDEVICE_OBJECT FileSystemObject)
  648. {
  649. NTSTATUS Status;
  650. PDFS_ATTACH_FILE_SYSTEM_OBJECT ourDevice;
  651. PDEVICE_OBJECT TargetFileSystemObject;
  652. //
  653. // Create our own device object.
  654. //
  655. Status = IoCreateDevice(
  656. DfsData.DriverObject, // Our own Driver Object
  657. sizeof(DFS_ATTACH_FILE_SYSTEM_OBJECT) -
  658. sizeof(DEVICE_OBJECT), // size of extension
  659. NULL, // Name - we don't need one
  660. FILE_DEVICE_DISK_FILE_SYSTEM, // Type of device
  661. 0, // Device Characteristics
  662. FALSE, // Exclusive
  663. (PDEVICE_OBJECT *) &ourDevice); // On return, new device
  664. DFS_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsAttachToFileSystem_Error_IoCreateDevice,
  665. LOGSTATUS(Status)
  666. LOGPTR(FileSystemObject));
  667. if (NT_SUCCESS(Status)) {
  668. DebugTrace(0, Dbg, "Created File System Attach Device %08lx\n",
  669. ourDevice);
  670. TargetFileSystemObject = IoAttachDeviceToDeviceStack(
  671. &ourDevice->DeviceObject,
  672. FileSystemObject );
  673. if (TargetFileSystemObject != NULL) {
  674. ourDevice->TargetDevice = TargetFileSystemObject;
  675. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  676. InsertTailList( &DfsData.AFsoQueue, &ourDevice->FsoLinks );
  677. ExReleaseResourceLite( &DfsData.Resource );
  678. ourDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
  679. } else {
  680. DebugTrace(0, Dbg, "Unable to attach %08lx\n", ULongToPtr( Status ));
  681. IoDeleteDevice( (PDEVICE_OBJECT) ourDevice );
  682. }
  683. } else {
  684. DebugTrace(0, Dbg, "Unable to create Device Object %08lx\n", ULongToPtr( Status ));
  685. }
  686. }
  687. //+----------------------------------------------------------------------------
  688. //
  689. // Function: DfsDetachFromFileSystem
  690. //
  691. // Synopsis: Finds and detaches a DFS_ATTACHED_FILE_SYSTEM_OBJECT from
  692. // its target File System Device Object.
  693. //
  694. // Arguments: [FileSystemObject] -- The one that purpotedly has one of our
  695. // device objects attached to it.
  696. //
  697. // Returns: Nothing
  698. //
  699. //-----------------------------------------------------------------------------
  700. VOID
  701. DfsDetachFromFileSystem(
  702. IN PDEVICE_OBJECT FileSystemObject)
  703. {
  704. PDFS_ATTACH_FILE_SYSTEM_OBJECT attachedDevice, candidateDevice;
  705. PLIST_ENTRY nextAFsoLink;
  706. //
  707. // First, we need to find our own device. For each device that is
  708. // attached to the FileSystemObject, we check our AFsoQueue to see if
  709. // the attached device belongs to us.
  710. //
  711. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  712. for (attachedDevice = (PDFS_ATTACH_FILE_SYSTEM_OBJECT)
  713. FileSystemObject->AttachedDevice;
  714. attachedDevice != NULL;
  715. attachedDevice = (PDFS_ATTACH_FILE_SYSTEM_OBJECT)
  716. attachedDevice->DeviceObject.AttachedDevice) {
  717. for (nextAFsoLink = DfsData.AFsoQueue.Flink;
  718. nextAFsoLink != &DfsData.AFsoQueue;
  719. nextAFsoLink = nextAFsoLink->Flink) {
  720. candidateDevice = CONTAINING_RECORD(
  721. nextAFsoLink,
  722. DFS_ATTACH_FILE_SYSTEM_OBJECT,
  723. FsoLinks);
  724. if (attachedDevice == candidateDevice) {
  725. DebugTrace(0, Dbg, "Found Attached Device %08lx\n",
  726. candidateDevice);
  727. RemoveEntryList( &attachedDevice->FsoLinks );
  728. ExReleaseResourceLite( &DfsData.Resource );
  729. IoDetachDevice( FileSystemObject );
  730. IoDeleteDevice( (PDEVICE_OBJECT) attachedDevice );
  731. return;
  732. }
  733. }
  734. }
  735. ExReleaseResourceLite( &DfsData.Resource );
  736. DebugTrace(0, Dbg, "Did not find a device attached to %08lx\n",
  737. FileSystemObject);
  738. }
  739. //+-------------------------------------------------------------------------
  740. //
  741. // Function: DfsDetachAllFileSystems
  742. //
  743. // Synopsis: Detaches from all file systems at unload time
  744. //
  745. //
  746. // Arguments: None
  747. //
  748. // Returns: Nothing
  749. //
  750. //
  751. //--------------------------------------------------------------------------
  752. VOID
  753. DfsDetachAllFileSystems(
  754. VOID
  755. )
  756. {
  757. PDFS_ATTACH_FILE_SYSTEM_OBJECT Device;
  758. PLIST_ENTRY ListEntry;
  759. FsRtlEnterFileSystem ();
  760. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  761. while (!IsListEmpty (&DfsData.AFsoQueue)) {
  762. ListEntry = RemoveHeadList (&DfsData.AFsoQueue);
  763. Device = CONTAINING_RECORD(ListEntry,
  764. DFS_ATTACH_FILE_SYSTEM_OBJECT,
  765. FsoLinks);
  766. ExReleaseResourceLite( &DfsData.Resource );
  767. FsRtlExitFileSystem ();
  768. IoDetachDevice( Device->TargetDevice );
  769. IoDeleteDevice( &Device->DeviceObject );
  770. FsRtlEnterFileSystem ();
  771. ExAcquireResourceExclusiveLite( &DfsData.Resource, TRUE );
  772. }
  773. ExReleaseResourceLite( &DfsData.Resource );
  774. FsRtlExitFileSystem ();
  775. }
  776. //+-------------------------------------------------------------------------
  777. //
  778. // Function: DfsSetupVdo, private
  779. //
  780. // Synopsis: A DFS volume device object is created and initialized. It is then
  781. // attached to the device object that is passed in.
  782. //
  783. // Arguments: [RootName] -- file path name of the root of the local
  784. // volume.
  785. // targetVdo -- The target device object we are attaching to.
  786. // realDevice -- the real device for this volume.
  787. // volNameLen -- Volume name length.
  788. // CreatedVdo -- The is the return value, from IoCreateDevice.
  789. //
  790. // Returns: [STATUS_INSUFFICIENT_RESOURCES] -- If unable to allocate
  791. // pool for provider name.
  792. // return status from IoCreateDevice or IoAttachDevice.
  793. //
  794. //
  795. //--------------------------------------------------------------------------
  796. NTSTATUS
  797. DfsSetupVdo (
  798. IN PUNICODE_STRING RootName,
  799. IN PDEVICE_OBJECT targetVdo,
  800. IN PDEVICE_OBJECT realDevice,
  801. IN ULONG volNameLen,
  802. OUT PDFS_VOLUME_OBJECT *CreatedVdo
  803. )
  804. {
  805. NTSTATUS Status;
  806. PDFS_VOLUME_OBJECT dfsVdo;
  807. DebugTrace(1, Dbg, "DfsSetupVdo: Attempting to create device\n",0);
  808. Status = IoCreateDevice(
  809. DfsData.DriverObject,
  810. sizeof(DFS_VOLUME_OBJECT) - sizeof(DEVICE_OBJECT),
  811. NULL,
  812. FILE_DEVICE_DFS_VOLUME,
  813. targetVdo->Characteristics,
  814. FALSE,
  815. (PDEVICE_OBJECT *) &dfsVdo);
  816. if (NT_SUCCESS(Status)) {
  817. dfsVdo->DeviceObject.StackSize = targetVdo->StackSize+1;
  818. dfsVdo->AttachCount = 1;
  819. dfsVdo->RealDevice = realDevice;
  820. dfsVdo->Provider.NodeTypeCode = DFS_NTC_PROVIDER;
  821. dfsVdo->Provider.NodeByteSize = sizeof ( PROVIDER_DEF );
  822. dfsVdo->Provider.eProviderId = ++LocalProviderID;
  823. dfsVdo->Provider.fProvCapability = 0;
  824. dfsVdo->Provider.DeviceObject = targetVdo;
  825. dfsVdo->Provider.FileObject = NULL;
  826. dfsVdo->Provider.DeviceName.Buffer = (PWCHAR) ExAllocatePoolWithTag(
  827. PagedPool,
  828. volNameLen,
  829. ' sfD');
  830. if (dfsVdo->Provider.DeviceName.Buffer == NULL) {
  831. IoDeleteDevice(&dfsVdo->DeviceObject);
  832. DebugTrace(-1, Dbg, "DfsSetupVdo: Cannot allocate memory\n", 0);
  833. return(STATUS_INSUFFICIENT_RESOURCES);
  834. }
  835. RtlMoveMemory(dfsVdo->Provider.DeviceName.Buffer, RootName->Buffer, volNameLen);
  836. dfsVdo->Provider.DeviceName.MaximumLength =
  837. dfsVdo->Provider.DeviceName.Length =
  838. (USHORT)volNameLen;
  839. //
  840. // If we successfully created the device object we can
  841. // begin the task of attaching.
  842. //
  843. DebugTrace(0, Dbg, "DfsSetupVdo: Attempting to attach device\n",0);
  844. Status = IoAttachDeviceByPointer(
  845. &dfsVdo->DeviceObject,
  846. targetVdo);
  847. if (!NT_SUCCESS(Status)) {
  848. ExFreePool(dfsVdo->Provider.DeviceName.Buffer);
  849. IoDeleteDevice(&dfsVdo->DeviceObject);
  850. }
  851. }
  852. if (NT_SUCCESS(Status)) {
  853. *CreatedVdo = dfsVdo;
  854. }
  855. DebugTrace(-1, Dbg, "DfsSetupVdo: Returning status %p\n", ULongToPtr( Status ));
  856. return Status;
  857. }
  858. PDEVICE_OBJECT
  859. DfsGetDfsFilterDeviceObject(
  860. PFILE_OBJECT fileObject)
  861. {
  862. PDEVICE_OBJECT DevObj;
  863. PDEVICE_OBJECT NextAttached;
  864. DevObj = fileObject->Vpb->DeviceObject;
  865. NextAttached = DevObj->AttachedDevice;
  866. while (NextAttached != NULL) {
  867. if (NextAttached->DeviceType == FILE_DEVICE_DFS_VOLUME) {
  868. return NextAttached;
  869. }
  870. NextAttached = NextAttached->AttachedDevice;
  871. }
  872. return NULL;
  873. }