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.

1243 lines
42 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dir.c
  5. Abstract:
  6. This module contains the code to implement the NtQueryDirectoryFile,
  7. and the NtNotifyChangeDirectoryFile system services for the NT I/O system.
  8. Author:
  9. Darryl E. Havens (darrylh) 21-Jun-1989
  10. Environment:
  11. Kernel mode only
  12. Revision History:
  13. --*/
  14. #include "iomgr.h"
  15. NTSTATUS
  16. BuildQueryDirectoryIrp(
  17. IN HANDLE FileHandle,
  18. IN HANDLE Event OPTIONAL,
  19. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  20. IN PVOID ApcContext OPTIONAL,
  21. OUT PIO_STATUS_BLOCK IoStatusBlock,
  22. OUT PVOID FileInformation,
  23. IN ULONG Length,
  24. IN FILE_INFORMATION_CLASS FileInformationClass,
  25. IN BOOLEAN ReturnSingleEntry,
  26. IN PUNICODE_STRING FileName OPTIONAL,
  27. IN BOOLEAN RestartScan,
  28. IN UCHAR MinorFunction,
  29. OUT BOOLEAN *SynchronousIo,
  30. OUT PDEVICE_OBJECT *DeviceObject,
  31. OUT PIRP *Irp,
  32. OUT PFILE_OBJECT *FileObject,
  33. OUT KPROCESSOR_MODE *RequestorMode
  34. );
  35. #ifdef ALLOC_PRAGMA
  36. #pragma alloc_text(PAGE, BuildQueryDirectoryIrp)
  37. #pragma alloc_text(PAGE, NtQueryDirectoryFile)
  38. #pragma alloc_text(PAGE, NtNotifyChangeDirectoryFile)
  39. #endif
  40. NTSTATUS
  41. BuildQueryDirectoryIrp(
  42. IN HANDLE FileHandle,
  43. IN HANDLE Event OPTIONAL,
  44. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  45. IN PVOID ApcContext OPTIONAL,
  46. OUT PIO_STATUS_BLOCK IoStatusBlock,
  47. OUT PVOID FileInformation,
  48. IN ULONG Length,
  49. IN FILE_INFORMATION_CLASS FileInformationClass,
  50. IN BOOLEAN ReturnSingleEntry,
  51. IN PUNICODE_STRING FileName OPTIONAL,
  52. IN BOOLEAN RestartScan,
  53. IN UCHAR MinorFunction,
  54. OUT BOOLEAN *SynchronousIo,
  55. OUT PDEVICE_OBJECT *DeviceObject,
  56. OUT PIRP *Irp,
  57. OUT PFILE_OBJECT *FileObject,
  58. OUT KPROCESSOR_MODE *RequestorMode
  59. )
  60. /*++
  61. Routine Description:
  62. This service operates on a directory file or OLE container specified by the
  63. FileHandle parameter. The service returns information about files in the
  64. directory or embeddings and streams in the container specified by the file
  65. handle. The ReturnSingleEntry parameter specifies that only a single entry
  66. should be returned rather than filling the buffer. The actual number of
  67. files whose information is returned, is the smallest of the following:
  68. o One entry, if the ReturnSingleEntry parameter is TRUE.
  69. o The number of entries whose information fits into the specified
  70. buffer.
  71. o The number of entries that exist.
  72. o One entry if the optional FileName parameter is specified.
  73. If the optional FileName parameter is specified, then the only information
  74. that is returned is for that single entries, if it exists. Note that the
  75. file name may not specify any wildcard characters according to the naming
  76. conventions of the target file system. The ReturnSingleEntry parameter is
  77. simply ignored.
  78. The information that is obtained about the entries in the directory or OLE
  79. container is based on the FileInformationClass parameter. Legal values are
  80. hard coded based on the MinorFunction.
  81. Arguments:
  82. FileHandle - Supplies a handle to the directory file or OLE container for
  83. which information should be returned.
  84. Event - Supplies an optional event to be set to the Signaled state when
  85. the query is complete.
  86. ApcRoutine - Supplies an optional APC routine to be executed when the
  87. query is complete.
  88. ApcContext - Supplies a context parameter to be passed to the ApcRoutine,
  89. if an ApcRoutine was specified.
  90. IoStatusBlock - Address of the caller's I/O status block.
  91. FileInformation - Supplies a buffer to receive the requested information
  92. returned about the contents of the directory.
  93. Length - Supplies the length, in bytes, of the FileInformation buffer.
  94. FileInformationClass - Specfies the type of information that is to be
  95. returned about the files in the specified directory or OLE container.
  96. ReturnSingleEntry - Supplies a BOOLEAN value that, if TRUE, indicates that
  97. only a single entry should be returned.
  98. FileName - Optionally supplies a file name within the specified directory
  99. or OLE container.
  100. RestartScan - Supplies a BOOLEAN value that, if TRUE, indicates that the
  101. scan should be restarted from the beginning. This parameter must be
  102. set to TRUE by the caller the first time the service is invoked.
  103. MinorFunction - IRP_MN_QUERY_DIRECTORY or IRP_MN_QUERY_OLE_DIRECTORY
  104. SynchronousIo - pointer to returned BOOLEAN; TRUE if synchronous I/O
  105. DeviceObject - pointer to returned pointer to device object
  106. Irp - pointer to returned pointer to device object
  107. FileObject - pointer to returned pointer to file object
  108. RequestorMode - pointer to returned requestor mode
  109. Return Value:
  110. The status returned is STATUS_SUCCESS if a valid irp was created for the
  111. query operation.
  112. --*/
  113. {
  114. PIRP irp;
  115. NTSTATUS status;
  116. PFILE_OBJECT fileObject;
  117. PDEVICE_OBJECT deviceObject;
  118. PKEVENT eventObject = (PKEVENT) NULL;
  119. KPROCESSOR_MODE requestorMode;
  120. PCHAR auxiliaryBuffer = (PCHAR) NULL;
  121. PIO_STACK_LOCATION irpSp;
  122. PMDL mdl;
  123. PETHREAD CurrentThread;
  124. PAGED_CODE();
  125. //
  126. // Get the previous mode; i.e., the mode of the caller.
  127. //
  128. CurrentThread = PsGetCurrentThread ();
  129. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  130. *RequestorMode = requestorMode;
  131. try {
  132. if (requestorMode != KernelMode) {
  133. ULONG operationlength = 0; // assume invalid
  134. //
  135. // The caller's access mode is not kernel so probe and validate
  136. // each of the arguments as necessary. If any failures occur,
  137. // the condition handler will be invoked to handle them. It
  138. // will simply cleanup and return an access violation status
  139. // code back to the system service dispatcher.
  140. //
  141. //
  142. // The IoStatusBlock parameter must be writeable by the caller.
  143. //
  144. ProbeForWriteIoStatusEx( IoStatusBlock, ApcRoutine);
  145. //
  146. // Ensure that the FileInformationClass parameter is legal for
  147. // querying information about files in the directory or object.
  148. //
  149. if (FileInformationClass == FileDirectoryInformation) {
  150. operationlength = sizeof(FILE_DIRECTORY_INFORMATION);
  151. } else if (MinorFunction == IRP_MN_QUERY_DIRECTORY) {
  152. switch (FileInformationClass)
  153. {
  154. case FileFullDirectoryInformation:
  155. operationlength = sizeof(FILE_FULL_DIR_INFORMATION);
  156. break;
  157. case FileIdFullDirectoryInformation:
  158. operationlength = sizeof(FILE_ID_FULL_DIR_INFORMATION);
  159. break;
  160. case FileBothDirectoryInformation:
  161. operationlength = sizeof(FILE_BOTH_DIR_INFORMATION);
  162. break;
  163. case FileIdBothDirectoryInformation:
  164. operationlength = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
  165. break;
  166. case FileNamesInformation:
  167. operationlength = sizeof(FILE_NAMES_INFORMATION);
  168. break;
  169. case FileObjectIdInformation:
  170. operationlength = sizeof(FILE_OBJECTID_INFORMATION);
  171. break;
  172. case FileQuotaInformation:
  173. operationlength = sizeof(FILE_QUOTA_INFORMATION);
  174. break;
  175. case FileReparsePointInformation:
  176. operationlength = sizeof(FILE_REPARSE_POINT_INFORMATION);
  177. break;
  178. }
  179. }
  180. //
  181. // If the FileInformationClass parameter is illegal, fail now.
  182. //
  183. if (operationlength == 0) {
  184. return STATUS_INVALID_INFO_CLASS;
  185. }
  186. //
  187. // Ensure that the caller's supplied buffer is at least large enough
  188. // to contain the fixed part of the structure required for this
  189. // query.
  190. //
  191. if (Length < operationlength) {
  192. return STATUS_INFO_LENGTH_MISMATCH;
  193. }
  194. //
  195. // The FileInformation buffer must be writeable by the caller.
  196. //
  197. #if defined(_X86_)
  198. ProbeForWrite( FileInformation, Length, sizeof( ULONG ) );
  199. #elif defined(_WIN64)
  200. //
  201. // If we are a wow64 process, follow the X86 rules
  202. //
  203. if (PsGetCurrentProcessByThread(CurrentThread)->Wow64Process) {
  204. ProbeForWrite( FileInformation, Length, sizeof( ULONG ) );
  205. } else {
  206. ProbeForWrite( FileInformation,
  207. Length,
  208. IopQuerySetAlignmentRequirement[FileInformationClass] );
  209. }
  210. #else
  211. ProbeForWrite( FileInformation,
  212. Length,
  213. IopQuerySetAlignmentRequirement[FileInformationClass] );
  214. #endif
  215. }
  216. //
  217. // If the optional FileName parameter was specified, then it must be
  218. // readable by the caller. Capture the file name string in a pool
  219. // block. Note that if an error occurs during the copy, the cleanup
  220. // code in the exception handler will deallocate the pool before
  221. // returning an access violation status.
  222. //
  223. if (ARGUMENT_PRESENT( FileName )) {
  224. UNICODE_STRING fileName;
  225. PUNICODE_STRING nameBuffer;
  226. //
  227. // Capture the string descriptor itself to ensure that the
  228. // string is readable by the caller without the caller being
  229. // able to change the memory while its being checked.
  230. //
  231. if (requestorMode != KernelMode) {
  232. fileName = ProbeAndReadUnicodeString( FileName );
  233. } else {
  234. fileName = *FileName;
  235. }
  236. //
  237. // If the length is not an even number of bytes
  238. // return an error.
  239. //
  240. if (fileName.Length & (sizeof(WCHAR) - 1)) {
  241. return STATUS_INVALID_PARAMETER;
  242. }
  243. if (fileName.Length) {
  244. //
  245. // The length of the string is non-zero, so probe the
  246. // buffer described by the descriptor if the caller was
  247. // not kernel mode. Likewise, if the caller's mode was
  248. // not kernel, then check the length of the name string
  249. // to ensure that it is not too long.
  250. //
  251. if (requestorMode != KernelMode) {
  252. ProbeForRead( fileName.Buffer,
  253. fileName.Length,
  254. sizeof( UCHAR ) );
  255. //
  256. // account for unicode
  257. //
  258. if (fileName.Length > MAXIMUM_FILENAME_LENGTH<<1) {
  259. ExRaiseStatus( STATUS_INVALID_PARAMETER );
  260. }
  261. }
  262. //
  263. // Allocate an auxiliary buffer large enough to contain
  264. // a file name descriptor and to hold the entire file
  265. // name itself. Copy the body of the string into the
  266. // buffer.
  267. //
  268. auxiliaryBuffer = ExAllocatePoolWithQuota( NonPagedPool,
  269. fileName.Length + sizeof( UNICODE_STRING ) );
  270. RtlCopyMemory( auxiliaryBuffer + sizeof( UNICODE_STRING ),
  271. fileName.Buffer,
  272. fileName.Length );
  273. //
  274. // Finally, build the Unicode string descriptor in the
  275. // auxiliary buffer.
  276. //
  277. nameBuffer = (PUNICODE_STRING) auxiliaryBuffer;
  278. nameBuffer->Length = fileName.Length;
  279. nameBuffer->MaximumLength = fileName.Length;
  280. nameBuffer->Buffer = (PWSTR) (auxiliaryBuffer + sizeof( UNICODE_STRING ) );
  281. }
  282. }
  283. } except(EXCEPTION_EXECUTE_HANDLER) {
  284. //
  285. // An exception was incurred while probing the caller's buffers,
  286. // attempting to allocate a pool buffer, or while trying to copy
  287. // the caller's data. Determine what happened, clean everything
  288. // up, and return an appropriate error status code.
  289. //
  290. if (auxiliaryBuffer) {
  291. ExFreePool( auxiliaryBuffer );
  292. }
  293. return GetExceptionCode();
  294. }
  295. //
  296. // There were no blatant errors so far, so reference the file object so
  297. // the target device object can be found. Note that if the handle does
  298. // not refer to a file object, or if the caller does not have the required
  299. // access to the file, then it will fail.
  300. //
  301. status = ObReferenceObjectByHandle( FileHandle,
  302. FILE_LIST_DIRECTORY,
  303. IoFileObjectType,
  304. requestorMode,
  305. (PVOID *) &fileObject,
  306. (POBJECT_HANDLE_INFORMATION) NULL );
  307. if (!NT_SUCCESS( status )) {
  308. if (auxiliaryBuffer) {
  309. ExFreePool( auxiliaryBuffer );
  310. }
  311. return status;
  312. }
  313. *FileObject = fileObject;
  314. //
  315. // If this file has an I/O completion port associated w/it, then ensure
  316. // that the caller did not supply an APC routine, as the two are mutually
  317. // exclusive methods for I/O completion notification.
  318. //
  319. if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) {
  320. ObDereferenceObject( fileObject );
  321. if (auxiliaryBuffer) {
  322. ExFreePool( auxiliaryBuffer );
  323. }
  324. return STATUS_INVALID_PARAMETER;
  325. }
  326. //
  327. // Get the address of the event object and set the event to the Not-
  328. // Signaled state, if an event was specified. Note here, too, that if
  329. // the handle does not refer to an event, or if the event cannot be
  330. // written, then the reference will fail.
  331. //
  332. if (ARGUMENT_PRESENT( Event )) {
  333. status = ObReferenceObjectByHandle( Event,
  334. EVENT_MODIFY_STATE,
  335. ExEventObjectType,
  336. requestorMode,
  337. (PVOID *) &eventObject,
  338. (POBJECT_HANDLE_INFORMATION) NULL );
  339. if (!NT_SUCCESS( status )) {
  340. if (auxiliaryBuffer) {
  341. ExFreePool( auxiliaryBuffer );
  342. }
  343. ObDereferenceObject( fileObject );
  344. return status;
  345. } else {
  346. KeClearEvent( eventObject );
  347. }
  348. }
  349. //
  350. // Make a special check here to determine whether this is a synchronous
  351. // I/O operation. If it is, then wait here until the file is owned by
  352. // the current thread.
  353. //
  354. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  355. BOOLEAN interrupted;
  356. if (!IopAcquireFastLock( fileObject )) {
  357. status = IopAcquireFileObjectLock( fileObject,
  358. requestorMode,
  359. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  360. &interrupted );
  361. if (interrupted) {
  362. if (auxiliaryBuffer != NULL) {
  363. ExFreePool( auxiliaryBuffer );
  364. }
  365. if (eventObject != NULL) {
  366. ObDereferenceObject( eventObject );
  367. }
  368. ObDereferenceObject( fileObject );
  369. return status;
  370. }
  371. }
  372. *SynchronousIo = TRUE;
  373. } else {
  374. *SynchronousIo = FALSE;
  375. }
  376. //
  377. // Set the file object to the Not-Signaled state.
  378. //
  379. KeClearEvent( &fileObject->Event );
  380. //
  381. // Get the address of the target device object.
  382. //
  383. deviceObject = IoGetRelatedDeviceObject( fileObject );
  384. *DeviceObject = deviceObject;
  385. //
  386. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  387. // The allocation is performed with an exception handler in case the
  388. // caller does not have enough quota to allocate the packet.
  389. irp = IoAllocateIrp( deviceObject->StackSize, !(*SynchronousIo) );
  390. if (!irp) {
  391. //
  392. // An IRP could not be allocated. Cleanup and return an appropriate
  393. // error status code.
  394. //
  395. IopAllocateIrpCleanup( fileObject, eventObject );
  396. if (auxiliaryBuffer) {
  397. ExFreePool( auxiliaryBuffer );
  398. }
  399. return STATUS_INSUFFICIENT_RESOURCES;
  400. }
  401. *Irp = irp;
  402. irp->Tail.Overlay.OriginalFileObject = fileObject;
  403. irp->Tail.Overlay.Thread = CurrentThread;
  404. irp->RequestorMode = requestorMode;
  405. //
  406. // Fill in the service independent parameters in the IRP.
  407. //
  408. irp->UserEvent = eventObject;
  409. irp->UserIosb = IoStatusBlock;
  410. irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
  411. irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
  412. //
  413. // Get a pointer to the stack location for the first driver. This will be
  414. // used to pass the original function codes and parameters.
  415. //
  416. irpSp = IoGetNextIrpStackLocation( irp );
  417. irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
  418. irpSp->MinorFunction = MinorFunction;
  419. irpSp->FileObject = fileObject;
  420. // Also, copy the caller's parameters to the service-specific portion of
  421. // the IRP.
  422. //
  423. irp->Tail.Overlay.AuxiliaryBuffer = auxiliaryBuffer;
  424. irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
  425. irp->MdlAddress = (PMDL) NULL;
  426. //
  427. // Now determine whether this driver expects to have data buffered to it
  428. // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO
  429. // flag in the device object. If the flag is set, then a system buffer is
  430. // allocated and the driver's data will be copied into it. Otherwise, a
  431. // Memory Descriptor List (MDL) is allocated and the caller's buffer is
  432. // locked down using it.
  433. //
  434. if (deviceObject->Flags & DO_BUFFERED_IO) {
  435. //
  436. // The device does not support direct I/O. Allocate a system buffer
  437. // and specify that it should be deallocated on completion. Also
  438. // indicate that this is an input operation so the data will be copied
  439. // into the caller's buffer. This is done using an exception handler
  440. // that will perform cleanup if the operation fails.
  441. //
  442. try {
  443. //
  444. // Allocate the intermediary system buffer from nonpaged pool and
  445. // charge quota for it.
  446. //
  447. irp->AssociatedIrp.SystemBuffer =
  448. ExAllocatePoolWithQuota( NonPagedPool, Length );
  449. } except(EXCEPTION_EXECUTE_HANDLER) {
  450. //
  451. // An exception was incurred while either probing the caller's
  452. // buffer or allocate the system buffer. Determine what actually
  453. // happened, clean everything up, and return an appropriate error
  454. // status code.
  455. //
  456. IopExceptionCleanup( fileObject,
  457. irp,
  458. eventObject,
  459. (PKEVENT) NULL );
  460. if (auxiliaryBuffer != NULL) {
  461. ExFreePool( auxiliaryBuffer );
  462. }
  463. return GetExceptionCode();
  464. }
  465. //
  466. // Remember the address of the caller's buffer so the copy can take
  467. // place during I/O completion. Also, set the flags so that the
  468. // completion code knows to do the copy and to deallocate the buffer.
  469. //
  470. irp->UserBuffer = FileInformation;
  471. irp->Flags = (ULONG) (IRP_BUFFERED_IO |
  472. IRP_DEALLOCATE_BUFFER |
  473. IRP_INPUT_OPERATION);
  474. } else if (deviceObject->Flags & DO_DIRECT_IO) {
  475. //
  476. // This is a direct I/O operation. Allocate an MDL and invoke the
  477. // memory management routine to lock the buffer into memory. This is
  478. // done using an exception handler that will perform cleanup if the
  479. // operation fails.
  480. //
  481. mdl = (PMDL) NULL;
  482. try {
  483. //
  484. // Allocate an MDL, charging quota for it, and hang it off of the
  485. // IRP. Probe and lock the pages associated with the caller's
  486. // buffer for write access and fill in the MDL with the PFNs of
  487. // those pages.
  488. //
  489. mdl = IoAllocateMdl( FileInformation, Length, FALSE, TRUE, irp );
  490. if (mdl == NULL) {
  491. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  492. }
  493. MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess );
  494. } except(EXCEPTION_EXECUTE_HANDLER) {
  495. //
  496. // An exception was incurred while either probing the caller's
  497. // buffer or allocating the MDL. Determine what actually happened,
  498. // clean everything up, and return an appropriate error status code.
  499. //
  500. IopExceptionCleanup( fileObject,
  501. irp,
  502. eventObject,
  503. (PKEVENT) NULL );
  504. if (auxiliaryBuffer != NULL) {
  505. ExFreePool( auxiliaryBuffer );
  506. }
  507. return GetExceptionCode();
  508. }
  509. } else {
  510. //
  511. // Pass the address of the user's buffer so the driver has access to
  512. // it. It is now the driver's responsibility to do everything.
  513. //
  514. irp->UserBuffer = FileInformation;
  515. }
  516. //
  517. // Copy the caller's parameters to the service-specific portion of the
  518. // IRP.
  519. //
  520. irpSp->Parameters.QueryDirectory.Length = Length;
  521. irpSp->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
  522. irpSp->Parameters.QueryDirectory.FileIndex = 0;
  523. irpSp->Parameters.QueryDirectory.FileName = (PUNICODE_STRING) auxiliaryBuffer;
  524. irpSp->Flags = 0;
  525. if (RestartScan) {
  526. irpSp->Flags = SL_RESTART_SCAN;
  527. }
  528. if (ReturnSingleEntry) {
  529. irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
  530. }
  531. irp->Flags |= IRP_DEFER_IO_COMPLETION;
  532. //
  533. // Return with everything set up for the caller to complete the I/O.
  534. //
  535. return STATUS_SUCCESS;
  536. }
  537. NTSTATUS
  538. NtQueryDirectoryFile(
  539. IN HANDLE FileHandle,
  540. IN HANDLE Event OPTIONAL,
  541. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  542. IN PVOID ApcContext OPTIONAL,
  543. OUT PIO_STATUS_BLOCK IoStatusBlock,
  544. OUT PVOID FileInformation,
  545. IN ULONG Length,
  546. IN FILE_INFORMATION_CLASS FileInformationClass,
  547. IN BOOLEAN ReturnSingleEntry,
  548. IN PUNICODE_STRING FileName OPTIONAL,
  549. IN BOOLEAN RestartScan
  550. )
  551. /*++
  552. Routine Description:
  553. This service operates on a directory file specified by the FileHandle
  554. parameter. The service returns information about files in the directory
  555. specified by the file handle. The ReturnSingleEntry parameter specifies
  556. that only a single entry should be returned rather than filling the buffer.
  557. The actual number of files whose information is returned, is the smallest
  558. of the following:
  559. o One entry, if the ReturnSingleEntry parameter is TRUE.
  560. o The number of files whose information fits into the specified
  561. buffer.
  562. o The number of files that exist.
  563. o One entry if the optional FileName parameter is specified.
  564. If the optional FileName parameter is specified, then the only information
  565. that is returned is for that single file, if it exists. Note that the
  566. file name may not specify any wildcard characters according to the naming
  567. conventions of the target file system. The ReturnSingleEntry parameter is
  568. simply ignored.
  569. The information that is obtained about the files in the directory is based
  570. on the FileInformationClass parameter. The legal values are as follows:
  571. o FileNamesInformation
  572. o FileDirectoryInformation
  573. o FileFullDirectoryInformation
  574. o FileBothDirectoryInformation
  575. o FileIdBothDirectoryInformation
  576. Arguments:
  577. FileHandle - Supplies a handle to the directory file for which information
  578. should be returned.
  579. Event - Supplies an optional event to be set to the Signaled state when
  580. the query is complete.
  581. ApcRoutine - Supplies an optional APC routine to be executed when the
  582. query is complete.
  583. ApcContext - Supplies a context parameter to be passed to the ApcRoutine,
  584. if an ApcRoutine was specified.
  585. IoStatusBlock - Address of the caller's I/O status block.
  586. FileInformation - Supplies a buffer to receive the requested information
  587. returned about the contents of the directory.
  588. Length - Supplies the length, in bytes, of the FileInformation buffer.
  589. FileInformationClass - Specfies the type of information that is to be
  590. returned about the files in the specified directory.
  591. ReturnSingleEntry - Supplies a BOOLEAN value that, if TRUE, indicates that
  592. only a single entry should be returned.
  593. FileName - Optionally supplies a file name within the specified directory.
  594. RestartScan - Supplies a BOOLEAN value that, if TRUE, indicates that the
  595. scan should be restarted from the beginning. This parameter must be
  596. set to TRUE by the caller the first time the service is invoked.
  597. Return Value:
  598. The status returned is success if the query operation was properly queued
  599. to the I/O system. Once the operation completes, the status of the query
  600. can be determined by examining the Status field of the I/O status block.
  601. --*/
  602. {
  603. NTSTATUS status;
  604. BOOLEAN synchronousIo;
  605. PDEVICE_OBJECT deviceObject;
  606. PIRP irp;
  607. PFILE_OBJECT fileObject;
  608. KPROCESSOR_MODE requestorMode;
  609. PAGED_CODE();
  610. //
  611. // Build the irp with the appropriate minor function & allowed info levels.
  612. //
  613. status = BuildQueryDirectoryIrp( FileHandle,
  614. Event,
  615. ApcRoutine,
  616. ApcContext,
  617. IoStatusBlock,
  618. FileInformation,
  619. Length,
  620. FileInformationClass,
  621. ReturnSingleEntry,
  622. FileName,
  623. RestartScan,
  624. IRP_MN_QUERY_DIRECTORY,
  625. &synchronousIo,
  626. &deviceObject,
  627. &irp,
  628. &fileObject,
  629. &requestorMode);
  630. if (status == STATUS_SUCCESS) {
  631. //
  632. // Queue the packet, call the driver, and synchronize appopriately with
  633. // I/O completion.
  634. //
  635. status = IopSynchronousServiceTail( deviceObject,
  636. irp,
  637. fileObject,
  638. TRUE,
  639. requestorMode,
  640. synchronousIo,
  641. OtherTransfer );
  642. }
  643. return status;
  644. }
  645. NTSTATUS
  646. NtNotifyChangeDirectoryFile(
  647. IN HANDLE FileHandle,
  648. IN HANDLE Event OPTIONAL,
  649. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  650. IN PVOID ApcContext OPTIONAL,
  651. OUT PIO_STATUS_BLOCK IoStatusBlock,
  652. OUT PVOID Buffer,
  653. IN ULONG Length,
  654. IN ULONG CompletionFilter,
  655. IN BOOLEAN WatchTree
  656. )
  657. /*++
  658. Routine Description:
  659. This service monitors a directory file for changes. Once a change is
  660. made to the directory specified by the FileHandle parameter, the I/O
  661. operation is completed.
  662. Arguments:
  663. FileHandle - Supplies a handle to the file whose EAs should be changed.
  664. Event - Supplies an optional event to be set to the Signaled state when the
  665. change is complete.
  666. ApcRoutine - Supplies an optional APC routine to be executed when the change
  667. is complete.
  668. ApcContext - Supplies a context parameter to be passed to the ApcRoutine,
  669. if an ApcRoutine was specified.
  670. IoStatusBlock - Address of the caller's I/O status block.
  671. Buffer - Address of variable to receive the names of the files or
  672. directories that have changed since the last time that the service
  673. was invoked.
  674. Length - Length of the output buffer. On the first call, this parameter
  675. also serves as a guideline for how large to make the system's
  676. internal buffer. Specifying a buffer length of zero causes the request
  677. to complete when changes are made, but no information about the
  678. changes are returned.
  679. CompletionFilter - Indicates the types of changes to files or directories
  680. within the directory that will complete the I/O operation.
  681. WatchTree - A BOOLEAN value that indicates whether or not changes to
  682. directories below the directory referred to by the FileHandle
  683. parameter cause the operation to complete.
  684. Return Value:
  685. The status returned is success if the operation was properly queued to the
  686. I/O system. Once the operation completes, the status of the operation can
  687. be determined by examining the Status field of the I/O status block.
  688. --*/
  689. {
  690. PIRP irp;
  691. NTSTATUS status;
  692. PFILE_OBJECT fileObject;
  693. PDEVICE_OBJECT deviceObject;
  694. PKEVENT eventObject = (PKEVENT) NULL;
  695. KPROCESSOR_MODE requestorMode;
  696. PIO_STACK_LOCATION irpSp;
  697. BOOLEAN synchronousIo;
  698. PETHREAD CurrentThread;
  699. PAGED_CODE();
  700. //
  701. // Get the previous mode; i.e., the mode of the caller.
  702. //
  703. CurrentThread = PsGetCurrentThread ();
  704. requestorMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
  705. if (requestorMode != KernelMode) {
  706. //
  707. // The caller's access mode is user, so probe each of the arguments
  708. // and capture them as necessary. If any failures occur, the condition
  709. // handler will be invoked to handle them. It will simply cleanup and
  710. // return an access violation status code back to the system service
  711. // dispatcher.
  712. //
  713. try {
  714. //
  715. // The IoStatusBlock parameter must be writeable by the caller.
  716. //
  717. ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine);
  718. //
  719. // The Buffer parameter must be writeable by the caller.
  720. //
  721. if (Length != 0) {
  722. ProbeForWrite( Buffer,
  723. Length,
  724. sizeof( ULONG ) );
  725. }
  726. } except(EXCEPTION_EXECUTE_HANDLER) {
  727. //
  728. // An exception was incurred probing the caller's I/O status
  729. // block. Simply return the appropriate error status code.
  730. //
  731. return GetExceptionCode();
  732. }
  733. //
  734. // The CompletionFilter parameter must not contain any values which
  735. // are illegal, nor may it not specifiy anything at all. Likewise,
  736. // the caller must supply a non-null buffer.
  737. //
  738. if (((CompletionFilter & ~FILE_NOTIFY_VALID_MASK) ||
  739. !CompletionFilter)) {
  740. return STATUS_INVALID_PARAMETER;
  741. }
  742. }
  743. //
  744. // There were no blatant errors so far, so reference the file object so
  745. // the target device object can be found. Note that if the handle does
  746. // not refer to a file object, or if the caller does not have the required
  747. // access to the file, then it will fail.
  748. //
  749. status = ObReferenceObjectByHandle( FileHandle,
  750. FILE_LIST_DIRECTORY,
  751. IoFileObjectType,
  752. requestorMode,
  753. (PVOID *) &fileObject,
  754. (POBJECT_HANDLE_INFORMATION) NULL );
  755. if (!NT_SUCCESS( status )) {
  756. return status;
  757. }
  758. //
  759. // If this file has an I/O completion port associated w/it, then ensure
  760. // that the caller did not supply an APC routine, as the two are mutually
  761. // exclusive methods for I/O completion notification.
  762. //
  763. if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) {
  764. ObDereferenceObject( fileObject );
  765. return STATUS_INVALID_PARAMETER;
  766. }
  767. //
  768. // Get the address of the event object and set the event to the Not-
  769. // Signaled state, if an event was specified. Note here too, that if
  770. // the handle does not refer to an event, or if the event cannot be
  771. // written, then the reference will fail.
  772. //
  773. if (ARGUMENT_PRESENT( Event )) {
  774. status = ObReferenceObjectByHandle( Event,
  775. EVENT_MODIFY_STATE,
  776. ExEventObjectType,
  777. requestorMode,
  778. (PVOID *) &eventObject,
  779. (POBJECT_HANDLE_INFORMATION) NULL );
  780. if (!NT_SUCCESS( status )) {
  781. ObDereferenceObject( fileObject );
  782. return status;
  783. } else {
  784. KeClearEvent( eventObject );
  785. }
  786. }
  787. //
  788. // Make a special check here to determine whether this is a synchronous
  789. // I/O operation. If it is, then wait here until the file is owned by
  790. // the current thread.
  791. //
  792. if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
  793. BOOLEAN interrupted;
  794. if (!IopAcquireFastLock( fileObject )) {
  795. status = IopAcquireFileObjectLock( fileObject,
  796. requestorMode,
  797. (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0),
  798. &interrupted );
  799. if (interrupted) {
  800. if (eventObject != NULL) {
  801. ObDereferenceObject( eventObject );
  802. }
  803. ObDereferenceObject( fileObject );
  804. return status;
  805. }
  806. }
  807. synchronousIo = TRUE;
  808. } else {
  809. synchronousIo = FALSE;
  810. }
  811. //
  812. // Set the file object to the Not-Signaled state.
  813. //
  814. KeClearEvent( &fileObject->Event );
  815. //
  816. // Get the address of the target device object.
  817. //
  818. deviceObject = IoGetRelatedDeviceObject( fileObject );
  819. //
  820. // Allocate and initialize the I/O Request Packet (IRP) for this operation.
  821. // The allocation is performed with an exception handler in case the
  822. // caller does not have enough quota to allocate the packet.
  823. irp = IoAllocateIrp( deviceObject->StackSize, !synchronousIo );
  824. if (!irp) {
  825. //
  826. // An IRP could not be allocated. Cleanup and return an appropriate
  827. // error status code.
  828. //
  829. IopAllocateIrpCleanup( fileObject, eventObject );
  830. return STATUS_INSUFFICIENT_RESOURCES;
  831. }
  832. irp->Tail.Overlay.OriginalFileObject = fileObject;
  833. irp->Tail.Overlay.Thread = CurrentThread;
  834. irp->RequestorMode = requestorMode;
  835. //
  836. // Fill in the service independent parameters in the IRP.
  837. //
  838. irp->UserEvent = eventObject;
  839. irp->UserIosb = IoStatusBlock;
  840. irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
  841. irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
  842. //
  843. // Get a pointer to the stack location for the first driver. This will be
  844. // used to pass the original function codes and the parameters.
  845. //
  846. irpSp = IoGetNextIrpStackLocation( irp );
  847. irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
  848. irpSp->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
  849. irpSp->FileObject = fileObject;
  850. //
  851. // Now determine whether this device expects to have data buffered to it
  852. // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO
  853. // flag in the device object. If the flag is set, then a system buffer is
  854. // allocated and the driver's data will be copied into it. Otherwise, a
  855. // Memory Descriptor List (MDL) is allocated and the caller's buffer is
  856. // locked down using it.
  857. //
  858. if (Length != 0) {
  859. if (deviceObject->Flags & DO_BUFFERED_IO) {
  860. //
  861. // The device does not support direct I/O. Allocate a system
  862. // buffer and specify that it should be deallocated on completion.
  863. // Also indicate that this is an input operation so the data will
  864. // be copied into the caller's buffer. This is done using an
  865. // exception handler that will perform cleanup if the operation
  866. // fails.
  867. //
  868. try {
  869. //
  870. // Allocate the intermediary system buffer from nonpaged pool
  871. // and charge quota for it.
  872. //
  873. irp->AssociatedIrp.SystemBuffer =
  874. ExAllocatePoolWithQuota( NonPagedPool, Length );
  875. } except(EXCEPTION_EXECUTE_HANDLER) {
  876. //
  877. // An exception was incurred while attempting to allocate the
  878. // intermediary system buffer. Clean everything up and return
  879. // an appropriate error status code.
  880. //
  881. IopExceptionCleanup( fileObject,
  882. irp,
  883. eventObject,
  884. (PKEVENT) NULL );
  885. return GetExceptionCode();
  886. }
  887. //
  888. // Remember the address of the caller's buffer so the copy can take
  889. // place during I/O completion. Also, set the flags so that the
  890. // completion code knows to do the copy and to deallocate the
  891. // buffer.
  892. //
  893. irp->UserBuffer = Buffer;
  894. irp->Flags = IRP_BUFFERED_IO |
  895. IRP_DEALLOCATE_BUFFER |
  896. IRP_INPUT_OPERATION;
  897. } else if (deviceObject->Flags & DO_DIRECT_IO) {
  898. //
  899. // This is a direct I/O operation. Allocate an MDL and invoke the
  900. // memory management routine to lock the buffer into memory. This
  901. // is done using an exception handler that will perform cleanup if
  902. // the operation fails.
  903. //
  904. PMDL mdl;
  905. mdl = (PMDL) NULL;
  906. try {
  907. //
  908. // Allocate an MDL, charging quota for it, and hang it off of
  909. // the IRP. Probe and lock the pages associated with the
  910. // caller's buffer for write access and fill in the MDL with
  911. // the PFNs of those pages.
  912. //
  913. mdl = IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp );
  914. if (mdl == NULL) {
  915. ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES );
  916. }
  917. MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess );
  918. } except(EXCEPTION_EXECUTE_HANDLER) {
  919. //
  920. // An exception was incurred while either probing the caller's
  921. // buffer of allocating the MDL. Determine what actually
  922. // happened, clean everything up, and return an appropriate
  923. // error status code.
  924. //
  925. IopExceptionCleanup( fileObject,
  926. irp,
  927. eventObject,
  928. (PKEVENT) NULL );
  929. return GetExceptionCode();
  930. }
  931. } else {
  932. //
  933. // Pass the address of the user's buffer so the driver has access
  934. // to it. It is now the driver's responsibility to do everything.
  935. //
  936. irp->UserBuffer = Buffer;
  937. }
  938. }
  939. //
  940. // Copy the caller's parameters to the service-specific portion of the
  941. // IRP.
  942. //
  943. irpSp->Parameters.NotifyDirectory.Length = Length;
  944. irpSp->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
  945. if (WatchTree) {
  946. irpSp->Flags = SL_WATCH_TREE;
  947. }
  948. //
  949. // Queue the packet, call the driver, and synchronize appopriately with
  950. // I/O completion.
  951. //
  952. return IopSynchronousServiceTail( deviceObject,
  953. irp,
  954. fileObject,
  955. FALSE,
  956. requestorMode,
  957. synchronousIo,
  958. OtherTransfer );
  959. }