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

qsfs.c File Reference

#include "iop.h"
#include <ioevent.h>

Go to the source code of this file.

Functions

NTSTATUS NtQueryVolumeInformationFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)
NTSTATUS NtSetVolumeInformationFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID FsInformation, IN ULONG Length, IN FS_INFORMATION_CLASS FsInformationClass)


Function Documentation

NTSTATUS NtQueryVolumeInformationFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PVOID  FsInformation,
IN ULONG  Length,
IN FS_INFORMATION_CLASS  FsInformationClass
 

Definition at line 37 of file qsfs.c.

References _IRP::AssociatedIrp, _DEVICE_OBJECT::Characteristics, _DEVICE_OBJECT::DeviceType, ExAllocatePool, ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_ALERTABLE_IO, FO_DIRECT_DEVICE_OPEN, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopExceptionCleanup(), IopGetMountFlag(), IopQueryFsOperationAccess, IopQueryFsOperationLength, IopQuerySetFsAlignmentRequirement, IopReleaseFileObjectLock, IopSynchronousApiServiceTail(), IopSynchronousServiceTail(), IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_DEFER_IO_COMPLETION, IRP_INPUT_OPERATION, IRP_MJ_QUERY_VOLUME_INFORMATION, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, ProbeForWrite(), ProbeForWriteIoStatus, PsGetCurrentProcess, PsGetCurrentThread, _IRP::RequestorMode, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, _IRP::UserIosb, and _DEVICE_OBJECT::Vpb.

Referenced by RtlSetCurrentDirectory_U().

