Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

dir.c File Reference

#include "iop.h"

Go to the source code of this file.

Functions

NTSTATUS BuildQueryDirectoryIrp (IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan, IN UCHAR MinorFunction, OUT BOOLEAN *SynchronousIo, OUT PDEVICE_OBJECT *DeviceObject, OUT PIRP *Irp, OUT PFILE_OBJECT *FileObject, OUT KPROCESSOR_MODE *RequestorMode)
NTSTATUS NtQueryDirectoryFile (IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass, IN BOOLEAN ReturnSingleEntry, IN PUNICODE_STRING FileName OPTIONAL, IN BOOLEAN RestartScan)
NTSTATUS NtNotifyChangeDirectoryFile (IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN ULONG CompletionFilter, IN BOOLEAN WatchTree)


Function Documentation

NTSTATUS BuildQueryDirectoryIrp IN HANDLE  FileHandle,
IN HANDLE Event  OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine  OPTIONAL,
IN PVOID ApcContext  OPTIONAL,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PVOID  FileInformation,
IN ULONG  Length,
IN FILE_INFORMATION_CLASS  FileInformationClass,
IN BOOLEAN  ReturnSingleEntry,
IN PUNICODE_STRING FileName  OPTIONAL,
IN BOOLEAN  RestartScan,
IN UCHAR  MinorFunction,
OUT BOOLEAN *  SynchronousIo,
OUT PDEVICE_OBJECT DeviceObject,
OUT PIRP Irp,
OUT PFILE_OBJECT FileObject,
OUT KPROCESSOR_MODE RequestorMode
 

Definition at line 57 of file dir.c.

