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.

2611 lines
91 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. parse.c
  5. Abstract:
  6. This module contains the code to implement the device object parse routine.
  7. Author:
  8. Darryl E. Havens (darrylh) 15-May-1988
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "iomgr.h"
  14. //
  15. // Define macro to round up the size of a name for buffer optimization.
  16. //
  17. #define RoundNameSize( Length ) ( \
  18. (Length < 64 - 8) ? 64 - 8 : \
  19. (Length < 128 - 8) ? 128 - 8 :\
  20. (Length < 256 - 8) ? 256 - 8 : Length )
  21. #define IO_MAX_REMOUNT_REPARSE_ATTEMPTS 32
  22. NTSTATUS
  23. IopGetNetworkOpenInformation(
  24. IN PFILE_OBJECT FileObject,
  25. IN POPEN_PACKET Op
  26. );
  27. #ifdef ALLOC_PRAGMA
  28. #pragma alloc_text(PAGE, IopParseFile)
  29. #pragma alloc_text(PAGE, IopParseDevice)
  30. #pragma alloc_text(PAGE, IopQueryName)
  31. #pragma alloc_text(PAGE, IopQueryNameInternal)
  32. #pragma alloc_text(PAGE, IopCheckBackupRestorePrivilege)
  33. #pragma alloc_text(PAGE, IopGetNetworkOpenInformation)
  34. #endif
  35. NTSTATUS
  36. IopCheckDeviceAndDriver(
  37. IN POPEN_PACKET op,
  38. IN PDEVICE_OBJECT parseDeviceObject
  39. )
  40. {
  41. NTSTATUS status;
  42. KIRQL irql;
  43. //
  44. // Make sure that the device and its driver are really there and they are
  45. // going to stay there. The object itself cannot go away just yet because
  46. // the object management system has performed a reference which bumps the
  47. // count of the number of reasons why the object must stick around.
  48. // However, the driver could be attempting to unload itself, so perform
  49. // this check. If the driver is being unloaded, then set the final status
  50. // of the operation to "No such device" and return with a NULL file object
  51. // pointer.
  52. //
  53. // Note that it is possible to "open" an exclusive device more than once
  54. // provided that the caller is performing a relative open. This feature
  55. // is how users "allocate" a device, and then use it to perform operations.
  56. //
  57. irql = KeAcquireQueuedSpinLock( LockQueueIoDatabaseLock );
  58. if (parseDeviceObject->DeviceObjectExtension->ExtensionFlags &
  59. (DOE_UNLOAD_PENDING | DOE_DELETE_PENDING | DOE_REMOVE_PENDING | DOE_REMOVE_PROCESSED | DOE_START_PENDING) ||
  60. parseDeviceObject->Flags & DO_DEVICE_INITIALIZING) {
  61. status = STATUS_NO_SUCH_DEVICE;
  62. } else if (parseDeviceObject->Flags & DO_EXCLUSIVE &&
  63. parseDeviceObject->ReferenceCount != 0 &&
  64. op->RelatedFileObject == NULL &&
  65. !(op->Options & IO_ATTACH_DEVICE)) {
  66. status = STATUS_ACCESS_DENIED;
  67. } else {
  68. parseDeviceObject->ReferenceCount++;
  69. status = STATUS_SUCCESS;
  70. }
  71. KeReleaseQueuedSpinLock( LockQueueIoDatabaseLock, irql );
  72. return status;
  73. }
  74. PVPB
  75. IopCheckVpbMounted(
  76. IN POPEN_PACKET op,
  77. IN PDEVICE_OBJECT parseDeviceObject,
  78. IN OUT PUNICODE_STRING RemainingName,
  79. OUT PNTSTATUS status
  80. )
  81. {
  82. PVPB vpb;
  83. PVPB mountVpb;
  84. KIRQL irql;
  85. BOOLEAN alertable;
  86. //
  87. // Loop here until the VPB_MOUNTED test can be passed while holding the
  88. // VPB spinlock. After the mount succeeds, it is still necessary to acquire
  89. // the spinlock to check that the VPB (which may be different from the one
  90. // before the mount) is still mounted. If it is, then its reference count
  91. // is incremented before releasing the spinlock.
  92. //
  93. irql = KeAcquireQueuedSpinLock( LockQueueIoVpbLock );
  94. while (!(parseDeviceObject->Vpb->Flags & VPB_MOUNTED)) {
  95. KeReleaseQueuedSpinLock( LockQueueIoVpbLock, irql );
  96. alertable = (op->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT) ? TRUE : FALSE;
  97. //
  98. // Try to mount the volume, allowing only RAW to perform the mount if
  99. // this is a DASD open.
  100. //
  101. mountVpb = NULL;
  102. *status = IopMountVolume( parseDeviceObject,
  103. (BOOLEAN) (!RemainingName->Length && !op->RelatedFileObject),
  104. FALSE,
  105. alertable,
  106. &mountVpb );
  107. //
  108. // If the mount operation was unsuccessful, adjust the reference
  109. // count for the device and return now.
  110. //
  111. if (!NT_SUCCESS( *status ) || *status == STATUS_USER_APC || *status == STATUS_ALERTED) {
  112. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  113. if (!NT_SUCCESS( *status )) {
  114. return NULL;
  115. } else {
  116. *status = STATUS_WRONG_VOLUME;
  117. return NULL;
  118. }
  119. } else {
  120. //
  121. // In this case IopMountVolume did the synchronization already.
  122. //
  123. if (mountVpb) {
  124. return mountVpb;
  125. }
  126. }
  127. irql = KeAcquireQueuedSpinLock( LockQueueIoVpbLock );
  128. }
  129. //
  130. // Synchronize here with the file system to make sure that volumes do not
  131. // go away while en route to the FS.
  132. //
  133. vpb = parseDeviceObject->Vpb;
  134. //
  135. // Check here that the VPB is not locked.
  136. //
  137. if (vpb->Flags & VPB_LOCKED) {
  138. *status = STATUS_ACCESS_DENIED;
  139. vpb = NULL;
  140. } else {
  141. vpb->ReferenceCount += 1;
  142. }
  143. KeReleaseQueuedSpinLock( LockQueueIoVpbLock, irql );
  144. //
  145. // This is because VPB is locked.
  146. // Do the decrement outside the VPB lock because of possible deadlocks.
  147. //
  148. if (!vpb) {
  149. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  150. }
  151. return vpb;
  152. }
  153. VOID
  154. IopDereferenceVpbAndFree(
  155. IN PVPB Vpb
  156. )
  157. {
  158. KIRQL irql;
  159. PVPB vpb = (PVPB) NULL;
  160. irql = KeAcquireQueuedSpinLock( LockQueueIoVpbLock );
  161. Vpb->ReferenceCount--;
  162. if ((Vpb->ReferenceCount == 0) &&
  163. (Vpb->RealDevice->Vpb != Vpb) &&
  164. !(Vpb->Flags & VPB_PERSISTENT)) {
  165. vpb = Vpb;
  166. }
  167. KeReleaseQueuedSpinLock( LockQueueIoVpbLock, irql );
  168. if (vpb) {
  169. ExFreePool( vpb );
  170. }
  171. }
  172. NTSTATUS
  173. IopParseDevice(
  174. IN PVOID ParseObject,
  175. IN PVOID ObjectType,
  176. IN PACCESS_STATE AccessState,
  177. IN KPROCESSOR_MODE AccessMode,
  178. IN ULONG Attributes,
  179. IN OUT PUNICODE_STRING CompleteName,
  180. IN OUT PUNICODE_STRING RemainingName,
  181. IN OUT PVOID Context OPTIONAL,
  182. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  183. OUT PVOID *Object
  184. )
  185. /*++
  186. Routine Description:
  187. This routine interfaces to the NT Object Manager. It is invoked when
  188. the object system is given the name of an entity to create or open and the
  189. name translates to a device object. This routine is specified as the parse
  190. routine for all device objects.
  191. In the normal case of an NtCreateFile, the user specifies either the name
  192. of a device or of a file. In the former situation, this routine is invoked
  193. with a pointer to the device and a null ("") string. For this case, the
  194. routine simply allocates an IRP, fills it in, and passes it to the driver
  195. for the device. The driver will then perform whatever rudimentary functions
  196. are necessary and will return a status code indicating whether an error was
  197. incurred. This status code is remembered in the Open Packet (OP).
  198. In the latter situation, the name string to be opened/created is non-null.
  199. That is, it contains the remainder of the pathname to the file that is to
  200. be opened or created. For this case, the routine allocates an IRP, fills
  201. it in, and passes it to the driver for the device. The driver may then
  202. need to take further action or it may complete the request immediately. If
  203. it needs to perform some work asynchronously, then it can queue the request
  204. and return a status of STATUS_PENDING. This allows this routine and its
  205. caller to return to the user so that he can continue. Otherwise, the open/
  206. create is basically finished.
  207. If the driver supports symbolic links, then it is also possible for the
  208. driver to return a new name. This name will be returned to the Object
  209. Manager as a new name to look up. The parsing will then begin again from
  210. the start.
  211. It is also the responsibility of this routine to create a file object for
  212. the file, if the name specifies a file. The file object's address is
  213. returned to the NtCreateFile service through the OP.
  214. Arguments:
  215. ParseObject - Pointer to the device object the name translated into.
  216. ObjectType - Type of the object being opened.
  217. AccessState - Running security access state information for operation.
  218. AccessMode - Access mode of the original caller.
  219. Attributes - Attributes to be applied to the object.
  220. CompleteName - Complete name of the object.
  221. RemainingName - Remaining name of the object.
  222. Context - Pointer to an Open Packet (OP) from NtCreateFile service.
  223. SecurityQos - Optional security quality of service indicator.
  224. Object - The address of a variable to receive the created file object, if
  225. any.
  226. Return Value:
  227. The function return value is one of the following:
  228. a) Success - This indicates that the function succeeded and the object
  229. parameter contains the address of the created file object.
  230. b) Error - This indicates that the file was not found or created and
  231. no file object was created.
  232. c) Reparse - This indicates that the remaining name string has been
  233. replaced by a new name that is to be parsed.
  234. --*/
  235. {
  236. PIRP irp;
  237. PIO_STACK_LOCATION irpSp;
  238. POPEN_PACKET op;
  239. PFILE_OBJECT fileObject;
  240. NTSTATUS status;
  241. IO_STATUS_BLOCK ioStatus;
  242. IO_SECURITY_CONTEXT securityContext;
  243. PDEVICE_OBJECT deviceObject;
  244. PDEVICE_OBJECT parseDeviceObject;
  245. BOOLEAN directDeviceOpen;
  246. PVPB vpb;
  247. ACCESS_MASK desiredAccess;
  248. PDUMMY_FILE_OBJECT localFileObject;
  249. LOGICAL realFileObjectRequired;
  250. KPROCESSOR_MODE modeForPrivilegeCheck;
  251. ULONG retryCount = 0;
  252. BOOLEAN relativeVolumeOpen = FALSE; // True if opening a filesystem volume
  253. PETHREAD CurrentThread;
  254. ULONG returnedLength;
  255. PAGED_CODE();
  256. UNREFERENCED_PARAMETER (ObjectType);
  257. CurrentThread = PsGetCurrentThread ();
  258. reparse_loop:
  259. //
  260. // Assume failure by setting the returned object pointer to NULL.
  261. //
  262. *Object = (PVOID) NULL;
  263. //
  264. // Get the address of the Open Packet (OP).
  265. //
  266. op = Context;
  267. //
  268. // Ensure that this routine is actually being invoked because someone is
  269. // attempting to open a device or a file through NtCreateFile. This code
  270. // must be invoked from there (as opposed to some other random object
  271. // create or open routine).
  272. //
  273. if (op == NULL ||
  274. op->Type != IO_TYPE_OPEN_PACKET ||
  275. op->Size != sizeof( OPEN_PACKET )) {
  276. return STATUS_OBJECT_TYPE_MISMATCH;
  277. }
  278. //
  279. // Obtain a pointer to the parse object as a device object, which is the
  280. // actual type of the object anyway.
  281. //
  282. parseDeviceObject = (PDEVICE_OBJECT) ParseObject;
  283. //
  284. // If we passed through a mountpoint do an extra set of validation checks
  285. // that we don't go to a remote device. We really have to let the object manager
  286. // open the new path. If we fail it in the path that obtains the reparse point and
  287. // validates the name (using IoIsValidNameGraftingBuffer) its not sufficient. This is because
  288. // the path may be valid at that time and change before OB does the reparse.
  289. //
  290. if (op->TraversedMountPoint) {
  291. ASSERT (op->Information == IO_REPARSE_TAG_MOUNT_POINT);
  292. if ((parseDeviceObject->DeviceType != FILE_DEVICE_DISK) &&
  293. (parseDeviceObject->DeviceType != FILE_DEVICE_CD_ROM) &&
  294. (parseDeviceObject->DeviceType != FILE_DEVICE_VIRTUAL_DISK) &&
  295. (parseDeviceObject->DeviceType != FILE_DEVICE_TAPE)) {
  296. status = STATUS_IO_REPARSE_DATA_INVALID;
  297. return op->FinalStatus = status;
  298. }
  299. }
  300. //
  301. // If this is a relative open, then get the device on which the file
  302. // is really being opened from the related file object and use that for
  303. // the remainder of this function and for all operations performed on
  304. // the file object that is about to be created.
  305. //
  306. if (op->RelatedFileObject) {
  307. parseDeviceObject = op->RelatedFileObject->DeviceObject;
  308. }
  309. //
  310. // Make sure that the device and its driver are really there and they are
  311. // going to stay there. The object itself cannot go away just yet because
  312. // the object management system has performed a reference which bumps the
  313. // count of the number of reasons why the object must stick around.
  314. // However, the driver could be attempting to unload itself, so perform
  315. // this check. If the driver is being unloaded, then set the final status
  316. // of the operation to "No such device" and return with a NULL file object
  317. // pointer.
  318. //
  319. // Note that it is possible to "open" an exclusive device more than once
  320. // provided that the caller is performing a relative open. This feature
  321. // is how users "allocate" a device, and then use it to perform operations.
  322. //
  323. status = IopCheckDeviceAndDriver( op, parseDeviceObject );
  324. if (!NT_SUCCESS(status)) {
  325. return op->FinalStatus = status;
  326. }
  327. //
  328. // Since ObOpenObjectByName is called without being passed
  329. // any object type information, we need to map the generic
  330. // bits in the DesiredAccess mask here. We also need to save
  331. // the object's generic mapping in the access state structure
  332. // here, because this is the earliest opportunity we have
  333. // to do so.
  334. //
  335. RtlMapGenericMask( &AccessState->RemainingDesiredAccess,
  336. &IoFileObjectType->TypeInfo.GenericMapping );
  337. RtlMapGenericMask( &AccessState->OriginalDesiredAccess,
  338. &IoFileObjectType->TypeInfo.GenericMapping );
  339. SeSetAccessStateGenericMapping( AccessState, &IoFileObjectType->TypeInfo.GenericMapping );
  340. desiredAccess = AccessState->RemainingDesiredAccess;
  341. //
  342. // Compute the previous mode to be passed in to the privilege check
  343. //
  344. if (AccessMode != KernelMode || op->Options & IO_FORCE_ACCESS_CHECK) {
  345. modeForPrivilegeCheck = UserMode;
  346. } else {
  347. modeForPrivilegeCheck = KernelMode;
  348. }
  349. IopCheckBackupRestorePrivilege( AccessState,
  350. &op->CreateOptions,
  351. modeForPrivilegeCheck,
  352. op->Disposition
  353. );
  354. //
  355. // If this is not the first time through here for this object, and the
  356. // object itself is being opened, then the desired access must also
  357. // include the previously granted access from the last pass. Likewise,
  358. // if the privileges have been checked already, then this is another
  359. // pass through for a file, so add in the previously granted access.
  360. //
  361. if ((op->Override && !RemainingName->Length) ||
  362. AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) {
  363. desiredAccess |= AccessState->PreviouslyGrantedAccess;
  364. }
  365. //
  366. // If its a filesystem volume open and we are doing a relative open to it
  367. // then do the access check. Note that relative opens can be nested and we propagate
  368. // the fact that the relative open is for a volume using the FO_VOLUME_OPEN flag.
  369. //
  370. if (op->RelatedFileObject) {
  371. if ((op->RelatedFileObject->Flags & FO_VOLUME_OPEN) && RemainingName->Length == 0) {
  372. relativeVolumeOpen = TRUE;
  373. }
  374. }
  375. //
  376. // Now determine what type of security check should be made. This is
  377. // based on whether the remaining name string is null. If it is null,
  378. // then the device itself is being opened, so a full security check is
  379. // performed. Otherwise, only a check to ensure that the caller can
  380. // traverse the device object is made. Note that these checks are only
  381. // made if the caller's mode is user, or if access checking is being
  382. // forced. Note also that if an access check was already made on the
  383. // device itself, and this code is being executed again because of a
  384. // reparse, then the access check need not be made the second time
  385. // around.
  386. //
  387. if ((AccessMode != KernelMode || op->Options & IO_FORCE_ACCESS_CHECK) &&
  388. (!op->RelatedFileObject || relativeVolumeOpen) &&
  389. !op->Override) {
  390. BOOLEAN subjectContextLocked = FALSE;
  391. BOOLEAN accessGranted;
  392. ACCESS_MASK grantedAccess;
  393. //
  394. // The caller's mode is either user or access checking is being
  395. // forced. Perform the appropriate access check on the device
  396. // object.
  397. //
  398. if (!RemainingName->Length) {
  399. UNICODE_STRING nameString;
  400. PPRIVILEGE_SET privileges = NULL;
  401. //
  402. // The device itself is being opened. Make a full security check
  403. // to ensure that the caller has the appropriate access.
  404. //
  405. KeEnterCriticalRegionThread( &CurrentThread->Tcb );
  406. ExAcquireResourceSharedLite( &IopSecurityResource, TRUE );
  407. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  408. subjectContextLocked = TRUE;
  409. accessGranted = SeAccessCheck( parseDeviceObject->SecurityDescriptor,
  410. &AccessState->SubjectSecurityContext,
  411. subjectContextLocked,
  412. desiredAccess,
  413. 0,
  414. &privileges,
  415. &IoFileObjectType->TypeInfo.GenericMapping,
  416. UserMode,
  417. &grantedAccess,
  418. &status );
  419. if (privileges) {
  420. (VOID) SeAppendPrivileges( AccessState,
  421. privileges );
  422. SeFreePrivileges( privileges );
  423. }
  424. if (accessGranted) {
  425. AccessState->PreviouslyGrantedAccess |= grantedAccess;
  426. AccessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  427. op->Override = TRUE;
  428. }
  429. nameString.Length = 8;
  430. nameString.MaximumLength = 8;
  431. nameString.Buffer = L"File";
  432. SeOpenObjectAuditAlarm( &nameString,
  433. parseDeviceObject,
  434. CompleteName,
  435. parseDeviceObject->SecurityDescriptor,
  436. AccessState,
  437. FALSE,
  438. accessGranted,
  439. UserMode,
  440. &AccessState->GenerateOnClose );
  441. ExReleaseResourceLite( &IopSecurityResource );
  442. KeLeaveCriticalRegionThread( &CurrentThread->Tcb );
  443. } else {
  444. //
  445. // The device is not being opened, rather, a file on the device
  446. // is being opened or created. Therefore, only perform a check
  447. // here for traverse access to the device.
  448. //
  449. //
  450. // First determine if we have to perform traverse checking at all.
  451. // Traverse checking only needs to be done if the device being
  452. // traversed is a disk, or if the caller does not already have
  453. // traverse checking privilege. Note that the former case is so
  454. // that an administrator can turn off access to the "system
  455. // partition", or someone would be able to install a trojan horse
  456. // into the system by simply replacing one of the files there with
  457. // something of their own.
  458. //
  459. if (!(AccessState->Flags & TOKEN_HAS_TRAVERSE_PRIVILEGE) ||
  460. parseDeviceObject->DeviceType == FILE_DEVICE_DISK ||
  461. parseDeviceObject->DeviceType == FILE_DEVICE_CD_ROM ) {
  462. KeEnterCriticalRegionThread( &CurrentThread->Tcb );
  463. ExAcquireResourceSharedLite( &IopSecurityResource, TRUE );
  464. accessGranted = SeFastTraverseCheck( parseDeviceObject->SecurityDescriptor,
  465. AccessState,
  466. FILE_TRAVERSE,
  467. UserMode );
  468. if (!accessGranted) {
  469. PPRIVILEGE_SET privileges = NULL;
  470. //
  471. // The caller was not granted traverse access through the
  472. // normal fast path lookup. Perform a full-blown access
  473. // check to determine whether some other ACE allows traverse
  474. // access.
  475. //
  476. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  477. subjectContextLocked = TRUE;
  478. accessGranted = SeAccessCheck( parseDeviceObject->SecurityDescriptor,
  479. &AccessState->SubjectSecurityContext,
  480. subjectContextLocked,
  481. FILE_TRAVERSE,
  482. 0,
  483. &privileges,
  484. &IoFileObjectType->TypeInfo.GenericMapping,
  485. UserMode,
  486. &grantedAccess,
  487. &status );
  488. if (privileges) {
  489. (VOID) SeAppendPrivileges( AccessState,
  490. privileges );
  491. SeFreePrivileges( privileges );
  492. }
  493. }
  494. ExReleaseResourceLite( &IopSecurityResource );
  495. KeLeaveCriticalRegionThread( &CurrentThread->Tcb );
  496. } else {
  497. accessGranted = TRUE;
  498. }
  499. }
  500. //
  501. // Unlock the subject's security context so that it can be changed,
  502. // if it was locked.
  503. //
  504. if (subjectContextLocked) {
  505. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  506. }
  507. //
  508. // Finally, determine whether or not access was granted to the device.
  509. // If not, clean everything up and get out now without even invoking
  510. // the device driver.
  511. //
  512. if (!accessGranted) {
  513. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  514. return STATUS_ACCESS_DENIED;
  515. }
  516. }
  517. realFileObjectRequired = !(op->QueryOnly || op->DeleteOnly);
  518. if (RemainingName->Length == 0 &&
  519. op->RelatedFileObject == NULL &&
  520. ((desiredAccess & ~(SYNCHRONIZE |
  521. FILE_READ_ATTRIBUTES |
  522. READ_CONTROL |
  523. ACCESS_SYSTEM_SECURITY |
  524. WRITE_OWNER |
  525. WRITE_DAC)) == 0) &&
  526. realFileObjectRequired) {
  527. //
  528. // If the name of the object being opened is just the name of the
  529. // device itself, and there is no related file object, and the caller
  530. // is opening the device for only read attributes access, then this
  531. // device will not be mounted. This allows applications to obtain
  532. // attributes about the device without actually mounting it.
  533. //
  534. // Note that if this *is* a direct device open, then the normal path
  535. // through the I/O system and drivers may never be used, even if
  536. // the device appears to be mounted. This is because the user may
  537. // remove the media from the drive (even though it is mounted), and
  538. // now attempting to determine what type of drive it is will still
  539. // fail, this time very hard, because a whole mount process is now
  540. // required, thus defeating this feature.
  541. //
  542. directDeviceOpen = TRUE;
  543. } else {
  544. //
  545. // Otherwise, this is a normal open of a file, directory, device, or
  546. // volume.
  547. //
  548. directDeviceOpen = FALSE;
  549. }
  550. //
  551. // There are now five different cases. These are as follows:
  552. //
  553. // 1) This is a relative open, in which case we want to send the
  554. // request to then same device that opened the relative file object.
  555. //
  556. // 2) The VPB pointer in the device object is NULL. This means that
  557. // this device does not support a file system. This includes
  558. // devices such as terminals, etc.
  559. //
  560. // 3) The VPB pointer in the device object is not NULL and:
  561. //
  562. // a) The VPB is "blank". That is, the VPB has never been filled
  563. // in, which means that the device has never been mounted.
  564. //
  565. // b) The VPB is non-blank, but the verify flag on the device is
  566. // set, indicating that the door to the drive may have been
  567. // opened and the media may therefore have been changed.
  568. //
  569. // c) The VPB is non-blank and the verify flag is not set.
  570. //
  571. // Both of the latter are not explicitly checked for, as #c is
  572. // the normal case, and #b is the responsibility of the file
  573. // system to check.
  574. //
  575. //
  576. // If this is a file system that supports volumes, vpbRefCount will
  577. // be filled in to point to the reference count in the Vpb. Error
  578. // exits paths later on key off this value to see if they should
  579. // decrement the ref count. Note that a direct device open does not
  580. // make it to the file system, so no increment is needed, and no
  581. // decrement will be performed in objsup.c IopDeleteFile().
  582. //
  583. vpb = NULL;
  584. //
  585. // If the related open was a direct device open then we should go through the full mount
  586. // path for this open as this may not be a direct device open.
  587. //
  588. if (op->RelatedFileObject && (!(op->RelatedFileObject->Flags & FO_DIRECT_DEVICE_OPEN))) {
  589. deviceObject = (PDEVICE_OBJECT)ParseObject;
  590. if (op->RelatedFileObject->Vpb) {
  591. vpb = op->RelatedFileObject->Vpb;
  592. //
  593. // Synchronize here with the file system to make sure that
  594. // volumes don't go away while en route to the FS.
  595. //
  596. IopInterlockedIncrementUlong( LockQueueIoVpbLock,
  597. (PLONG) &vpb->ReferenceCount);
  598. }
  599. } else {
  600. deviceObject = parseDeviceObject;
  601. if (parseDeviceObject->Vpb && !directDeviceOpen) {
  602. vpb = IopCheckVpbMounted( op,
  603. parseDeviceObject,
  604. RemainingName,
  605. &status );
  606. //
  607. // Device object reference is decremented in IopCheckVpbMounted.
  608. //
  609. if ( !vpb ) {
  610. return status;
  611. }
  612. //
  613. // Set the address of the device object associated with the VPB.
  614. //
  615. deviceObject = vpb->DeviceObject;
  616. }
  617. //
  618. // If the top deviceobject hint is set use the hint if possible.
  619. //
  620. if (op->InternalFlags & IOP_CREATE_USE_TOP_DEVICE_OBJECT_HINT) {
  621. //
  622. // You cannot use the device object hint if you are trying to
  623. // open the device directly or if you are dealing with a device
  624. // that is not a file system. In these cases, return an error.
  625. //
  626. if (directDeviceOpen ||
  627. (deviceObject->DeviceType != FILE_DEVICE_DISK_FILE_SYSTEM &&
  628. deviceObject->DeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM &&
  629. deviceObject->DeviceType != FILE_DEVICE_TAPE_FILE_SYSTEM &&
  630. deviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM &&
  631. deviceObject->DeviceType != FILE_DEVICE_DFS_FILE_SYSTEM)) {
  632. if (vpb) {
  633. IopDereferenceVpbAndFree( vpb );
  634. }
  635. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  636. return STATUS_INVALID_PARAMETER;
  637. }
  638. if (IopVerifyDeviceObjectOnStack(deviceObject, op->TopDeviceObjectHint)) {
  639. deviceObject = op->TopDeviceObjectHint;
  640. } else {
  641. if (vpb) {
  642. IopDereferenceVpbAndFree(vpb);
  643. }
  644. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  645. if (op->TraversedMountPoint) {
  646. op->TraversedMountPoint = FALSE;
  647. return STATUS_MOUNT_POINT_NOT_RESOLVED;
  648. } else {
  649. return STATUS_INVALID_DEVICE_OBJECT_PARAMETER;
  650. }
  651. }
  652. } else {
  653. //
  654. // Walk the attached device list.
  655. //
  656. if (deviceObject->AttachedDevice) {
  657. deviceObject = IoGetAttachedDevice( deviceObject );
  658. }
  659. }
  660. }
  661. //
  662. // If the TraversedMountPoint flag is still set, clear it now. We needed
  663. // to keep it to return the correct status if IopVerifyDeviceObjectOnStack
  664. // failed above.
  665. //
  666. if (op->TraversedMountPoint) {
  667. op->TraversedMountPoint = FALSE;
  668. }
  669. //
  670. // If the driver says that the IO manager should do the access checks, lets do it here.
  671. // We do the check against the parse device object as that device object has a name
  672. // and we can set an ACL against it.
  673. // We only worry about related opens of devices as the other case is taken care of in the
  674. // filesystem.
  675. //
  676. if ((deviceObject->Characteristics & FILE_DEVICE_SECURE_OPEN) &&
  677. (AccessMode != KernelMode || op->Options & IO_FORCE_ACCESS_CHECK) &&
  678. (op->RelatedFileObject || RemainingName->Length) && (!relativeVolumeOpen)) {
  679. BOOLEAN subjectContextLocked = FALSE;
  680. BOOLEAN accessGranted;
  681. ACCESS_MASK grantedAccess;
  682. UNICODE_STRING nameString;
  683. PPRIVILEGE_SET privileges = NULL;
  684. //
  685. // If the device wants to ensure secure opens then lets check the two
  686. // cases which were skipped earlier. These cases are if its a relative
  687. // open or if there are trailing names.
  688. //
  689. KeEnterCriticalRegionThread( &CurrentThread->Tcb );
  690. ExAcquireResourceSharedLite( &IopSecurityResource, TRUE );
  691. SeLockSubjectContext( &AccessState->SubjectSecurityContext );
  692. subjectContextLocked = TRUE;
  693. accessGranted = SeAccessCheck( parseDeviceObject->SecurityDescriptor,
  694. &AccessState->SubjectSecurityContext,
  695. subjectContextLocked,
  696. desiredAccess,
  697. 0,
  698. &privileges,
  699. &IoFileObjectType->TypeInfo.GenericMapping,
  700. UserMode,
  701. &grantedAccess,
  702. &status );
  703. if (privileges) {
  704. (VOID) SeAppendPrivileges( AccessState,
  705. privileges );
  706. SeFreePrivileges( privileges );
  707. }
  708. if (accessGranted) {
  709. AccessState->PreviouslyGrantedAccess |= grantedAccess;
  710. AccessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  711. }
  712. nameString.Length = 8;
  713. nameString.MaximumLength = 8;
  714. nameString.Buffer = L"File";
  715. SeOpenObjectAuditAlarm( &nameString,
  716. deviceObject,
  717. CompleteName,
  718. parseDeviceObject->SecurityDescriptor,
  719. AccessState,
  720. FALSE,
  721. accessGranted,
  722. UserMode,
  723. &AccessState->GenerateOnClose );
  724. SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
  725. ExReleaseResourceLite( &IopSecurityResource );
  726. KeLeaveCriticalRegionThread( &CurrentThread->Tcb );
  727. if (!accessGranted) {
  728. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  729. if (vpb) {
  730. IopDereferenceVpbAndFree(vpb);
  731. }
  732. return STATUS_ACCESS_DENIED;
  733. }
  734. }
  735. //
  736. // Allocate and fill in the I/O Request Packet (IRP) to use in interfacing
  737. // to the driver. The allocation is done using an exception handler in
  738. // case the caller does not have enough quota to allocate the packet.
  739. //
  740. irp = IopAllocateIrp( deviceObject->StackSize, FALSE );
  741. if (!irp) {
  742. //
  743. // An IRP could not be allocated. Cleanup and return an appropriate
  744. // error status code.
  745. //
  746. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  747. if (vpb) {
  748. IopDereferenceVpbAndFree(vpb);
  749. }
  750. return STATUS_INSUFFICIENT_RESOURCES;
  751. }
  752. irp->Tail.Overlay.Thread = CurrentThread;
  753. irp->RequestorMode = AccessMode;
  754. irp->Flags = IRP_CREATE_OPERATION | IRP_SYNCHRONOUS_API | IRP_DEFER_IO_COMPLETION;
  755. securityContext.SecurityQos = SecurityQos;
  756. securityContext.AccessState = AccessState;
  757. securityContext.DesiredAccess = desiredAccess;
  758. securityContext.FullCreateOptions = op->CreateOptions;
  759. //
  760. // Get a pointer to the stack location for the first driver. This is where
  761. // the original function codes and parameters are passed.
  762. //
  763. irpSp = IoGetNextIrpStackLocation( irp );
  764. irpSp->Control = 0;
  765. if (op->CreateFileType == CreateFileTypeNone) {
  766. //
  767. // This is a normal file open or create function.
  768. //
  769. irpSp->MajorFunction = IRP_MJ_CREATE;
  770. irpSp->Parameters.Create.EaLength = op->EaLength;
  771. irpSp->Flags = (UCHAR) op->Options;
  772. if (!(Attributes & OBJ_CASE_INSENSITIVE)) {
  773. irpSp->Flags |= SL_CASE_SENSITIVE;
  774. }
  775. } else if (op->CreateFileType == CreateFileTypeNamedPipe) {
  776. //
  777. // A named pipe is being created.
  778. //
  779. irpSp->MajorFunction = IRP_MJ_CREATE_NAMED_PIPE;
  780. irpSp->Parameters.CreatePipe.Parameters = op->ExtraCreateParameters;
  781. } else {
  782. //
  783. // A mailslot is being created.
  784. //
  785. irpSp->MajorFunction = IRP_MJ_CREATE_MAILSLOT;
  786. irpSp->Parameters.CreateMailslot.Parameters = op->ExtraCreateParameters;
  787. }
  788. //
  789. // Also fill in the NtCreateFile service's caller's parameters.
  790. //
  791. irp->Overlay.AllocationSize = op->AllocationSize;
  792. irp->AssociatedIrp.SystemBuffer = op->EaBuffer;
  793. irpSp->Parameters.Create.Options = (op->Disposition << 24) | (op->CreateOptions & 0x00ffffff);
  794. irpSp->Parameters.Create.FileAttributes = op->FileAttributes;
  795. irpSp->Parameters.Create.ShareAccess = op->ShareAccess;
  796. irpSp->Parameters.Create.SecurityContext = &securityContext;
  797. //
  798. // Fill in local parameters so this routine can determine when the I/O is
  799. // finished, and the normal I/O completion code will not get any errors.
  800. //
  801. irp->UserIosb = &ioStatus;
  802. irp->MdlAddress = (PMDL) NULL;
  803. irp->PendingReturned = FALSE;
  804. irp->Cancel = FALSE;
  805. irp->UserEvent = (PKEVENT) NULL;
  806. irp->CancelRoutine = (PDRIVER_CANCEL) NULL;
  807. irp->Tail.Overlay.AuxiliaryBuffer = (PVOID) NULL;
  808. //
  809. // Allocate and initialize the file object that will be used in dealing
  810. // with the device for the remainder of this session with the user. How
  811. // the file object is allocated is based on whether or not a real file
  812. // object is actually required. It is not required for the query and
  813. // delete only operations.
  814. //
  815. if (realFileObjectRequired) {
  816. OBJECT_ATTRIBUTES objectAttributes;
  817. ULONG fileObjectSize;
  818. //
  819. // A real, full-blown file object is actually required.
  820. //
  821. InitializeObjectAttributes( &objectAttributes,
  822. (PUNICODE_STRING) NULL,
  823. Attributes,
  824. (HANDLE) NULL,
  825. (PSECURITY_DESCRIPTOR) NULL
  826. );
  827. if (op->InternalFlags &
  828. (IOP_CREATE_USE_TOP_DEVICE_OBJECT_HINT|IOP_CREATE_IGNORE_SHARE_ACCESS_CHECK)) {
  829. fileObjectSize = sizeof(FILE_OBJECT) + sizeof(IOP_FILE_OBJECT_EXTENSION);
  830. } else {
  831. fileObjectSize = sizeof(FILE_OBJECT);
  832. }
  833. status = ObCreateObject( KernelMode,
  834. IoFileObjectType,
  835. &objectAttributes,
  836. AccessMode,
  837. (PVOID) NULL,
  838. fileObjectSize,
  839. 0,
  840. 0,
  841. (PVOID *) &fileObject );
  842. if (!NT_SUCCESS( status )) {
  843. IoFreeIrp( irp );
  844. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  845. if (vpb) {
  846. IopDereferenceVpbAndFree(vpb);
  847. }
  848. return op->FinalStatus = status;
  849. }
  850. IopPerfLogFileCreate(fileObject, CompleteName);
  851. RtlZeroMemory( fileObject, sizeof( FILE_OBJECT ) );
  852. if (op->CreateOptions & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)) {
  853. fileObject->Flags = FO_SYNCHRONOUS_IO;
  854. if (op->CreateOptions & FILE_SYNCHRONOUS_IO_ALERT) {
  855. fileObject->Flags |= FO_ALERTABLE_IO;
  856. }
  857. }
  858. if (op->InternalFlags &
  859. (IOP_CREATE_USE_TOP_DEVICE_OBJECT_HINT|IOP_CREATE_IGNORE_SHARE_ACCESS_CHECK)) {
  860. PIOP_FILE_OBJECT_EXTENSION fileObjectExtension;
  861. fileObject->Flags |= FO_FILE_OBJECT_HAS_EXTENSION;
  862. fileObjectExtension = (PIOP_FILE_OBJECT_EXTENSION)(fileObject + 1);
  863. fileObjectExtension->FileObjectExtensionFlags = 0;
  864. fileObjectExtension->TopDeviceObjectHint = NULL;
  865. fileObjectExtension->FilterContext = NULL;
  866. if (op->InternalFlags & IOP_CREATE_USE_TOP_DEVICE_OBJECT_HINT) {
  867. fileObjectExtension->TopDeviceObjectHint = deviceObject;
  868. }
  869. if (op->InternalFlags & IOP_CREATE_IGNORE_SHARE_ACCESS_CHECK) {
  870. fileObjectExtension->FileObjectExtensionFlags |=FO_EXTENSION_IGNORE_SHARE_ACCESS_CHECK;
  871. }
  872. }
  873. //
  874. // Now fill in the file object as best is possible at this point and set
  875. // a pointer to it in the IRP so everyone else can find it.
  876. //
  877. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  878. KeInitializeEvent( &fileObject->Lock, SynchronizationEvent, FALSE );
  879. fileObject->Waiters = 0;
  880. fileObject->CurrentByteOffset.QuadPart = 0;
  881. }
  882. if (op->CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING) {
  883. fileObject->Flags |= FO_NO_INTERMEDIATE_BUFFERING;
  884. }
  885. if (op->CreateOptions & FILE_WRITE_THROUGH) {
  886. fileObject->Flags |= FO_WRITE_THROUGH;
  887. }
  888. if (op->CreateOptions & FILE_SEQUENTIAL_ONLY) {
  889. fileObject->Flags |= FO_SEQUENTIAL_ONLY;
  890. }
  891. if (op->CreateOptions & FILE_RANDOM_ACCESS) {
  892. fileObject->Flags |= FO_RANDOM_ACCESS;
  893. }
  894. } else {
  895. //
  896. // This is either a quick delete or query operation. For these cases,
  897. // it is possible to optimize the Object Manager out of the picture by
  898. // simply putting together something that "looks" like a file object,
  899. // and then operating on it.
  900. //
  901. localFileObject = op->LocalFileObject;
  902. RtlZeroMemory( localFileObject, sizeof( DUMMY_FILE_OBJECT ) );
  903. fileObject = (PFILE_OBJECT) &localFileObject->ObjectHeader.Body;
  904. localFileObject->ObjectHeader.Type = IoFileObjectType;
  905. localFileObject->ObjectHeader.PointerCount = 1;
  906. }
  907. if (directDeviceOpen) {
  908. fileObject->Flags |= FO_DIRECT_DEVICE_OPEN;
  909. }
  910. if (!(Attributes & OBJ_CASE_INSENSITIVE)) {
  911. fileObject->Flags |= FO_OPENED_CASE_SENSITIVE;
  912. }
  913. fileObject->Type = IO_TYPE_FILE;
  914. fileObject->Size = sizeof( FILE_OBJECT );
  915. fileObject->RelatedFileObject = op->RelatedFileObject;
  916. fileObject->DeviceObject = parseDeviceObject;
  917. irp->Tail.Overlay.OriginalFileObject = fileObject;
  918. irpSp->FileObject = fileObject;
  919. //
  920. // Allocate a file name string buffer which is large enough to contain
  921. // the entire remaining name string and initialize the maximum length.
  922. //
  923. if (RemainingName->Length) {
  924. fileObject->FileName.MaximumLength = RoundNameSize( RemainingName->Length );
  925. fileObject->FileName.Buffer = ExAllocatePoolWithTag( PagedPool,
  926. fileObject->FileName.MaximumLength,
  927. 'mNoI' );
  928. if (!fileObject->FileName.Buffer) {
  929. IoFreeIrp( irp );
  930. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  931. if (vpb) {
  932. IopDereferenceVpbAndFree(vpb);
  933. }
  934. fileObject->DeviceObject = (PDEVICE_OBJECT) NULL;
  935. if (realFileObjectRequired) {
  936. ObDereferenceObject( fileObject );
  937. }
  938. return STATUS_INSUFFICIENT_RESOURCES;
  939. }
  940. }
  941. //
  942. // Now copy the name string into the file object from the remaining name
  943. // that is being reparsed. If the driver decides to reparse, then it must
  944. // replace this name.
  945. //
  946. RtlCopyUnicodeString( &fileObject->FileName, RemainingName );
  947. //
  948. // Before invoking the driver's open routine, check to see whether or not
  949. // this is a fast network attributes query and, if so, and the driver
  950. // implements the function, attempt to call it here.
  951. //
  952. if (op->QueryOnly) {
  953. PFAST_IO_DISPATCH fastIoDispatch = deviceObject->DriverObject->FastIoDispatch;
  954. BOOLEAN result;
  955. if (fastIoDispatch &&
  956. fastIoDispatch->SizeOfFastIoDispatch > FIELD_OFFSET( FAST_IO_DISPATCH, FastIoQueryOpen ) &&
  957. fastIoDispatch->FastIoQueryOpen) {
  958. IoSetNextIrpStackLocation( irp );
  959. irpSp->DeviceObject = deviceObject;
  960. result = (fastIoDispatch->FastIoQueryOpen)( irp,
  961. op->NetworkInformation,
  962. deviceObject );
  963. if (result) {
  964. op->FinalStatus = irp->IoStatus.Status;
  965. op->Information = irp->IoStatus.Information;
  966. //
  967. // The operation worked, so simply dereference and free the
  968. // resources acquired up to this point.
  969. //
  970. if ((op->FinalStatus == STATUS_REPARSE) &&
  971. irp->Tail.Overlay.AuxiliaryBuffer) {
  972. ASSERT( op->Information > IO_REPARSE_TAG_RESERVED_ONE );
  973. ExFreePool( irp->Tail.Overlay.AuxiliaryBuffer );
  974. irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  975. op->RelatedFileObject = (PFILE_OBJECT) NULL;
  976. }
  977. if (fileObject->FileName.Length) {
  978. ExFreePool( fileObject->FileName.Buffer );
  979. }
  980. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  981. if (vpb) {
  982. IopDereferenceVpbAndFree(vpb);
  983. }
  984. #if DBG
  985. irp->CurrentLocation = irp->StackCount + 2;
  986. #endif // DBG
  987. IoFreeIrp( irp );
  988. //
  989. // Finally, indicate that the parse routine was actually
  990. // invoked and that the information returned herein can be
  991. // used.
  992. //
  993. op->ParseCheck = OPEN_PACKET_PATTERN;
  994. status = STATUS_SUCCESS;
  995. if (!op->FullAttributes) {
  996. try {
  997. op->BasicInformation->FileAttributes = op->NetworkInformation->FileAttributes;
  998. } except(EXCEPTION_EXECUTE_HANDLER) {
  999. status = GetExceptionCode();
  1000. }
  1001. }
  1002. return status;
  1003. } else {
  1004. //
  1005. // The fast I/O operation did not work, so take the longer
  1006. // route.
  1007. //
  1008. irp->Tail.Overlay.CurrentStackLocation++;
  1009. irp->CurrentLocation++;
  1010. }
  1011. }
  1012. }
  1013. //
  1014. // Finally, initialize the file object's event to the Not Signaled state
  1015. // and remember that a file object was created.
  1016. //
  1017. KeInitializeEvent( &fileObject->Event, NotificationEvent, FALSE );
  1018. op->FileObject = fileObject;
  1019. //
  1020. // Insert the packet at the head of the IRP list for the thread.
  1021. //
  1022. IopQueueThreadIrp( irp );
  1023. //
  1024. // Now invoke the driver itself to open the file.
  1025. //
  1026. status = IoCallDriver( deviceObject, irp );
  1027. //
  1028. // One of four things may have happened when the driver was invoked:
  1029. //
  1030. // 1. The I/O operation is pending (Status == STATUS_PENDING). This can
  1031. // occur on devices which need to perform some sort of device
  1032. // manipulation (such as opening a file for a file system).
  1033. //
  1034. // 2. The driver returned an error (Status < 0). This occurs when either
  1035. // a supplied parameter was in error, or the device or file system
  1036. // incurred or discovered an error.
  1037. //
  1038. // 3. The operation ended in a reparse (Status == STATUS_REPARSE). This
  1039. // occurs when a file system opens the file, only to discover that it
  1040. // represents a symbolic link.
  1041. //
  1042. // 4. The operation is complete and was successful (Status ==
  1043. // STATUS_SUCCESS). Note that for this case the only action is to
  1044. // return a pointer to the file object.
  1045. //
  1046. if (status == STATUS_PENDING) {
  1047. (VOID) KeWaitForSingleObject( &fileObject->Event,
  1048. Executive,
  1049. KernelMode,
  1050. FALSE,
  1051. (PLARGE_INTEGER) NULL );
  1052. status = ioStatus.Status;
  1053. } else {
  1054. //
  1055. // The I/O operation was completed without returning a status of
  1056. // pending. This means that at this point, the IRP has not been
  1057. // fully completed. Complete it now.
  1058. //
  1059. KIRQL irql;
  1060. ASSERT( !irp->PendingReturned );
  1061. ASSERT( !irp->MdlAddress );
  1062. //
  1063. // In the case of name junctions do the transmogrify work.
  1064. //
  1065. if (irp->IoStatus.Status == STATUS_REPARSE &&
  1066. irp->IoStatus.Information == IO_REPARSE_TAG_MOUNT_POINT ) {
  1067. PREPARSE_DATA_BUFFER reparseBuffer = NULL;
  1068. ASSERT ( irp->Tail.Overlay.AuxiliaryBuffer != NULL );
  1069. reparseBuffer = (PREPARSE_DATA_BUFFER) irp->Tail.Overlay.AuxiliaryBuffer;
  1070. ASSERT( reparseBuffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT );
  1071. ASSERT( reparseBuffer->ReparseDataLength < MAXIMUM_REPARSE_DATA_BUFFER_SIZE );
  1072. ASSERT( reparseBuffer->Reserved < MAXIMUM_REPARSE_DATA_BUFFER_SIZE );
  1073. IopDoNameTransmogrify( irp,
  1074. fileObject,
  1075. reparseBuffer );
  1076. }
  1077. //
  1078. // Now finish up the request.
  1079. //
  1080. KeRaiseIrql( APC_LEVEL, &irql );
  1081. //
  1082. // Note that normally the system would simply call IopCompleteRequest
  1083. // here to complete the packet. However, because this is a create
  1084. // operation, several assumptions can be made that make it much faster
  1085. // to perform the couple of operations that completing the request
  1086. // would perform. These include: copying the I/O status block,
  1087. // dequeueing the IRP and freeing it, and setting the file object's
  1088. // event to the signalled state. The latter is done here by hand,
  1089. // since it is known that it is not possible for any thread to be
  1090. // waiting on the event.
  1091. //
  1092. ioStatus = irp->IoStatus;
  1093. status = ioStatus.Status;
  1094. fileObject->Event.Header.SignalState = 1;
  1095. IopDequeueThreadIrp( irp );
  1096. //
  1097. // The SystemBuffer is in some cases used by the driver, and
  1098. // needs to be freed if present.
  1099. //
  1100. if ((irp->Flags & IRP_BUFFERED_IO) && (irp->Flags & IRP_DEALLOCATE_BUFFER)) {
  1101. ExFreePool(irp->AssociatedIrp.SystemBuffer);
  1102. }
  1103. IoFreeIrp( irp );
  1104. KeLowerIrql( irql );
  1105. }
  1106. //
  1107. // Copy the information field of the I/O status block back to the
  1108. // original caller in case it is required.
  1109. //
  1110. op->Information = ioStatus.Information;
  1111. if (!NT_SUCCESS( status )) {
  1112. int openCancelled;
  1113. //
  1114. // The operation ended in an error. Kill the file object, dereference
  1115. // the device object, and return a null pointer.
  1116. //
  1117. if (fileObject->FileName.Length) {
  1118. ExFreePool( fileObject->FileName.Buffer );
  1119. fileObject->FileName.Length = 0;
  1120. }
  1121. fileObject->DeviceObject = (PDEVICE_OBJECT) NULL;
  1122. openCancelled = (fileObject->Flags & FO_FILE_OPEN_CANCELLED);
  1123. if (realFileObjectRequired) {
  1124. ObDereferenceObject( fileObject );
  1125. }
  1126. op->FileObject = (PFILE_OBJECT) NULL;
  1127. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  1128. if ((!openCancelled) && (vpb )) {
  1129. IopDereferenceVpbAndFree(vpb);
  1130. }
  1131. return op->FinalStatus = status;
  1132. } else if (status == STATUS_REPARSE) {
  1133. //
  1134. // The operation resulted in a reparse. This means that the file
  1135. // name in the file object is the new name to be looked up. Replace
  1136. // the complete name string with the new name and return STATUS_REPARSE
  1137. // so the object manager knows to start over again. Note, however,
  1138. // that the file name buffer in the file object itself is kept intact
  1139. // so that it can be reused when coming back here again.
  1140. //
  1141. // A reparse status may also have been returned from the file system if
  1142. // the volume that was in a drive needed to have been verified, but
  1143. // the verification failed, and a new volume was mounted. In this
  1144. // case, everything starts over again using the new volume.
  1145. //
  1146. ASSERT( IO_REPARSE == IO_REPARSE_TAG_RESERVED_ZERO );
  1147. if ((ioStatus.Information == IO_REPARSE) ||
  1148. (ioStatus.Information == IO_REPARSE_TAG_MOUNT_POINT)) {
  1149. //
  1150. // If the complete name buffer isn't large enough, reallocate it.
  1151. //
  1152. if (CompleteName->MaximumLength < fileObject->FileName.Length) {
  1153. PVOID buffer;
  1154. buffer = ExAllocatePoolWithTag( PagedPool,
  1155. fileObject->FileName.Length,
  1156. 'cFoI' );
  1157. if (!buffer) {
  1158. return op->FinalStatus = STATUS_INSUFFICIENT_RESOURCES;
  1159. } else {
  1160. if (CompleteName->Buffer) {
  1161. ExFreePool( CompleteName->Buffer );
  1162. }
  1163. CompleteName->Buffer = buffer;
  1164. CompleteName->MaximumLength = fileObject->FileName.Length;
  1165. }
  1166. }
  1167. RtlCopyUnicodeString( CompleteName, &fileObject->FileName );
  1168. //
  1169. // For NTFS directory junction points we NULL the RelatedFileObject.
  1170. // If the prior call was a relative open, the subsequent one will
  1171. // not be.
  1172. //
  1173. if (ioStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) {
  1174. op->RelatedFileObject = (PFILE_OBJECT) NULL;
  1175. }
  1176. }
  1177. //
  1178. // Kill the file object, dereference the device object, and return a
  1179. // null pointer.
  1180. //
  1181. if (fileObject->FileName.Length) {
  1182. ExFreePool( fileObject->FileName.Buffer );
  1183. fileObject->FileName.Length = 0;
  1184. }
  1185. fileObject->DeviceObject = (PDEVICE_OBJECT) NULL;
  1186. if (realFileObjectRequired) {
  1187. ObDereferenceObject( fileObject );
  1188. }
  1189. op->FileObject = (PFILE_OBJECT) NULL;
  1190. IopDecrementDeviceObjectRef( parseDeviceObject, FALSE, FALSE );
  1191. if (vpb) {
  1192. IopDereferenceVpbAndFree(vpb);
  1193. }
  1194. ASSERT( IO_REMOUNT == IO_REPARSE_TAG_RESERVED_ONE );
  1195. if (ioStatus.Information == IO_REPARSE_TAG_RESERVED_ONE) {
  1196. //
  1197. // If we are reparsing to verify a volume, restart the reparse
  1198. // by attempting to parse the device once again. Note that it
  1199. // would be best to simply recurse, but it's not possible since
  1200. // there is a limited amount of stack available to kernel mode
  1201. // and a limit needs to be enforced for the number of times that
  1202. // verify reparse can occur.
  1203. //
  1204. if (++retryCount > IO_MAX_REMOUNT_REPARSE_ATTEMPTS) {
  1205. return STATUS_UNSUCCESSFUL;
  1206. }
  1207. goto reparse_loop;
  1208. } else {
  1209. //
  1210. // Really reparsing a symbolic link, so go back to the object
  1211. // manager so it can begin the parse from the top.
  1212. //
  1213. op->RelatedFileObject = (PFILE_OBJECT) NULL;
  1214. //
  1215. // Note that the mountpoint should be set only for the correct
  1216. // tag. IO_REMOUNT is sent by FAT,CDFS and UDFS to remount a volume.
  1217. // IO_REPARSE is set by the network filesystems to just use a different path.
  1218. //
  1219. if (ioStatus.Information == IO_REPARSE_TAG_MOUNT_POINT) {
  1220. op->TraversedMountPoint = TRUE;
  1221. }
  1222. //
  1223. // No driver should return this status for a volume open.
  1224. // If they do then we would skip the security check as override is true.
  1225. // To catch that case we bugcheck here.
  1226. //
  1227. if (op->Override) {
  1228. KeBugCheckEx(DRIVER_RETURNED_STATUS_REPARSE_FOR_VOLUME_OPEN,
  1229. (ULONG_PTR)parseDeviceObject,
  1230. (ULONG_PTR)deviceObject,
  1231. (ULONG_PTR)CompleteName,
  1232. (ULONG_PTR)ioStatus.Information
  1233. );
  1234. }
  1235. return STATUS_REPARSE;
  1236. }
  1237. } else {
  1238. //
  1239. // The operation was successful. The first thing to do is to see if
  1240. // the device that processed the open also opened the file. If
  1241. // not, we need to adjust the vpb reference counts. Then, if this is
  1242. // not a query or a delete, but rather a normal open/create, return
  1243. // the address of the FileObject to the caller and set the
  1244. // information returned in the original requestor's I/O status block.
  1245. // Also set the value of the parse check field in the open packet to
  1246. // a value which will let the caller know that this routine was
  1247. // successful in creating the file object. Finally, return the status
  1248. // of the operation to the caller.
  1249. //
  1250. PDEVICE_OBJECT deviceObjectThatOpenedFile;
  1251. deviceObjectThatOpenedFile = IoGetRelatedDeviceObject(fileObject);
  1252. if (deviceObject != deviceObjectThatOpenedFile) {
  1253. PVPB newVpb;
  1254. //
  1255. // The device that opened the related file is not the one
  1256. // that opened this file. So, readjust the vpb reference
  1257. // counts.
  1258. //
  1259. newVpb = fileObject->Vpb;
  1260. //
  1261. // If the new VPB is not the same as the original VPB
  1262. // then reference the new one before freeing the old one.
  1263. // If a filter was just added to the fileobject stack the VPB will not
  1264. // change. So check for a difference in VPB as well.
  1265. //
  1266. if (newVpb != vpb) {
  1267. if (newVpb) {
  1268. IopInterlockedIncrementUlong( LockQueueIoVpbLock,
  1269. (PLONG) &newVpb->ReferenceCount);
  1270. }
  1271. if (vpb) {
  1272. IopDereferenceVpbAndFree(vpb);
  1273. }
  1274. }
  1275. }
  1276. if (realFileObjectRequired) {
  1277. *Object = fileObject;
  1278. op->ParseCheck = OPEN_PACKET_PATTERN;
  1279. //
  1280. // Add a reference so the file object cannot go away before
  1281. // the create routine gets chance to flag the object for handle
  1282. // create.
  1283. //
  1284. ObReferenceObject( fileObject );
  1285. //
  1286. // If the filename length is zero and its not a relative open or
  1287. // its a relative open to a volume open then set the volume open flag.
  1288. // Also set it only for filesystem device object volume.
  1289. //
  1290. if ((!fileObject->RelatedFileObject || fileObject->RelatedFileObject->Flags & FO_VOLUME_OPEN) &&
  1291. (!fileObject->FileName.Length)) {
  1292. switch (deviceObjectThatOpenedFile->DeviceType) {
  1293. case FILE_DEVICE_DISK_FILE_SYSTEM:
  1294. case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
  1295. case FILE_DEVICE_TAPE_FILE_SYSTEM:
  1296. case FILE_DEVICE_FILE_SYSTEM:
  1297. fileObject->Flags |= FO_VOLUME_OPEN;
  1298. break;
  1299. default:
  1300. break;
  1301. }
  1302. }
  1303. return op->FinalStatus = ioStatus.Status;
  1304. } else {
  1305. //
  1306. // This is either a quick query or delete operation. Determine
  1307. // which it is and quickly perform the operation.
  1308. //
  1309. if (op->QueryOnly) {
  1310. PFAST_IO_DISPATCH fastIoDispatch;
  1311. BOOLEAN queryResult = FALSE;
  1312. fastIoDispatch = deviceObjectThatOpenedFile->DriverObject->FastIoDispatch;
  1313. if (!op->FullAttributes) {
  1314. PFILE_BASIC_INFORMATION basicInfo = NULL;
  1315. //
  1316. // This is a simple FAT file attribute query. Attempt to
  1317. // obtain the basic information about the file.
  1318. //
  1319. try {
  1320. if (fastIoDispatch && fastIoDispatch->FastIoQueryBasicInfo) {
  1321. queryResult = fastIoDispatch->FastIoQueryBasicInfo(
  1322. fileObject,
  1323. TRUE,
  1324. op->BasicInformation,
  1325. &ioStatus,
  1326. deviceObjectThatOpenedFile
  1327. );
  1328. }
  1329. if (!queryResult) {
  1330. basicInfo = ExAllocatePool( NonPagedPool,
  1331. sizeof( FILE_BASIC_INFORMATION ) );
  1332. if (basicInfo) {
  1333. status = IoQueryFileInformation(
  1334. fileObject,
  1335. FileBasicInformation,
  1336. sizeof( FILE_BASIC_INFORMATION ),
  1337. basicInfo,
  1338. &returnedLength
  1339. );
  1340. if (NT_SUCCESS( status )) {
  1341. RtlCopyMemory( op->BasicInformation,
  1342. basicInfo,
  1343. returnedLength );
  1344. }
  1345. ExFreePool( basicInfo );
  1346. } else {
  1347. status = STATUS_INSUFFICIENT_RESOURCES;
  1348. }
  1349. } else {
  1350. status = ioStatus.Status;
  1351. }
  1352. } except(EXCEPTION_EXECUTE_HANDLER) {
  1353. if (basicInfo) {
  1354. ExFreePool( basicInfo );
  1355. }
  1356. status = GetExceptionCode();
  1357. }
  1358. } else {
  1359. //
  1360. // This is a full attribute query. Attempt to obtain the
  1361. // full network attributes for the file. This includes
  1362. // both the basic and standard information about the
  1363. // file. Try the fast path first, if it exists.
  1364. //
  1365. if (fastIoDispatch &&
  1366. fastIoDispatch->SizeOfFastIoDispatch > FIELD_OFFSET( FAST_IO_DISPATCH, FastIoQueryNetworkOpenInfo ) &&
  1367. fastIoDispatch->FastIoQueryNetworkOpenInfo) {
  1368. queryResult = fastIoDispatch->FastIoQueryNetworkOpenInfo(
  1369. fileObject,
  1370. TRUE,
  1371. op->NetworkInformation,
  1372. &ioStatus,
  1373. deviceObjectThatOpenedFile
  1374. );
  1375. }
  1376. if (!queryResult) {
  1377. //
  1378. // Either the fast dispatch routine did not exist, or
  1379. // it simply wasn't callable at this time. Attempt to
  1380. // obtain all of the information at once via an IRP-
  1381. // based call.
  1382. //
  1383. status = IoQueryFileInformation(
  1384. fileObject,
  1385. FileNetworkOpenInformation,
  1386. sizeof( FILE_NETWORK_OPEN_INFORMATION ),
  1387. op->NetworkInformation,
  1388. &returnedLength
  1389. );
  1390. if (!NT_SUCCESS( status )) {
  1391. if (status == STATUS_INVALID_PARAMETER ||
  1392. status == STATUS_NOT_IMPLEMENTED) {
  1393. status = IopGetNetworkOpenInformation(fileObject, op);
  1394. }
  1395. }
  1396. }
  1397. }
  1398. } else {
  1399. //
  1400. // There is nothing to do for a quick delete since the caller
  1401. // set the FILE_DELETE_ON_CLOSE CreateOption so it is already
  1402. // set in the file system.
  1403. //
  1404. NOTHING;
  1405. }
  1406. op->ParseCheck = OPEN_PACKET_PATTERN;
  1407. if (realFileObjectRequired) {
  1408. ObDereferenceObject( fileObject );
  1409. } else {
  1410. IopDeleteFile( fileObject );
  1411. }
  1412. op->FileObject = (PFILE_OBJECT) NULL;
  1413. op->FinalStatus = status;
  1414. return status;
  1415. }
  1416. }
  1417. }
  1418. NTSTATUS
  1419. IopGetNetworkOpenInformation(
  1420. IN PFILE_OBJECT FileObject,
  1421. IN POPEN_PACKET Op
  1422. )
  1423. /*++
  1424. Routine Description:
  1425. This routines gets the network information in two steps.
  1426. Its called out as a separate routine from IopParseDevice to save stack for
  1427. common create paths.
  1428. Arguments:
  1429. FileObject - Pointer to the fileobject for the opened file.
  1430. Op - Pointer to the open packet.
  1431. Return Value:
  1432. NTSTATUS
  1433. --*/
  1434. {
  1435. #define COPY_ATTRIBUTES( n, b, s ) { \
  1436. (n)->CreationTime.QuadPart = (b)->CreationTime.QuadPart; \
  1437. (n)->LastAccessTime.QuadPart = (b)->LastAccessTime.QuadPart; \
  1438. (n)->LastWriteTime.QuadPart = (b)->LastWriteTime.QuadPart; \
  1439. (n)->ChangeTime.QuadPart = (b)->ChangeTime.QuadPart; \
  1440. (n)->AllocationSize.QuadPart = (s)->AllocationSize.QuadPart; \
  1441. (n)->EndOfFile.QuadPart = (s)->EndOfFile.QuadPart; \
  1442. (n)->FileAttributes = (b)->FileAttributes; }
  1443. FILE_BASIC_INFORMATION basicInfo;
  1444. FILE_STANDARD_INFORMATION stdInfo;
  1445. ULONG returnedLength;
  1446. NTSTATUS status;
  1447. PAGED_CODE();
  1448. //
  1449. // The IRP-based call did not work either, so
  1450. // simply try to obtain the information by
  1451. // doing IRP-based queries for the basic and
  1452. // standard information and piecing together
  1453. // the results into the caller's buffer. Note
  1454. // that it might be possible to perform fast
  1455. // I/O operations to get the data, but it
  1456. // might also fail because of the above. So
  1457. // simply query the information the long way.
  1458. //
  1459. status = IoQueryFileInformation(
  1460. FileObject,
  1461. FileBasicInformation,
  1462. sizeof( FILE_BASIC_INFORMATION ),
  1463. &basicInfo,
  1464. &returnedLength
  1465. );
  1466. if (NT_SUCCESS( status )) {
  1467. status = IoQueryFileInformation(
  1468. FileObject,
  1469. FileStandardInformation,
  1470. sizeof( FILE_STANDARD_INFORMATION ),
  1471. &stdInfo,
  1472. &returnedLength
  1473. );
  1474. if (NT_SUCCESS( status )) {
  1475. COPY_ATTRIBUTES( Op->NetworkInformation,
  1476. &basicInfo,
  1477. &stdInfo );
  1478. }
  1479. }
  1480. return status;
  1481. }
  1482. NTSTATUS
  1483. IopParseFile(
  1484. IN PVOID ParseObject,
  1485. IN PVOID ObjectType,
  1486. IN PACCESS_STATE AccessState,
  1487. IN KPROCESSOR_MODE AccessMode,
  1488. IN ULONG Attributes,
  1489. IN OUT PUNICODE_STRING CompleteName,
  1490. IN OUT PUNICODE_STRING RemainingName,
  1491. IN OUT PVOID Context OPTIONAL,
  1492. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  1493. OUT PVOID *Object
  1494. )
  1495. /*++
  1496. Routine Description:
  1497. This routine interfaces to the NT Object Manager. It is invoked when
  1498. the object system is given the name of an entity to create or open and is
  1499. also given a handle to a directory file object that the operation is to be
  1500. performed relative to. This routine is specified as the parse routine for
  1501. all file objects.
  1502. This routine simply invokes the parse routine for the appropriate device
  1503. that is associated with the file object. It is the responsibility of that
  1504. routine to perform the operation.
  1505. Arguments:
  1506. ParseObject - Pointer to the file object that the name is to be opened or
  1507. created relative to.
  1508. ObjectType - Type of the object being opened.
  1509. AccessState - Running security access state information for operation.
  1510. AccessMode - Access mode of the original caller.
  1511. Attributes - Attributes to be applied to the object.
  1512. CompleteName - Complete name of the object.
  1513. RemainingName - Remaining name of the object.
  1514. Context - Pointer to an Open Packet (OP) from NtCreateFile service.
  1515. SecurityQos - Supplies a pointer to the captured QOS information
  1516. if available.
  1517. Object - The address of a variable to receive the created file object, if
  1518. any.
  1519. Return Value:
  1520. The function return value is one of the following:
  1521. a) Success - This indicates that the function succeeded and the object
  1522. parameter contains the address of the created file object.
  1523. b) Error - This indicates that the file was not found or created and
  1524. no file object was created.
  1525. c) Reparse - This indicates that the remaining name string has been
  1526. replaced by a new name that is to be parsed.
  1527. --*/
  1528. {
  1529. PDEVICE_OBJECT deviceObject;
  1530. POPEN_PACKET op;
  1531. PAGED_CODE();
  1532. //
  1533. // Get the address of the Open Packet (OP).
  1534. //
  1535. op = (POPEN_PACKET) Context;
  1536. //
  1537. // Ensure that this routine is actually being invoked because someone is
  1538. // attempting to open a device or a file through NtCreateFile. This code
  1539. // must be invoked from there (as opposed to some other random object
  1540. // create or open routine).
  1541. //
  1542. if (op == NULL ||
  1543. op->Type != IO_TYPE_OPEN_PACKET ||
  1544. op->Size != sizeof( OPEN_PACKET )) {
  1545. return STATUS_OBJECT_TYPE_MISMATCH;
  1546. }
  1547. //
  1548. // Get a pointer to the device object for this file.
  1549. //
  1550. deviceObject = IoGetRelatedDeviceObject( (PFILE_OBJECT) ParseObject );
  1551. //
  1552. // Pass the related file object to the device object parse routine.
  1553. //
  1554. op->RelatedFileObject = (PFILE_OBJECT) ParseObject;
  1555. //
  1556. // Open or create the specified file.
  1557. //
  1558. return IopParseDevice( deviceObject,
  1559. ObjectType,
  1560. AccessState,
  1561. AccessMode,
  1562. Attributes,
  1563. CompleteName,
  1564. RemainingName,
  1565. Context,
  1566. SecurityQos,
  1567. Object );
  1568. }
  1569. NTSTATUS
  1570. IopQueryNameInternal(
  1571. IN PVOID Object,
  1572. IN BOOLEAN HasObjectName,
  1573. IN BOOLEAN UseDosDeviceName,
  1574. OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
  1575. IN ULONG Length,
  1576. OUT PULONG ReturnLength,
  1577. IN KPROCESSOR_MODE Mode
  1578. )
  1579. /*++
  1580. Routine Description:
  1581. This function implements the query name procedure for the Object Manager
  1582. for querying the names of file objects.
  1583. Arguments:
  1584. Object - Pointer to the file object whose name is to be retrieved.
  1585. HasObjectName - Indicates whether or not the object has a name.
  1586. UseDosDeviceName - Indicates whether to translate the device object part
  1587. of the fileobject into the dosdevice name space or the
  1588. regular \device namespace via ob
  1589. ObjectNameInfo - Buffer in which to return the name.
  1590. Length - Specifies the length of the output buffer, in bytes.
  1591. ReturnLength - Specifies the number of bytes actually returned in the
  1592. output buffer or the number of bytes needed if Length is smaller
  1593. than needed.
  1594. Return Value:
  1595. The function return value is the final status of the query operation.
  1596. --*/
  1597. {
  1598. NTSTATUS status;
  1599. ULONG lengthNeeded;
  1600. PFILE_OBJECT fileObject;
  1601. PUCHAR buffer;
  1602. PWSTR p;
  1603. POBJECT_NAME_INFORMATION deviceNameInfo;
  1604. PFILE_NAME_INFORMATION fileNameInfo;
  1605. ULONG length;
  1606. BOOLEAN deviceNameOverflow;
  1607. BOOLEAN dosLookupSuccess = 0;
  1608. UNREFERENCED_PARAMETER( HasObjectName );
  1609. PAGED_CODE();
  1610. ASSERT( FIELD_OFFSET( FILE_NAME_INFORMATION, FileName ) < sizeof( OBJECT_NAME_INFORMATION ) );
  1611. //
  1612. // Ensure that the size of the output buffer is at least the minimum
  1613. // size required to include the basic object name information structure.
  1614. //
  1615. if (Length < sizeof( OBJECT_NAME_INFORMATION )) {
  1616. *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
  1617. return STATUS_INFO_LENGTH_MISMATCH;
  1618. }
  1619. //
  1620. // Begin by allocating a buffer in which to build the name of the file.
  1621. //
  1622. buffer = ExAllocatePoolWithTag( PagedPool, Length, ' oI' );
  1623. if (!buffer) {
  1624. return STATUS_INSUFFICIENT_RESOURCES;
  1625. }
  1626. //
  1627. // Query the name of the device on which the file is open.
  1628. //
  1629. fileObject = (PFILE_OBJECT) Object;
  1630. deviceNameInfo = (POBJECT_NAME_INFORMATION) buffer;
  1631. if (UseDosDeviceName) {
  1632. if (fileObject->DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {
  1633. lengthNeeded = sizeof(OBJECT_NAME_INFORMATION) + 2*sizeof(WCHAR); // For the extra '\' and '\0'
  1634. if (lengthNeeded > Length) {
  1635. status = STATUS_BUFFER_OVERFLOW;
  1636. } else {
  1637. status = STATUS_SUCCESS;
  1638. }
  1639. deviceNameInfo->Name.Length = sizeof(WCHAR);
  1640. deviceNameInfo->Name.MaximumLength = sizeof(WCHAR);
  1641. p = (PWSTR) (deviceNameInfo + 1);
  1642. *p = '\\'; // Start with a '\' as RDR does not return the extra
  1643. deviceNameInfo->Name.Buffer = p;
  1644. } else {
  1645. status = IoVolumeDeviceToDosName( fileObject->DeviceObject, &deviceNameInfo->Name );
  1646. lengthNeeded = sizeof(OBJECT_NAME_INFORMATION) + deviceNameInfo->Name.Length + sizeof(WCHAR);
  1647. }
  1648. //
  1649. // If querying the dos name fails try to atleast get the real device name
  1650. //
  1651. if (!NT_SUCCESS(status)) {
  1652. status = ObQueryNameString( (PVOID) fileObject->DeviceObject,
  1653. deviceNameInfo,
  1654. Length,
  1655. &lengthNeeded );
  1656. } else {
  1657. dosLookupSuccess++;
  1658. }
  1659. } else {
  1660. status = ObQueryNameString( (PVOID) fileObject->DeviceObject,
  1661. deviceNameInfo,
  1662. Length,
  1663. &lengthNeeded );
  1664. }
  1665. if (!NT_SUCCESS( status )) {
  1666. if (status != STATUS_INFO_LENGTH_MISMATCH) {
  1667. return status;
  1668. }
  1669. }
  1670. //
  1671. // Ensure that there is enough room in the output buffer to return the
  1672. // name and copy it.
  1673. //
  1674. p = (PWSTR) (ObjectNameInfo + 1);
  1675. //
  1676. // If we got a DOS name, note the name isn't contiguous to the device name info,
  1677. // and that we should free it (the Rtl call did not know we allocated this big
  1678. // buffer, and made a new one).
  1679. //
  1680. try {
  1681. if (UseDosDeviceName && dosLookupSuccess) {
  1682. ULONG BaseCopyLength;
  1683. ULONG NameCopyLength;
  1684. //
  1685. // We will never take an exception in this path. That's why we don't have to free
  1686. // the device name buffer in the exception handler.
  1687. //
  1688. ASSERT(Mode == KernelMode);
  1689. //
  1690. // Figure out how much of each part we can copy.
  1691. //
  1692. BaseCopyLength = sizeof(UNICODE_STRING);
  1693. if ( Length < lengthNeeded ) {
  1694. if ( Length < sizeof(UNICODE_STRING)) {
  1695. BaseCopyLength = Length;
  1696. NameCopyLength = 0;
  1697. } else {
  1698. NameCopyLength = Length - BaseCopyLength;
  1699. }
  1700. } else {
  1701. NameCopyLength = deviceNameInfo->Name.Length;
  1702. }
  1703. //
  1704. // Copy in two parts - the base chunk of the UNICODE_STRING and then
  1705. // as much of the name as will fit.
  1706. //
  1707. RtlCopyMemory( ObjectNameInfo,
  1708. deviceNameInfo,
  1709. BaseCopyLength );
  1710. RtlCopyMemory( p,
  1711. deviceNameInfo->Name.Buffer,
  1712. NameCopyLength );
  1713. if (fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM) {
  1714. ExFreePool( deviceNameInfo->Name.Buffer );
  1715. }
  1716. } else {
  1717. RtlCopyMemory( ObjectNameInfo,
  1718. deviceNameInfo,
  1719. lengthNeeded > Length ? Length : lengthNeeded );
  1720. }
  1721. ObjectNameInfo->Name.Buffer = p;
  1722. p = (PWSTR) ((PCHAR) p + deviceNameInfo->Name.Length);
  1723. //
  1724. // If the buffer is already full, note and continue to pick up the filename length.
  1725. // We want to return the required length for the entire result.
  1726. //
  1727. deviceNameOverflow = FALSE;
  1728. if (lengthNeeded > Length) {
  1729. *ReturnLength = lengthNeeded;
  1730. deviceNameOverflow = TRUE;
  1731. }
  1732. //
  1733. // Reset the state for the buffer to obtain the filename portion of the
  1734. // name and calculate the remaining length of the caller's buffer. Note
  1735. // that in the following calculations, there are two assumptions and
  1736. // and dependencies:
  1737. //
  1738. // 1) The above query of the device name's returned length needed
  1739. // include a NULL character which will be included at the end
  1740. // of the entire name. This is included in the calculations
  1741. // although it does not appear to be included.
  1742. //
  1743. // 2) The sizeof the object name information buffer is assumed
  1744. // (and guaranteed because it can never change) to be larger
  1745. // than the filename offset in a file name information buffer.
  1746. // Therefore it is known that the new length of the "buffer"
  1747. // variable can be set to the remaining length plus at least 4.
  1748. //
  1749. fileNameInfo = (PFILE_NAME_INFORMATION) buffer;
  1750. if (deviceNameOverflow) {
  1751. length = Length;
  1752. } else {
  1753. length = Length - lengthNeeded;
  1754. length += FIELD_OFFSET( FILE_NAME_INFORMATION, FileName );
  1755. }
  1756. if (((Mode == UserMode) && (!UseDosDeviceName)) ||
  1757. !(fileObject->Flags & FO_SYNCHRONOUS_IO)) {
  1758. //
  1759. // Query the name of the file based using an intermediary buffer.
  1760. //
  1761. status = IopQueryXxxInformation( fileObject,
  1762. FileNameInformation,
  1763. length,
  1764. Mode,
  1765. (PVOID) fileNameInfo,
  1766. &lengthNeeded,
  1767. TRUE );
  1768. } else {
  1769. //
  1770. // This is a kernel mode request for a file that was opened for
  1771. // synchronous I/O. A special function that does not obtain the
  1772. // file object lock is required, otherwise the request may deadlock
  1773. // since the lock is probably already owned.
  1774. //
  1775. status = IopGetFileInformation( fileObject,
  1776. length,
  1777. FileNameInformation,
  1778. fileNameInfo,
  1779. &lengthNeeded );
  1780. }
  1781. //
  1782. // If an error occurred attempting to obtain the filename return now. Note
  1783. // that buffer overflow is a warning, not an error.
  1784. //
  1785. if (NT_ERROR( status )) {
  1786. if (status == STATUS_INVALID_PARAMETER ||
  1787. status == STATUS_INVALID_DEVICE_REQUEST ||
  1788. status == STATUS_NOT_IMPLEMENTED ||
  1789. status == STATUS_INVALID_INFO_CLASS) {
  1790. lengthNeeded = FIELD_OFFSET( FILE_NAME_INFORMATION, FileName );
  1791. fileNameInfo->FileNameLength = 0;
  1792. fileNameInfo->FileName[0] = OBJ_NAME_PATH_SEPARATOR;
  1793. status = STATUS_SUCCESS;
  1794. } else {
  1795. leave;
  1796. }
  1797. }
  1798. //
  1799. // Compute the correct length
  1800. // Note that ReturnLength already contains a space for NULL added by the previous ObQueryNameString.
  1801. //
  1802. if (deviceNameOverflow) {
  1803. *ReturnLength += fileNameInfo->FileNameLength;
  1804. status = STATUS_BUFFER_OVERFLOW;
  1805. leave;
  1806. }
  1807. //
  1808. // Set the remaining length of the caller's buffer as well as the total
  1809. // length needed to contain the entire name of the file.
  1810. //
  1811. length = lengthNeeded - FIELD_OFFSET( FILE_NAME_INFORMATION, FileName );
  1812. lengthNeeded = (ULONG)((PUCHAR) p - (PUCHAR) ObjectNameInfo) + fileNameInfo->FileNameLength;
  1813. //
  1814. // Attempt to copy the name of the file into the output buffer. Note
  1815. // that if the file name does not begin w/a '\', then it is not volume
  1816. // relative, so the name of the file cannot be expressed as the
  1817. // concatenation of the name of the device and the file. Therefore an
  1818. // error is returned.
  1819. //
  1820. // The only example of this situation known at this time is when one
  1821. // opens a directory by file ID, and then opens a file relative to that
  1822. // directory. When attempting to query the path, if the caller did not
  1823. // have traverse access to open the directory, then the only name that
  1824. // can be returned is the path name to the file from the directory, but
  1825. // the volume-relative name cannot be returned. Therefore, the file
  1826. // system returns only the name of the directory and the path to the
  1827. // file, but this is not volume-relative so the only recourse is to
  1828. // return an error.
  1829. //
  1830. // Note that if the caller were to call NtQueryInformationFile and
  1831. // request FileNameInformation, then the name above named will be
  1832. // successfully returned from the file system.
  1833. //
  1834. if (fileNameInfo->FileName[0] != OBJ_NAME_PATH_SEPARATOR) {
  1835. status = STATUS_OBJECT_PATH_INVALID;
  1836. leave;
  1837. }
  1838. RtlCopyMemory( p,
  1839. fileNameInfo->FileName,
  1840. length );
  1841. p = (PWSTR) ((PCH) p + length);
  1842. *p = '\0';
  1843. lengthNeeded += sizeof( WCHAR );
  1844. *ReturnLength = lengthNeeded;
  1845. length = (ULONG)((PUCHAR) p - (PUCHAR) ObjectNameInfo);
  1846. ObjectNameInfo->Name.Length = (USHORT) (length - sizeof( *ObjectNameInfo ));
  1847. ObjectNameInfo->Name.MaximumLength = (USHORT) ((length - sizeof( *ObjectNameInfo )) + sizeof( WCHAR ));
  1848. }
  1849. finally {
  1850. //
  1851. // Finally, free the temporary buffer.
  1852. //
  1853. ExFreePool( buffer );
  1854. }
  1855. return status;
  1856. }
  1857. NTSTATUS
  1858. IopQueryName(
  1859. IN PVOID Object,
  1860. IN BOOLEAN HasObjectName,
  1861. OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
  1862. IN ULONG Length,
  1863. OUT PULONG ReturnLength,
  1864. IN KPROCESSOR_MODE Mode
  1865. )
  1866. /*++
  1867. Routine Description:
  1868. This function implements the query name procedure for the Object Manager
  1869. for querying the names of file objects.
  1870. Arguments:
  1871. Object - Pointer to the file object whose name is to be retrieved.
  1872. HasObjectName - Indicates whether or not the object has a name.
  1873. ObjectNameInfo - Buffer in which to return the name.
  1874. Length - Specifies the length of the output buffer, in bytes.
  1875. ReturnLength - Specifies the number of bytes actually returned in the
  1876. output buffer.
  1877. Mode = Processor mode of the caller
  1878. Return Value:
  1879. The function return value is the final status of the query operation.
  1880. --*/
  1881. {
  1882. UNREFERENCED_PARAMETER (Mode);
  1883. return IopQueryNameInternal( Object,
  1884. HasObjectName,
  1885. FALSE,
  1886. ObjectNameInfo,
  1887. Length,
  1888. ReturnLength,
  1889. Mode );
  1890. }
  1891. VOID
  1892. IopCheckBackupRestorePrivilege(
  1893. IN PACCESS_STATE AccessState,
  1894. IN OUT PULONG CreateOptions,
  1895. IN KPROCESSOR_MODE PreviousMode,
  1896. IN ULONG Disposition
  1897. )
  1898. /*++
  1899. Routine Description:
  1900. This funcion will determine if the caller is asking for any accesses
  1901. that may be satisfied by Backup or Restore privileges, and if so,
  1902. perform the privilge checks. If the privilege checks succeed, then
  1903. the appropriate bits will be moved out of the RemainingDesiredAccess
  1904. field in the AccessState structure and placed into the PreviouslyGrantedAccess
  1905. field.
  1906. Note that access is not denied if the caller does not have either or
  1907. both of the privileges, since he may be granted the desired access
  1908. via the security descriptor on the object.
  1909. This routine will also set a flag in the AccessState structure so that
  1910. it will not perform these privilege checks again in case we come through
  1911. this way again due to a reparse.
  1912. Arguments:
  1913. AccessState - The AccessState containing the current state of this access
  1914. attempt.
  1915. CreateOptions - The CreateOptions field from the OPEN_PACKET structure for
  1916. this open attempt.
  1917. PreviousMode - The processor mode to be used in checking parameters.
  1918. Disposition - The create disposition for this request.
  1919. Return Value:
  1920. None.
  1921. --*/
  1922. {
  1923. ACCESS_MASK desiredAccess;
  1924. ACCESS_MASK readAccess;
  1925. ACCESS_MASK writeAccess;
  1926. PRIVILEGE_SET requiredPrivileges;
  1927. BOOLEAN accessGranted;
  1928. BOOLEAN keepBackupIntent = FALSE;
  1929. BOOLEAN ForceRestoreCheck = FALSE;
  1930. PAGED_CODE();
  1931. //
  1932. // Check to determine whether or not this check has already been made.
  1933. // If so, simply return back to the caller.
  1934. //
  1935. if (AccessState->Flags & SE_BACKUP_PRIVILEGES_CHECKED) {
  1936. return;
  1937. }
  1938. if (*CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT) {
  1939. AccessState->Flags |= SE_BACKUP_PRIVILEGES_CHECKED;
  1940. readAccess = READ_CONTROL | ACCESS_SYSTEM_SECURITY | FILE_GENERIC_READ | FILE_TRAVERSE;
  1941. writeAccess = WRITE_DAC | WRITE_OWNER | ACCESS_SYSTEM_SECURITY | FILE_GENERIC_WRITE | FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | DELETE;
  1942. desiredAccess = AccessState->RemainingDesiredAccess;
  1943. //
  1944. // If the caller has requested MAXIMUM_ALLOWED, then make it appear as
  1945. // if the request was for everything permitted by Backup and Restore,
  1946. // and then grant everything that can actually be granted.
  1947. //
  1948. if (desiredAccess & MAXIMUM_ALLOWED) {
  1949. desiredAccess |= ( readAccess | writeAccess );
  1950. }
  1951. //
  1952. // If the disposition says that we're opening the file, check for both backup
  1953. // and restore privilege, depending on what's in the desired access.
  1954. //
  1955. // If the disposition says that we're creating or trying to overwrite the file,
  1956. // then all we need to do is to check for restore privilege, and if it's there,
  1957. // grant every possible access.
  1958. //
  1959. if ((Disposition == FILE_OPEN ) || (Disposition == FILE_OPEN_IF) || (Disposition == FILE_OVERWRITE_IF)) {
  1960. //
  1961. // If the request was for any of the bits in the read access mask, then
  1962. // assume that this is a backup operation, and check for the Backup
  1963. // privielege. If the caller has it, then grant the intersection of
  1964. // the desired access and read access masks.
  1965. //
  1966. if (readAccess & desiredAccess) {
  1967. requiredPrivileges.PrivilegeCount = 1;
  1968. requiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
  1969. requiredPrivileges.Privilege[0].Luid = SeBackupPrivilege;
  1970. requiredPrivileges.Privilege[0].Attributes = 0;
  1971. accessGranted = SePrivilegeCheck( &requiredPrivileges,
  1972. &AccessState->SubjectSecurityContext,
  1973. PreviousMode );
  1974. if (accessGranted) {
  1975. //
  1976. // The caller has Backup privilege, so grant the appropriate
  1977. // accesses.
  1978. //
  1979. keepBackupIntent = TRUE;
  1980. (VOID) SeAppendPrivileges( AccessState, &requiredPrivileges );
  1981. AccessState->PreviouslyGrantedAccess |= ( desiredAccess & readAccess );
  1982. AccessState->RemainingDesiredAccess &= ~readAccess;
  1983. desiredAccess &= ~readAccess;
  1984. AccessState->Flags |= TOKEN_HAS_BACKUP_PRIVILEGE;
  1985. }
  1986. }
  1987. } else {
  1988. ForceRestoreCheck = TRUE;
  1989. }
  1990. //
  1991. // If the request was for any of the bits in the write access mask, then
  1992. // assume that this is a restore operation, so check for the Restore
  1993. // privilege. If the caller has it, then grant the intersection of
  1994. // the desired access and write access masks.
  1995. //
  1996. if ((writeAccess & desiredAccess) || ForceRestoreCheck) {
  1997. requiredPrivileges.PrivilegeCount = 1;
  1998. requiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
  1999. requiredPrivileges.Privilege[0].Luid = SeRestorePrivilege;
  2000. requiredPrivileges.Privilege[0].Attributes = 0;
  2001. accessGranted = SePrivilegeCheck( &requiredPrivileges,
  2002. &AccessState->SubjectSecurityContext,
  2003. PreviousMode );
  2004. if (accessGranted) {
  2005. //
  2006. // The caller has Restore privilege, so grant the appropriate
  2007. // accesses.
  2008. //
  2009. keepBackupIntent = TRUE;
  2010. (VOID) SeAppendPrivileges( AccessState, &requiredPrivileges );
  2011. AccessState->PreviouslyGrantedAccess |= (desiredAccess & writeAccess);
  2012. AccessState->RemainingDesiredAccess &= ~writeAccess;
  2013. AccessState->Flags |= TOKEN_HAS_RESTORE_PRIVILEGE;
  2014. }
  2015. }
  2016. //
  2017. // If either of the access types was granted because the caller had
  2018. // backup or restore privilege, then the backup intent flag is kept.
  2019. // Otherwise, it is cleared so that it is not passed onto the driver
  2020. // so that it is not incorrectly propogated anywhere else, since this
  2021. // caller does not actually have the privilege enabled.
  2022. //
  2023. if (!keepBackupIntent) {
  2024. *CreateOptions &= ~FILE_OPEN_FOR_BACKUP_INTENT;
  2025. }
  2026. }
  2027. }