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

misc.c File Reference

#include "iop.h"

Go to the source code of this file.

Functions

VOID IopProcessWorkItem (IN PVOID Parameter)
NTSTATUS NtCancelIoFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS NtDeleteFile (IN POBJECT_ATTRIBUTES ObjectAttributes)
NTSTATUS NtFlushBuffersFile (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock)
NTSTATUS NtQueryAttributesFile (IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PFILE_BASIC_INFORMATION FileInformation)
NTSTATUS NtQueryFullAttributesFile (IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation)
PIO_WORKITEM IoAllocateWorkItem (PDEVICE_OBJECT DeviceObject)
VOID IoFreeWorkItem (PIO_WORKITEM IoWorkItem)
VOID IoQueueWorkItem (IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)


Function Documentation

PIO_WORKITEM IoAllocateWorkItem PDEVICE_OBJECT  DeviceObject  ) 
 

Definition at line 891 of file io/misc.c.

References _IO_WORKITEM::DeviceObject, ExAllocatePool, ExInitializeWorkItem, IO_WORKITEM, IopProcessWorkItem(), NonPagedPool, NULL, and _IO_WORKITEM::WorkItem.

00894 { 00895 PIO_WORKITEM ioWorkItem; 00896 PWORK_QUEUE_ITEM exWorkItem; 00897 00898 // 00899 // Allocate a new workitem structure. 00900 // 00901 00902 ioWorkItem = ExAllocatePool( NonPagedPool, sizeof( IO_WORKITEM )); 00903 if (ioWorkItem != NULL) { 00904 00905 // 00906 // Initialize the invariant portions of both ioWorkItem and 00907 // exWorkItem. 00908 // 00909 00910 #if DBG 00911 ioWorkItem->Size = sizeof( IO_WORKITEM ); 00912 #endif 00913 00914 ioWorkItem->DeviceObject = DeviceObject; 00915 00916 exWorkItem = &ioWorkItem->WorkItem; 00917 ExInitializeWorkItem( exWorkItem, IopProcessWorkItem, ioWorkItem ); 00918 } 00919 00920 return ioWorkItem; 00921 }

VOID IoFreeWorkItem PIO_WORKITEM  IoWorkItem  ) 
 

Definition at line 924 of file io/misc.c.

References ASSERT, and ExFreePool().

00930 : 00931 00932 This function is the "wrapper" routine for IoQueueWorkItem. It calls 00933 the original worker function, then dereferences the device object to 00934 (possibly) allow the driver object to go away. 00935 00936 Arguments: 00937 00938 Parameter - Supplies a pointer to an IO_WORKITEM for us to process. 00939 00940 Return Value: 00941 00942 None 00943 00944 --*/ 00945 00946 { 00947 ASSERT( IoWorkItem->Size == sizeof( IO_WORKITEM )); 00948 00949 ExFreePool( IoWorkItem ); 00950 }

VOID IopProcessWorkItem IN PVOID  Parameter  ) 
 

Definition at line 1016 of file io/misc.c.

References _IO_WORKITEM::Context, _IO_WORKITEM::DeviceObject, ObDereferenceObject, PAGED_CODE, and _IO_WORKITEM::Routine.

Referenced by IoAllocateWorkItem().

