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

qsquota.c File Reference

#include "iop.h"

Go to the source code of this file.

Defines

#define ALIGN_LONG(Address)   ( (Address + 3) & ~3 )

Functions

NTSTATUS NtQueryQuotaInformationFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID Buffer, IN ULONG Length, IN BOOLEAN ReturnSingleEntry, IN PVOID SidList OPTIONAL, IN ULONG SidListLength, IN PULONG StartSid OPTIONAL, IN BOOLEAN RestartScan)
NTSTATUS NtSetQuotaInformationFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN PVOID Buffer, IN ULONG Length)


Define Documentation

#define ALIGN_LONG Address   )     ( (Address + 3) & ~3 )
 


Function Documentation

NTSTATUS NtQueryQuotaInformationFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
OUT PVOID  Buffer,
IN ULONG  Length,
IN BOOLEAN  ReturnSingleEntry,
IN PVOID SidList  OPTIONAL,
IN ULONG  SidListLength,
IN PULONG StartSid  OPTIONAL,
IN BOOLEAN  RestartScan
 

Definition at line 35 of file qsquota.c.

References ALIGN_LONG, _IRP::AssociatedIrp, Buffer, DO_BUFFERED_IO, DO_DIRECT_IO, ExAllocatePool, ExAllocatePoolWithQuota, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), ExRaiseStatus(), FALSE, _IO_STACK_LOCATION::FileObject, _IO_STACK_LOCATION::Flags, _DEVICE_OBJECT::Flags, _IRP::Flags, FO_ALERTABLE_IO, FO_SYNCHRONOUS_IO, IoAllocateIrp(), IoAllocateMdl(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopCheckGetQuotaBufferValidity(), IopExceptionCleanup(), IopSynchronousApiServiceTail(), IopSynchronousServiceTail(), IoWriteAccess, IRP_BUFFERED_IO, IRP_DEALLOCATE_BUFFER, IRP_INPUT_OPERATION, IRP_MJ_QUERY_QUOTA, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, MmProbeAndLockPages(), NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, PagedPool, _IO_STACK_LOCATION::Parameters, ProbeAndReadUchar, ProbeForRead, ProbeForWrite(), ProbeForWriteIoStatus, PsGetCurrentProcess, PsGetCurrentThread, _IRP::RequestorMode, RtlLengthRequiredSid(), RtlValidSid(), SL_INDEX_SPECIFIED, SL_RESTART_SCAN, SL_RETURN_SINGLE_ENTRY, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserBuffer, _IRP::UserEvent, and _IRP::UserIosb.

00049 : 00050 00051 This service returns quota entries associated with the volume specified 00052 by the FileHandle parameter. The amount of information returned is based 00053 on the size of the quota information associated with the volume, the size 00054 of the buffer, and whether or not a specific set of entries has been 00055 requested. 00056 00057 Arguments: 00058 00059 FileHandle - Supplies a handle to the file/volume for which the quota 00060 information is returned. 00061 00062 IoStatusBlock - Address of the caller's I/O status block. 00063 00064 Buffer - Supplies a buffer to receive the quota information for the volume. 00065 00066 Length - Supplies the length, in bytes, of the buffer. 00067 00068 ReturnSingleEntry - Indicates that only a single entry should be returned 00069 rather than filling the buffer with as many entries as possible. 00070 00071 SidList - Optionally supplies a list of SIDs whose quota information is to 00072 be returned. 00073 00074 SidListLength - Supplies the length of the SID list, if one was specified. 00075 00076 StartSid - Supplies an optional SID that indicates that the returned 00077 information is to start with an entry other than the first. This 00078 parameter is ignored if a SidList is specified. 00079 00080 RestartScan - Indicates whether the scan of the quota information is to be 00081 restarted from the beginning. 00082 00083 Return Value: 00084 00085 The status returned is the final completion status of the operation. 00086 00087 --*/ 00088 00089 { 00090 00091 #define ALIGN_LONG( Address ) ( (Address + 3) & ~3 ) 00092 00093 PIRP irp; 00094 NTSTATUS status; 00095 PFILE_OBJECT fileObject; 00096 PDEVICE_OBJECT deviceObject; 00097 PKEVENT event = (PKEVENT) NULL; 00098 PCHAR auxiliaryBuffer = (PCHAR) NULL; 00099 ULONG startSidLength = 0; 00100 PSID startSid = (PSID) NULL; 00101 PFILE_GET_QUOTA_INFORMATION sidList = (PFILE_GET_QUOTA_INFORMATION) NULL; 00102 KPROCESSOR_MODE requestorMode; 00103 PIO_STACK_LOCATION irpSp; 00104 IO_STATUS_BLOCK localIoStatus; 00105 BOOLEAN synchronousIo; 00106 UCHAR subCount; 00107 00108 PAGED_CODE(); 00109 00110 // 00111 // Get the previous mode; i.e., the mode of the caller. 00112 // 00113 00114 requestorMode = KeGetPreviousMode(); 00115 00116 if (requestorMode != KernelMode) { 00117 00118 // 00119 // The caller's access mode is not kernel so probe each of the arguments 00120 // and capture them as necessary. If any failures occur, the condition 00121 // handler will be invoked to handle them. It will simply cleanup and 00122 // return an access violation status code back to the system service 00123 // dispatcher. 00124 // 00125 00126 try { 00127 00128 // 00129 // The IoStatusBlock parameter must be writeable by the caller. 00130 // 00131 00132 ProbeForWriteIoStatus( IoStatusBlock ); 00133 00134 // 00135 // The buffer must be writeable by the caller. 00136 // 00137 00138 #if defined(_X86_) 00139 ProbeForWrite( Buffer, Length, sizeof( ULONG ) ); 00140 #elif defined(_WIN64) 00141 00142 // 00143 // If we are a wow64 process, follow the X86 rules 00144 // 00145 00146 if (PsGetCurrentProcess()->Wow64Process) { 00147 ProbeForWrite( Buffer, Length, sizeof( ULONG ) ); 00148 } else { 00149 ProbeForWrite( Buffer, Length, sizeof( ULONGLONG ) ); 00150 } 00151 #else 00152 ProbeForWrite( Buffer, Length, sizeof( ULONGLONG ) ); 00153 #endif 00154 00155 // 00156 // If the optional StartSid parameter was specified, then it must 00157 // be readable by the caller. Begin by capturing the length of 00158 // the SID so that the SID itself can be captured. 00159 // 00160 00161 if (ARGUMENT_PRESENT( StartSid )) { 00162 00163 subCount = ProbeAndReadUchar( &(((SID *)(StartSid))->SubAuthorityCount) ); 00164 startSidLength = RtlLengthRequiredSid( subCount ); 00165 ProbeForRead( StartSid, startSidLength, sizeof( ULONG ) ); 00166 } 00167 00168 // 00169 // If the optional SidList parameter was specified, then it must 00170 // be readable by the caller. Validate that the buffer contains 00171 // a legal get information structure. 00172 // 00173 00174 if (ARGUMENT_PRESENT( SidList ) && SidListLength) { 00175 00176 ProbeForRead( SidList, SidListLength, sizeof( ULONG ) ); 00177 auxiliaryBuffer = ExAllocatePoolWithQuota( NonPagedPool, 00178 ALIGN_LONG( SidListLength ) + 00179 startSidLength ); 00180 sidList = (PFILE_GET_QUOTA_INFORMATION) auxiliaryBuffer; 00181 00182 RtlCopyMemory( auxiliaryBuffer, SidList, SidListLength ); 00183 00184 } else { 00185 00186 // 00187 // No SidList was specified. Check to see whether or not a 00188 // StartSid was specified and, if so, capture it. Note that 00189 // the SID has already been probed. 00190 // 00191 00192 SidListLength = 0; 00193 if (ARGUMENT_PRESENT( StartSid )) { 00194 auxiliaryBuffer = ExAllocatePoolWithQuota( PagedPool, 00195 startSidLength ); 00196 } 00197 } 00198 00199 // 00200 // If a StartSid was specified tack it onto the end of the auxiliary 00201 // buffer. 00202 // 00203 00204 if (ARGUMENT_PRESENT( StartSid )) { 00205 startSid = (PSID) (auxiliaryBuffer + ALIGN_LONG( SidListLength )); 00206 00207 RtlCopyMemory( startSid, StartSid, startSidLength ); 00208 ((SID *) startSid)->SubAuthorityCount = subCount; 00209 } 00210 00211 00212 } except(EXCEPTION_EXECUTE_HANDLER) { 00213 00214 // 00215 // An exception was incurred while probing the caller's 00216 // parameters, allocating the pool buffer, or copying the 00217 // caller's EA list to the buffer. Cleanup and return an 00218 // appropriate error status code. 00219 // 00220 00221 if (auxiliaryBuffer) { 00222 ExFreePool( auxiliaryBuffer ); 00223 } 00224 00225 return GetExceptionCode(); 00226 00227 } 00228 00229 } else { 00230 00231 // 00232 // The caller's mode was KernelMode. Simply allocate pool for the 00233 // SidList, if one was specified, and copy the string to it. Also, 00234 // if a StartSid was specified copy it as well. 00235 // 00236 00237 if (ARGUMENT_PRESENT( SidList ) && SidListLength) { 00238 sidList = SidList; 00239 } 00240 00241 if (ARGUMENT_PRESENT( StartSid )) { 00242 startSid = StartSid; 00243 } 00244 } 00245 00246 // 00247 // Always check the validity of the buffer since the server uses this 00248 // routine. 00249 // 00250 00251 if (sidList != NULL) { 00252 status = IopCheckGetQuotaBufferValidity( sidList, 00253 SidListLength, 00254 &IoStatusBlock->Information ); 00255 if (!NT_SUCCESS( status )) { 00256 if (auxiliaryBuffer != NULL) { 00257 ExFreePool( auxiliaryBuffer ); 00258 } 00259 return status; 00260 00261 } 00262 } 00263 00264 if (startSid != NULL) { 00265 00266 if (!RtlValidSid( startSid )) { 00267 if (auxiliaryBuffer != NULL) { 00268 ExFreePool( auxiliaryBuffer ); 00269 } 00270 return STATUS_INVALID_SID; 00271 } 00272 } 00273 00274 // 00275 // There were no blatant errors so far, so reference the file object so 00276 // the target device object can be found. Note that if the handle does 00277 // not refer to a file object, or if the caller does not have the required 00278 // access to the file, then it will fail. 00279 // 00280 00281 status = ObReferenceObjectByHandle( FileHandle, 00282 0, 00283 IoFileObjectType, 00284 requestorMode, 00285 (PVOID *) &fileObject, 00286 NULL ); 00287 if (!NT_SUCCESS( status )) { 00288 if (auxiliaryBuffer) { 00289 ExFreePool( auxiliaryBuffer ); 00290 } 00291 return status; 00292 } 00293 00294 // 00295 // Make a special check here to determine whether this is a synchronous 00296 // I/O operation. If it is, then wait here until the file is owned by 00297 // the current thread. If this is not a (serialized) synchronous I/O 00298 // operation, then allocate and initialize the local event. 00299 // 00300 00301 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00302 00303 BOOLEAN interrupted; 00304 00305 if (!IopAcquireFastLock( fileObject )) { 00306 status = IopAcquireFileObjectLock( fileObject, 00307 requestorMode, 00308 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00309 &interrupted ); 00310 if (interrupted) { 00311 if (auxiliaryBuffer) { 00312 ExFreePool( auxiliaryBuffer ); 00313 } 00314 ObDereferenceObject( fileObject ); 00315 return status; 00316 } 00317 } 00318 synchronousIo = TRUE; 00319 } else { 00320 00321 // 00322 // This is a synchronous API being invoked for a file that is opened 00323 // for asynchronous I/O. This means that this system service is 00324 // to synchronize the completion of the operation before returning 00325 // to the caller. A local event is used to do this. 00326 // 00327 00328 event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) ); 00329 if (!event) { 00330 if (auxiliaryBuffer) { 00331 ExFreePool( auxiliaryBuffer ); 00332 } 00333 ObDereferenceObject( fileObject ); 00334 return STATUS_INSUFFICIENT_RESOURCES; 00335 } 00336 KeInitializeEvent( event, SynchronizationEvent, FALSE ); 00337 synchronousIo = FALSE; 00338 } 00339 00340 // 00341 // Set the file object to the Not-Signaled state. 00342 // 00343 00344 KeClearEvent( &fileObject->Event ); 00345 00346 // 00347 // Get the address of the target device object. 00348 // 00349 00350 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00351 00352 // 00353 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00354 // The allocation is performed with an exception handler in case the 00355 // caller does not have enough quota to allocate the packet. 00356 00357 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00358 if (!irp) { 00359 00360 // 00361 // An IRP could not be allocated. Cleanup and return an appropriate 00362 // error status code. 00363 // 00364 00365 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00366 ExFreePool( event ); 00367 } 00368 00369 IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL ); 00370 00371 if (auxiliaryBuffer) { 00372 ExFreePool( auxiliaryBuffer ); 00373 } 00374 00375 return STATUS_INSUFFICIENT_RESOURCES; 00376 } 00377 irp->Tail.Overlay.OriginalFileObject = fileObject; 00378 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00379 irp->RequestorMode = requestorMode; 00380 00381 // 00382 // Fill in the service independent parameters in the IRP. 00383 // 00384 00385 if (synchronousIo) { 00386 irp->UserEvent = (PKEVENT) NULL; 00387 irp->UserIosb = IoStatusBlock; 00388 } else { 00389 irp->UserEvent = event; 00390 irp->UserIosb = &localIoStatus; 00391 irp->Flags = IRP_SYNCHRONOUS_API; 00392 } 00393 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 00394 00395 // 00396 // Get a pointer to the stack location for the first driver. This will be 00397 // used to pass the original function codes and parameters. 00398 // 00399 00400 irpSp = IoGetNextIrpStackLocation( irp ); 00401 irpSp->MajorFunction = IRP_MJ_QUERY_QUOTA; 00402 irpSp->FileObject = fileObject; 00403 00404 // 00405 // If the caller specified an SID list of names to be queried, then pass 00406 // the address of the intermediary buffer containing the list to the 00407 // driver. 00408 // 00409 00410 irp->Tail.Overlay.AuxiliaryBuffer = auxiliaryBuffer; 00411 irpSp->Parameters.QueryQuota.SidList = sidList; 00412 irpSp->Parameters.QueryQuota.SidListLength = SidListLength; 00413 00414 // 00415 // Now determine whether this driver expects to have data buffered 00416 // to it or whether it performs direct I/O. This is based on the 00417 // DO_BUFFERED_IO flag in the device object. If the flag is set, 00418 // then a system buffer is allocated and the driver's data will be 00419 // copied to it. If the DO_DIRECT_IO flag is set in the device 00420 // object, then a Memory Descriptor List (MDL) is allocated and 00421 // the caller's buffer is locked down using it. Finally, if the 00422 // driver specifies neither of the flags, then simply pass the 00423 // address and length of the buffer and allow the driver to perform 00424 // all of the checking and buffering if any is required. 00425 // 00426 00427 if (deviceObject->Flags & DO_BUFFERED_IO) { 00428 00429 // 00430 // The driver wishes the caller's buffered be copied into an 00431 // intermediary buffer. Allocate the system buffer and specify 00432 // that it should be deallocated on completion. Also indicate 00433 // that this is an input operation so the data will be copied 00434 // into the caller's buffer. This is done using an exception 00435 // handler that will perform cleanup if the operation fails. 00436 // 00437 00438 if (Length) { 00439 try { 00440 00441 // 00442 // Allocate the intermediary system buffer from nonpaged 00443 // pool and charge quota for it. 00444 // 00445 00446 irp->AssociatedIrp.SystemBuffer = 00447 ExAllocatePoolWithQuota( NonPagedPool, Length ); 00448 00449 } except(EXCEPTION_EXECUTE_HANDLER) { 00450 00451 // 00452 // An exception was incurred while either probing the 00453 // caller's buffer or allocating the system buffer. 00454 // Determine what actually happened, clean everything 00455 // up, and return an appropriate error status code. 00456 // 00457 00458 IopExceptionCleanup( fileObject, 00459 irp, 00460 (PKEVENT) NULL, 00461 event ); 00462 00463 if (auxiliaryBuffer) { 00464 ExFreePool( auxiliaryBuffer ); 00465 } 00466 00467 return GetExceptionCode(); 00468 } 00469 00470 // 00471 // Remember the address of the caller's buffer so the copy can 00472 // take place during I/O completion. Also, set the flags so 00473 // that the completion code knows to do the copy and to deallocate 00474 // the buffer. 00475 // 00476 00477 irp->UserBuffer = Buffer; 00478 irp->Flags |= (ULONG) (IRP_BUFFERED_IO | 00479 IRP_DEALLOCATE_BUFFER | 00480 IRP_INPUT_OPERATION); 00481 } else { 00482 irp->AssociatedIrp.SystemBuffer = NULL; 00483 irp->UserBuffer = Buffer; 00484 } 00485 00486 } else if (deviceObject->Flags & DO_DIRECT_IO) { 00487 00488 PMDL mdl; 00489 00490 // 00491 // This is a direct I/O operation. Allocate an MDL and invoke 00492 // the memory management routine to lock the buffer into memory. 00493 // This is done using an exception handler that will perform 00494 // cleanup if the operation fails. 00495 // 00496 00497 mdl = (PMDL) NULL; 00498 00499 if (Length) { 00500 try { 00501 00502 // 00503 // Allocate an MDL, charging quota for it, and hang it off 00504 // of the IRP. Probe and lock the pages associated with 00505 // the caller's buffer for write access and fill in the MDL 00506 // with the PFNs of those pages. 00507 // 00508 00509 mdl = IoAllocateMdl( Buffer, Length, FALSE, TRUE, irp ); 00510 if (!mdl) { 00511 ExRaiseStatus( STATUS_INSUFFICIENT_RESOURCES ); 00512 } 00513 MmProbeAndLockPages( mdl, requestorMode, IoWriteAccess ); 00514 00515 } except(EXCEPTION_EXECUTE_HANDLER) { 00516 00517 // 00518 // An exception was incurred while either probing the 00519 // caller's buffer or allocating the MDL. Determine what 00520 // actually happened, clean everything up, and return an 00521 // appropriate error status code. 00522 // 00523 00524 IopExceptionCleanup( fileObject, 00525 irp, 00526 (PKEVENT) NULL, 00527 event ); 00528 00529 if (auxiliaryBuffer) { 00530 ExFreePool( auxiliaryBuffer ); 00531 } 00532 00533 return GetExceptionCode(); 00534 00535 } 00536 } 00537 00538 } else { 00539 00540 // 00541 // Pass the address of the user's buffer so the driver has access 00542 // to it. It is now the driver's responsibility to do everything. 00543 // 00544 00545 irp->UserBuffer = Buffer; 00546 00547 } 00548 00549 // 00550 // Copy the caller's parameters to the service-specific portion of the 00551 // IRP. 00552 // 00553 00554 irpSp->Parameters.QueryQuota.Length = Length; 00555 irpSp->Parameters.QueryQuota.StartSid = StartSid; 00556 irpSp->Flags = 0; 00557 if (RestartScan) { 00558 irpSp->Flags = SL_RESTART_SCAN; 00559 } 00560 if (ReturnSingleEntry) { 00561 irpSp->Flags |= SL_RETURN_SINGLE_ENTRY; 00562 } 00563 if (ARGUMENT_PRESENT( StartSid )) { 00564 irpSp->Flags |= SL_INDEX_SPECIFIED; 00565 } 00566 00567 // 00568 // Queue the packet, call the driver, and synchronize appropriately with 00569 // I/O completion. 00570 // 00571 00572 status = IopSynchronousServiceTail( deviceObject, 00573 irp, 00574 fileObject, 00575 FALSE, 00576 requestorMode, 00577 synchronousIo, 00578 OtherTransfer ); 00579 00580 // 00581 // If the file for this operation was not opened for synchronous I/O, then 00582 // synchronization of completion of the I/O operation has not yet occurred 00583 // since the allocated event must be used for synchronous APIs on files 00584 // opened for asynchronous I/O. Synchronize the completion of the I/O 00585 // operation now. 00586 // 00587 00588 if (!synchronousIo) { 00589 00590 status = IopSynchronousApiServiceTail( status, 00591 event, 00592 irp, 00593 requestorMode, 00594 &localIoStatus, 00595 IoStatusBlock ); 00596 } 00597 00598 return status; 00599 }

NTSTATUS NtSetQuotaInformationFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN PVOID  Buffer,
IN ULONG  Length
 

Definition at line 602 of file qsquota.c.

References Buffer, FALSE, IopSetEaOrQuotaInformationFile(), and PAGED_CODE.

00611 : 00612 00613 This service changes quota entries for the volume associated with the 00614 FileHandle parameter. All of the quota entries in the specified buffer 00615 are applied to the volume. 00616 00617 Arguments: 00618 00619 FileHandle - Supplies a handle to the file/volume for which the quota 00620 entries are to be applied. 00621 00622 IoStatusBlock - Address of the caller's I/O status block. 00623 00624 Buffer - Supplies a buffer containing the new quota entries that should 00625 be applied to the volume. 00626 00627 Length - Supplies the length, in bytes, of the buffer. 00628 00629 Return Value: 00630 00631 The status returned is the final completion status of the operation. 00632 00633 --*/ 00634 00635 { 00636 PAGED_CODE(); 00637 00638 // 00639 // Simply return the status from the internal common routine for setting 00640 // EAs on a file or quotas on a volume. 00641 // 00642 00643 return IopSetEaOrQuotaInformationFile( FileHandle, 00644 IoStatusBlock, 00645 Buffer, 00646 Length, 00647 FALSE ); 00648 } }


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