References DO_BUFFERED_IO, DO_DIRECT_IO, Event(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExEventObjectType, ExFreePool(), ExRaiseStatus(), FALSE, FileName, _IO_STACK_LOCATION::FileObject, _IO_STACK_LOCATION::Flags, FO_ALERTABLE_IO, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoAllocateMdl(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopApcRoutinePresent, IopExceptionCleanup(), IopQuerySetAlignmentRequirement, IoWriteAccess, Irp, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_DEFER_IO_COMPLETION, IRP_INPUT_OPERATION, IRP_MJ_DIRECTORY_CONTROL, IRP_MN_QUERY_DIRECTORY, KeClearEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, MmProbeAndLockPages(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, _IO_STACK_LOCATION::Parameters, ProbeAndReadUnicodeString, ProbeForRead, ProbeForWrite(), ProbeForWriteIoStatusEx, PsGetCurrentProcess, PsGetCurrentThread, SL_RESTART_SCAN, SL_RETURN_SINGLE_ENTRY, SynchronousIo, _IRP::Tail, and TRUE.

Referenced by NtQueryDirectoryFile().

00079 : 00080 00081 This service operates on a directory file or OLE container specified by the 00082 FileHandle parameter. The service returns information about files in the 00083 directory or embeddings and streams in the container specified by the file 00084 handle. The ReturnSingleEntry parameter specifies that only a single entry 00085 should be returned rather than filling the buffer. The actual number of 00086 files whose information is returned, is the smallest of the following: 00087 00088 o One entry, if the ReturnSingleEntry parameter is TRUE. 00089 00090 o The number of entries whose information fits into the specified 00091 buffer. 00092 00093 o The number of entries that exist. 00094 00095 o One entry if the optional FileName parameter is specified. 00096 00097 If the optional FileName parameter is specified, then the only information 00098 that is returned is for that single entries, if it exists. Note that the 00099 file name may not specify any wildcard characters according to the naming 00100 conventions of the target file system. The ReturnSingleEntry parameter is 00101 simply ignored. 00102 00103 The information that is obtained about the entries in the directory or OLE 00104 container is based on the FileInformationClass parameter. Legal values are 00105 hard coded based on the MinorFunction. 00106 00107 Arguments: 00108 00109 FileHandle - Supplies a handle to the directory file or OLE container for 00110 which information should be returned. 00111 00112 Event - Supplies an optional event to be set to the Signaled state when 00113 the query is complete. 00114 00115 ApcRoutine - Supplies an optional APC routine to be executed when the 00116 query is complete. 00117 00118 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, 00119 if an ApcRoutine was specified. 00120 00121 IoStatusBlock - Address of the caller's I/O status block. 00122 00123 FileInformation - Supplies a buffer to receive the requested information 00124 returned about the contents of the directory. 00125 00126 Length - Supplies the length, in bytes, of the FileInformation buffer. 00127 00128 FileInformationClass - Specfies the type of information that is to be 00129 returned about the files in the specified directory or OLE container. 00130 00131 ReturnSingleEntry - Supplies a BOOLEAN value that, if TRUE, indicates that 00132 only a single entry should be returned. 00133 00134 FileName - Optionally supplies a file name within the specified directory 00135 or OLE container. 00136 00137 RestartScan - Supplies a BOOLEAN value that, if TRUE, indicates that the 00138 scan should be restarted from the beginning. This parameter must be 00139 set to TRUE by the caller the first time the service is invoked. 00140 00141 MinorFunction - IRP_MN_QUERY_DIRECTORY or IRP_MN_QUERY_OLE_DIRECTORY 00142 00143 SynchronousIo - pointer to returned BOOLEAN; TRUE if synchronous I/O 00144 00145 DeviceObject - pointer to returned pointer to device object 00146 00147 Irp - pointer to returned pointer to device object 00148 00149 FileObject - pointer to returned pointer to file object 00150 00151 RequestorMode - pointer to returned requestor mode 00152 00153 Return Value: 00154 00155 The status returned is STATUS_SUCCESS if a valid irp was created for the 00156 query operation. 00157 00158 --*/ 00159 00160 { 00161 PIRP irp; 00162 NTSTATUS status; 00163 PFILE_OBJECT fileObject; 00164 PDEVICE_OBJECT deviceObject; 00165 PKEVENT eventObject = (PKEVENT) NULL; 00166 KPROCESSOR_MODE requestorMode; 00167 PCHAR auxiliaryBuffer = (PCHAR) NULL; 00168 PIO_STACK_LOCATION irpSp; 00169 PMDL mdl; 00170 00171 PAGED_CODE(); 00172 00173 // 00174 // Get the previous mode; i.e., the mode of the caller. 00175 // 00176 00177 requestorMode = KeGetPreviousMode(); 00178 *RequestorMode = requestorMode; 00179 00180 try { 00181 00182 if (requestorMode != KernelMode) { 00183 00184 ULONG operationlength = 0; // assume invalid 00185 00186 // 00187 // The caller's access mode is not kernel so probe and validate 00188 // each of the arguments as necessary. If any failures occur, 00189 // the condition handler will be invoked to handle them. It 00190 // will simply cleanup and return an access violation status 00191 // code back to the system service dispatcher. 00192 // 00193 00194 // 00195 // The IoStatusBlock parameter must be writeable by the caller. 00196 // 00197 00198 ProbeForWriteIoStatusEx( IoStatusBlock, ApcRoutine); 00199 00200 // 00201 // Ensure that the FileInformationClass parameter is legal for 00202 // querying information about files in the directory or object. 00203 // 00204 00205 if (FileInformationClass == FileDirectoryInformation) { 00206 operationlength = sizeof(FILE_DIRECTORY_INFORMATION); 00207 } else if (MinorFunction == IRP_MN_QUERY_DIRECTORY) { 00208 switch (FileInformationClass) 00209 { 00210 case FileFullDirectoryInformation: 00211 operationlength = sizeof(FILE_FULL_DIR_INFORMATION); 00212 break; 00213 00214 case FileBothDirectoryInformation: 00215 operationlength = sizeof(FILE_BOTH_DIR_INFORMATION); 00216 break; 00217 00218 case FileNamesInformation: 00219 operationlength = sizeof(FILE_NAMES_INFORMATION); 00220 break; 00221 00222 case FileObjectIdInformation: 00223 operationlength = sizeof(FILE_OBJECTID_INFORMATION); 00224 break; 00225 00226 case FileQuotaInformation: 00227 operationlength = sizeof(FILE_QUOTA_INFORMATION); 00228 break; 00229 00230 case FileReparsePointInformation: 00231 operationlength = sizeof(FILE_REPARSE_POINT_INFORMATION); 00232 break; 00233 } 00234 } 00235 00236 // 00237 // If the FileInformationClass parameter is illegal, fail now. 00238 // 00239 00240 if (operationlength == 0) { 00241 return STATUS_INVALID_INFO_CLASS; 00242 } 00243 00244 // 00245 // Ensure that the caller's supplied buffer is at least large enough 00246 // to contain the fixed part of the structure required for this 00247 // query. 00248 // 00249 00250 if (Length < operationlength) { 00251 return STATUS_INFO_LENGTH_MISMATCH; 00252 } 00253 00254 00255 // 00256 // The FileInformation buffer must be writeable by the caller. 00257 // 00258 00259 #if defined(_X86_) 00260 ProbeForWrite( FileInformation, Length, sizeof( ULONG ) ); 00261 #elif defined(_WIN64) 00262 00263 // 00264 // If we are a wow64 process, follow the X86 rules 00265 // 00266 00267 if (PsGetCurrentProcess()->Wow64Process) { 00268 ProbeForWrite( FileInformation, Length, sizeof( ULONG ) ); 00269 } else { 00270 ProbeForWrite( FileInformation, 00271 Length, 00272 IopQuerySetAlignmentRequirement[FileInformationClass] ); 00273 } 00274 00275 #else 00276 ProbeForWrite( FileInformation, 00277 Length, 00278 IopQuerySetAlignmentRequirement[FileInformationClass] ); 00279 #endif 00280 } 00281 00282 // 00283 // If the optional FileName parameter was specified, then it must be 00284 // readable by the caller. Capture the file name string in a pool 00285 // block. Note that if an error occurs during the copy, the cleanup 00286 // code in the exception handler will deallocate the pool before 00287 // returning an access violation status. 00288 // 00289 00290 if (ARGUMENT_PRESENT( FileName )) { 00291 00292 UNICODE_STRING fileName; 00293 PUNICODE_STRING nameBuffer; 00294 00295 // 00296 // Capture the string descriptor itself to ensure that the 00297 // string is readable by the caller without the caller being 00298 // able to change the memory while its being checked. 00299 // 00300 00301 if (requestorMode != KernelMode) { 00302 fileName = ProbeAndReadUnicodeString( FileName ); 00303 } else { 00304 fileName = *FileName; 00305 } 00306 00307 if (fileName.Length) { 00308 00309 // 00310 // The length of the string is non-zero, so probe the 00311 // buffer described by the descriptor if the caller was 00312 // not kernel mode. Likewise, if the caller's mode was 00313 // not kernel, then check the length of the name string 00314 // to ensure that it is not too long. 00315 // 00316 00317 if (requestorMode != KernelMode) { 00318 ProbeForRead( fileName.Buffer, 00319 fileName.Length, 00320 sizeof( UCHAR ) ); 00321 // 00322 // account for unicode 00323 // 00324 00325 if (fileName.Length > MAXIMUM_FILENAME_LENGTH<<1) { 00326 ExRaiseStatus( STATUS_INVALID_PARAMETER ); 00327 } 00328 } 00329 00330 // 00331 // Allocate an auxiliary buffer large enough to contain 00332 // a file name descriptor and to hold the entire file 00333 // name itself. Copy the body of the string into the 00334 // buffer. 00335 // 00336 00337 auxiliaryBuffer = ExAllocatePoolWithQuota( NonPagedPool, 00338 fileName.Length + sizeof( UNICODE_STRING ) ); 00339 RtlCopyMemory( auxiliaryBuffer + sizeof( UNICODE_STRING ), 00340 fileName.Buffer, 00341 fileName.Length ); 00342 00343 // 00344 // Finally, build the Unicode string descriptor in the 00345 // auxiliary buffer. 00346 // 00347 00348 nameBuffer = (PUNICODE_STRING) auxiliaryBuffer; 00349 nameBuffer->Length = fileName.Length; 00350 nameBuffer->MaximumLength = fileName.Length; 00351 nameBuffer->Buffer = (PWSTR) (auxiliaryBuffer + sizeof( UNICODE_STRING ) ); 00352 } 00353 } 00354 00355 } except(EXCEPTION_EXECUTE_HANDLER) { 00356 00357 // 00358 // An exception was incurred while probing the caller's buffers, 00359 // attempting to allocate a pool buffer, or while trying to copy 00360 // the caller's data. Determine what happened, clean everything 00361 // up, and return an appropriate error status code. 00362 // 00363 00364 if (auxiliaryBuffer) { 00365 ExFreePool( auxiliaryBuffer ); 00366 } 00367 00368 #if DBG 00369 if (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) { 00370 DbgBreakPoint(); 00371 } 00372 #endif // DBG 00373 00374 return GetExceptionCode(); 00375 } 00376 00377 // 00378 // There were no blatant errors so far, so reference the file object so 00379 // the target device object can be found. Note that if the handle does 00380 // not refer to a file object, or if the caller does not have the required 00381 // access to the file, then it will fail. 00382 // 00383 00384 status = ObReferenceObjectByHandle( FileHandle, 00385 FILE_LIST_DIRECTORY, 00386 IoFileObjectType, 00387 requestorMode, 00388 (PVOID *) &fileObject, 00389 (POBJECT_HANDLE_INFORMATION) NULL ); 00390 if (!NT_SUCCESS( status )) { 00391 if (auxiliaryBuffer) { 00392 ExFreePool( auxiliaryBuffer ); 00393 } 00394 return status; 00395 } 00396 *FileObject = fileObject; 00397 00398 // 00399 // If this file has an I/O completion port associated w/it, then ensure 00400 // that the caller did not supply an APC routine, as the two are mutually 00401 // exclusive methods for I/O completion notification. 00402 // 00403 00404 if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) { 00405 ObDereferenceObject( fileObject ); 00406 if (auxiliaryBuffer) { 00407 ExFreePool( auxiliaryBuffer ); 00408 } 00409 return STATUS_INVALID_PARAMETER; 00410 00411 } 00412 00413 // 00414 // Get the address of the event object and set the event to the Not- 00415 // Signaled state, if an event was specified. Note here, too, that if 00416 // the handle does not refer to an event, or if the event cannot be 00417 // written, then the reference will fail. 00418 // 00419 00420 if (ARGUMENT_PRESENT( Event )) { 00421 status = ObReferenceObjectByHandle( Event, 00422 EVENT_MODIFY_STATE, 00423 ExEventObjectType, 00424 requestorMode, 00425 (PVOID *) &eventObject, 00426 (POBJECT_HANDLE_INFORMATION) NULL ); 00427 if (!NT_SUCCESS( status )) { 00428 if (auxiliaryBuffer) { 00429 ExFreePool( auxiliaryBuffer ); 00430 } 00431 ObDereferenceObject( fileObject ); 00432 return status; 00433 } else { 00434 KeClearEvent( eventObject ); 00435 } 00436 } 00437 00438 // 00439 // Make a special check here to determine whether this is a synchronous 00440 // I/O operation. If it is, then wait here until the file is owned by 00441 // the current thread. 00442 // 00443 00444 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00445 00446 BOOLEAN interrupted; 00447 00448 if (!IopAcquireFastLock( fileObject )) { 00449 status = IopAcquireFileObjectLock( fileObject, 00450 requestorMode, 00451 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00452 &interrupted ); 00453 if (interrupted) { 00454 if (auxiliaryBuffer != NULL) { 00455 ExFreePool( auxiliaryBuffer ); 00456 } 00457 if (eventObject != NULL) { 00458 ObDereferenceObject( eventObject ); 00459 } 00460 ObDereferenceObject( fileObject ); 00461 return status; 00462 } 00463 } 00464 *SynchronousIo = TRUE; 00465 } else { 00466 *SynchronousIo = FALSE; 00467 } 00468 00469 // 00470 // Set the file object to the Not-Signaled state. 00471 // 00472 00473 KeClearEvent( &fileObject->Event ); 00474 00475 // 00476 // Get the address of the target device object. 00477 // 00478 00479 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00480 *DeviceObject = deviceObject; 00481 00482 // 00483 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00484 // The allocation is performed with an exception handler in case the 00485 // caller does not have enough quota to allocate the packet. 00486 00487 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00488 if (!irp) { 00489 00490 // 00491 // An IRP could not be allocated. Cleanup and return an appropriate 00492 // error status code. 00493 // 00494 00495 IopAllocateIrpCleanup( fileObject, eventObject ); 00496 if (auxiliaryBuffer) { 00497 ExFreePool( auxiliaryBuffer ); 00498 } 00499 00500 return STATUS_INSUFFICIENT_RESOURCES; 00501 } 00502 *Irp = irp; 00503 00504 irp->Tail.Overlay.OriginalFileObject = fileObject; 00505 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00506 irp->RequestorMode = requestorMode; 00507 00508 // 00509 // Fill in the service independent parameters in the IRP. 00510 // 00511 00512 irp->UserEvent = eventObject; 00513 irp->UserIosb = IoStatusBlock; 00514 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 00515 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 00516 00517 // 00518 // Get a pointer to the stack location for the first driver. This will be 00519 // used to pass the original function codes and parameters. 00520 // 00521 00522 irpSp = IoGetNextIrpStackLocation( irp ); 00523 irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; 00524 irpSp->MinorFunction = MinorFunction; 00525 irpSp->FileObject = fileObject; 00526 00527 // Also, copy the caller's parameters to the service-specific portion of 00528 // the IRP. 00529 // 00530 00531 irp->Tail.Overlay.AuxiliaryBuffer = auxiliaryBuffer; 00532 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 00533 irp->MdlAddress = (PMDL) NULL; 00534 00535 // 00536 // Now determine whether this driver expects to have data buffered to it 00537 // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO 00538 // flag in the device object. If the flag is set, then a system buffer is 00539 // allocated and the driver's data will be copied into it. Otherwise, a 00540 // Memory Descriptor List (MDL) is allocated and the caller's buffer is 00541 // locked down using it. 00542 // 00543 00544 if (deviceObject->Flags & DO_BUFFERED_IO) { 00545 00546 // 00547 // The device does not support direct I/O. Allocate a system buffer 00548 // and specify that it should be deallocated on completion. Also 00549 // indicate that this is an input operation so the data will be copied 00550 // into the caller's buffer. This is done using an exception handler 00551 // that will perform cleanup if the operation fails. 00552 // 00553 00554 try { 00555 00556 // 00557 // Allocate the intermediary system buffer from nonpaged pool and 00558 // charge quota for it. 00559 // 00560 00561 irp->AssociatedIrp.SystemBuffer = 00562 ExAllocatePoolWithQuota( NonPagedPool, Length ); 00563 00564 } except(EXCEPTION_EXECUTE_HANDLER) { 00565 00566 // 00567 // An exception was incurred while either probing the caller's 00568 // buffer or allocate the system buffer. Determine what actually 00569 // happened, clean everything up, and return an appropriate error 00570 // status code. 00571 // 00572 00573 IopExceptionCleanup( fileObject, 00574 irp, 00575 eventObject, 00576 (PKEVENT) NULL ); 00577 00578 if (auxiliaryBuffer != NULL) { 00579 ExFreePool( auxiliaryBuffer ); 00580 } 00581 00582 return GetExceptionCode(); 00583 00584 } 00585 00586 // 00587 // Remember the address of the caller's buffer so the copy can take 00588 // place during I/O completion. Also, set the flags so that the 00589 // completion code knows to do the copy and to deallocate the buffer. 00590 // 00591 00592 irp->UserBuffer = FileInformation; 00593 irp->Flags = (ULONG) (IRP_BUFFERED_IO | 00594 IRP_DEALLOCATE_BUFFER | 00595 IRP_INPUT_OPERATION); 00596 00597 } else if (deviceObject->Flags & DO_DIRECT_IO) { 00598 00599 // 00600 // This is a direct I/O operation. Allocate an MDL and invoke the 00601 // memory management routine to lock the buffer into memory. This is 00602 // done using an exception handler that will perform cleanup if the 00603 // operation fails. 00604 // 00605 00606 mdl = (PMDL) NULL; 00607 00608 try { 00609 00610 // 00611 // Allocate an MDL, charging quota for it, and hang it off of the 00612 // IRP. Probe and lock the pages associated with the caller's 00613 // buffer for write access and fill in the MDL with the PFNs of 00614 // those pages. 00615 // 00616 00617 mdl = IoAllocateMdl( FileInformation, Length, FALSE, TRUE, irp ); 00618 if (mdl == NULL) { 00619 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00620 } 00621 MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess ); 00622 00623 } except(EXCEPTION_EXECUTE_HANDLER) { 00624 00625 // 00626 // An exception was incurred while either probing the caller's 00627 // buffer or allocating the MDL. Determine what actually happened, 00628 // clean everything up, and return an appropriate error status code. 00629 // 00630 00631 IopExceptionCleanup( fileObject, 00632 irp, 00633 eventObject, 00634 (PKEVENT) NULL ); 00635 00636 if (auxiliaryBuffer != NULL) { 00637 ExFreePool( auxiliaryBuffer ); 00638 } 00639 00640 return GetExceptionCode(); 00641 00642 } 00643 00644 } else { 00645 00646 // 00647 // Pass the address of the user's buffer so the driver has access to 00648 // it. It is now the driver's responsibility to do everything. 00649 // 00650 00651 irp->UserBuffer = FileInformation; 00652 00653 } 00654 00655 // 00656 // Copy the caller's parameters to the service-specific portion of the 00657 // IRP. 00658 // 00659 00660 irpSp->Parameters.QueryDirectory.Length = Length; 00661 irpSp->Parameters.QueryDirectory.FileInformationClass = FileInformationClass; 00662 irpSp->Parameters.QueryDirectory.FileIndex = 0; 00663 irpSp->Parameters.QueryDirectory.FileName = (PSTRING) auxiliaryBuffer; 00664 irpSp->Flags = 0; 00665 if (RestartScan) { 00666 irpSp->Flags = SL_RESTART_SCAN; 00667 } 00668 if (ReturnSingleEntry) { 00669 irpSp->Flags |= SL_RETURN_SINGLE_ENTRY; 00670 } 00671 00672 irp->Flags |= IRP_DEFER_IO_COMPLETION; 00673 00674 // 00675 // Return with everything set up for the caller to complete the I/O. 00676 // 00677 00678 return STATUS_SUCCESS; 00679 }

NTSTATUS NtNotifyChangeDirectoryFile IN HANDLE  FileHandle,
IN HANDLE Event  OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine  OPTIONAL,
IN PVOID ApcContext  OPTIONAL,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PVOID  Buffer,
IN ULONG  Length,
IN ULONG  CompletionFilter,
IN BOOLEAN  WatchTree
 

Definition at line 821 of file dir.c.

References _IRP::AssociatedIrp, Buffer, DO_BUFFERED_IO, DO_DIRECT_IO, Event(), ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExEventObjectType, ExRaiseStatus(), FALSE, _IO_STACK_LOCATION::FileObject, _IO_STACK_LOCATION::Flags, _IRP::Flags, _DEVICE_OBJECT::Flags, FO_ALERTABLE_IO, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoAllocateMdl(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopApcRoutinePresent, IopExceptionCleanup(), IopSynchronousServiceTail(), IoWriteAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_INPUT_OPERATION, IRP_MJ_DIRECTORY_CONTROL, IRP_MN_NOTIFY_CHANGE_DIRECTORY, KeClearEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, _IO_STACK_LOCATION::MinorFunction, MmProbeAndLockPages(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, ProbeForWrite(), ProbeForWriteIoStatusEx, PsGetCurrentThread, _IRP::RequestorMode, SL_WATCH_TREE, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, _IRP::UserIosb, and WatchTree.

00835 : 00836 00837 This service monitors a directory file for changes. Once a change is 00838 made to the directory specified by the FileHandle parameter, the I/O 00839 operation is completed. 00840 00841 Arguments: 00842 00843 FileHandle - Supplies a handle to the file whose EAs should be changed. 00844 00845 Event - Supplies an optional event to be set to the Signaled state when the 00846 change is complete. 00847 00848 ApcRoutine - Supplies an optional APC routine to be executed when the change 00849 is complete. 00850 00851 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, 00852 if an ApcRoutine was specified. 00853 00854 IoStatusBlock - Address of the caller's I/O status block. 00855 00856 Buffer - Address of variable to receive the names of the files or 00857 directories that have changed since the last time that the service 00858 was invoked. 00859 00860 Length - Length of the output buffer. On the first call, this parameter 00861 also serves as a guideline for how large to make the system's 00862 internal buffer. Specifying a buffer length of zero causes the request 00863 to complete when changes are made, but no information about the 00864 changes are returned. 00865 00866 CompletionFilter - Indicates the types of changes to files or directories 00867 within the directory that will complete the I/O operation. 00868 00869 WatchTree - A BOOLEAN value that indicates whether or not changes to 00870 directories below the directory referred to by the FileHandle 00871 parameter cause the operation to complete. 00872 00873 Return Value: 00874 00875 The status returned is success if the operation was properly queued to the 00876 I/O system. Once the operation completes, the status of the operation can 00877 be determined by examining the Status field of the I/O status block. 00878 00879 --*/ 00880 00881 { 00882 PIRP irp; 00883 NTSTATUS status; 00884 PFILE_OBJECT fileObject; 00885 PDEVICE_OBJECT deviceObject; 00886 PKEVENT eventObject = (PKEVENT) NULL; 00887 KPROCESSOR_MODE requestorMode; 00888 PIO_STACK_LOCATION irpSp; 00889 BOOLEAN synchronousIo; 00890 00891 PAGED_CODE(); 00892 00893 // 00894 // Get the previous mode; i.e., the mode of the caller. 00895 // 00896 00897 requestorMode = KeGetPreviousMode(); 00898 00899 if (requestorMode != KernelMode) { 00900 00901 // 00902 // The caller's access mode is user, so probe each of the arguments 00903 // and capture them as necessary. If any failures occur, the condition 00904 // handler will be invoked to handle them. It will simply cleanup and 00905 // return an access violation status code back to the system service 00906 // dispatcher. 00907 // 00908 00909 try { 00910 00911 // 00912 // The IoStatusBlock parameter must be writeable by the caller. 00913 // 00914 00915 ProbeForWriteIoStatusEx( IoStatusBlock , ApcRoutine); 00916 00917 // 00918 // The Buffer parameter must be writeable by the caller. 00919 // 00920 00921 if (Length != 0) { 00922 ProbeForWrite( Buffer, 00923 Length, 00924 sizeof( ULONG ) ); 00925 } 00926 00927 } except(EXCEPTION_EXECUTE_HANDLER) { 00928 00929 // 00930 // An exception was incurred probing the caller's I/O status 00931 // block. Simply return the appropriate error status code. 00932 // 00933 00934 return GetExceptionCode(); 00935 00936 } 00937 00938 // 00939 // The CompletionFilter parameter must not contain any values which 00940 // are illegal, nor may it not specifiy anything at all. Likewise, 00941 // the caller must supply a non-null buffer. 00942 // 00943 00944 if (((CompletionFilter & ~FILE_NOTIFY_VALID_MASK) || 00945 !CompletionFilter)) { 00946 return STATUS_INVALID_PARAMETER; 00947 } 00948 00949 } 00950 00951 // 00952 // There were no blatant errors so far, so reference the file object so 00953 // the target device object can be found. Note that if the handle does 00954 // not refer to a file object, or if the caller does not have the required 00955 // access to the file, then it will fail. 00956 // 00957 00958 status = ObReferenceObjectByHandle( FileHandle, 00959 FILE_LIST_DIRECTORY, 00960 IoFileObjectType, 00961 requestorMode, 00962 (PVOID *) &fileObject, 00963 (POBJECT_HANDLE_INFORMATION) NULL ); 00964 if (!NT_SUCCESS( status )) { 00965 return status; 00966 } 00967 00968 // 00969 // If this file has an I/O completion port associated w/it, then ensure 00970 // that the caller did not supply an APC routine, as the two are mutually 00971 // exclusive methods for I/O completion notification. 00972 // 00973 00974 if (fileObject->CompletionContext && IopApcRoutinePresent( ApcRoutine )) { 00975 ObDereferenceObject( fileObject ); 00976 return STATUS_INVALID_PARAMETER; 00977 } 00978 00979 // 00980 // Get the address of the event object and set the event to the Not- 00981 // Signaled state, if an event was specified. Note here too, that if 00982 // the handle does not refer to an event, or if the event cannot be 00983 // written, then the reference will fail. 00984 // 00985 00986 if (ARGUMENT_PRESENT( Event )) { 00987 status = ObReferenceObjectByHandle( Event, 00988 EVENT_MODIFY_STATE, 00989 ExEventObjectType, 00990 requestorMode, 00991 (PVOID *) &eventObject, 00992 (POBJECT_HANDLE_INFORMATION) NULL ); 00993 if (!NT_SUCCESS( status )) { 00994 ObDereferenceObject( fileObject ); 00995 return status; 00996 } else { 00997 KeClearEvent( eventObject ); 00998 } 00999 } 01000 01001 // 01002 // Make a special check here to determine whether this is a synchronous 01003 // I/O operation. If it is, then wait here until the file is owned by 01004 // the current thread. 01005 // 01006 01007 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 01008 01009 BOOLEAN interrupted; 01010 01011 if (!IopAcquireFastLock( fileObject )) { 01012 status = IopAcquireFileObjectLock( fileObject, 01013 requestorMode, 01014 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 01015 &interrupted ); 01016 if (interrupted) { 01017 if (eventObject != NULL) { 01018 ObDereferenceObject( eventObject ); 01019 } 01020 ObDereferenceObject( fileObject ); 01021 return status; 01022 } 01023 } 01024 synchronousIo = TRUE; 01025 } else { 01026 synchronousIo = FALSE; 01027 } 01028 01029 // 01030 // Set the file object to the Not-Signaled state. 01031 // 01032 01033 KeClearEvent( &fileObject->Event ); 01034 01035 // 01036 // Get the address of the target device object. 01037 // 01038 01039 deviceObject = IoGetRelatedDeviceObject( fileObject ); 01040 01041 // 01042 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 01043 // The allocation is performed with an exception handler in case the 01044 // caller does not have enough quota to allocate the packet. 01045 01046 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 01047 if (!irp) { 01048 01049 // 01050 // An IRP could not be allocated. Cleanup and return an appropriate 01051 // error status code. 01052 // 01053 01054 IopAllocateIrpCleanup( fileObject, eventObject ); 01055 01056 return STATUS_INSUFFICIENT_RESOURCES; 01057 } 01058 irp->Tail.Overlay.OriginalFileObject = fileObject; 01059 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 01060 irp->RequestorMode = requestorMode; 01061 01062 // 01063 // Fill in the service independent parameters in the IRP. 01064 // 01065 01066 irp->UserEvent = eventObject; 01067 irp->UserIosb = IoStatusBlock; 01068 irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; 01069 irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; 01070 01071 // 01072 // Get a pointer to the stack location for the first driver. This will be 01073 // used to pass the original function codes and the parameters. 01074 // 01075 01076 irpSp = IoGetNextIrpStackLocation( irp ); 01077 irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL; 01078 irpSp->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY; 01079 irpSp->FileObject = fileObject; 01080 01081 // 01082 // Now determine whether this device expects to have data buffered to it 01083 // or whether it performs direct I/O. This is based on the DO_BUFFERED_IO 01084 // flag in the device object. If the flag is set, then a system buffer is 01085 // allocated and the driver's data will be copied into it. Otherwise, a 01086 // Memory Descriptor List (MDL) is allocated and the caller's buffer is 01087 // locked down using it. 01088 // 01089 01090 if (Length != 0) { 01091 01092 if (deviceObject->Flags & DO_BUFFERED_IO) { 01093 01094 // 01095 // The device does not support direct I/O. Allocate a system 01096 // buffer and specify that it should be deallocated on completion. 01097 // Also indicate that this is an input operation so the data will 01098 // be copied into the caller's buffer. This is done using an 01099 // exception handler that will perform cleanup if the operation 01100 // fails. 01101 // 01102 01103 try { 01104 01105 // 01106 // Allocate the intermediary system buffer from nonpaged pool 01107 // and charge quota for it. 01108 // 01109 01110 irp->AssociatedIrp.SystemBuffer = 01111 ExAllocatePoolWithQuota( NonPagedPool, Length ); 01112 01113 } except(EXCEPTION_EXECUTE_HANDLER) { 01114 01115 // 01116 // An exception was incurred while attempting to allocate the 01117 // intermediary system buffer. Clean everything up and return 01118 // an appropriate error status code. 01119 // 01120 01121 IopExceptionCleanup( fileObject, 01122 irp, 01123 eventObject, 01124 (PKEVENT) NULL ); 01125 01126 return GetExceptionCode(); 01127 01128 } 01129 01130 // 01131 // Remember the address of the caller's buffer so the copy can take 01132 // place during I/O completion. Also, set the flags so that the 01133 // completion code knows to do the copy and to deallocate the 01134 // buffer. 01135 // 01136 01137 irp->UserBuffer = Buffer; 01138 irp->Flags = IRP_BUFFERED_IO | 01139 IRP_DEALLOCATE_BUFFER | 01140 IRP_INPUT_OPERATION; 01141 01142 } else if (deviceObject->Flags & DO_DIRECT_IO) { 01143 01144 // 01145 // This is a direct I/O operation. Allocate an MDL and invoke the 01146 // memory management routine to lock the buffer into memory. This 01147 // is done using an exception handler that will perform cleanup if 01148 // the operation fails. 01149 // 01150 01151 PMDL mdl; 01152 01153 mdl = (PMDL) NULL; 01154 01155 try { 01156 01157 // 01158 // Allocate an MDL, charging quota for it, and hang it off of 01159 // the IRP. Probe and lock the pages associated with the 01160 // caller's buffer for write access and fill in the MDL with 01161 // the PFNs of those pages. 01162 // 01163 01164 mdl = IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp ); 01165 if (mdl == NULL) { 01166 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 01167 } 01168 MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess ); 01169 01170 } except(EXCEPTION_EXECUTE_HANDLER) { 01171 01172 // 01173 // An exception was incurred while either probing the caller's 01174 // buffer of allocating the MDL. Determine what actually 01175 // happened, clean everything up, and return an appropriate 01176 // error status code. 01177 // 01178 01179 IopExceptionCleanup( fileObject, 01180 irp, 01181 eventObject, 01182 (PKEVENT) NULL ); 01183 01184 return GetExceptionCode(); 01185 01186 } 01187 01188 } else { 01189 01190 // 01191 // Pass the address of the user's buffer so the driver has access 01192 // to it. It is now the driver's responsibility to do everything. 01193 // 01194 01195 irp->UserBuffer = Buffer; 01196 01197 } 01198 } 01199 01200 // 01201 // Copy the caller's parameters to the service-specific portion of the 01202 // IRP. 01203 // 01204 01205 irpSp->Parameters.NotifyDirectory.Length = Length; 01206 irpSp->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter; 01207 if (WatchTree) { 01208 irpSp->Flags = SL_WATCH_TREE; 01209 } 01210 01211 // 01212 // Queue the packet, call the driver, and synchronize appopriately with 01213 // I/O completion. 01214 // 01215 01216 return IopSynchronousServiceTail( deviceObject, 01217 irp, 01218 fileObject, 01219 FALSE, 01220 requestorMode, 01221 synchronousIo, 01222 OtherTransfer ); 01223 } }

NTSTATUS NtQueryDirectoryFile IN HANDLE  FileHandle,
IN HANDLE Event  OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine  OPTIONAL,
IN PVOID ApcContext  OPTIONAL,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PVOID  FileInformation,
IN ULONG  Length,
IN FILE_INFORMATION_CLASS  FileInformationClass,
IN BOOLEAN  ReturnSingleEntry,
IN PUNICODE_STRING FileName  OPTIONAL,
IN BOOLEAN  RestartScan
 

Definition at line 682 of file dir.c.

References BuildQueryDirectoryIrp(), Event(), FileName, IopSynchronousServiceTail(), IRP_MN_QUERY_DIRECTORY, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), OtherTransfer, PAGED_CODE, and TRUE.

00698 : 00699 00700 This service operates on a directory file specified by the FileHandle 00701 parameter. The service returns information about files in the directory 00702 specified by the file handle. The ReturnSingleEntry parameter specifies 00703 that only a single entry should be returned rather than filling the buffer. 00704 The actual number of files whose information is returned, is the smallest 00705 of the following: 00706 00707 o One entry, if the ReturnSingleEntry parameter is TRUE. 00708 00709 o The number of files whose information fits into the specified 00710 buffer. 00711 00712 o The number of files that exist. 00713 00714 o One entry if the optional FileName parameter is specified. 00715 00716 If the optional FileName parameter is specified, then the only information 00717 that is returned is for that single file, if it exists. Note that the 00718 file name may not specify any wildcard characters according to the naming 00719 conventions of the target file system. The ReturnSingleEntry parameter is 00720 simply ignored. 00721 00722 The information that is obtained about the files in the directory is based 00723 on the FileInformationClass parameter. The legal values are as follows: 00724 00725 o FileNamesInformation 00726 00727 o FileDirectoryInformation 00728 00729 o FileFullDirectoryInformation 00730 00731 Arguments: 00732 00733 FileHandle - Supplies a handle to the directory file for which information 00734 should be returned. 00735 00736 Event - Supplies an optional event to be set to the Signaled state when 00737 the query is complete. 00738 00739 ApcRoutine - Supplies an optional APC routine to be executed when the 00740 query is complete. 00741 00742 ApcContext - Supplies a context parameter to be passed to the ApcRoutine, 00743 if an ApcRoutine was specified. 00744 00745 IoStatusBlock - Address of the caller's I/O status block. 00746 00747 FileInformation - Supplies a buffer to receive the requested information 00748 returned about the contents of the directory. 00749 00750 Length - Supplies the length, in bytes, of the FileInformation buffer. 00751 00752 FileInformationClass - Specfies the type of information that is to be 00753 returned about the files in the specified directory. 00754 00755 ReturnSingleEntry - Supplies a BOOLEAN value that, if TRUE, indicates that 00756 only a single entry should be returned. 00757 00758 FileName - Optionally supplies a file name within the specified directory. 00759 00760 RestartScan - Supplies a BOOLEAN value that, if TRUE, indicates that the 00761 scan should be restarted from the beginning. This parameter must be 00762 set to TRUE by the caller the first time the service is invoked. 00763 00764 Return Value: 00765 00766 The status returned is success if the query operation was properly queued 00767 to the I/O system. Once the operation completes, the status of the query 00768 can be determined by examining the Status field of the I/O status block. 00769 00770 --*/ 00771 00772 { 00773 NTSTATUS status; 00774 BOOLEAN synchronousIo; 00775 PDEVICE_OBJECT deviceObject; 00776 PIRP irp; 00777 PFILE_OBJECT fileObject; 00778 KPROCESSOR_MODE requestorMode; 00779 00780 PAGED_CODE(); 00781 00782 // 00783 // Build the irp with the appropriate minor function & allowed info levels. 00784 // 00785 00786 status = BuildQueryDirectoryIrp( FileHandle, 00787 Event, 00788 ApcRoutine, 00789 ApcContext, 00790 IoStatusBlock, 00791 FileInformation, 00792 Length, 00793 FileInformationClass, 00794 ReturnSingleEntry, 00795 FileName, 00796 RestartScan, 00797 IRP_MN_QUERY_DIRECTORY, 00798 &synchronousIo, 00799 &deviceObject, 00800 &irp, 00801 &fileObject, 00802 &requestorMode); 00803 if (NT_SUCCESS( status )) { 00804 00805 // 00806 // Queue the packet, call the driver, and synchronize appopriately with 00807 // I/O completion. 00808 // 00809 status = IopSynchronousServiceTail( deviceObject, 00810 irp, 00811 fileObject, 00812 TRUE, 00813 requestorMode, 00814 synchronousIo, 00815 OtherTransfer ); 00816 } 00817 return status; 00818 }


Generated on Sat May 15 19:43:27 2004 for test by doxygen 1.3.7