01022 : 01023 01024 This function is the "wrapper" routine for IoQueueWorkItem. It calls 01025 the original worker function, then dereferences the device object to 01026 (possibly) allow the driver object to go away. 01027 01028 Arguments: 01029 01030 Parameter - Supplies a pointer to an IO_WORKITEM for us to process. 01031 01032 Return Value: 01033 01034 None 01035 01036 --*/ 01037 01038 { 01039 PIO_WORKITEM ioWorkItem; 01040 PDEVICE_OBJECT deviceObject; 01041 01042 PAGED_CODE(); 01043 01044 // 01045 // Get a pointer to the ioWorkItem and store a copy of DeviceObject 01046 // locally. This allow us to function properly if the worker routine 01047 // elects to free the work item. 01048 // 01049 01050 ioWorkItem = (PIO_WORKITEM)Parameter; 01051 deviceObject = ioWorkItem->DeviceObject; 01052 01053 // 01054 // Call the original worker. 01055 // 01056 01057 ioWorkItem->Routine( deviceObject, 01058 ioWorkItem->Context ); 01059 01060 // 01061 // Now we can dereference the device object, since its code is no longer 01062 // being executed for this work item. 01063 // 01064 01065 ObDereferenceObject( deviceObject ); 01066 }

VOID IoQueueWorkItem IN PIO_WORKITEM  IoWorkItem,
IN PIO_WORKITEM_ROUTINE  WorkerRoutine,
IN WORK_QUEUE_TYPE  QueueType,
IN PVOID  Context
 

Definition at line 953 of file io/misc.c.

References ASSERT, DISPATCH_LEVEL, ExQueueWorkItem(), and ObReferenceObject.

00961 : 00962 00963 This function inserts a work item into a work queue that is processed 00964 by a worker thread of the corresponding type. It effectively 00965 "wraps" ExQueueWorkItem, ensuring that the device object is referenced 00966 for the duration of the call. 00967 00968 Arguments: 00969 00970 IoWorkItem - Supplies a pointer to the work item to add the the queue. 00971 This structure must have been allocated via IoAllocateWorkItem(). 00972 00973 WorkerRoutine - Supplies a pointer to the routine that is to be called 00974 in system thread context. 00975 00976 QueueType - Specifies the type of work queue that the work item 00977 should be placed in. 00978 00979 Context - Supplies the context parameter for the callback routine. 00980 00981 Return Value: 00982 00983 None 00984 00985 --*/ 00986 00987 { 00988 PWORK_QUEUE_ITEM exWorkItem; 00989 00990 ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 00991 ASSERT( IoWorkItem->Size == sizeof( IO_WORKITEM )); 00992 00993 // 00994 // Keep a reference on the device object so it doesn't go away. 00995 // 00996 00997 ObReferenceObject( IoWorkItem->DeviceObject ); 00998 00999 // 01000 // Initialize the fields in IoWorkItem 01001 // 01002 01003 IoWorkItem->Routine = WorkerRoutine; 01004 IoWorkItem->Context = Context; 01005 01006 // 01007 // Get a pointer to the ExWorkItem, queue it, and return. 01008 // IopProcessWorkItem() will perform the dereference. 01009 // 01010 01011 exWorkItem = &IoWorkItem->WorkItem; 01012 ExQueueWorkItem( exWorkItem, QueueType ); 01013 }

NTSTATUS NtCancelIoFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 49 of file io/misc.c.

References APC_LEVEL, EXCEPTION_EXECUTE_HANDLER, FALSE, IoCancelIrp(), IoFileObjectType, IopUpdateOtherOperationCount(), _ETHREAD::IrpList, KeDelayExecutionThread(), KeLowerIrql(), KeRaiseIrql(), KernelMode, KPROCESSOR_MODE, L, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, ProbeForWriteIoStatus, PsGetCurrentThread, _IRP::Tail, TRUE, and VOID().

00056 : 00057 00058 This service causes all pending I/O operations for the specified file to be 00059 marked as canceled. Most types of operations can be canceled immediately, 00060 while others may continue toward completion before they are actually 00061 canceled and the caller is notified. 00062 00063 Only those pending operations that were issued by the current thread using 00064 the specified handle are canceled. Any operations issued for the file by 00065 any other thread or any other process continues normally. 00066 00067 Arguments: 00068 00069 FileHandle - Supplies a handle to the file whose operations are to be 00070 canceled. 00071 00072 IoStatusBlock - Address of the caller's I/O status block. 00073 00074 Return Value: 00075 00076 The status returned is the final completion status of the operation. 00077 00078 --*/ 00079 00080 { 00081 PIRP irp; 00082 NTSTATUS status; 00083 PFILE_OBJECT fileObject; 00084 KPROCESSOR_MODE requestorMode; 00085 PETHREAD thread; 00086 BOOLEAN found = FALSE; 00087 PLIST_ENTRY header; 00088 PLIST_ENTRY entry; 00089 KIRQL irql; 00090 00091 PAGED_CODE(); 00092 00093 // 00094 // Get the previous mode; i.e., the mode of the caller. 00095 // 00096 00097 requestorMode = KeGetPreviousMode(); 00098 00099 if (requestorMode != KernelMode) { 00100 00101 // 00102 // The caller's access mode is user, so probe each of the arguments 00103 // and capture them as necessary. If any failures occur, the condition 00104 // handler will be invoked to handle them. It will simply cleanup and 00105 // return an access violation status code back to the system service 00106 // dispatcher. 00107 // 00108 00109 try { 00110 00111 // 00112 // The IoStatusBlock parameter must be writeable by the caller. 00113 // 00114 00115 ProbeForWriteIoStatus( IoStatusBlock ); 00116 00117 } except(EXCEPTION_EXECUTE_HANDLER) { 00118 00119 // 00120 // An exception was incurred attempting to probe the caller' 00121 // I/O status block. Simply return an appropriate error status 00122 // code. 00123 // 00124 00125 return GetExceptionCode(); 00126 } 00127 } 00128 00129 // 00130 // There were no blatant errors so far, so reference the file object so 00131 // the target device object can be found. Note that if the handle does 00132 // not refer to a file object, or if the caller does not have the required 00133 // access to the file, then it will fail. 00134 // 00135 00136 status = ObReferenceObjectByHandle( FileHandle, 00137 0, 00138 IoFileObjectType, 00139 requestorMode, 00140 (PVOID *) &fileObject, 00141 NULL ); 00142 if (!NT_SUCCESS( status )) { 00143 return(status); 00144 } 00145 00146 // 00147 // Note that here the I/O system would normally make a check to determine 00148 // whether or not the file was opened for synchronous I/O. If it was, then 00149 // it would attempt to exclusively acquire the file object lock. However, 00150 // since this service is attempting to cancel all of the I/O for the file, 00151 // it does not make much sense to wait until it has all completed before 00152 // attempting to cancel it. 00153 // 00154 00155 // 00156 // Get the address of the current thread. The thread contains a list of 00157 // the pending operations for this file. 00158 // 00159 00160 thread = PsGetCurrentThread(); 00161 00162 // 00163 // Update the operation count statistic for the current process for 00164 // operations other than read and write. 00165 // 00166 00167 IopUpdateOtherOperationCount(); 00168 00169 // 00170 // Walk the list of IRPs on the thread's pending I/O queue looking for IRPs 00171 // which specify the same file as the FileHandle refers to. For each IRP 00172 // found, set its cancel flag. If no IRPs are found, simply complete the 00173 // I/O here. The only synchronization needed here is to block out all APCs 00174 // for this thread so that no I/O can complete and remove packets from the 00175 // queue. No considerations need be made for multi-processing since this 00176 // thread can only be running on one processor at a time and this routine 00177 // has control of the thread for now. 00178 // 00179 00180 KeRaiseIrql( APC_LEVEL, &irql ); 00181 00182 header = &thread->IrpList; 00183 entry = thread->IrpList.Flink; 00184 00185 while (header != entry) { 00186 00187 // 00188 // An IRP has been found for this thread. If the IRP refers to the 00189 // appropriate file object, set its cancel flag and remember that it 00190 // was found; otherwise, simply continue the loop. 00191 // 00192 00193 irp = CONTAINING_RECORD( entry, IRP, ThreadListEntry ); 00194 if (irp->Tail.Overlay.OriginalFileObject == fileObject) { 00195 found = TRUE; 00196 IoCancelIrp( irp ); 00197 } 00198 00199 entry = entry->Flink; 00200 } 00201 00202 // 00203 // Lower the IRQL back down to what it was on entry to this procedure. 00204 // 00205 00206 KeLowerIrql( irql ); 00207 00208 if (found) { 00209 00210 LARGE_INTEGER interval; 00211 00212 // 00213 // Delay execution for a time and let the request 00214 // finish. The delay time is 10ms. 00215 // 00216 00217 interval.QuadPart = -10 * 1000 * 10; 00218 00219 // 00220 // Wait for a while so the canceled requests can complete. 00221 // 00222 00223 while (found) { 00224 00225 (VOID) KeDelayExecutionThread( KernelMode, FALSE, &interval ); 00226 00227 found = FALSE; 00228 00229 // 00230 // Raise the IRQL to prevent modification to the IRP list by the 00231 // thread's APC routine. 00232 // 00233 00234 KeRaiseIrql( APC_LEVEL, &irql ); 00235 00236 // 00237 // Check the IRP list for requests which refer to the specified 00238 // file object. 00239 // 00240 00241 entry = thread->IrpList.Flink; 00242 00243 while (header != entry) { 00244 00245 // 00246 // An IRP has been found for this thread. If the IRP refers 00247 // to the appropriate file object, remember that it 00248 // was found; otherwise, simply continue the loop. 00249 // 00250 00251 irp = CONTAINING_RECORD( entry, IRP, ThreadListEntry ); 00252 if (irp->Tail.Overlay.OriginalFileObject == fileObject) { 00253 found = TRUE; 00254 break; 00255 } 00256 00257 entry = entry->Flink; 00258 } 00259 00260 // 00261 // Lower the IRQL back down to what it was on entry to this procedure. 00262 // 00263 00264 KeLowerIrql( irql ); 00265 00266 } 00267 } 00268 00269 try { 00270 00271 // 00272 // Write the status back to the user. 00273 // 00274 00275 IoStatusBlock->Status = STATUS_SUCCESS; 00276 IoStatusBlock->Information = 0L; 00277 00278 } except(EXCEPTION_EXECUTE_HANDLER) { 00279 00280 // 00281 // An exception was incurred attempting to write the caller's 00282 // I/O status block; however, the service completed sucessfully so 00283 // just return sucess. 00284 // 00285 00286 } 00287 00288 // 00289 // Dereference the file object. 00290 // 00291 00292 ObDereferenceObject( fileObject ); 00293 00294 return STATUS_SUCCESS; 00295 }

NTSTATUS NtDeleteFile IN POBJECT_ATTRIBUTES  ObjectAttributes  ) 
 

Definition at line 298 of file io/misc.c.

References _OPEN_PACKET::CreateOptions, _OPEN_PACKET::DeleteOnly, _OPEN_PACKET::Disposition, _OPEN_PACKET::FinalStatus, IO_TYPE_OPEN_PACKET, IopUpdateOtherOperationCount(), KPROCESSOR_MODE, _OPEN_PACKET::LocalFileObject, NTSTATUS(), NULL, ObjectAttributes, ObOpenObjectByName(), OPEN_PACKET, OPEN_PACKET_PATTERN, PAGED_CODE, _OPEN_PACKET::ParseCheck, _OPEN_PACKET::ShareAccess, _OPEN_PACKET::Size, TRUE, _OPEN_PACKET::Type, and USHORT.

Referenced by ZwDeleteFile().

00304 : 00305 00306 This service deletes the specified file. 00307 00308 Arguments: 00309 00310 ObjectAttributes - Supplies the attributes to be used for file object (name, 00311 SECURITY_DESCRIPTOR, etc.) 00312 00313 Return Value: 00314 00315 The status returned is the final completion status of the operation. 00316 00317 --*/ 00318 00319 { 00320 KPROCESSOR_MODE requestorMode; 00321 NTSTATUS status; 00322 OPEN_PACKET openPacket; 00323 DUMMY_FILE_OBJECT localFileObject; 00324 HANDLE handle; 00325 00326 PAGED_CODE(); 00327 00328 // 00329 // Get the previous mode; i.e., the mode of the caller. 00330 // 00331 00332 requestorMode = KeGetPreviousMode(); 00333 00334 // 00335 // Build a parse open packet that tells the parse method to open the file 00336 // for open for delete access w/the delete bit set, and then close it. 00337 // 00338 00339 RtlZeroMemory( &openPacket, sizeof( OPEN_PACKET ) ); 00340 00341 openPacket.Type = IO_TYPE_OPEN_PACKET; 00342 openPacket.Size = sizeof( OPEN_PACKET ); 00343 openPacket.CreateOptions = FILE_DELETE_ON_CLOSE; 00344 openPacket.ShareAccess = (USHORT) FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 00345 openPacket.Disposition = FILE_OPEN; 00346 openPacket.DeleteOnly = TRUE; 00347 openPacket.LocalFileObject = &localFileObject; 00348 00349 // 00350 // Update the open count for this process. 00351 // 00352 00353 IopUpdateOtherOperationCount(); 00354 00355 // 00356 // Open the object by its name. Because of the special DeleteOnly flag 00357 // set in the open packet, the parse routine will open the file, and 00358 // then realize that it is only deleting the file, and will therefore 00359 // immediately dereference the file. This will cause the cleanup and 00360 // the close to be sent to the file system, thus causing the file to 00361 // be deleted. 00362 // 00363 00364 status = ObOpenObjectByName( ObjectAttributes, 00365 (POBJECT_TYPE) NULL, 00366 requestorMode, 00367 NULL, 00368 DELETE, 00369 &openPacket, 00370 &handle ); 00371 00372 // 00373 // The operation is successful if the parse check field of the open packet 00374 // indicates that the parse routine was actually invoked, and the final 00375 // status field of the packet is set to success. 00376 // 00377 00378 if (openPacket.ParseCheck != OPEN_PACKET_PATTERN) { 00379 return status; 00380 } else { 00381 return openPacket.FinalStatus; 00382 } 00383 }

NTSTATUS NtFlushBuffersFile IN HANDLE  FileHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock
 

Definition at line 386 of file io/misc.c.

References ExAllocatePool, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, _IO_STACK_LOCATION::FileObject, _IRP::Flags, FO_ALERTABLE_IO, FO_NAMED_PIPE, FO_SYNCHRONOUS_IO, _OBJECT_HANDLE_INFORMATION::GrantedAccess, IoAllocateIrp(), IoFileObjectType, IoGetNextIrpStackLocation, IoGetRelatedDeviceObject(), IopAcquireFastLock, IopAcquireFileObjectLock(), IopAllocateIrpCleanup(), IopSynchronousApiServiceTail(), IopSynchronousServiceTail(), IRP_MJ_FLUSH_BUFFERS, IRP_SYNCHRONOUS_API, KeClearEvent, KeInitializeEvent, KernelMode, KPROCESSOR_MODE, _IO_STACK_LOCATION::MajorFunction, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), OtherTransfer, _IRP::Overlay, PAGED_CODE, ProbeForWriteIoStatus, PsGetCurrentThread, _IRP::RequestorMode, SeComputeGrantedAccesses, _DEVICE_OBJECT::StackSize, _IRP::Tail, TRUE, _IRP::UserEvent, and _IRP::UserIosb.

Referenced by SepServerDisconnectPipe().

00393 : 00394 00395 This service causes all buffered data to the file to be written. 00396 00397 Arguments: 00398 00399 FileHandle - Supplies a handle to the file whose buffers should be flushed. 00400 00401 IoStatusBlock - Address of the caller's I/O status block. 00402 00403 Return Value: 00404 00405 The status returned is the final completion status of the operation. 00406 00407 --*/ 00408 00409 { 00410 PIRP irp; 00411 NTSTATUS status; 00412 PFILE_OBJECT fileObject; 00413 PDEVICE_OBJECT deviceObject; 00414 PKEVENT event; 00415 KPROCESSOR_MODE requestorMode; 00416 PIO_STACK_LOCATION irpSp; 00417 IO_STATUS_BLOCK localIoStatus; 00418 OBJECT_HANDLE_INFORMATION objectHandleInformation; 00419 BOOLEAN synchronousIo; 00420 00421 PAGED_CODE(); 00422 00423 // 00424 // Get the previous mode; i.e., the mode of the caller. 00425 // 00426 00427 requestorMode = KeGetPreviousMode(); 00428 00429 if (requestorMode != KernelMode) { 00430 00431 // 00432 // The caller's access mode is not kernel so probe each of the arguments 00433 // and capture them as necessary. If any failures occur, the condition 00434 // handler will be invoked to handle them. It will simply cleanup and 00435 // return an access violation status code back to the system service 00436 // dispatcher. 00437 // 00438 00439 try { 00440 00441 // 00442 // The IoStatusBlock parameter must be writeable by the caller. 00443 // 00444 00445 ProbeForWriteIoStatus( IoStatusBlock ); 00446 00447 } except(EXCEPTION_EXECUTE_HANDLER) { 00448 00449 // 00450 // An exception was incurred attempting to probe the caller's 00451 // I/O status block. Simply return an appropriate error status 00452 // code. 00453 // 00454 00455 return GetExceptionCode(); 00456 00457 } 00458 } 00459 00460 // 00461 // There were no blatant errors so far, so reference the file object so 00462 // the target device object can be found. Note that if the handle does 00463 // not refer to a file object, or if the caller does not have the required 00464 // access to the file, then it will fail. 00465 // 00466 00467 status = ObReferenceObjectByHandle( FileHandle, 00468 0, 00469 IoFileObjectType, 00470 requestorMode, 00471 (PVOID *) &fileObject, 00472 &objectHandleInformation ); 00473 if (!NT_SUCCESS( status )) { 00474 return status; 00475 } 00476 00477 // 00478 // Ensure that the caller has either WRITE or APPEND access to the file 00479 // before allowing this call to continue. This is especially important 00480 // if the caller opened a volume, where a flush operation may flush more 00481 // than what this opener has written to buffers. Note however that if 00482 // this is a pipe, then the APPEND access cannot be made since this 00483 // access code is overlaid with the CREATE_PIPE_INSTANCE access. 00484 // 00485 00486 if (SeComputeGrantedAccesses( objectHandleInformation.GrantedAccess, 00487 (!(fileObject->Flags & FO_NAMED_PIPE) ? 00488 FILE_APPEND_DATA : 0) | 00489 FILE_WRITE_DATA ) == 0) { 00490 ObDereferenceObject( fileObject ); 00491 return STATUS_ACCESS_DENIED; 00492 } 00493 00494 // 00495 // Make a special check here to determine whether this is a synchronous 00496 // I/O operation. If it is, then wait here until the file is owned by 00497 // the current thread. If this is not a (serialized) synchronous I/O 00498 // operation, then allocate and initialize the local event. 00499 // 00500 00501 if (fileObject->Flags & FO_SYNCHRONOUS_IO) { 00502 00503 BOOLEAN interrupted; 00504 00505 if (!IopAcquireFastLock( fileObject )) { 00506 status = IopAcquireFileObjectLock( fileObject, 00507 requestorMode, 00508 (BOOLEAN) ((fileObject->Flags & FO_ALERTABLE_IO) != 0), 00509 &interrupted ); 00510 if (interrupted) { 00511 ObDereferenceObject( fileObject ); 00512 return status; 00513 } 00514 } 00515 synchronousIo = TRUE; 00516 } else { 00517 00518 // 00519 // This is a synchronous API being invoked for a file that is opened 00520 // for asynchronous I/O. This means that this system service is 00521 // to synchronize the completion of the operation before returning 00522 // to the caller. A local event is used to do this. 00523 // 00524 00525 event = ExAllocatePool( NonPagedPool, sizeof( KEVENT ) ); 00526 if (event == NULL) { 00527 ObDereferenceObject( fileObject ); 00528 return STATUS_INSUFFICIENT_RESOURCES; 00529 } 00530 KeInitializeEvent( event, SynchronizationEvent, FALSE ); 00531 synchronousIo = FALSE; 00532 } 00533 00534 // 00535 // Set the file object to the Not-Signaled state. 00536 // 00537 00538 KeClearEvent( &fileObject->Event ); 00539 00540 // 00541 // Get the address of the target device object. 00542 // 00543 00544 deviceObject = IoGetRelatedDeviceObject( fileObject ); 00545 00546 // 00547 // Allocate and initialize the I/O Request Packet (IRP) for this operation. 00548 // The allocation is performed with an exception handler in case the 00549 // caller does not have enough quota to allocate the packet. 00550 00551 irp = IoAllocateIrp( deviceObject->StackSize, TRUE ); 00552 if (!irp) { 00553 00554 // 00555 // An exception was incurred while attempting to allocate the IRP. 00556 // Cleanup and return an appropriate error status code. 00557 // 00558 00559 if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) { 00560 ExFreePool( event ); 00561 } 00562 00563 IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL ); 00564 00565 return STATUS_INSUFFICIENT_RESOURCES; 00566 } 00567 irp->Tail.Overlay.OriginalFileObject = fileObject; 00568 irp->Tail.Overlay.Thread = PsGetCurrentThread(); 00569 irp->RequestorMode = requestorMode; 00570 00571 // 00572 // Fill in the service independent parameters in the IRP. 00573 // 00574 00575 if (synchronousIo) { 00576 irp->UserEvent = (PKEVENT) NULL; 00577 irp->UserIosb = IoStatusBlock; 00578 } else { 00579 irp->UserEvent = event; 00580 irp->UserIosb = &localIoStatus; 00581 irp->Flags = IRP_SYNCHRONOUS_API; 00582 } 00583 irp->Overlay.AsynchronousParameters.UserApcRoutine = (PIO_APC_ROUTINE) NULL; 00584 00585 // 00586 // Get a pointer to the stack location for the first driver. This is used 00587 // to pass the original function codes and parameters. 00588 // 00589 00590 irpSp = IoGetNextIrpStackLocation( irp ); 00591 irpSp->MajorFunction = IRP_MJ_FLUSH_BUFFERS; 00592 irpSp->FileObject = fileObject; 00593 00594 // 00595 // Queue the packet, call the driver, and synchronize appopriately with 00596 // I/O completion. 00597 // 00598 00599 status = IopSynchronousServiceTail( deviceObject, 00600 irp, 00601 fileObject, 00602 FALSE, 00603 requestorMode, 00604 synchronousIo, 00605 OtherTransfer ); 00606 00607 // 00608 // If the file for this operation was not opened for synchronous I/O, then 00609 // synchronization of completion of the I/O operation has not yet occurred 00610 // since the allocated event must be used for synchronous APIs on files 00611 // opened for asynchronous I/O. Synchronize the completion of the I/O 00612 // operation now. 00613 // 00614 00615 if (!synchronousIo) { 00616 00617 status = IopSynchronousApiServiceTail( status, 00618 event, 00619 irp, 00620 requestorMode, 00621 &localIoStatus, 00622 IoStatusBlock ); 00623 } 00624 00625 return status; 00626 }

NTSTATUS NtQueryAttributesFile IN POBJECT_ATTRIBUTES  ObjectAttributes,
OUT PFILE_BASIC_INFORMATION  FileInformation
 

Definition at line 629 of file io/misc.c.

References _OPEN_PACKET::BasicInformation, _OPEN_PACKET::CreateOptions, _OPEN_PACKET::Disposition, EXCEPTION_EXECUTE_HANDLER, _OPEN_PACKET::FinalStatus, IO_TYPE_OPEN_PACKET, IopUpdateOtherOperationCount(), KernelMode, KPROCESSOR_MODE, _OPEN_PACKET::LocalFileObject, _OPEN_PACKET::NetworkInformation, NTSTATUS(), NULL, ObjectAttributes, ObOpenObjectByName(), OPEN_PACKET, OPEN_PACKET_PATTERN, PAGED_CODE, _OPEN_PACKET::ParseCheck, ProbeForWrite(), _OPEN_PACKET::QueryOnly, _OPEN_PACKET::ShareAccess, _OPEN_PACKET::Size, TRUE, _OPEN_PACKET::Type, and USHORT.

Referenced by FileExists(), RtlDoesFileExists_UEx(), and ZwQueryAttributesFile().

00636 : 00637 00638 This service queries the basic attributes information for a specified file. 00639 00640 Arguments: 00641 00642 ObjectAttributes - Supplies the attributes to be used for file object (name, 00643 SECURITY_DESCRIPTOR, etc.) 00644 00645 FileInformation - Supplies an output buffer to receive the returned file 00646 attributes information. 00647 00648 Return Value: 00649 00650 The status returned is the final completion status of the operation. 00651 00652 --*/ 00653 00654 { 00655 KPROCESSOR_MODE requestorMode; 00656 NTSTATUS status; 00657 OPEN_PACKET openPacket; 00658 DUMMY_FILE_OBJECT localFileObject; 00659 FILE_NETWORK_OPEN_INFORMATION networkInformation; 00660 HANDLE handle; 00661 00662 PAGED_CODE(); 00663 00664 // 00665 // Get the previous mode; i.e., the mode of the caller. 00666 // 00667 00668 requestorMode = KeGetPreviousMode(); 00669 00670 if (requestorMode != KernelMode) { 00671 00672 try { 00673 00674 // 00675 // The caller's mode is not kernel, so probe the output buffer. 00676 // 00677 00678 ProbeForWrite( FileInformation, 00679 sizeof( FILE_BASIC_INFORMATION ), 00680 sizeof( ULONG )); 00681 00682 } except(EXCEPTION_EXECUTE_HANDLER) { 00683 00684 // 00685 // An exception was incurred while probing the caller's parameters. 00686 // Simply return an appropriate error status code. 00687 // 00688 00689 return GetExceptionCode(); 00690 } 00691 } 00692 00693 // 00694 // Build a parse open packet that tells the parse method to open the file, 00695 // query the file's basic attributes, and close the file. 00696 // 00697 00698 RtlZeroMemory( &openPacket, sizeof( OPEN_PACKET ) ); 00699 00700 openPacket.Type = IO_TYPE_OPEN_PACKET; 00701 openPacket.Size = sizeof( OPEN_PACKET ); 00702 openPacket.ShareAccess = (USHORT) FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 00703 openPacket.Disposition = FILE_OPEN; 00704 openPacket.CreateOptions = FILE_OPEN_REPARSE_POINT; 00705 openPacket.BasicInformation = FileInformation; 00706 openPacket.NetworkInformation = &networkInformation; 00707 openPacket.QueryOnly = TRUE; 00708 openPacket.LocalFileObject = &localFileObject; 00709 00710 // 00711 // Update the open count for this process. 00712 // 00713 00714 IopUpdateOtherOperationCount(); 00715 00716 // 00717 // Open the object by its name. Because of the special QueryOnly flag set 00718 // in the open packet, the parse routine will open the file, and then 00719 // realize that it is only performing a query. It will therefore perform 00720 // the query, and immediately close the file. 00721 // 00722 00723 status = ObOpenObjectByName( ObjectAttributes, 00724 (POBJECT_TYPE) NULL, 00725 requestorMode, 00726 NULL, 00727 FILE_READ_ATTRIBUTES, 00728 &openPacket, 00729 &handle ); 00730 00731 // 00732 // The operation is successful if the parse check field of the open packet 00733 // indicates that the parse routine was actually invoked, and the final 00734 // status field of the packet is set to success. 00735 // 00736 00737 if (openPacket.ParseCheck != OPEN_PACKET_PATTERN) { 00738 return status; 00739 } else { 00740 return openPacket.FinalStatus; 00741 } 00742 }

NTSTATUS NtQueryFullAttributesFile IN POBJECT_ATTRIBUTES  ObjectAttributes,
OUT PFILE_NETWORK_OPEN_INFORMATION  FileInformation
 

Definition at line 745 of file io/misc.c.

References _X86_, _OPEN_PACKET::CreateOptions, _OPEN_PACKET::Disposition, EXCEPTION_EXECUTE_HANDLER, _OPEN_PACKET::FinalStatus, _OPEN_PACKET::FullAttributes, IO_TYPE_OPEN_PACKET, IopUpdateOtherOperationCount(), KernelMode, KPROCESSOR_MODE, _OPEN_PACKET::LocalFileObject, _OPEN_PACKET::NetworkInformation, NT_SUCCESS, NTSTATUS(), NULL, ObjectAttributes, ObOpenObjectByName(), OPEN_PACKET, OPEN_PACKET_PATTERN, PAGED_CODE, _OPEN_PACKET::ParseCheck, ProbeForWrite(), _OPEN_PACKET::QueryOnly, _OPEN_PACKET::ShareAccess, _OPEN_PACKET::Size, TRUE, _OPEN_PACKET::Type, and USHORT.

00752 : 00753 00754 This service queries the network attributes information for a specified 00755 file. 00756 00757 Arguments: 00758 00759 ObjectAttributes - Supplies the attributes to be used for file object (name, 00760 SECURITY_DESCRIPTOR, etc.) 00761 00762 FileInformation - Supplies an output buffer to receive the returned file 00763 attributes information. 00764 00765 Return Value: 00766 00767 The status returned is the final completion status of the operation. 00768 00769 --*/ 00770 00771 { 00772 KPROCESSOR_MODE requestorMode; 00773 NTSTATUS status; 00774 OPEN_PACKET openPacket; 00775 DUMMY_FILE_OBJECT localFileObject; 00776 FILE_NETWORK_OPEN_INFORMATION networkInformation; 00777 HANDLE handle; 00778 00779 PAGED_CODE(); 00780 00781 // 00782 // Get the previous mode; i.e., the mode of the caller. 00783 // 00784 00785 requestorMode = KeGetPreviousMode(); 00786 00787 if (requestorMode != KernelMode) { 00788 00789 try { 00790 00791 // 00792 // The caller's mode is not kernel, so probe the output buffer. 00793 // 00794 00795 ProbeForWrite( FileInformation, 00796 sizeof( FILE_NETWORK_OPEN_INFORMATION ), 00797 #if defined(_X86_) 00798 sizeof( LONG )); 00799 #else 00800 sizeof( LONGLONG )); 00801 #endif // defined(_X86_) 00802 00803 } except(EXCEPTION_EXECUTE_HANDLER) { 00804 00805 // 00806 // An exception was incurred while probing the caller's parameters. 00807 // Simply return an appropriate error status code. 00808 // 00809 00810 return GetExceptionCode(); 00811 } 00812 } 00813 00814 // 00815 // Build a parse open packet that tells the parse method to open the file, 00816 // query the file's full attributes, and close the file. 00817 // 00818 00819 RtlZeroMemory( &openPacket, sizeof( OPEN_PACKET ) ); 00820 00821 openPacket.Type = IO_TYPE_OPEN_PACKET; 00822 openPacket.Size = sizeof( OPEN_PACKET ); 00823 openPacket.ShareAccess = (USHORT) FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; 00824 openPacket.Disposition = FILE_OPEN; 00825 openPacket.CreateOptions = FILE_OPEN_REPARSE_POINT; 00826 openPacket.QueryOnly = TRUE; 00827 openPacket.FullAttributes = TRUE; 00828 openPacket.LocalFileObject = &localFileObject; 00829 if (requestorMode != KernelMode) { 00830 openPacket.NetworkInformation = &networkInformation; 00831 } else { 00832 openPacket.NetworkInformation = FileInformation; 00833 } 00834 00835 // 00836 // Update the open count for this process. 00837 // 00838 00839 IopUpdateOtherOperationCount(); 00840 00841 // 00842 // Open the object by its name. Because of the special QueryOnly flag set 00843 // in the open packet, the parse routine will open the file, and then 00844 // realize that it is only performing a query. It will therefore perform 00845 // the query, and immediately close the file. 00846 // 00847 00848 status = ObOpenObjectByName( ObjectAttributes, 00849 (POBJECT_TYPE) NULL, 00850 requestorMode, 00851 NULL, 00852 FILE_READ_ATTRIBUTES, 00853 &openPacket, 00854 &handle ); 00855 00856 // 00857 // The operation is successful if the parse check field of the open packet 00858 // indicates that the parse routine was actually invoked, and the final 00859 // status field of the packet is set to success. 00860 // 00861 00862 if (openPacket.ParseCheck != OPEN_PACKET_PATTERN) { 00863 return status; 00864 } else { 00865 status = openPacket.FinalStatus; 00866 } 00867 00868 if (NT_SUCCESS( status )) { 00869 if (requestorMode != KernelMode) { 00870 try { 00871 00872 // 00873 // The query worked, so copy the returned information to the 00874 // caller's output buffer. 00875 // 00876 00877 RtlMoveMemory( FileInformation, 00878 &networkInformation, 00879 sizeof( FILE_NETWORK_OPEN_INFORMATION ) ); 00880 00881 } except(EXCEPTION_EXECUTE_HANDLER) { 00882 status = GetExceptionCode(); 00883 } 00884 } 00885 } 00886 00887 return status; 00888 }


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