00047 : 00048 00049 This service returns information about the volume associated with the 00050 FileHandle parameter. The information returned in the buffer is defined 00051 by the FsInformationClass parameter. The legal values for this parameter 00052 are as follows: 00053 00054 o FileFsVolumeInformation 00055 00056 o FileFsSizeInformation 00057 00058 o FileFsDeviceInformation 00059 00060 o FileFsAttributeInformation 00061 00062 Arguments: 00063 00064 FileHandle - Supplies a handle to an open volume, directory, or file 00065 for which information about the volume is returned. 00066 00067 IoStatusBlock - Address of the caller's I/O status block. 00068 00069 FsInformation - Supplies a buffer to receive the requested information 00070 returned about the volume. 00071 00072 Length - Supplies the length, in bytes, of the FsInformation buffer. 00073 00074 FsInformationClass - Specifies the type of information which should be 00075 returned about the volume. 00076 00077 Return Value: 00078 00079 The status returned is the final completion status of the operation. 00080 00081 --*/ 00082 00083 { 00084 PIRP irp; 00085 NTSTATUS status; 00086 PFILE_OBJECT fileObject; 00087 PDEVICE_OBJECT deviceObject; 00088 PKEVENT event = (PKEVENT) NULL; 00089 KPROCESSOR_MODE requestorMode; 00090 PIO_STACK_LOCATION irpSp; 00091 IO_STATUS_BLOCK localIoStatus; 00092 BOOLEAN synchronousIo; 00093 00094 PAGED_CODE(); 00095 00096 00097 // 00098 // Get the previous mode; i.e., the mode of the caller. 00099 // 00100 00101 requestorMode = KeGetPreviousMode(); 00102 00103 if (requestorMode != KernelMode) { 00104 00105 // 00106 // Ensure that the FsInformationClass parameter is legal for querying 00107 // information about the volume. 00108 // 00109 00110 if ((ULONG) FsInformationClass >= FileFsMaximumInformation || 00111 IopQueryFsOperationLength[FsInformationClass] == 0) { 00112 return STATUS_INVALID_INFO_CLASS; 00113 } 00114 00115 // 00116 // Finally, ensure that the supplied buffer is large enough to contain 00117 // the information associated with the specified query operation that 00118 // is to be performed. 00119 // 00120 00121 if (Length < (ULONG) IopQueryFsOperationLength[FsInformationClass]) { 00122 return STATUS_INFO_LENGTH_MISMATCH; 00123 } 00124 00125 // 00126 // The caller's access mode is not kernel so probe each of the arguments 00127 // and capture them as necessary. If any failures occur, the condition 00128 // handler will be invoked to handle them. It will simply cleanup and 00129 // return an access violation status code back to the system service 00130 // dispatcher. 00131 // 00132 00133 try { 00134 00135 // 00136 // The IoStatusBlock parameter must be writeable by the caller. 00137 // 00138 00139 ProbeForWriteIoStatus( IoStatusBlock ); 00140 00141 // 00142 // The FsInformation buffer must be writeable by the caller. 00143 // 00144 00145 #if defined(_X86_) 00146 ProbeForWrite( FsInformation, Length, sizeof( ULONG ) ); 00147 #elif defined(_WIN64) 00148 00149 // 00150 // If we are a wow64 process, follow the X86 rules 00151 // 00152 00153 if (PsGetCurrentProcess()->Wow64Process) { 00154 ProbeForWrite( FsInformation, Length, sizeof( ULONG ) ); 00155 } else { 00156 ProbeForWrite( FsInformation, 00157 Length, 00158 IopQuerySetFsAlignmentRequirement[FsInformationClass] ); 00159 00160 } 00161 #else 00162 ProbeForWrite( FsInformation, 00163 Length, 00164 IopQuerySetFsAlignmentRequirement[FsInformationClass] ); 00165 #endif 00166 00167 } except(EXCEPTION_EXECUTE_HANDLER) { 00168 00169 // 00170 // An exception was incurred probing the caller's parameters. 00171 // Simply return an appropriate error status code. 00172 // 00173 00174 #if DBG 00175 if (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) { 00176 DbgBreakPoint(); 00177 } 00178 #endif // DBG 00179 00180 return GetExceptionCode(); 00181 00182 } 00183 } 00184 00185 // 00186 // There were no blatant errors so far, so reference the file object so 00187 // the target device object can be found. Note that if the handle does 00188 // not refer to a file object, or if the caller does not have the required 00189 // access to the file, then it will fail. 00190 // 00191 00192 status = ObReferenceObjectByHandle( FileHandle, 00193 IopQueryFsOperationAccess[FsInformationClass], 00194 IoFileObjectType, 00195 requestorMode, 00196 (PVOID *) &fileObject, 00197 NULL ); 00198 if (!NT_SUCCESS( status )) { 00199 return status; 00200 } 00201 00202 // 00203 // If this open file object represents an open device that was explicitly 00204 // opened for querying the device's attributes, then ensure that the type 00205 // of information class was device information. 00206 // 00207 00208 if ((fileObject->Flags & FO_DIRECT_DEVICE_OPEN) && 00209 FsInformationClass != FileFsDeviceInformation) { 00210 ObDereferenceObject( fileObject ); 00211 return STATUS_INVALID_DEVICE_REQUEST; 00212 } 00213 00214 // 00215 // Make a special check here to determine whether this is a synchronous 00216 // I/O operation. If it is, then wait here until the file is owned by 00217 // the current thread. If this is not a (serialized) synchronous I/O 00218 // operation, then allocate and initialize the local event. 00219 // 00220 00221 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00222 00223 BOOLEAN interrupted; 00224 00225 if (!IopAcquireFastLock( fileObject )) { 00226 status = IopAcquireFileObjectLock( fileObject, 00227 requestorMode, 00228 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00229 &interrupted ); 00230 if (interrupted) { 00231 ObDereferenceObject( fileObject ); 00232 return status; 00233 } 00234 } 00235 synchronousIo = TRUE; 00236 } else { 00237 synchronousIo = FALSE; 00238 } 00239 00240 // 00241 // Get the address of the target device object. A special check is made 00242 // here to determine whether this query is for device information. If 00243 // it is, and either: 00244 // 00245 // a) The open was for the device itself, or 00246 // 00247 // b) The open was for a file but this is not a redirected device, 00248 // 00249 // then perform the query operation in-line. That is, do not allocate 00250 // an IRP and call the driver, rather, simply copy the device type and 00251 // characteristics information from the target device object pointed 00252 // to by the device object in the file object (the "real" device object 00253 // in a mass storage device stack). 00254 // 00255 00256 if (FsInformationClass == FileFsDeviceInformation && 00257 (fileObject->Flags & FO_DIRECT_DEVICE_OPEN || 00258 fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM)) { 00259 00260 PFILE_FS_DEVICE_INFORMATION deviceAttributes; 00261 BOOLEAN deviceMounted = FALSE; 00262 00263 // 00264 // This query operation can be performed in-line. Simply copy the 00265 // information directly from the target device object and indicate 00266 // that the operation was successful. Begin, however, by determining 00267 // whether or not the device is mounted. This cannot be done at the 00268 // same time as attempting to touch the user's buffer, as looking at 00269 // the mounted bit occurs at raised IRQL. 00270 // 00271 00272 deviceObject = fileObject->DeviceObject; 00273 if (deviceObject->Vpb) { 00274 deviceMounted = IopGetMountFlag( deviceObject ); 00275 } 00276 00277 // 00278 // Copy the characteristics information from the device's object 00279 // into the caller's buffer. 00280 // 00281 00282 deviceAttributes = (PFILE_FS_DEVICE_INFORMATION) FsInformation; 00283 00284 try { 00285 00286 deviceAttributes->DeviceType = deviceObject->DeviceType; 00287 deviceAttributes->Characteristics = deviceObject->Characteristics; 00288 if (deviceMounted) { 00289 deviceAttributes->Characteristics |= FILE_DEVICE_IS_MOUNTED; 00290 } 00291 00292 IoStatusBlock->Status = STATUS_SUCCESS; 00293 IoStatusBlock->Information = sizeof( FILE_FS_DEVICE_INFORMATION ); 00294 status = STATUS_SUCCESS; 00295 00296 } except( EXCEPTION_EXECUTE_HANDLER ) { 00297 00298 // 00299 // An error occurred attempting to write into one of the caller's 00300 // buffers. Simply indicate that the error occurred, and fall 00301 // through. 00302 // 00303 00304 status = GetExceptionCode(); 00305 } 00306 00307 // 00308 // If this operation was performed as synchronous I/O, then release 00309 // the file object lock. 00310 // 00311 00312 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00313 IopReleaseFileObjectLock( fileObject ); 00314 } 00315 00316 // 00317 // Now simply cleanup and return the final status of the operation. 00318 // 00319 00320 ObDereferenceObject( fileObject ); 00321 return status; 00322 00323 } 00324 00325 // 00326 // This is either a query that is not for device characteristics 00327 // information, or it is a query for device information, but it is 00328 // a query for a redirected device. Take the long route and actually 00329 // invoke the driver for the target device to get the information. 00330 // 00331 // Set the file object to the Not-Signaled state. 00332 // 00333 00334 KeClearEvent( &fileObject->Event ); 00335 00336 // 00337 // Get a pointer to the device object for the target device. 00338 // 00339 00340 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00341 00342 // 00343 // If this I/O operation is not being performed as synchronous I/O, 00344 // then allocate an event that will be used to synchronize the 00345 // completion of this operation. That is, this system service is 00346 // a synchronous API being invoked for a file that is opened for 00347 // asynchronous I/O. 00348 // 00349 00350 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00351 event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) ); 00352 if (event == NULL) { 00353 ObDereferenceObject( fileObject ); 00354 return STATUS_INSUFFICIENT_RESOURCES; 00355 } 00356 KeInitializeEvent( event, SynchronizationEvent, FALSE ); 00357 } 00358 00359 // 00360 // Allocate and initialize the I/O Request Packet (IRP) for this 00361 // operation. The allocation is performed with an exception handler 00362 // in case the caller does not have enough quota to allocate the packet. 00363 00364 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00365 if (!irp) { 00366 00367 // 00368 // An IRP could not be allocated. Cleanup and return an 00369 // appropriate error status code. 00370 // 00371 00372 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00373 ExFreePool( event ); 00374 } 00375 00376 IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL ); 00377 00378 return STATUS_INSUFFICIENT_RESOURCES; 00379 } 00380 irp->Tail.Overlay.OriginalFileObject = fileObject; 00381 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00382 irp->RequestorMode = requestorMode; 00383 00384 // 00385 // Fill in the service independent parameters in the IRP. 00386 // 00387 00388 if (synchronousIo) { 00389 irp->UserEvent = (PKEVENT) NULL; 00390 irp->UserIosb = IoStatusBlock; 00391 } else { 00392 irp->UserEvent = event; 00393 irp->UserIosb = &localIoStatus; 00394 irp->Flags = IRP_SYNCHRONOUS_API; 00395 } 00396 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 00397 00398 // 00399 // Get a pointer to the stack location for the first driver. This will 00400 // be used to pass the original function codes and parameters. 00401 // 00402 00403 irpSp = IoGetNextIrpStackLocation( irp ); 00404 irpSp->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; 00405 irpSp->FileObject = fileObject; 00406 00407 // 00408 // Allocate a buffer which should be used to put the information into 00409 // by the driver. This will be copied back to the caller's buffer when 00410 // the service completes. This is done by setting the flag which says 00411 // that this is an input operation. 00412 // 00413 00414 irp->UserBuffer = FsInformation; 00415 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 00416 irp->MdlAddress = (PMDL) NULL; 00417 00418 // 00419 // Allocate the system buffer using an exception handler in case the 00420 // caller doesn't have enough quota remaining. 00421 // 00422 00423 try { 00424 00425 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuota( NonPagedPool, 00426 Length ); 00427 } except(EXCEPTION_EXECUTE_HANDLER) { 00428 00429 // 00430 // An exception was incurred attempting to allocate the inter- 00431 // mediary buffer. Cleanup and return with an appropriate error 00432 // status code. 00433 // 00434 00435 IopExceptionCleanup( fileObject, 00436 irp, 00437 (PKEVENT) NULL, 00438 event ); 00439 00440 return GetExceptionCode(); 00441 00442 } 00443 00444 irp->Flags |= (ULONG) (IRP_BUFFERED_IO | 00445 IRP_DEALLOCATE_BUFFER | 00446 IRP_INPUT_OPERATION | 00447 IRP_DEFER_IO_COMPLETION); 00448 00449 // 00450 // Copy the caller's parameters to the service-specific portion of the 00451 // IRP. 00452 // 00453 00454 irpSp->Parameters.QueryVolume.Length = Length; 00455 irpSp->Parameters.QueryVolume.FsInformationClass = FsInformationClass; 00456 00457 // 00458 // Queue the packet, call the driver, and synchronize appopriately with 00459 // I/O completion. 00460 // 00461 00462 status = IopSynchronousServiceTail( deviceObject, 00463 irp, 00464 fileObject, 00465 TRUE, 00466 requestorMode, 00467 synchronousIo, 00468 OtherTransfer ); 00469 00470 // 00471 // If the file for this operation was not opened for synchronous I/O, then 00472 // synchronization of completion of the I/O operation has not yet occurred 00473 // since the allocated event must be used for synchronous APIs on files 00474 // opened for asynchronous I/O. Synchronize the completion of the I/O 00475 // operation now. 00476 // 00477 00478 if (!synchronousIo) { 00479 00480 status = IopSynchronousApiServiceTail( status, 00481 event, 00482 irp, 00483 requestorMode, 00484 &localIoStatus, 00485 IoStatusBlock ); 00486 } 00487 00488 return status; 00489 }

NTSTATUS NtSetVolumeInformationFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN PVOID  FsInformation,
IN ULONG  Length,
IN FS_INFORMATION_CLASS  FsInformationClass
 

Definition at line 492 of file qsfs.c.

References ASSERT, _IRP::AssociatedIrp, _TARGET_DEVICE_CUSTOM_NOTIFICATION::Event, ExAllocatePool, ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, _TARGET_DEVICE_CUSTOM_NOTIFICATION::FileObject, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_ALERTABLE_IO, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IoGetRelatedTargetDevice(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopExceptionCleanup(), IopQuerySetFsAlignmentRequirement, IopSetFsOperationAccess, IopSetFsOperationLength, IopSynchronousApiServiceTail(), IopSynchronousServiceTail(), IoReportTargetDeviceChange(), IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_MJ_SET_VOLUME_INFORMATION, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, _IRP::MdlAddress, _TARGET_DEVICE_CUSTOM_NOTIFICATION::NameBufferOffset, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, _IO_STACK_LOCATION::Parameters, ProbeForRead, ProbeForWriteIoStatus, PsGetCurrentProcess, PsGetCurrentThread, _IRP::RequestorMode, _TARGET_DEVICE_CUSTOM_NOTIFICATION::Size, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, _IRP::UserIosb, USHORT, and _TARGET_DEVICE_CUSTOM_NOTIFICATION::Version.

00502 : 00503 00504 This service changes information about the volume "mounted" on the device 00505 specified by the FileHandle parameter. The information to be changed is 00506 in the FsInformation buffer. Its contents are defined by the FsInformation- 00507 Class parameter, whose values may be as follows: 00508 00509 o FileFsLabelInformation 00510 00511 Arguments: 00512 00513 FileHandle - Supplies a handle to the volume whose information should be 00514 changed. 00515 00516 IoStatusBlock - Address of the caller's I/O status block. 00517 00518 FsInformation - Supplies a buffer containing the information which should 00519 be changed on the volume. 00520 00521 Length - Supplies the length, in bytes, of the FsInformation buffer. 00522 00523 FsInformationClass - Specifies the type of information which should be 00524 changed about the volume. 00525 00526 Return Value: 00527 00528 The status returned is the final completion status of the operation. 00529 block. 00530 00531 --*/ 00532 00533 { 00534 PIRP irp; 00535 NTSTATUS status; 00536 PFILE_OBJECT fileObject; 00537 PDEVICE_OBJECT deviceObject; 00538 PKEVENT event = (PKEVENT) NULL; 00539 KPROCESSOR_MODE requestorMode; 00540 PIO_STACK_LOCATION irpSp; 00541 IO_STATUS_BLOCK localIoStatus; 00542 PFILE_FS_LABEL_INFORMATION labelInformation; 00543 BOOLEAN synchronousIo; 00544 PDEVICE_OBJECT targetDeviceObject; 00545 00546 PAGED_CODE(); 00547 00548 // 00549 // Get the previous mode; i.e., the mode of the caller. 00550 // 00551 00552 requestorMode = KeGetPreviousMode(); 00553 00554 if (requestorMode != KernelMode) { 00555 00556 // 00557 // Ensure that the FsInformationClass parameter is legal for setting 00558 // information about the volume. 00559 // 00560 00561 if ((ULONG) FsInformationClass >= FileFsMaximumInformation || 00562 IopSetFsOperationLength[FsInformationClass] == 0) { 00563 return STATUS_INVALID_INFO_CLASS; 00564 } 00565 00566 // 00567 // Finally, ensure that the supplied buffer is large enough to contain 00568 // the information associated with the specified set operation that is 00569 // to be performed. 00570 // 00571 00572 if (Length < (ULONG) IopSetFsOperationLength[FsInformationClass]) { 00573 return STATUS_INFO_LENGTH_MISMATCH; 00574 } 00575 00576 // 00577 // The caller's access mode is user, so probe each of the arguments 00578 // and capture them as necessary. If any failures occur, the condition 00579 // handler will be invoked to handle them. It will simply cleanup and 00580 // return an access violation status code back to the system service 00581 // dispatcher. 00582 // 00583 00584 try { 00585 00586 // 00587 // The IoStatusBlock parameter must be writeable by the caller. 00588 // 00589 00590 ProbeForWriteIoStatus( IoStatusBlock ); 00591 00592 // 00593 // The FsInformation buffer must be readable by the caller. 00594 // 00595 00596 #if defined(_X86_) 00597 ProbeForRead( FsInformation, Length, sizeof( ULONG ) ); 00598 #elif defined(_IA64_) 00599 // If we are a wow64 process, follow the X86 rules 00600 if (PsGetCurrentProcess()->Wow64Process) { 00601 ProbeForRead( FsInformation, Length, sizeof( ULONG ) ); 00602 } 00603 else { 00604 ProbeForRead( FsInformation, 00605 Length, 00606 IopQuerySetFsAlignmentRequirement[FsInformationClass] ); 00607 00608 } 00609 #else 00610 ProbeForRead( FsInformation, 00611 Length, 00612 IopQuerySetFsAlignmentRequirement[FsInformationClass] ); 00613 #endif 00614 00615 } except(EXCEPTION_EXECUTE_HANDLER) { 00616 00617 // 00618 // An exception was incurred probing the caller's parameters. 00619 // Simply return an appropriate error status code. 00620 // 00621 00622 00623 #if DBG 00624 if (GetExceptionCode() == STATUS_DATATYPE_MISALIGNMENT) { 00625 DbgBreakPoint(); 00626 } 00627 #endif DBG 00628 00629 return GetExceptionCode(); 00630 00631 } 00632 } 00633 00634 // 00635 // There were no blatant errors so far, so reference the file object so 00636 // the target device object can be found. Note that if the handle does 00637 // not refer to a file object, or if the caller does not have the required 00638 // access to the file, then it will fail. 00639 // 00640 00641 status = ObReferenceObjectByHandle( FileHandle, 00642 IopSetFsOperationAccess[FsInformationClass], 00643 IoFileObjectType, 00644 requestorMode, 00645 (PVOID *) &fileObject, 00646 NULL ); 00647 if (!NT_SUCCESS( status )) { 00648 return status; 00649 } 00650 00651 // 00652 // Retrieve the device object associated with this file handle. 00653 // 00654 00655 status = IoGetRelatedTargetDevice( fileObject, &targetDeviceObject ); 00656 00657 if (NT_SUCCESS( status )) { 00658 // 00659 // The PDO associated with the devnode we got back from 00660 // IoGetRelatedTargetDevice has already been referenced by that 00661 // routine. Store this reference away in the notification entry, 00662 // so we can deref it later when the notification entry is unregistered. 00663 // 00664 00665 ASSERT(targetDeviceObject); 00666 00667 } else { 00668 targetDeviceObject = NULL; 00669 } 00670 00671 00672 // 00673 // Make a special check here to determine whether this is a synchronous 00674 // I/O operation. If it is, then wait here until the file is owned by 00675 // the current thread. if this is not a (serialized) synchronous I/O 00676 // operation, then allocate and initialize the local event. 00677 // 00678 00679 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00680 00681 BOOLEAN interrupted; 00682 00683 if (!IopAcquireFastLock( fileObject )) { 00684 status = IopAcquireFileObjectLock( fileObject, 00685 requestorMode, 00686 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00687 &interrupted ); 00688 if (interrupted) { 00689 ObDereferenceObject( fileObject ); 00690 if (targetDeviceObject != NULL) { 00691 ObDereferenceObject( targetDeviceObject ); 00692 } 00693 return status; 00694 } 00695 } 00696 synchronousIo = TRUE; 00697 } else { 00698 00699 // 00700 // This is a synchronous API being invoked for a file that is opened 00701 // for asynchronous I/O. This means that this system service is 00702 // to synchronize the completion of the operation before returning 00703 // to the caller. A local event is used to do this. 00704 // 00705 00706 event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) ); 00707 if (event == NULL) { 00708 ObDereferenceObject( fileObject ); 00709 if (targetDeviceObject != NULL) { 00710 ObDereferenceObject( targetDeviceObject ); 00711 } 00712 return STATUS_INSUFFICIENT_RESOURCES; 00713 } 00714 KeInitializeEvent( event, SynchronizationEvent, FALSE ); 00715 synchronousIo = FALSE; 00716 } 00717 00718 // 00719 // Set the file object to the Not-Signaled state. 00720 // 00721 00722 KeClearEvent( &fileObject->Event ); 00723 00724 // 00725 // Get the address of the target device object. 00726 // 00727 00728 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00729 00730 // 00731 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00732 // The allocation is performed with an exception handler in case the 00733 // caller does not have enough quota to allocate the packet. 00734 00735 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00736 if (!irp) { 00737 00738 // 00739 // An IRP could not be allocated. Cleanup and return an appropriate 00740 // error status code. 00741 // 00742 00743 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00744 ExFreePool( event ); 00745 } 00746 00747 IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL ); 00748 00749 if (targetDeviceObject != NULL) { 00750 ObDereferenceObject( targetDeviceObject ); 00751 } 00752 00753 return STATUS_INSUFFICIENT_RESOURCES; 00754 } 00755 irp->Tail.Overlay.OriginalFileObject = fileObject; 00756 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00757 irp->RequestorMode = requestorMode; 00758 00759 // 00760 // Fill in the service independent parameters in the IRP. 00761 // 00762 00763 if (synchronousIo) { 00764 irp->UserEvent = (PKEVENT) NULL; 00765 irp->UserIosb = IoStatusBlock; 00766 } else { 00767 irp->UserEvent = event; 00768 irp->UserIosb = &localIoStatus; 00769 irp->Flags = IRP_SYNCHRONOUS_API; 00770 } 00771 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 00772 00773 // 00774 // Get a pointer to the stack location for the first driver. This will be 00775 // used to pass the original function codes and parameters. 00776 // 00777 00778 irpSp = IoGetNextIrpStackLocation( irp ); 00779 irpSp->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION; 00780 irpSp->FileObject = fileObject; 00781 00782 // 00783 // Allocate a buffer and copy the information that is to be set on the 00784 // file into it. Also, set the flags so that the completion code will 00785 // properly handle getting rid of the buffer and will not attempt to 00786 // copy data. 00787 // 00788 00789 irp->AssociatedIrp.SystemBuffer = (PVOID) NULL; 00790 irp->MdlAddress = (PMDL) NULL; 00791 00792 try { 00793 00794 irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuota( NonPagedPool, 00795 Length ); 00796 RtlCopyMemory( irp->AssociatedIrp.SystemBuffer, FsInformation, Length ); 00797 00798 } except(EXCEPTION_EXECUTE_HANDLER) { 00799 00800 // 00801 // An exception was incurred attempting to allocate the intermediary 00802 // buffer or while copying the caller's data to the buffer. Determine 00803 // what happened, cleanup, and return an appropriate error status 00804 // code. 00805 // 00806 00807 IopExceptionCleanup( fileObject, 00808 irp, 00809 (PKEVENT) NULL, 00810 event ); 00811 00812 if (targetDeviceObject != NULL) { 00813 ObDereferenceObject( targetDeviceObject ); 00814 } 00815 00816 return GetExceptionCode(); 00817 00818 } 00819 00820 // 00821 // If the previous mode was not kernel, check the captured label buffer 00822 // for consistency. 00823 // 00824 00825 if (requestorMode != KernelMode && 00826 FsInformationClass == FileFsLabelInformation) { 00827 00828 // 00829 // The previous mode was something other than kernel. Check to see 00830 // whether or not the length of the label specified within the label 00831 // structure is consistent with the overall length of the structure 00832 // itself. If not, then cleanup and get out. 00833 // 00834 00835 labelInformation = (PFILE_FS_LABEL_INFORMATION) irp->AssociatedIrp.SystemBuffer; 00836 00837 if ((LONG) labelInformation->VolumeLabelLength < 0 || 00838 labelInformation->VolumeLabelLength + 00839 FIELD_OFFSET( FILE_FS_LABEL_INFORMATION, VolumeLabel ) > Length) { 00840 00841 IopExceptionCleanup( fileObject, 00842 irp, 00843 (PKEVENT) NULL, 00844 event ); 00845 00846 if (targetDeviceObject != NULL) { 00847 ObDereferenceObject( targetDeviceObject ); 00848 } 00849 00850 return STATUS_INVALID_PARAMETER; 00851 } 00852 } 00853 00854 irp->Flags |= (ULONG) (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); 00855 00856 // 00857 // Copy the caller's parameters to the service-specific portion of the 00858 // IRP. 00859 // 00860 00861 irpSp->Parameters.SetVolume.Length = Length; 00862 irpSp->Parameters.SetVolume.FsInformationClass = FsInformationClass; 00863 00864 00865 // 00866 // Queue the packet, call the driver, and synchronize appopriately with 00867 // I/O completion. 00868 // 00869 00870 status = IopSynchronousServiceTail( deviceObject, 00871 irp, 00872 fileObject, 00873 FALSE, 00874 requestorMode, 00875 synchronousIo, 00876 OtherTransfer ); 00877 00878 // 00879 // If the file for this operation was not opened for synchronous I/O, then 00880 // synchronization of completion of the I/O operation has not yet occurred 00881 // since the allocated event must be used for synchronous APIs on files 00882 // opened for asynchronous I/O. Synchronize the completion of the I/O 00883 // operation now. 00884 // 00885 00886 if (!synchronousIo) { 00887 00888 status = IopSynchronousApiServiceTail( status, 00889 event, 00890 irp, 00891 requestorMode, 00892 &localIoStatus, 00893 IoStatusBlock ); 00894 } 00895 00896 // 00897 // Notify anyone who cares about the label change 00898 // 00899 00900 if (targetDeviceObject != NULL) { 00901 if (NT_SUCCESS( status )) { 00902 TARGET_DEVICE_CUSTOM_NOTIFICATION ChangeEvent; 00903 00904 ChangeEvent.Version = 1; 00905 ChangeEvent.FileObject = NULL; 00906 ChangeEvent.NameBufferOffset = -1; 00907 ChangeEvent.Size = (USHORT)FIELD_OFFSET( TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer ); 00908 00909 RtlCopyMemory( &ChangeEvent.Event, &GUID_IO_VOLUME_CHANGE, sizeof( GUID_IO_VOLUME_CHANGE )); 00910 00911 IoReportTargetDeviceChange( targetDeviceObject, &ChangeEvent ); 00912 } 00913 00914 ObDereferenceObject( targetDeviceObject ); 00915 } 00916 00917 return status; 00918 } }


Generated on Sat May 15 19:45:24 2004 for test by doxygen 1.3.7